pax_global_header00006660000000000000000000000064136023537550014523gustar00rootroot0000000000000052 comment=14e9257b9bdf03d0654641c0ccb7564fc6856c72 squashfs-tools-ng-0.8/000077500000000000000000000000001360235375500147675ustar00rootroot00000000000000squashfs-tools-ng-0.8/.gitignore000066400000000000000000000006201360235375500167550ustar00rootroot00000000000000.deps .dirstamp .gdb_history .libs Makefile Makefile.in aclocal.m4 autom4te.cache compile config.h.in config.log config.status configure depcomp install-sh missing stamp-h1 config.* *.o *.lo *.la *.a *~ *.pc .#* *.exe *.dll *.log *.trs gensquashfs rdsquashfs sqfs2tar tar2sqfs sqfsdiff tar_fuzz fstree_fuzz test_* test-* fscompare libtool ltmain.sh m4/libtool.m4 m4/lt*.m4 Doxyfile tests/cantrbry.sh squashfs-tools-ng-0.8/CHANGELOG.md000066400000000000000000000244101360235375500166010ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.8] - 2019-12-30 ### Added - Experimental Windows port using MinGW cross compilation toolchain. - Port to BSD systems. - Explicit argument invalid error code in `libsquashfs`. - A `--root-becomes` option to `tar2sqfs` and `sqfs2tar`. - A `--no-tail-packing` option to `tar2sqfs` and `sqfs2tar`. - CHANGELOG.md now references GitHub issue numbers. - Simple integration and regression test suit. - Simple creation of an NFS export table throught `libsquashfs`. - Support for non-directory hard links in `gensquashfs`, `tar2sqfs` and `sqfs2tar`. ### Changed - Return propper error code from `sqfs_get_xattr_prefix_id`. - Return propper error code from `sqfs_compressor_id_from_name`. - Combined error and value return from `sqfs_compressor_id_from_name`. - Return error code from compressor functions if input is larger than 2G. - Lots of cleanups, including the build system. ### Removed - Entirely redundant `sqfs_has_xattr` function from `libsquashfs`. ### Fixed - LZO compressor moved out of libsquashfs to avoid licensing problems. - Make overriding configure variables for LZO library actually work. - Do not follow symlinks when reading xattrs from input files. - Ignore directory entry named `./` in tar2sqfs. (#22, #31) - Reject empty string as directory name in libsquashfs. (#22, #31) - Fix memory leak in tar2sqfs if entries are skipped. - Fix tar_fuzz error check after seek. - Fix the `fstree_init` test to account for defaults from `SOURCE_DATE_EPOCH`. - Honor the no_xattr flag when generating SquashFS images. - Block size check in `sqfs_super_init`. (#29) - Fix pthread block processor interfering with application signal handling. - Added pthread flags to the programs using libsquashfs. - Fix "buffer too small" being treated as fatal error by the zstd compressor. - Fix out of bounds write in the LZO compressor. - Fix queue accounting in the compressor thread pool. (#29) - Fix name of `libsquashfs` pkg-config file. - Reading of binary (i.e. non-textual) xattr values from tar files. (#32) - A bug in parsing the GNU.sparse.name PAX attribute from tar files. - sqfsdiff: recurse into directories that are only in one image. ## [0.7] - 2019-10-08 ### Added - LGPLv3 licensed, shared library `libsquashfs.so` containing all the SquashFS related logic. - Sanitized, public headers and pkg-config file for libsquashfs. - Doxygen reference manual for libsquashfs. - Legacy LZMA compression support. (#17) - User configurable queue backlog for tar2sqfs and gensquashfs. ### Changed - Make sqfsdiff continue comparing even if the types are different, but compatible (e.g. extended directory vs basic directory). - Try to determine the number of available CPU cores and use the maximum by default. - Start numbering inodes at 1, instead of 2. - Only store permission bits in inodes, the reader reconstructs them from the inode type. - Make "--keep-time" the default for tar2sqfs and use flag to disable it. ### Fixed - An off-by-one error in the directory packing code. (#18) - Typo in configure fallback path searching for LZO library. - Typo that caused LZMA2 VLI filters to not be used at all. - Possible out-of-bounds access in LZO compressor constructor. - Inverted logic in sqfs2tar extended attributes processing. ### Removed - Comparisong with directory from sqfsdiff. ## [0.6.1] - 2019-08-27 ### Added - Add a change log - Add test programs for fuzzing tar and gensquashfs file format parsers ### Fixed - Harden against integer overflows when parsing squashfs images (#13, #14) - Test against format limits when parsing directory entries (#12) - More thorough bounds checking when reading metadata blocks (#13, #14, #15) ## [0.6.0] - 2019-08-22 ### Added - New utility `sqfsdiff` that can compare squashfs images - rdsquashfs can now dump extended attributes for an inode (#2) - rdsquashfs can now optionally set xattrs on unpacked files (#2) - rdsquashfs can now optionally restore timestamps on unpacked files (#2) - sqfs2tar can now optionally copy xattrs over to the resulting tarball (#2) - gensquashfs can now optionally read xattrs from input files (#2) - gensquashfs now has a --one-file-system option - tar2sqfs and gensquashfs now output some simple statistics - Full fragment and data block deduplication - Support for SOURCE_DATE_EPOCH environment variable - Optimized, faster file unpacking order - Faster, pthread based, parallel block compressor ### Fixed - Return the correct value from data_reader_create - Fix free() of stack pointer in id_table_read error path - Fix missing initialization of file fragment fields - Fix xattr OOL position - Fix super block flags: clear "no xattr" flag when writing xattrs - Fix xattr writer size accounting - Fix explicit NULL dereference in deserialize_fstree failure path - Fix tar header error reporting on 32 bit systems - Make sure file listing generated by rdsquashfs -d is properly escaped - Fix functions with side effect being used inside asserts - Fix zero padding of extracted data blocks - Fix forward seek when unpacking sparse files - Fix wrong argument type for gensquashfs --keep-time - Fix memory leak in dir-scan error code path - Fix chmod of symlinks in restore_fstree - Add proper copyright headers to all source files ### Changed - Various internal data structure and code cleanups - Overhaul README and convert it to markdown ## [0.5.0] - 2019-07-28 ### Added - Support for NFS export - Support for xattr value deduplication - Flag in packers to optionally keep the original time stamps - Largefile support - Implement simple, fork() based parallel unpacking in rdsquashfs ### Fixed - Remove unfriendly words about squashfs-tools from README (#10) - Propper error message for ZSTD compressor - Correct copy-and-paste mistake in the build system - Make sure xattr string table is propperly initialized - More lenient tar checksum verification - Fix xattr unit test - Fix possible leak in tar2sqfs if writing xattrs fails - Fix corner cases in directory list parsing - Fix processing of tar mtime on 32 bit systems (#8) - libfstree: fix signed/unsigned comparisons - Fix fragment reader out of bounds read when loading table - Fix checks of super block block size - Fix potential resource leak in deserialize_tree - Enforce reasonable upper and low bounds on the size of tar headers - Make sure target in fstree_mknode is always set when creating a symlink - Use safer string copy function to fill tar header ## [0.4.2] - 2019-07-17 ### Fixed - Sanity check id table size read from super block - Various bug fixes through Coverity scan - Fix dirindex writing for ext dir inode - fstree: mknode: initialize fragment data, add extra blocksize slot - Fix directory index creation - Support for reading files without fragments - Support for spaces in filenames - Eleminate use of temporary file ## [0.4.1] - 2019-07-07 ### Fixed - read_inode: determine mode bits from inode type - Actually encode/decode directory inode difference as signed - Fix regression in fstree_from_file device node format - Always initialize gensquashfs defaults option ## [0.4.0] - 2019-07-04 ### Added - no-skip option in tar2sqfs and sqfs2tar - Option for sqfs2tar to extract only some subdirectories - Support for xattr extensions in tar parser - Support repacking xattrs from tarball into squashfs filesystem ### Fixed - Null-pointer dereference in restore_unpack - Memory leak in gzip compressor - Stack pointer free() in fstree_from_dir - Use of uninitialized xattr structure - Initialize return status in fstree_relabel_selinux - Make pax header parser bail if parsing a number fails - Double free in GNU tar sparse file parser - Never used overflow error message in fstree_from_file - Unused variable assignment in tar header writer - Make sure fragment and id tables are initialized - Directory index offset calculation - Missing htole32 transformations - Don't blindly strcpy() the tar header name - Typos in README - Composition order of prefix + name for ustar - Actually check return value when writing xattrs - Possible out of bounds read in libcompress.a - Check block_log range before deriving block size from it - tar2sqfs: check for invalid file names first ### Changed - Tar writer: Use more widely supported GNU tar extensions instead of PAX - Simplify deduction logic for squashfs inode type ## [0.3.0] - 2019-06-30 ### Added - Add utility to turn a squashfs image into a POSIX tar archvie - Add utility to turn a POSIX/PAX tar archive into a squashfs image - Add unit tests - Add support for packing sparse files - Add support for unpacking sparse files as sparse files ### Fixed - Actually update permissions in fstree add by path - Always set permissions on symlinks to 0777 - gensquashfs: Fix typo in help text - Fix inode fragment & sparse counter initialization - Ommit fragment table if there really are no fragments ### Changed - Lots of internal cleanups and restructuring ## [0.2.0] - 2019-06-13 ### Fixed - Make empty directories with xattrs work - Flush the last, unfinished fragment block ### Changed - Add pushd/popd utility functions and replace directory traversal code - Lots of internal cleanups - Use abstractions for many operations and move them to support libraries ## [0.1.0] - 2019-06-08 ### Added - Salvage protoype from Pygos project and turn it into generic squashfs packer - Add unpacker ### Changed - Insert abstraction layers and split generic code off into support libraries [Unreleased]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.7...HEAD [0.7.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.6.1...v0.7 [0.6.1]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.6...v0.6.1 [0.6.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.5...v0.6 [0.5.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.4...v0.5 [0.4.2]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.4.1...v0.4.2 [0.4.1]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.4...v0.4.1 [0.4.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.3...v0.4 [0.3.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.2...v0.3 [0.2.0]: https://github.com/AgentD/squashfs-tools-ng/compare/v0.1...v0.2 [0.1.0]: https://github.com/AgentD/squashfs-tools-ng/releases/tag/v0.1 squashfs-tools-ng-0.8/COPYING.md000066400000000000000000000042211360235375500164200ustar00rootroot00000000000000# License of squashfs-tools-ng The `libsquashfs` library is released under the terms and conditions of the **GNU Lesser General Public License version 3 or later**. This applies to all source code in the directories `lib/sqfs` and `include/sqfs`. The rest of squashfs-tools-ng is released under the terms and conditions of the **GNU General Public License version 3 or later**. Copies of the licenses are included in `licenses/LGPLv3.txt` and `licenses/GPLv3.txt` respectively. The original source code of squashfs-tools-ng has been written by David Oberhollenzer in 2019. Additional contributions have been added since the initial release which makes some parts of the package subject to the copyright of the respective authors. Appropriate copyright notices and SPDX identifiers are included in the source code files. Although the existing squashfs-tools and the Linux kernel implementation have been used for testing, the source code in this package is neither based on, nor derived from either of them. # Binary Packages with 3rd Party Libraries If this file is included in a binary release package, additional 3rd party libraries may be included, which are subject to the copyright of their respective authors and the terms and conditions of their respective liceses. The following may be included: - The LZO compression library. Copyright Markus F.X.J. Oberhumer. This is released under the terms and conditions of the GNU General Public License version 2. A copy of the license is included in `licenses/GPLv2.txt`. - The LZ4 compression library. Copyright Yann Collet. This is released under a 2 clause BSD style license, included in `licenses/LZ4.txt`. - The XZ utils liblzma library is released into the public domain. An excerpt from the `COPYING` file of its source code archive is included in `licenses/xz.txt`. - The zlib compression library. Copyright Jean-loup Gailly and Mark Adler. This is released under the terms and conditions of the zlib license, included in `licenses/zlib.txt` - The zstd compression library. Copyright Facebook, Inc. All rights reserved. This is released under a BSD style license, included in `licenses/zstd.txt`. squashfs-tools-ng-0.8/Doxyfile.in000066400000000000000000000261611360235375500171100ustar00rootroot00000000000000# Doxyfile 1.8.8 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = @PACKAGE_NAME@ PROJECT_NUMBER = @PACKAGE_VERSION@ PROJECT_BRIEF = "@PROJECT_BRIEF@" PROJECT_LOGO = OUTPUT_DIRECTORY = @DX_DOCDIR@ CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = YES LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_PACKAGE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = YES SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = @top_srcdir@/include/sqfs/ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h *.dox RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = *.c EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = YES ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO EXTERNAL_SEARCH = NO SEARCHENGINE_URL = SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = pdflatex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = MAN_LINKS = NO #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration options related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = YES UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = NO INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = png INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = PLANTUML_JAR_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES squashfs-tools-ng-0.8/Makefile.am000066400000000000000000000014631360235375500170270ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -I$(top_srcdir)/include -D_GNU_SOURCE AM_CFLAGS = $(WARN_CFLAGS) if WITH_LZO AM_CPPFLAGS += -DWITH_LZO endif noinst_LTLIBRARIES = noinst_LIBRARIES = noinst_PROGRAMS = bin_PROGRAMS = lib_LTLIBRARIES = dist_man1_MANS = check_PROGRAMS = check_SCRIPTS = pkgconfig_DATA = EXTRA_DIST = autogen.sh README.md CHANGELOG.md COPYING.md mkwinbins.sh licenses TESTS = include lib/sqfs/Makemodule.am if BUILD_TOOLS include doc/Makemodule.am include lib/fstree/Makemodule.am include lib/common/Makemodule.am include lib/tar/Makemodule.am include lib/compat/Makemodule.am include tar/Makemodule.am include mkfs/Makemodule.am include unpack/Makemodule.am include difftool/Makemodule.am endif include tests/Makemodule.am if HAVE_DOXYGEN @DX_RULES@ MOSTLYCLEANFILES = $(DX_CLEANFILES) endif squashfs-tools-ng-0.8/README.md000066400000000000000000000153241360235375500162530ustar00rootroot00000000000000# About SquashFS is a highly compressed, read only file system often used as a root fs on embedded devices, live systems or simply as a compressed archive format. Think of it as a .tar.gz that you can mount (or XZ, LZO, LZ4, ZSTD). As the name suggests, this is not the original user space tooling for SquashFS, which is currently maintained in parallel elsewhere. After a long period of silence on the SourceForge site and mailing list, I attempted to fork the existing code base with the intention to restructure/clean it up and add many features I personally perceived to be missing, but I ultimately decided that it would be easier to start from scratch than to work with the existing code. Here are some of the features that primarily distinguish this package from the squashfs-tools 4.3 (latest recent version at the time this project was started): - A shared library that encapsulates code for accessing SquashFS images, usable by 3rd party applications. - Reproducible, deterministic SquashFS images. - Linux `gen_init_cpio` like file listing for micro managing the file system contents, permissions, and ownership without having to replicate the file system (and especially permissions) locally. - Support for SELinux contexts file (see selabel_file(5)) to generate SELinux labels. - Structured and (hopefully) more readable source code that should be better maintainable in the long run. In addition to that, tools have been added to directly convert a tar archive into a SquashFS filesystem image and back. This allows for using existing tools can work on tar archives seamlessly on SquashFS images. The tools in this package have different names, so they can be installed together with the existing tools: - `gensquashfs` can be used to produce SquashFS images from `gen_init_cpio` like file listings or simply pack an input directory. - `rdsquashfs` can be used to inspect and unpack SquashFS images. - `sqfs2tar` can turn a SquashFS image into a tarball, written to stdout. - `tar2sqfs` can turn a tarball (read from stdin) into a SquashFS image. - `sqfsdiff` can compare the contents of two SquashFS images. Most of the actual logic of those tools is implemented in the `libsquashfs` library that (by default) gets installed on the system along with its header files, allowing 3rd party applications to use it (e.g. for embedding SquashFS inside a custom container format without having to implement the SquashFS part). # Pre-built Windows binary Packages Pre-compiled binary packages for Windows are available here: https://infraroot.at/pub/squashfs/windows Those packages contain the binaries for the tools, the SquashFS library and pre-compiled dependency libraries (zlib, zstd, lzo, lzma, lz4). The binary package does not contain any source code. See below on how to obtain and compile the source for squashfs-tools-ng. The corresponding source code from which the 3rd party libraries have been built is also available for download at the above location. The headers and import libraries to build applications that use libsquashfs are included. For convenience, the pre-compiled, 3rd party dependency libraries also come with headers and import libraries. # Getting and Building the Source Code Official release tarballs can be obtained here: https://infraroot.at/pub/squashfs The official git tree is currently located here: https://github.com/AgentD/squashfs-tools-ng If you are working on an official release tarball, you can build the package like every autotools based package: ./configure make make install If you work on the git tree, you need to bootstrap the build system first: ./autogen.sh If Doxygen is available, a reference manual can be built as follows: make doxygen-doc The pre-compiled binary packages for Windows are built using a helper script that uses a MinGW cross toolchain to build squashfs-tools-ng and any of the required dependencies: ./mkwinbins.sh ## Structure of the Source Code The main functionality of the package is split up into a number libraries. The actual tools are mainly wrappers around the libraries that combine their functionality in a useful way. The headers of all the libraries can be found in the `include` directory, whereas the source code is in a per-library sub-directory within `lib`. The `include` directory has a sub-directory `sqfs` which contains the public headers of `libsquashfs.so` which are installed along with the library. All other headers are private to this package. The following components exist: - `libfstree.a` built from files in `lib/fstree` contains functions for manipulating a file system tree. - `libtar.a` built from files in `lib/tar` contains data structures and functions for parsing and creating tar files. - `libsquashfs.so` built from files in `lib/sqfs` contains all kinds of data structures for reading and writing SquashFS archives. Abstractions for data compression and so on. It contains the actual brains of this package. - `libcommon.a` built from files in `lib/common` contains a bunch of commonly used code shared across the utilities. - `libcompat.a` built from files in `lib/compat` contains minimal implementations of POSIX or GNU functions that are not available on some platforms. Optionally, `libsquashfs` can be compiled with builtin, custom versions of zlib and lz4. The configure options `--with-builtin-zlib` and `--with-builtin-lz4` can be used. The respective library sources are in `lib/sqfs/comp` in the squashfs-tools-ng source tree. The headers in `include` are stuffed with comments on functions an data structures. The `tests` sub-directory contains unit tests for the libraries. To allow 3rd party applications to use `libsquashfs.so` without restricting their choice of license, the code in the `lib/sqfs` sub-directories is licensed under the LGPLv3, in contrast to the rest of this package. ## A Note on LZO Support The SquashFS format supports compression using LZO. The `liblzo2` library itself is released under the GNU GPL, version 2. To make the `libsquashfs` library available as an LGPL library, it *cannot* be linked against `liblzo2`, neither statically nor dynamically. This legal problem has been solved using the following technical measure: - `libsquashfs`, as of right now, does not support LZO compression. - The `libcommon` helper library has an implementation of an `liblzo2` based compressor. This library and the tools that use it are released under the GPL. This way, the tools themselves *do* support LZO compression seamlessly, while the `libsquashfs` library does not. ## Further Information A documentation of the SquashFS on-disk format can be found here: https://dr-emann.github.io/squashfs/ # Copyright & License See [COPYING.md](COPYING.md) for copyright and licensing information. squashfs-tools-ng-0.8/autogen.sh000077500000000000000000000000621360235375500167660ustar00rootroot00000000000000#!/bin/sh autoreconf --force --install --symlink squashfs-tools-ng-0.8/configure.ac000066400000000000000000000202001360235375500172470ustar00rootroot00000000000000AC_PREREQ([2.60]) AC_INIT([squashfs-tools-ng], [0.8], [goliath@infraroot.at], squashfs-tools-ng) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign dist-xz subdir-objects]) AM_SILENT_RULES([yes]) AC_PROG_CC([cc gcc clang]) LT_INIT([win32-dll]) AC_PROG_CC_C99 AC_PROG_INSTALL AC_SYS_LARGEFILE AC_CANONICAL_HOST m4_ifndef([PKG_PROG_PKG_CONFIG], [m4_fatal([Could not locate the pkg-config autoconf macros. These are usually located in /usr/share/aclocal/pkg.m4. If your macros are in a different location, try setting the environment variable AL_OPTS="-I/other/macro/dir" before running ./autogen.sh or autoreconf again. Make sure pkg-config is installed.])]) PKG_PROG_PKG_CONFIG PKG_INSTALLDIR UL_WARN_ADD([-Wall]) UL_WARN_ADD([-Wextra]) UL_WARN_ADD([-Wunused]) UL_WARN_ADD([-Wmissing-prototypes]) UL_WARN_ADD([-Wmissing-declarations]) UL_WARN_ADD([-Wwrite-strings]) UL_WARN_ADD([-Wjump-misses-init]) UL_WARN_ADD([-Wuninitialized]) UL_WARN_ADD([-Winit-self]) UL_WARN_ADD([-Wlogical-op]) UL_WARN_ADD([-Wunused-but-set-parameter]) UL_WARN_ADD([-Wunused-but-set-variable]) UL_WARN_ADD([-Wunused-parameter]) UL_WARN_ADD([-Wunused-result]) UL_WARN_ADD([-Wunused-variable]) UL_WARN_ADD([-Wduplicated-cond]) UL_WARN_ADD([-Wduplicated-branches]) UL_WARN_ADD([-Wrestrict]) UL_WARN_ADD([-Wnull-dereference]) UL_WARN_ADD([-pedantic]) AC_SUBST([WARN_CFLAGS]) ##### target detection & target specific stuff ##### build_windows="no" case "${host_os}" in cygwin*|mingw*) build_windows=yes ;; esac AM_CONDITIONAL([WINDOWS], [test "x$build_windows" = "xyes"]) ##### config options ##### AC_ARG_WITH([xz], [AS_HELP_STRING([--with-xz], [Build with xz compression support])], [], [with_xz="check"]) AC_ARG_WITH([lzo], [AS_HELP_STRING([--with-lzo], [Build with lzo compression support])], [], [with_lzo="check"]) AC_ARG_WITH([lz4], [AS_HELP_STRING([--with-lz4], [Build with lz4 compression support])], [], [with_lz4="check"]) AC_ARG_WITH([builtin-lz4], [AS_HELP_STRING([--with-builtin-lz4], [Use a custom, static liblz4])], [], [with_builtin_lz4="no"]) AC_ARG_WITH([zstd], [AS_HELP_STRING([--with-zstd], [Build with zstd compression support])], [], [with_zstd="check"]) AC_ARG_WITH([builtin-zlib], [AS_HELP_STRING([--with-builtin-zlib], [Use a custom, static zlib])], [], [with_builtin_zlib="no"]) AC_ARG_WITH([selinux], [AS_HELP_STRING([--with-selinux], [Build with SELinux label file support])], [], [with_selinux="check"]) AC_ARG_WITH([pthread], [AS_HELP_STRING([--without-pthread], [Build without pthread based block compressor])], [], [with_pthread="yes"]) AC_ARG_WITH([tools], [AS_HELP_STRING([--without-tools], [Only build libsquashfs, do not build the tools.])], [], [with_tools="yes"]) AC_ARG_ENABLE([copora-tests], [AS_HELP_STRING([--enable-copora-tests], [Perform coprora based reproducability tests.])], [], [enable_copora_tests="no"]) AM_CONDITIONAL([CORPORA_TESTS], [test "x$enable_copora_tests" = "xyes"]) AS_IF([test "x$build_windows" = "xyes"], [with_pthread="no"], []) AS_IF([test "x$with_tools" != "xyes"], [with_selinux="no"], []) AM_CONDITIONAL([BUILD_TOOLS], [test "x$with_tools" = "xyes"]) with_gzip="yes" ##### Doxygen reference manual ##### AC_CHECK_PROGS([DOXYGEN], [doxygen]) AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) if test -z "$DOXYGEN"; then with_doxygen="no" else with_doxygen="yes" DX_DOXYGEN_FEATURE(ON) DX_DOT_FEATURE(ON) DX_HTML_FEATURE(ON) DX_CHM_FEATURE(OFF) DX_CHI_FEATURE(OFF) DX_MAN_FEATURE(OFF) DX_RTF_FEATURE(OFF) DX_XML_FEATURE(OFF) DX_PDF_FEATURE(OFF) DX_PS_FEATURE(OFF) DX_INIT_DOXYGEN(libsquashfs, Doxyfile) fi ##### search for dependencies ##### AS_IF([test "x$with_gzip" != "xno" -a "x$with_builtin_zlib" != "xyes"], [ PKG_CHECK_MODULES(ZLIB, [zlib], [with_gzip="yes"], [AS_IF([test "x$with_gzip" != "xcheck"], [AC_MSG_ERROR([cannot find zlib])], [with_gzip="no"])]) ], []) AS_IF([test "x$with_builtin_zlib" != "xno"], [with_gzip="yes"], []) AS_IF([test "x$with_xz" != "xno"], [ PKG_CHECK_MODULES(XZ, [liblzma >= 5.0.0], [with_xz="yes"], [AS_IF([test "x$with_xz" != "xcheck"], [AC_MSG_ERROR([cannot XZ sdk])], [with_xz="no"])]) ], []) AS_IF([test "x$with_lz4" != "xno" -a "x$with_builtin_lz4" != "xyes"], [ PKG_CHECK_MODULES(LZ4, [liblz4], [with_lz4="yes"], [AS_IF([test "x$with_lz4" = "xyes"], [AC_MSG_ERROR([cannot find liblz4])], [with_lz4="no"])]) ], []) AS_IF([test "x$with_builtin_lz4" != "xno"], [with_lz4="yes"], []) AS_IF([test "x$with_zstd" != "xno"], [ PKG_CHECK_MODULES(ZSTD, [libzstd], [with_zstd="yes"], [AS_IF([test "x$with_zstd" = "xyes"], [AC_MSG_ERROR([cannot find zstd])], [with_zstd="no"])]) ], []) AS_IF([test "x$with_selinux" != "xno"], [ have_selinux="yes" PKG_CHECK_MODULES(LIBSELINUX, [libselinux], [], [have_selinux="no"]) AC_CHECK_HEADERS([selinux/selinux.h], [], [have_selinux="no"]) AC_CHECK_HEADERS([selinux/label.h], [], [have_selinux="no"]) AS_IF([test "x$with_selinux" != "xcheck" -a "x$have_selinux" = "xno"], [AC_MSG_ERROR([cannot find SELinux libraries])], [with_selinux="$have_selinux"]) ], []) AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo]) AC_ARG_VAR([LZO_LIBS], [linker flags for lzo]) AS_IF([test -z "$LZO_LIBS" -a "x$with_lzo" != "xno"], [ AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [LZO_LIBS="-llzo2"], [AC_CHECK_LIB([lzo],[lzo1x_1_15_compress], [LZO_LIBS="-llzo"], [] )] ) ], []) AS_IF([test -z "$LZO_LIBS"], [AS_IF([test "x$with_lzo" = "xyes"], [AC_MSG_ERROR([cannot find liblzo])], [with_lzo="no"])], [with_lzo="yes"]) AS_IF([test "x$with_pthread" != "xno"], [ AX_PTHREAD([with_pthread="yes"], [AS_IF([test "x$with_pthread" = "xyes"], [AC_MSG_ERROR([cannot find pthread])], [with_pthread="no"])]) ], []) AM_CONDITIONAL([WITH_GZIP], [test "x$with_gzip" = "xyes"]) AM_CONDITIONAL([WITH_XZ], [test "x$with_xz" = "xyes"]) AM_CONDITIONAL([WITH_LZ4], [test "x$with_lz4" = "xyes"]) AM_CONDITIONAL([WITH_ZSTD], [test "x$with_zstd" = "xyes"]) AM_CONDITIONAL([WITH_LZO], [test "x$with_lzo" = "xyes"]) AM_CONDITIONAL([WITH_SELINUX], [test "x$with_selinux" = "xyes"]) AM_CONDITIONAL([HAVE_PTHREAD], [test "x$with_pthread" = "xyes"]) AM_CONDITIONAL([WITH_OWN_LZ4], [test "x$with_builtin_lz4" = "xyes"]) AM_CONDITIONAL([WITH_OWN_ZLIB], [test "x$with_builtin_zlib" = "xyes"]) libsqfs_dep_mod="" AS_IF([test "x$with_lz4" = "xyes" -a "x$with_builtin_lz4" != "xyes"], [libsqfs_dep_mod="$libsqfs_dep_mod liblz4"], []) AS_IF([test "x$with_gzip" = "xyes" -a "x$with_builtin_zlib" != "xyes"], [libsqfs_dep_mod="$libsqfs_dep_mod zlib"], []) AM_COND_IF([WITH_XZ], [libsqfs_dep_mod="$libsqfs_dep_mod liblzma >= 5.0.0"], []) AM_COND_IF([WITH_ZSTD], [libsqfs_dep_mod="$libsqfs_dep_mod libzstd"], []) AC_SUBST([LIBSQFS_DEP_MOD], ["$libsqfs_dep_mod"]) ##### additional checks ##### AX_COMPILE_CHECK_SIZEOF(time_t) AX_COMPILE_CHECK_SIZEOF(size_t) AX_COMPILE_CHECK_SIZEOF(short) AX_COMPILE_CHECK_SIZEOF(int) AX_COMPILE_CHECK_SIZEOF(long) AX_COMPILE_CHECK_SIZEOF(long long) AC_CHECK_HEADERS([sys/xattr.h], [], []) AC_CHECK_HEADERS([sys/sysinfo.h], [], []) AC_CHECK_FUNCS([strndup getline getsubopt]) ##### generate output ##### AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([lib/sqfs/libsquashfs0.pc]) AC_CONFIG_FILES([Doxyfile]) AC_CONFIG_FILES([tests/cantrbry.sh], [chmod +x tests/cantrbry.sh]) AC_CONFIG_FILES([tests/test_tar_sqfs.sh], [chmod +x tests/test_tar_sqfs.sh]) AC_OUTPUT([Makefile]) AC_MSG_RESULT([ ${PACKAGE} ${VERSION} prefix: ${prefix} exec prefix: ${exec_prefix} runstatedir: ${runstatedir} bindir: ${bindir} sbindir: ${sbindir} libdir: ${libdir} includedir: ${includedir} compiler: ${CC} cflags: ${CFLAGS} ldflags: ${LDFLAGS} GZIP support: ${with_gzip} XZ/LZMA support: ${with_xz} LZO support: ${with_lzo} LZ4 support: ${with_lz4} ZSTD support: ${with_zstd} SELinux support: ${with_selinux} Using pthreads: ${with_pthread} Building tools: ${with_tools} Doxygen found: ${with_doxygen} warnings: ${WARN_CFLAGS} Type 'make' or 'make ' to compile. ]) squashfs-tools-ng-0.8/difftool/000077500000000000000000000000001360235375500165755ustar00rootroot00000000000000squashfs-tools-ng-0.8/difftool/Makemodule.am000066400000000000000000000007031360235375500211770ustar00rootroot00000000000000sqfsdiff_SOURCES = difftool/sqfsdiff.c difftool/sqfsdiff.h difftool/util.c sqfsdiff_SOURCES += difftool/compare_dir.c difftool/node_compare.c sqfsdiff_SOURCES += difftool/compare_files.c difftool/super.c sqfsdiff_SOURCES += difftool/extract.c difftool/options.c sqfsdiff_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) sqfsdiff_LDADD = libcommon.a libsquashfs.la libcompat.a $(LZO_LIBS) libfstree.a sqfsdiff_LDADD += $(PTHREAD_LIBS) bin_PROGRAMS += sqfsdiff squashfs-tools-ng-0.8/difftool/compare_dir.c000066400000000000000000000037101360235375500212260ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * compare_dir.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static int print_omitted(sqfsdiff_t *sd, bool is_old, sqfs_tree_node_t *n) { char *path = node_path(n); if (path == NULL) return -1; fprintf(stdout, "%c %s\n", is_old ? '<' : '>', path); if ((sd->compare_flags & COMPARE_EXTRACT_FILES) && S_ISREG(n->inode->base.mode)) { if (extract_files(sd, is_old ? n->inode : NULL, is_old ? NULL : n->inode, path)) { free(path); return -1; } } free(path); for (n = n->children; n->children != NULL; n = n->next) { if (print_omitted(sd, is_old, n)) return -1; } return 0; } int compare_dir_entries(sqfsdiff_t *sd, sqfs_tree_node_t *old, sqfs_tree_node_t *new) { sqfs_tree_node_t *old_it = old->children, *old_prev = NULL; sqfs_tree_node_t *new_it = new->children, *new_prev = NULL; int ret, result = 0; while (old_it != NULL || new_it != NULL) { if (old_it != NULL && new_it != NULL) { ret = strcmp((const char *)old_it->name, (const char *)new_it->name); } else if (old_it == NULL) { ret = 1; } else { ret = -1; } if (ret < 0) { result = 1; if (print_omitted(sd, true, old_it)) return -1; if (old_prev == NULL) { old->children = old_it->next; sqfs_dir_tree_destroy(old_it); old_it = old->children; } else { old_prev->next = old_it->next; sqfs_dir_tree_destroy(old_it); old_it = old_prev->next; } } else if (ret > 0) { result = 1; if (print_omitted(sd, false, new_it)) return -1; if (new_prev == NULL) { new->children = new_it->next; sqfs_dir_tree_destroy(new_it); new_it = new->children; } else { new_prev->next = new_it->next; sqfs_dir_tree_destroy(new_it); new_it = new_prev->next; } } else { old_prev = old_it; old_it = old_it->next; new_prev = new_it; new_it = new_it->next; } } return result; } squashfs-tools-ng-0.8/difftool/compare_files.c000066400000000000000000000031431360235375500215520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * compare_files.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static unsigned char old_buf[MAX_WINDOW_SIZE]; static unsigned char new_buf[MAX_WINDOW_SIZE]; static int read_blob(const char *prefix, const char *path, sqfs_data_reader_t *rd, const sqfs_inode_generic_t *inode, void *buffer, sqfs_u64 offset, size_t size) { ssize_t ret; ret = sqfs_data_reader_read(rd, inode, offset, buffer, size); ret = (ret < 0 || (size_t)ret < size) ? -1 : 0; if (ret) { fprintf(stderr, "Failed to read %s from %s\n", path, prefix); return -1; } return 0; } int compare_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old, const sqfs_inode_generic_t *new, const char *path) { sqfs_u64 offset, diff, oldsz, newsz; int status = 0, ret; sqfs_inode_get_file_size(old, &oldsz); sqfs_inode_get_file_size(new, &newsz); if (oldsz != newsz) goto out_different; if (sd->compare_flags & COMPARE_NO_CONTENTS) return 0; for (offset = 0; offset < oldsz; offset += diff) { diff = oldsz - offset; if (diff > MAX_WINDOW_SIZE) diff = MAX_WINDOW_SIZE; ret = read_blob(sd->old_path, path, sd->sqfs_old.data, old, old_buf, offset, diff); if (ret) return -1; ret = read_blob(sd->new_path, path, sd->sqfs_new.data, new, new_buf, offset, diff); if (ret) return -1; if (memcmp(old_buf, new_buf, diff) != 0) goto out_different; } return status; out_different: if (sd->compare_flags & COMPARE_EXTRACT_FILES) { if (extract_files(sd, old, new, path)) return -1; } return 1; } squashfs-tools-ng-0.8/difftool/extract.c000066400000000000000000000021511360235375500204120ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * extract.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static int extract(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, const char *prefix, const char *path, size_t block_size) { char *ptr, *temp; FILE *fp; temp = alloca(strlen(prefix) + strlen(path) + 2); sprintf(temp, "%s/%s", prefix, path); ptr = strrchr(temp, '/'); *ptr = '\0'; if (mkdir_p(temp)) return -1; *ptr = '/'; fp = fopen(temp, "wb"); if (fp == NULL) { perror(temp); return -1; } if (sqfs_data_reader_dump(path, data, inode, fp, block_size, true)) { fclose(fp); return -1; } fflush(fp); fclose(fp); return 0; } int extract_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old, const sqfs_inode_generic_t *new, const char *path) { if (old != NULL) { if (extract(sd->sqfs_old.data, old, "old", path, sd->sqfs_old.super.block_size)) return -1; } if (new != NULL) { if (extract(sd->sqfs_new.data, new, "new", path, sd->sqfs_new.super.block_size)) return -1; } return 0; } squashfs-tools-ng-0.8/difftool/node_compare.c000066400000000000000000000111011360235375500213660ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * node_compare.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" int node_compare(sqfsdiff_t *sd, sqfs_tree_node_t *a, sqfs_tree_node_t *b) { char *path = sqfs_tree_node_get_path(a); sqfs_tree_node_t *ait, *bit; bool promoted, demoted; int ret, status = 0; if (path == NULL) { perror("constructing absolute file path"); return -1; } if (a->inode->base.type != b->inode->base.type) { promoted = demoted = false; switch (a->inode->base.type) { case SQFS_INODE_DIR: if (b->inode->base.type == SQFS_INODE_EXT_DIR) promoted = true; break; case SQFS_INODE_FILE: if (b->inode->base.type == SQFS_INODE_EXT_FILE) promoted = true; break; case SQFS_INODE_SLINK: if (b->inode->base.type == SQFS_INODE_EXT_SLINK) promoted = true; break; case SQFS_INODE_BDEV: if (b->inode->base.type == SQFS_INODE_EXT_BDEV) promoted = true; break; case SQFS_INODE_CDEV: if (b->inode->base.type == SQFS_INODE_EXT_CDEV) promoted = true; break; case SQFS_INODE_FIFO: if (b->inode->base.type == SQFS_INODE_EXT_FIFO) promoted = true; break; case SQFS_INODE_SOCKET: if (b->inode->base.type == SQFS_INODE_EXT_SOCKET) promoted = true; break; case SQFS_INODE_EXT_DIR: if (b->inode->base.type == SQFS_INODE_DIR) demoted = true; break; case SQFS_INODE_EXT_FILE: if (b->inode->base.type == SQFS_INODE_FILE) demoted = true; break; case SQFS_INODE_EXT_SLINK: if (b->inode->base.type == SQFS_INODE_SLINK) demoted = true; break; case SQFS_INODE_EXT_BDEV: if (b->inode->base.type == SQFS_INODE_BDEV) demoted = true; break; case SQFS_INODE_EXT_CDEV: if (b->inode->base.type == SQFS_INODE_CDEV) demoted = true; break; case SQFS_INODE_EXT_FIFO: if (b->inode->base.type == SQFS_INODE_FIFO) demoted = true; break; case SQFS_INODE_EXT_SOCKET: if (b->inode->base.type == SQFS_INODE_SOCKET) demoted = true; break; } if (promoted) { fprintf(stdout, "%s has an extended type\n", path); status = 1; } else if (demoted) { fprintf(stdout, "%s has a basic type\n", path); status = 1; } else { fprintf(stdout, "%s has a different type\n", path); free(path); return 1; } } if (!(sd->compare_flags & COMPARE_NO_PERM)) { if ((a->inode->base.mode & ~S_IFMT) != (b->inode->base.mode & ~S_IFMT)) { fprintf(stdout, "%s has different permissions\n", path); status = 1; } } if (!(sd->compare_flags & COMPARE_NO_OWNER)) { if (a->uid != b->uid || a->gid != b->gid) { fprintf(stdout, "%s has different ownership\n", path); status = 1; } } if (sd->compare_flags & COMPARE_TIMESTAMP) { if (a->inode->base.mod_time != b->inode->base.mod_time) { fprintf(stdout, "%s has a different timestamp\n", path); status = 1; } } if (sd->compare_flags & COMPARE_INODE_NUM) { if (a->inode->base.inode_number != b->inode->base.inode_number) { fprintf(stdout, "%s has a different inode number\n", path); status = 1; } } switch (a->inode->base.type) { case SQFS_INODE_SOCKET: case SQFS_INODE_EXT_SOCKET: case SQFS_INODE_FIFO: case SQFS_INODE_EXT_FIFO: break; case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: if (a->inode->data.dev.devno != b->inode->data.dev.devno) { fprintf(stdout, "%s has different device number\n", path); status = 1; } break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: if (a->inode->data.dev_ext.devno != b->inode->data.dev_ext.devno) { fprintf(stdout, "%s has different device number\n", path); status = 1; } break; case SQFS_INODE_SLINK: case SQFS_INODE_EXT_SLINK: if (strcmp(a->inode->slink_target, b->inode->slink_target)) { fprintf(stdout, "%s has a different link target\n", path); } break; case SQFS_INODE_DIR: case SQFS_INODE_EXT_DIR: ret = compare_dir_entries(sd, a, b); if (ret < 0) { status = -1; break; } if (ret > 0) status = 1; free(path); path = NULL; ait = a->children; bit = b->children; while (ait != NULL && bit != NULL) { ret = node_compare(sd, ait, bit); if (ret < 0) return -1; if (ret > 0) status = 1; ait = ait->next; bit = bit->next; } break; case SQFS_INODE_FILE: case SQFS_INODE_EXT_FILE: ret = compare_files(sd, a->inode, b->inode, path); if (ret < 0) { status = -1; } else if (ret > 0) { fprintf(stdout, "regular file %s differs\n", path); status = 1; } break; default: fprintf(stdout, "%s has unknown type, ignoring\n", path); break; } free(path); return status; } squashfs-tools-ng-0.8/difftool/options.c000066400000000000000000000074341360235375500204440ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * sqfsdiff.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static struct option long_opts[] = { { "old", required_argument, NULL, 'a' }, { "new", required_argument, NULL, 'b' }, { "no-owner", no_argument, NULL, 'O' }, { "no-permissions", no_argument, NULL, 'P' }, { "no-contents", no_argument, NULL, 'C' }, { "timestamps", no_argument, NULL, 'T' }, { "inode-num", no_argument, NULL, 'I' }, { "super", no_argument, NULL, 'S' }, { "extract", required_argument, NULL, 'e' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, }; static const char *short_opts = "a:b:OPCTISe:hV"; static const char *usagestr = "Usage: sqfsdiff [OPTIONS...] --old,-a --new,-b \n" "\n" "Compare two squashfs images. In contrast to doing a direct diff of the\n" "images, this actually parses the filesystems and generates a more\n" "meaningful difference report.\n" "\n" "If only contents are compared, any differences in packed file layout,\n" "ordering, compression, inode meta data and so on is ignored and the two\n" "images are considered equal if each directory contains the same entries,\n" "symlink with the same paths have the same targets, device nodes the same\n" "device number and files the same size and contents.\n" "\n" "A report of any difference is printed to stdout. The exit status is similar\n" "that of diff(1): 0 means equal, 1 means different, 2 means problem.\n" "\n" "Possible options:\n" "\n" " --old, -a The first of the two filesystems to compare.\n" " --new, -b The second of the two filesystems to compare.\n" "\n" " --no-contents, -C Do not compare file contents.\n" " --no-owner, -O Do not compare file owners.\n" " --no-permissions, -P Do not compare permission bits.\n" "\n" " --timestamps, -T Compare file timestamps.\n" " --inode-num, -I Compare inode numbers of all files.\n" " --super, -S Also compare meta data in super blocks.\n" "\n" " --extract, -e Extract files that differ to the specified\n" " directory. Contents of the first filesystem\n" " end up in a subdirectory 'old' and of the\n" " second filesystem in a subdirectory 'new'.\n" "\n" " --help, -h Print help text and exit.\n" " --version, -V Print version information and exit.\n" "\n"; void process_options(sqfsdiff_t *sd, int argc, char **argv) { int i; for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'a': sd->old_path = optarg; break; case 'b': sd->new_path = optarg; break; case 'O': sd->compare_flags |= COMPARE_NO_OWNER; break; case 'P': sd->compare_flags |= COMPARE_NO_PERM; break; case 'C': sd->compare_flags |= COMPARE_NO_CONTENTS; break; case 'T': sd->compare_flags |= COMPARE_TIMESTAMP; break; case 'I': sd->compare_flags |= COMPARE_INODE_NUM; break; case 'S': sd->compare_super = true; break; case 'e': sd->compare_flags |= COMPARE_EXTRACT_FILES; sd->extract_dir = optarg; break; case 'h': fputs(usagestr, stdout); exit(0); case 'V': print_version("sqfsdiff"); exit(0); default: goto fail_arg; } } if (sd->old_path == NULL) { fputs("Missing arguments: first filesystem\n", stderr); goto fail_arg; } if (sd->new_path == NULL) { fputs("Missing arguments: second filesystem\n", stderr); goto fail_arg; } if (optind < argc) { fputs("Unknown extra arguments\n", stderr); goto fail_arg; } return; fail_arg: fprintf(stderr, "Try `sqfsdiff --help' for more information.\n"); exit(2); } squashfs-tools-ng-0.8/difftool/sqfsdiff.c000066400000000000000000000075701360235375500205570ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * sqfsdiff.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static int open_sfqs(sqfs_state_t *state, const char *path) { int ret; state->file = sqfs_open_file(path, SQFS_FILE_OPEN_READ_ONLY); if (state->file == NULL) { perror(path); return -1; } ret = sqfs_super_read(&state->super, state->file); if (ret) { sqfs_perror(path, "reading super block", ret); goto fail_file; } ret = sqfs_compressor_exists(state->super.compression_id); #ifdef WITH_LZO if (state->super.compression_id == SQFS_COMP_LZO) ret = true; #endif if (!ret) { fprintf(stderr, "%s: unknown compressor used.\n", path); goto fail_file; } sqfs_compressor_config_init(&state->cfg, state->super.compression_id, state->super.block_size, SQFS_COMP_FLAG_UNCOMPRESS); state->cmp = sqfs_compressor_create(&state->cfg); #ifdef WITH_LZO if (state->super.compression_id == SQFS_COMP_LZO && state->cmp == NULL) state->cmp = lzo_compressor_create(&state->cfg); #endif if (state->cmp == NULL) { fprintf(stderr, "%s: error creating compressor.\n", path); goto fail_file; } if (state->super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { ret = state->cmp->read_options(state->cmp, state->file); if (ret) { sqfs_perror(path, "reading compressor options", ret); goto fail_cmp; } } state->idtbl = sqfs_id_table_create(); if (state->idtbl == NULL) { sqfs_perror(path, "creating ID table", SQFS_ERROR_ALLOC); goto fail_cmp; } ret = sqfs_id_table_read(state->idtbl, state->file, &state->super, state->cmp); if (ret) { sqfs_perror(path, "loading ID table", ret); goto fail_id; } state->dr = sqfs_dir_reader_create(&state->super, state->cmp, state->file); if (state->dr == NULL) { sqfs_perror(path, "creating directory reader", SQFS_ERROR_ALLOC); goto fail_id; } ret = sqfs_dir_reader_get_full_hierarchy(state->dr, state->idtbl, NULL, 0, &state->root); if (ret) { sqfs_perror(path, "loading filesystem tree", ret); goto fail_dr; } state->data = sqfs_data_reader_create(state->file, state->super.block_size, state->cmp); if (state->data == NULL) { sqfs_perror(path, "creating data reader", SQFS_ERROR_ALLOC); goto fail_tree; } ret = sqfs_data_reader_load_fragment_table(state->data, &state->super); if (ret) { sqfs_perror(path, "loading fragment table", ret); goto fail_data; } return 0; fail_data: sqfs_data_reader_destroy(state->data); fail_tree: sqfs_dir_tree_destroy(state->root); fail_dr: sqfs_dir_reader_destroy(state->dr); fail_id: sqfs_id_table_destroy(state->idtbl); fail_cmp: state->cmp->destroy(state->cmp); fail_file: state->file->destroy(state->file); return -1; } static void close_sfqs(sqfs_state_t *state) { sqfs_data_reader_destroy(state->data); sqfs_dir_tree_destroy(state->root); sqfs_dir_reader_destroy(state->dr); sqfs_id_table_destroy(state->idtbl); state->cmp->destroy(state->cmp); state->file->destroy(state->file); } int main(int argc, char **argv) { int status, ret = 0; sqfsdiff_t sd; memset(&sd, 0, sizeof(sd)); process_options(&sd, argc, argv); if (sd.extract_dir != NULL) { if (mkdir_p(sd.extract_dir)) return 2; } if (open_sfqs(&sd.sqfs_old, sd.old_path)) return 2; if (open_sfqs(&sd.sqfs_new, sd.new_path)) { status = 2; goto out_sqfs_old; } if (sd.extract_dir != NULL) { if (chdir(sd.extract_dir)) { perror(sd.extract_dir); ret = -1; goto out; } } ret = node_compare(&sd, sd.sqfs_old.root, sd.sqfs_new.root); if (ret != 0) goto out; if (sd.compare_super) { ret = compare_super_blocks(&sd.sqfs_old.super, &sd.sqfs_new.super); if (ret != 0) goto out; } out: if (ret < 0) { status = 2; } else if (ret > 0) { status = 1; } else { status = 0; } close_sfqs(&sd.sqfs_new); out_sqfs_old: close_sfqs(&sd.sqfs_old); return status; } squashfs-tools-ng-0.8/difftool/sqfsdiff.h000066400000000000000000000030611360235375500205530ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * sqfsdiff.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef DIFFTOOL_H #define DIFFTOOL_H #include "config.h" #include "common.h" #include "fstree.h" #include #include #include #include #define MAX_WINDOW_SIZE (1024 * 1024 * 4) typedef struct { sqfs_compressor_config_t cfg; sqfs_compressor_t *cmp; sqfs_super_t super; sqfs_file_t *file; sqfs_id_table_t *idtbl; sqfs_dir_reader_t *dr; sqfs_tree_node_t *root; sqfs_data_reader_t *data; } sqfs_state_t; typedef struct { const char *old_path; const char *new_path; int compare_flags; sqfs_state_t sqfs_old; sqfs_state_t sqfs_new; bool compare_super; const char *extract_dir; } sqfsdiff_t; enum { COMPARE_NO_PERM = 0x01, COMPARE_NO_OWNER = 0x02, COMPARE_NO_CONTENTS = 0x04, COMPARE_TIMESTAMP = 0x08, COMPARE_INODE_NUM = 0x10, COMPARE_EXTRACT_FILES = 0x20, }; int compare_dir_entries(sqfsdiff_t *sd, sqfs_tree_node_t *old, sqfs_tree_node_t *new); char *node_path(const sqfs_tree_node_t *n); int compare_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old, const sqfs_inode_generic_t *new, const char *path); int node_compare(sqfsdiff_t *sd, sqfs_tree_node_t *a, sqfs_tree_node_t *b); int compare_super_blocks(const sqfs_super_t *a, const sqfs_super_t *b); int extract_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old, const sqfs_inode_generic_t *new, const char *path); void process_options(sqfsdiff_t *sd, int argc, char **argv); #endif /* DIFFTOOL_H */ squashfs-tools-ng-0.8/difftool/super.c000066400000000000000000000067451360235375500201130ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * super.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" static const struct { sqfs_u16 mask; const char *name; } sqfs_flags[] = { { SQFS_FLAG_UNCOMPRESSED_INODES, "uncompressed inodes" }, { SQFS_FLAG_UNCOMPRESSED_DATA, "uncompressed data" }, { SQFS_FLAG_UNCOMPRESSED_FRAGMENTS, "uncompressed fragments" }, { SQFS_FLAG_NO_FRAGMENTS, "no fragments" }, { SQFS_FLAG_ALWAYS_FRAGMENTS, "always fragments" }, { SQFS_FLAG_DUPLICATES, "duplicates" }, { SQFS_FLAG_EXPORTABLE, "exportable" }, { SQFS_FLAG_UNCOMPRESSED_XATTRS, "uncompressed xattrs" }, { SQFS_FLAG_NO_XATTRS, "no xattrs" }, { SQFS_FLAG_COMPRESSOR_OPTIONS, "compressor options" }, { SQFS_FLAG_UNCOMPRESSED_IDS, "uncompressed ids" }, }; static void print_value_difference(const char *name, sqfs_u64 a, sqfs_u64 b) { sqfs_u64 diff; char c; if (a != b) { if (a < b) { c = '+'; diff = b - a; } else { c = '-'; diff = a - b; } fprintf(stdout, "%s: %c%lu\n", name, c, (unsigned long)diff); } } static void print_offset_diff(const char *name, sqfs_u64 a, sqfs_u64 b) { if (a != b) fprintf(stdout, "Location of %s differs\n", name); } static void print_flag_diff(sqfs_u16 a, sqfs_u16 b) { sqfs_u16 diff = a ^ b, mask; size_t i; char c; if (diff == 0) return; fputs("flags:\n", stdout); for (i = 0; i < sizeof(sqfs_flags) / sizeof(sqfs_flags[0]); ++i) { if (diff & sqfs_flags[i].mask) { c = a & sqfs_flags[i].mask ? '<' : '>'; fprintf(stdout, "\t%c%s\n", c, sqfs_flags[i].name); } a &= ~sqfs_flags[i].mask; b &= ~sqfs_flags[i].mask; diff &= ~sqfs_flags[i].mask; } for (i = 0, mask = 0x01; i < 16; ++i, mask <<= 1) { if (diff & mask) { fprintf(stdout, "\t%c additional unknown\n", a & mask ? '<' : '>'); } } } int compare_super_blocks(const sqfs_super_t *a, const sqfs_super_t *b) { if (memcmp(a, b, sizeof(*a)) == 0) return 0; fputs("======== super blocks are different ========\n", stdout); /* TODO: if a new magic number or squashfs version is introduced, compare them. */ print_value_difference("inode count", a->inode_count, b->inode_count); print_value_difference("modification time", a->modification_time, b->modification_time); print_value_difference("block size", a->block_size, b->block_size); print_value_difference("block log", a->block_log, b->block_log); print_value_difference("fragment table entries", a->fragment_entry_count, b->fragment_entry_count); print_value_difference("ID table entries", a->id_count, b->id_count); if (a->compression_id != b->compression_id) { fprintf(stdout, "compressor: %s vs %s\n", sqfs_compressor_name_from_id(a->compression_id), sqfs_compressor_name_from_id(b->compression_id)); } print_flag_diff(a->flags, b->flags); print_value_difference("total bytes used", a->bytes_used, b->bytes_used); print_offset_diff("root inode", a->root_inode_ref, b->root_inode_ref); print_offset_diff("ID table", a->id_table_start, b->id_table_start); print_offset_diff("xattr ID table", a->xattr_id_table_start, b->xattr_id_table_start); print_offset_diff("inode table", a->inode_table_start, b->inode_table_start); print_offset_diff("directory table", a->directory_table_start, b->directory_table_start); print_offset_diff("fragment table", a->fragment_table_start, b->fragment_table_start); print_offset_diff("export table", a->export_table_start, b->export_table_start); return 1; } squashfs-tools-ng-0.8/difftool/util.c000066400000000000000000000007011360235375500177140ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * util.c * * Copyright (C) 2019 David Oberhollenzer */ #include "sqfsdiff.h" char *node_path(const sqfs_tree_node_t *n) { char *path = sqfs_tree_node_get_path(n); if (path == NULL) { perror("get path"); return NULL; } if (canonicalize_name(path)) { fprintf(stderr, "failed to canonicalization '%s'\n", path); free(path); return NULL; } return path; } squashfs-tools-ng-0.8/doc/000077500000000000000000000000001360235375500155345ustar00rootroot00000000000000squashfs-tools-ng-0.8/doc/Makemodule.am000066400000000000000000000001641360235375500201370ustar00rootroot00000000000000dist_man1_MANS += doc/gensquashfs.1 doc/rdsquashfs.1 doc/sqfs2tar.1 dist_man1_MANS += doc/tar2sqfs.1 doc/sqfsdiff.1 squashfs-tools-ng-0.8/doc/gensquashfs.1000066400000000000000000000126651360235375500201570ustar00rootroot00000000000000.TH GENSQUASHFS "1" "June 2019" "generate squashfs images" "User Commands" .SH NAME gensquashfs \- generate squashfs images .SH SYNOPSIS .B gensquashfs [\fI\,OPTIONS\/\fR] \/\fR .SH DESCRIPTION Generate a SquashFS image. .SH OPTIONS .TP \fB\-\-pack\-file\fR, \fB\-F\fR Use a \fBgen_init_cpio\fR style description file. The file format is specified below. If \fB\-\-pack\-dir\fR is used, input file paths are relative to the pack directory, otherwise they are relative to the directory the pack file is in. .TP \fB\-\-pack\-dir\fR, \fB\-D\fR If \fB\-\-pack\-file\fR is used, this is the root path relative to which to read files. If no pack file is specified, pack the contents of the given directory into a SquashFS image. The directory becomes the root of the file system. .TP \fB\-\-compressor\fR, \fB\-c\fR Select the compressor to use. Run \fBgensquashfs \-\-help\fR to get a list of all available compressors and the default selection. .TP \fB\-\-comp\-extra\fR, \fB\-X\fR A comma separated list of extra options for the selected compressor. Specify \fBhelp\fR to get a list of available options. .TP \fB\-\-num\-jobs\fR, \fB\-j\fR If libsquashfs was compiled with a built in thread pool based, parallel data compressor, this option can be used to set the number of compressor threads. If not set, the default is the number of available CPU cores. .TP \fB\-\-queue\-backlog\fR, \fB\-Q\fR Maximum number of data blocks in the thread worker queue before the packer starts waiting for the block processors to catch up. Higher values result in higher memory consumption. Defaults to 10 times the number of workers. .TP \fB\-\-block\-size\fR, \fB\-b\fR Block size to use for Squashfs image. Defaults to 131072. .TP \fB\-\-dev\-block\-size\fR, \fB\-B\fR Device block size to padd the image to. Defaults to 4096. .TP \fB\-\-keep\-time\fR, \fB\-k\fR When using \fB\-\-pack\-dir\fR only, use the timestamps from the input files instead of setting defaults on all input paths. The root inode and the modification time on the SquashFS image itself will still be set to defaults. .TP \fB\-\-one\-file\-system\fR, \fB\-o\fR When using \fB\-\-pack\-dir\fR only, stay in local filesystem and do not cross mount points. .TP \fB\-\-defaults\fR, \fB\-d\fR A comma separated list of default values for implicitly created directories. The following values can be set: .TS tab(;) allbox; l l l l l l l l l l rd. \fBOption\fR;\fBDefault\fR uid=;0 gid=;0 mode=;0755 mtime=;\fB$SOURCE\_DATE\_EPOCH\fR if set, 0 otherwise .TE .TP .TP \fB\-\-selinux\fR, \fB\-s\fR If built with SELinux support, use the given SELinux label file to add context labels to the elements packed into the SquashFS image. .TP \fB\-\-exportable\fR, \fB\-e\fR Generate an export table for NFS support. .TP \fB\-\-force\fR, \fB\-f\fR Overwrite the output file if it exists. .TP \fB\-\-quiet\fR, \fB\-q\fR Do not print out progress reports. .TP \fB\-\-help\fR, \fB\-h\fR Print help text and exit. .TP \fB\-\-version\fR, \fB\-V\fR Print version information and exit. .SH INPUT FILE FORMAT The input file contains a simple, newline separated list that describe the files to be included in the squashfs image: .PP .in +4n .nf # a comment file [] dir nod slink link pipe sock .fi .in .TS tab(;) allbox; l l l l l l l l l l l l l l l l l l rd. ;T{ Absolute path of the entry in the image. Can be put in quotes if some components contain spaces. T} ;T{ Optional location of the input file. Can be specified relative to either the description file or the pack directory. If omitted, the image path is used as a relative path. T} ;Symlink or hardlink target. ;Mode/permissions of the entry. ;Numeric user id. ;Numeric group id. ;Device type (b=block, c=character). ;Major number of a device special file. ;Minor number of a device special file. .TE .PP Example: .PP .in +4n .nf # A simple squashfs image dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 dir /root 0700 0 0 dir /sbin 0755 0 0 # Add a file. Input is relative to pack dir or listing path file /sbin/init 0755 0 0 ../init/sbin/init # Read from ./bin/bash relative to pack dir or listing path # /bin is created implicitly with default attributes. file /bin/bash 0755 0 0 # file name with a space in it and a "special" name file "/opt/my app/\\"special\\"/data" 0600 0 0 .fi .in .SH ENVIRONMENT If the command line switch \fB\-\-defaults\fR is not used or no default mtime is specified, the value of the environment variable \fBSOURCE\_DATE\_EPOCH\fR is used for all file and filesystem timestamps. If \fBSOURCE\_DATE\_EPOCH\fR is not set, not a parsable number or it is out of range, the timestamps default to 0. Environment variables are only used if no explicit command line switches are set. Explicit command line switches are always preferred over the environment variables. .SH SEE ALSO rdsquashfs(1), tar2sqfs(1) .SH AUTHOR Written by David Oberhollenzer. .SH COPYRIGHT Copyright \(co 2019 David Oberhollenzer License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. squashfs-tools-ng-0.8/doc/rdsquashfs.1000066400000000000000000000060011360235375500177760ustar00rootroot00000000000000.TH RDSQUASHFS "1" "May 2019" "inspect SquashFS filesystems" "User Commands" .SH NAME rdsquashfs \- tool to examine or uncompress SquashFS filesystems .SH SYNOPSIS .B rdsquashfs [\fI\,OPTIONS\/\fR] \fI\,\/\fR .SH DESCRIPTION View or extract the contents of a squashfs image. .PP The following options can be used to specify what operation to perform. One of those has to be present: .TP \fB\-\-list\fR, \fB\-l\fR Produce a directory listing similar to \fBls \-l\fR for a given path in the SquashFS image. .TP \fB\-\-cat\fR, \fB\-c\fR If the specified path is a regular file in the image, extract it and dump its contents to stdout. .TP \fB\-\-xattr\fR, \fB\-x\fR If the inode that the specified path resolves to has extended attributes, dump them as key value pairs to stdout. .TP \fB\-\-unpack\-path\fR, \fB\-u\fR Unpack the specified sub directory from the image. To unpack everything, simply specify /. .TP \fB\-\-describe\fR, \fB\-d\fR Produce a file listing from the image compatible with the format consumed by gensquashfs. .PP The following options can be used to control the behaviour of the specified operation: .TP \fB\-\-unpack\-root\fR, \fB\-p\fR If used with \fB\-\-unpack\-path\fR, this is where the data is unpacked to. If used with \fB\-\-describe\fR, this is used as a prefix for the input path of regular files. .TP \fB\-\-no\-dev\fR, \fB\-D\fR Skip device special files when parsing the filesystem tree. .TP \fB\-\-no\-sock\fR, \fB\-S\fR Skip socket files when parsing the filesystem tree. .TP \fB\-\-no\-fifo\fR, \fB\-F\fR Skip named pipes files when parsing the filesystem tree. .TP \fB\-\-no\-slink\fR, \fB\-L\fR Skip symbolic links when parsing the filesystem tree. .TP \fB\-\-no\-empty\-dir\fR, \fB\-E\fR Skip directories that would end up empty after applying the above rules. .PP The following options are specific to unpacking files from a SquashFS image to disk: .TP \fB\-\-no\-sparse\fR, \fB\-Z\fR Do not create sparse files. Always unpack sparse files by writing blocks of zeros to disk. .TP \fB\-\-set\-xattr\fR, \fB\-X\fR Set the extended attributes from the SquashFS image. .TP \fB\-\-set\-times\fR, \fB\-T\fR Set the create and modify timestamps of the file to the mtime from the SquashFS image. .TP \fB\-\-chmod\fR, \fB\-C\fR Change permission flags of unpacked files to those store in the SquashFS image. .TP \fB\-\-chown\fR, \fB\-O\fR Change ownership of unpacked files to the UID/GID set in the SquashFS image. .TP \fB\-\-quiet\fR, \fB\-q\fR Do not print out progress while unpacking. .PP Other options: .TP \fB\-\-help\fR, \fB\-h\fR Print help text and exit. .TP \fB\-\-version\fR, \fB\-V\fR Print version information and exit. .SH SEE ALSO gensquashfs(1), sqfs2tar(1), sqfsdiff(1) .SH AUTHOR Written by David Oberhollenzer. .SH COPYRIGHT Copyright \(co 2019 David Oberhollenzer License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. squashfs-tools-ng-0.8/doc/sqfs2tar.1000066400000000000000000000066611360235375500173740ustar00rootroot00000000000000.TH SQFS2TAR "1" "June 2019" "sqfs2tar" "User Commands" .SH NAME sqfs2tar \- turn a SquashFS image into a tar archive .SH SYNOPSIS .B sqfs2tar [\fI\,OPTIONS\/\fR...] \fI\,\/\fR .SH DESCRIPTION Quickly and painlessly turn a SquashFS filesystem image into a tar archive that can then be examined and processed by any tool that can work on tar archives. The resulting archive is written to stdout. .PP Possible options: .TP \fB\-\-root\-becomes\fR, \fB\-r\fR Prefix all paths in the tarball with the given directory name and add an entry for this directory that receives all meta data (permissions, ownership, extended attributes, et cetera) of the root inode. The special value \fB.\fR can be used since many tar archivers themselves pack the attributes of the root directory that way and naturally support this. If this option is not used, all meta data from the root inode IS LOST! .TP \fB\-\-subdir\fR, \fB\-d\fR Unpack the given sub directory instead of the filesystem root. Can be specified more than once to select multiple directories. If only one is specified, it becomes the new root of the archive filesystem tree. .TP \fB\-\-keep\-as\-dir\fR, \fB\-k\fR If \fB\-\-subdir\fR is used only once, don't make the subdir the archive root, instead keep it as prefix for all unpacked files. Using \fB\-\-subdir\fR more than once implies \fB\-\-keep\-as\-dir\fR. .TP \fB\-\-no\-xattr\fR, \fB\-X\fR Discard extended attributes from the SquashFS image. The default behavior is to copy all xattrs attached to SquashFS inodes into the resulting tar archive. .TP \fB\-\-no\-hard\-links\fR, \fB\-L\fR Normally, sqfs2tar runs hard link detection and generates hard links for entries that refer to the same inode. If this flag is set, hard link detection is not performed and duplicate data records are generated instead. .TP \fB\-\-no\-skip\fR, \fB\-s\fR Abort if a file cannot be stored in a tar record instead of skipping it. .TP \fB\-\-help\fR, \fB\-h\fR Print help text and exit. .TP \fB\-\-version\fR, \fB\-V\fR Print version information and exit. .SH COMPATIBILITY The output format is pre-POSIX ustar using GNU extensions where necessary. Experimentation determined that this is most widely supported by activeley used tar implementations (besides GNU tar), even more than the newer POSIX format with PAX extensions. If any file or directory is encountered that cannot be converted, it is skipped and a warning is written to stderr. Unless the \fB\-\-no\-skip\fR option is set, which aborts processing if a file cannot be converted. This is mainly affects socket files which are supported by SquashFS but not by POSIX tar, GNU tar or PAX. Since the tar format contains a sequence of files with absolute names, it has no direct concept of a tree or an unnamed root node. Consequently, meta data from the SquashFS root inode is lost. .SH EXAMPLES Turn a SquashFS image into a tar archive: .IP sqfs2tar rootfs.sqfs > rootfs.tar .TP Turn a SquashFS image into a gzip'ed tar archive: .IP sqfs2tar rootfs.sqfs | gzip > rootfs.tar.gz .TP Turn a SquashFS image into an LZMA2 compressed tar archive: .IP sqfs2tar rootfs.sqfs | xz > rootfs.tar.xz .SH SEE ALSO rdsquashfs(1), tar2sqfs(1) .SH AUTHOR Written by David Oberhollenzer. .SH COPYRIGHT Copyright \(co 2019 David Oberhollenzer License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. squashfs-tools-ng-0.8/doc/sqfsdiff.1000066400000000000000000000046331360235375500174310ustar00rootroot00000000000000.TH SQFSDIFF "1" "August 2019" "sqfsdiff" "User Commands" .SH NAME sqfsdiff \- compare two squashfs images by contents and metadata .SH SYNOPSIS .B sqfsdiff [\fI\,OPTIONS\/\fR...] \-\-old \fI\,\fR \-\-new \fI\,\/\fR .SH DESCRIPTION Compare two squashfs images. In contrast to doing a direct diff of the images, this actually parses the filesystems and generates a more meaningful difference report. .PP If only contents are compared, any differences in packed file layout, ordering, compression, inode meta data and so on is ignored and the two images are considered equal if each directory contains the same entries, symlink with the same paths have the same targets, device nodes the same device number and files the same size and contents. .PP A report of any difference is printed to stdout. The exit status is similar that of diff(1): 0 means equal, 1 means different, 2 means problem. .PP Possible options: .TP \fB\-\-old\fR, \fB\-a\fR Specify the first filesystem image or source directory, relativ to which the changes are evaluated. .TP \fB\-\-new\fR, \fB\-b\fR Specify the second filesystem image to source directory to compare to the first one. .TP \fB\-\-no\-contents\fR, \fB\-C\fR Do not compare file contents. .TP \fB\-\-no\-owner\fR, \fB\-O\fR Do not compare file owners. .TP \fB\-\-no\-permissions\fR, \fB\-P\fR Do not compare permission bits. .TP \fB\-\-timestamps\fR, \fB\-T\fR Compare file timestamps. .TP \fB\-\-inode\-num\fR, \fB\-I\fR Compare inode numbers of all files. .TP \fB\-\-super\fR, \fB\-S\fR Also compare meta data in super blocks. .TP \fB\-\-extract\fR, \fB\-e\fR Extract files that exist in both images but have different contents to the specified directory. Contents of the first image end up in a sub directory named \fBold\fR and the contents of the second image in a sub directory named \fBnew\fR. .TP \fB\-\-help\fR, \fB\-h\fR Print help text and exit. .TP \fB\-\-version\fR, \fB\-V\fR Print version information and exit. .SH EXIT STATUS The exit status is similar that of diff(1): 0 means equal, 1 means different, 2 means problem. .SH SEE ALSO rdsquashfs(1), sqfs2tar(1) .SH AUTHOR Written by David Oberhollenzer. .SH COPYRIGHT Copyright \(co 2019 David Oberhollenzer et al License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. squashfs-tools-ng-0.8/doc/tar2sqfs.1000066400000000000000000000130221360235375500173610ustar00rootroot00000000000000.TH TAR2SQFS "1" "June 2019" "tar2sqfs" "User Commands" .SH NAME tar2sqfs \- create a SquashFS image from a tar archive .SH SYNOPSIS .B tar2sqfs [\fI\,OPTIONS\/\fR...] \fI\,\/\fR .SH DESCRIPTION Read an uncompressed tar archive from stdin and turn it into a SquashFS filesystem image. The idea is to quickly and painlessly turn a tar ball into a SquashFS filesystem image, so existing tools that work with tar can be used for SquashFS. .PP Possible options: .TP \fB\-\-root\-becomes\fR, \fB\-r\fR If set, only pack entries that are underneath the specified directory and the prefix is stripped. The meta data for the directory itself is copied to the root inode, i.e. the ownership, permissions, extended attributes (unless \f\-\-no\-xattr\R is set), and modification time (unless \fB\-\-no\-keep\-time\fR is set). If this option is not set, tar2sqfs implicitly treats \fB./\fR or absolute paths this way, i.e. if the archive contains an entry for \fB./\fR, it becomes the root node and the prefix is stripped from all paths (and similar for absolute paths and \fB/\fR). .TP \fB\-\-compressor\fR, \fB\-c\fR Select the compressor to use. Run \fBtar2sqfs \-\-help\fR to get a list of all available compressors and the default selection. .TP \fB\-\-comp\-extra\fR, \fB\-X\fR A comma separated list of extra options for the selected compressor. Specify \fBhelp\fR to get a list of available options. .TP \fB\-\-num\-jobs\fR, \fB\-j\fR If libsquashfs was compiled with a thread pool based, parallel data compressor, this option can be used to set the number of compressor threads. If not set, the default is the number of available CPU cores. .TP \fB\-\-queue\-backlog\fR, \fB\-Q\fR Maximum number of data blocks in the thread worker queue before the packer starts waiting for the block processors to catch up. Higher values result in higher memory consumption. Defaults to 10 times the number of workers. .TP \fB\-\-block\-size\fR, \fB\-b\fR Block size to use for SquashFS image. Defaults to 131072. .TP \fB\-\-dev\-block\-size\fR, \fB\-B\fR Device block size to padd the image to. Defaults to 4096. .TP \fB\-\-defaults\fR, \fB\-d\fR A comma separated list of default values for implicitly created directories. The following values can be set: .TS tab(;) allbox; l l l l l l l l l l rd. \fBOption\fR;\fBDefault\fR uid=;0 gid=;0 mode=;0755 mtime=;\fB$SOURCE\_DATE\_EPOCH\fR if set, 0 otherwise .TE .TP .TP \fB\-\-no\-keep\-time\fR, \fB\-k\fR Replace the time stamps from the tar archive with default time stamps for all entries. The default behavior if not specified, is to preserve the time stamps from the archive to the extent possible (SquashFS has second resolution and 32 bit time stamps; tar can use extensions to specify much larger timestamps with arbitrary precision). The root inode and the modification time on the SquashFS image itself will always still be set to defaults. .TP \fB\-\-no\-xattr\fR, \fB\-x\fR Do not copy extended attributes from archive. Default behaviour is to copy all extended attributes and skip the ones that cannot be encoded in SquashFS. .TP \fB\-\-no\-skip\fR, \fB\-s\fR Abort if a tar record cannot be read instead of skipping it. .TP \fB\-\-exportable\fR, \fB\-e\fR Generate an export table for NFS support. .TP \fB\-\-force\fR, \fB\-f\fR Overwrite the output file if it exists. .TP \fB\-\-quiet\fR, \fB\-q\fR Do not print out progress reports. .TP \fB\-\-help\fR, \fB\-h\fR Print help text and exit. .TP \fB\-\-version\fR, \fB\-V\fR Print version information and exit. .SH COMPATIBILITY Currently the program can process v7 format, pre-POSIX ustar, POSIX tar and GNU tar archives. PAX extension headers are also supported. The support for GNU tar is limited to commonly used subset (i.e. some legacy extensions that GNU tar itself no longer generates are not supported; neither are mutli volume archives). Hard links are currently not supported and silently converted to symlinks. Extended attributes are supported through the SCHILY.xattr PAX extension (favoured by GNU tar and star) or through the LIBARCHIVE.xattr PAX extension. If any unsupported section or extended attribute key is encountered in an archive a warning message is written to stderr. If the \fB\-\-no\-skip\fR option is set, processing aborts. By default, unknown sections and unsupported extended attributes are simply skipped after issuing a warning. .SH ENVIRONMENT If the command line switch \fB\-\-defaults\fR is not used or no default mtime is specified, the value of the environment variable \fBSOURCE\_DATE\_EPOCH\fR is used for all file and filesystem timestamps. If \fBSOURCE\_DATE\_EPOCH\fR is not set, not a parsable number or it is out of range, the timestamps default to 0. Environment variables are only used if no explicit command line switches are set. Explicit command line switches are always preferred over the environment variables. .SH EXAMPLES .TP Turn an uncompressed tar archive into a SquashFS image: .IP tar2sqfs rootfs.sqfs < rootfs.tar .TP Turn a gzip'ed tar archive into a SquashFS image: .IP zcat rootfs.tar.gz | tar2sqfs rootfs.sqfs .TP Turn an LZMA2 compressed tar archive into a SquashFS image: .IP xzcat rootfs.tar.xz | tar2sqfs rootfs.sqfs .SH SEE ALSO gensquashfs(1), rdsquashfs(1), sqfs2tar(1) .SH AUTHOR Written by David Oberhollenzer. .SH COPYRIGHT Copyright \(co 2019 David Oberhollenzer License GPLv3+: GNU GPL version 3 or later . .br This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. squashfs-tools-ng-0.8/include/000077500000000000000000000000001360235375500164125ustar00rootroot00000000000000squashfs-tools-ng-0.8/include/common.h000066400000000000000000000102511360235375500200520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * common.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef COMMON_H #define COMMON_H #include "config.h" #include "sqfs/xattr_writer.h" #include "sqfs/xattr_reader.h" #include "sqfs/compressor.h" #include "sqfs/id_table.h" #include "sqfs/inode.h" #include "sqfs/table.h" #include "sqfs/error.h" #include "sqfs/meta_writer.h" #include "sqfs/data_reader.h" #include "sqfs/data_writer.h" #include "sqfs/dir_writer.h" #include "sqfs/dir_reader.h" #include "sqfs/block.h" #include "sqfs/xattr.h" #include "sqfs/dir.h" #include "sqfs/io.h" #include "compat.h" #include "fstree.h" #include "tar.h" #include typedef struct { size_t file_count; size_t blocks_written; size_t frag_blocks_written; size_t duplicate_blocks; size_t sparse_blocks; size_t frag_count; size_t frag_dup; sqfs_u64 bytes_written; sqfs_u64 bytes_read; } data_writer_stats_t; typedef struct { sqfs_data_writer_t *data; sqfs_dir_writer_t *dirwr; sqfs_meta_writer_t *dm; sqfs_meta_writer_t *im; sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; sqfs_file_t *outfile; sqfs_super_t super; fstree_t fs; data_writer_stats_t stats; sqfs_xattr_writer_t *xwr; } sqfs_writer_t; typedef struct { const char *filename; char *fs_defaults; char *comp_extra; size_t block_size; size_t devblksize; size_t max_backlog; size_t num_jobs; int outmode; E_SQFS_COMPRESSOR comp_id; bool exportable; bool no_xattr; bool quiet; } sqfs_writer_cfg_t; typedef struct sqfs_hard_link_t { struct sqfs_hard_link_t *next; sqfs_u32 inode_number; char *target; } sqfs_hard_link_t; #define container_of(ptr, type, member) \ ((type *)((char *)ptr - offsetof(type, member))) /* High level helper function to serialize an entire file system tree to a squashfs inode table and directory table. The data is written to the given file descriptor and the super block is update accordingly (inode and directory table start and total size). The function internally creates two meta data writers and uses meta_writer_write_inode to serialize the inode table of the fstree. Returns 0 on success. Prints error messages to stderr on failure. */ int sqfs_serialize_fstree(const char *filename, sqfs_writer_t *wr); /* Print out fancy statistics for squashfs packing tools */ void sqfs_print_statistics(sqfs_super_t *super, data_writer_stats_t *stats); void compressor_print_available(void); E_SQFS_COMPRESSOR compressor_get_default(void); int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, E_SQFS_COMPRESSOR id, size_t block_size, char *options); void compressor_print_help(E_SQFS_COMPRESSOR id); int inode_stat(const sqfs_tree_node_t *node, struct stat *sb); char *sqfs_tree_node_get_path(const sqfs_tree_node_t *node); int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, FILE *fp, size_t block_size, bool allow_sparse); sqfs_file_t *sqfs_get_stdin_file(FILE *fp, const sparse_map_t *map, sqfs_u64 size); void register_stat_hooks(sqfs_data_writer_t *data, data_writer_stats_t *stats); int write_data_from_file(const char *filename, sqfs_data_writer_t *data, sqfs_inode_generic_t *inode, sqfs_file_t *file, int flags); void sqfs_writer_cfg_init(sqfs_writer_cfg_t *cfg); int sqfs_writer_init(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *wrcfg); int sqfs_writer_finish(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *cfg); void sqfs_writer_cleanup(sqfs_writer_t *sqfs); void sqfs_perror(const char *file, const char *action, int error_code); int sqfs_tree_find_hard_links(const sqfs_tree_node_t *root, sqfs_hard_link_t **out); /* A wrapper around mkdir() that behaves like 'mkdir -p'. It tries to create every component of the given path and skips already existing entries. Returns 0 on success. */ int mkdir_p(const char *path); /* A common implementation of the '--version' command line flag. */ void print_version(const char *progname); /* Create an liblzo2 based LZO compressor. XXX: This must be in libcommon instead of libsquashfs for legal reasons. */ sqfs_compressor_t *lzo_compressor_create(const sqfs_compressor_config_t *cfg); #endif /* COMMON_H */ squashfs-tools-ng-0.8/include/compat.h000066400000000000000000000107061360235375500200520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * compat.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef COMPAT_H #define COMPAT_H #include "sqfs/predef.h" #if defined(__GNUC__) || defined(__clang__) # if defined(__GNUC__) && __GNUC__ < 5 # if SIZEOF_SIZE_T <= SIZEOF_INT # define SZ_ADD_OV __builtin_uadd_overflow # define SZ_MUL_OV __builtin_umul_overflow # elif SIZEOF_SIZE_T == SIZEOF_LONG # define SZ_ADD_OV __builtin_uaddl_overflow # define SZ_MUL_OV __builtin_umull_overflow # elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define SZ_ADD_OV __builtin_uaddll_overflow # define SZ_MUL_OV __builtin_umulll_overflow # else # error Cannot determine maximum value of size_t # endif # else # define SZ_ADD_OV __builtin_add_overflow # define SZ_MUL_OV __builtin_mul_overflow # endif #else # error I do not know how to trap integer overflows with this compiler #endif #if SIZEOF_SIZE_T <= SIZEOF_INT # define PRI_SZ "%u" #elif SIZEOF_SIZE_T == SIZEOF_LONG # define PRI_SZ "%lu" #elif defined(_WIN32) && SIZEOF_SIZE_T == 8 # define PRI_SZ "%I64u" #else # error Cannot figure out propper printf specifier for size_t #endif #if defined(__APPLE__) #include #define htole16(x) OSSwapHostToLittleInt16(x) #define htole32(x) OSSwapHostToLittleInt32(x) #define htole64(x) OSSwapHostToLittleInt64(x) #define le32toh(x) OSSwapLittleToHostInt32(x) #define le16toh(x) OSSwapLittleToHostInt16(x) #define le64toh(x) OSSwapLittleToHostInt64(x) #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #elif defined(_WIN32) || defined(__WINDOWS__) #define htole16(x) (x) #define htole32(x) (x) #define htole64(x) (x) #define le16toh(x) (x) #define le32toh(x) (x) #define le64toh(x) (x) #define WIN32_LEAN_AND_MEAN #include #else #include #endif #if defined(_WIN32) || defined(__WINDOWS__) #include "sqfs/inode.h" #define S_IFSOCK SQFS_INODE_MODE_SOCK #define S_IFLNK SQFS_INODE_MODE_LNK #define S_IFREG SQFS_INODE_MODE_REG #define S_IFBLK SQFS_INODE_MODE_BLK #define S_IFDIR SQFS_INODE_MODE_DIR #define S_IFCHR SQFS_INODE_MODE_CHR #define S_IFIFO SQFS_INODE_MODE_FIFO #define S_IFMT SQFS_INODE_MODE_MASK #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #define S_ISUID SQFS_INODE_SET_UID #define S_ISGID SQFS_INODE_SET_GID #define S_ISVTX SQFS_INODE_STICKY #define S_IRWXU SQFS_INODE_OWNER_MASK #define S_IRUSR SQFS_INODE_OWNER_R #define S_IWUSR SQFS_INODE_OWNER_W #define S_IXUSR SQFS_INODE_OWNER_X #define S_IRWXG SQFS_INODE_GROUP_MASK #define S_IRGRP SQFS_INODE_GROUP_R #define S_IWGRP SQFS_INODE_GROUP_W #define S_IXGRP SQFS_INODE_GROUP_X #define S_IRWXO SQFS_INODE_OTHERS_MASK #define S_IROTH SQFS_INODE_OTHERS_R #define S_IWOTH SQFS_INODE_OTHERS_W #define S_IXOTH SQFS_INODE_OTHERS_X struct stat { sqfs_u32 st_dev; sqfs_u32 st_ino; sqfs_u16 st_mode; sqfs_u16 st_nlink; sqfs_u32 st_uid; sqfs_u32 st_gid; sqfs_u32 st_rdev; sqfs_u64 st_size; sqfs_u32 st_blksize; sqfs_u32 st_blocks; sqfs_u64 st_atime; sqfs_u64 st_mtime; sqfs_u64 st_ctime; }; /* lifted from musl libc */ #define major(x) \ ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) )) #define minor(x) \ ((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) )) #define makedev(x,y) ( \ (((x)&0xfffff000ULL) << 32) | \ (((x)&0x00000fffULL) << 8) | \ (((y)&0xffffff00ULL) << 12) | \ (((y)&0x000000ffULL)) ) #define AT_FDCWD ((int)0xDEADBEEF) #define AT_SYMLINK_NOFOLLOW (0x01) int fchownat(int dirfd, const char *path, int uid, int gid, int flags); int fchmodat(int dirfd, const char *path, int mode, int flags); int chdir(const char *path); #else #include #include #include #include #ifdef __linux__ #include #endif #endif #ifndef HAVE_GETLINE #include ssize_t getline(char **line, size_t *n, FILE *fp); #endif #ifndef HAVE_STRNDUP char *strndup(const char *str, size_t max_len); #endif #ifndef HAVE_GETSUBOPT int getsubopt(char **opt, char *const *keys, char **val); #endif #if defined(_WIN32) || defined(__WINDOWS__) WCHAR *path_to_windows(const char *input); #endif #endif /* COMPAT_H */ squashfs-tools-ng-0.8/include/fstree.h000066400000000000000000000156301360235375500200600ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef FSTREE_H #define FSTREE_H #include "config.h" #include #include #include #include #include "sqfs/predef.h" #include "compat.h" #define FSTREE_MODE_HARD_LINK (0) #define FSTREE_MODE_HARD_LINK_RESOLVED (1) typedef struct tree_node_t tree_node_t; typedef struct file_info_t file_info_t; typedef struct dir_info_t dir_info_t; typedef struct fstree_t fstree_t; /* Additional meta data stored in a tree_node_t for regular files. */ struct file_info_t { /* Linked list pointer for files in fstree_t */ file_info_t *next; /* Path to the input file. */ char *input_file; void *user_ptr; }; /* Additional meta data stored in a tree_node_t for directories */ struct dir_info_t { /* Linked list head for children in the directory */ tree_node_t *children; /* Set to true for implicitly generated directories. */ bool created_implicitly; /* Used by recursive tree walking code to avoid hard link loops */ bool visited; }; /* A node in a file system tree */ struct tree_node_t { /* Parent directory children linked list pointer. */ tree_node_t *next; /* Root node has this set to NULL. */ tree_node_t *parent; /* For the root node, this points to an empty string. */ char *name; sqfs_u32 xattr_idx; sqfs_u32 uid; sqfs_u32 gid; sqfs_u32 inode_num; sqfs_u32 mod_time; sqfs_u16 mode; sqfs_u16 link_count; /* SquashFS inode refernce number. 32 bit offset of the meta data block start (relative to inode table start), shifted left by 16 and ored with a 13 bit offset into the uncompressed meta data block. Generated on the fly when writing inodes. */ sqfs_u64 inode_ref; /* Type specific data. "target" pointer is into payload area below. */ union { dir_info_t dir; file_info_t file; char *target; sqfs_u64 devno; tree_node_t *target_node; } data; sqfs_u8 payload[]; }; /* Encapsulates a file system tree */ struct fstree_t { struct stat defaults; size_t unique_inode_count; /* flat array of all nodes that have an inode number */ tree_node_t **inodes; tree_node_t *root; /* linear linked list of all regular files */ file_info_t *files; }; /* Initializing means copying over the default values and creating a root node. On error, an error message is written to stderr. The string `defaults` can specify default attributes (mode, uid, gid, mtime) as a comma separated list of key value paris (=[,...]). The string is passed to getsubopt and will be altered. Returns 0 on success. */ int fstree_init(fstree_t *fs, char *defaults); void fstree_cleanup(fstree_t *fs); /* Create a tree node from a struct stat, node name and extra data. For symlinks, the extra part is interpreted as target. For regular files, it is interpreted as input path (can be NULL). The name doesn't have to be null terminated, a length has to be specified. This function does not print anything to stderr, instead it sets an appropriate errno value. The resulting node can be freed with a single free() call. */ tree_node_t *fstree_mknode(tree_node_t *parent, const char *name, size_t name_len, const char *extra, const struct stat *sb); /* Add a node to an fstree at a specific path. If some components of the path don't exist, they are created as directories with default permissions, like mkdir -p would, and marked as implcitily created. A subsequent call that tries to create an existing tree node will fail, except if the target is an implicitly created directory node and the call tries to create it as a directory (this will simply overwrite the permissions and ownership). The implicitly created flag is then cleared. Subsequent attempts to create an existing directory again will then also fail. This function does not print anything to stderr, instead it sets an appropriate errno value. Internally it uses fstree_mknode to create the node. */ tree_node_t *fstree_add_generic(fstree_t *fs, const char *path, const struct stat *sb, const char *extra); /* Parses the file format accepted by gensquashfs and produce a file system tree from it. File input paths are interpreted as relative to the current working directory. Data is read from the given file pointer. The filename is only used for producing error messages. On failure, an error report with filename and line number is written to stderr. Returns 0 on success. */ int fstree_from_file(fstree_t *fs, const char *filename, FILE *fp); /* This function performs all the necessary post processing steps on the file system tree, i.e. recursively sorting all directory entries by name, allocating inode numbers, resolving hard links and stringing all files nodes together into a linked list. The total inode count is stored in unique_inode_count. The head of the file list is pointed to by fs->files. The "inodes" array is allocated and each node that has an inode number is mapped into the array at index inode_num - 1. Returns 0 on success, prints to stderr on failure. */ int fstree_post_process(fstree_t *fs); /* Generate a string holding the full path of a node. Returned string must be freed. Returns NULL on failure and sets errno. */ char *fstree_get_path(tree_node_t *node); /* Resolve a path to a tree node. Returns NULL on failure and sets errno. If "create_implicitly" is set to true, the function acts essentially like mkdir_p if part of the path doesn't exist yet. If "stop_at_parent" is true, the function stops at the last component and returns the parent or would-be-parent of the last path component, but doesn't check if the last path component exists or not. */ tree_node_t *fstree_get_node_by_path(fstree_t *fs, tree_node_t *root, const char *path, bool create_implicitly, bool stop_at_parent); /* Convert back to forward slashed, remove all preceeding and trailing slashes, collapse all sequences of slashes, remove all path components that are '.' and returns failure state if one of the path components is '..'. Returns 0 on success. */ int canonicalize_name(char *filename); /* Returns true if a given filename is sane, false if it is not (e.g. contains slashes or it is equal to '.' or '..'). If check_os_specific is true, this also checks if the filename contains a character, or is equal to a name, that is black listed on the current OS. E.g. on Windows, a file named "COM0" or "AUX" is a no-no. */ bool is_filename_sane(const char *name, bool check_os_specific); /* Add a hard link node. Returns NULL on failure and sets errno. */ tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path, const char *target); /* Resolve a hard link node and replace it with a direct pointer to the target. Returns 0 on success. On failure, errno is set. */ int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node); #endif /* FSTREE_H */ squashfs-tools-ng-0.8/include/sqfs/000077500000000000000000000000001360235375500173665ustar00rootroot00000000000000squashfs-tools-ng-0.8/include/sqfs/block.h000066400000000000000000000104511360235375500206320ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * block.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_BLOCK_H #define SQFS_BLOCK_H #include "sqfs/predef.h" /** * @file block.h * * @brief Contains on-disk data structures for data block management, * helper macros and the higher level @ref sqfs_block_t structure. */ #define SQFS_META_BLOCK_SIZE 8192 #define SQFS_IS_BLOCK_COMPRESSED(size) (((size) & (1 << 24)) == 0) #define SQFS_ON_DISK_BLOCK_SIZE(size) ((size) & ((1 << 24) - 1)) #define SQFS_IS_SPARSE_BLOCK(size) (SQFS_ON_DISK_BLOCK_SIZE(size) == 0) /** * @struct sqfs_fragment_t * * @brief Data structure that makes up the fragment table entries. */ struct sqfs_fragment_t { /** * @brief Location of the fragment block on-disk. */ sqfs_u64 start_offset; /** * @brief Size of the fragment block in bytes. */ sqfs_u32 size; /** * @brief Unused. Always initialize this to 0. */ sqfs_u32 pad0; }; /** * @enum E_SQFS_BLK_FLAGS * * @brief Generic flags that tell the processor what to do with a block and * flags that the processor sets when it is done with a block. */ typedef enum { /** * @brief Only calculate checksum, do NOT compress the data. * * If set, the blocks of a file will not be compressed by the * @ref sqfs_data_writer_t. */ SQFS_BLK_DONT_COMPRESS = 0x0001, /** * @brief Align the block on disk to device block size. * * If set, the @ref sqfs_data_writer_t will add padding before the * first block of the affected file and after the last block. */ SQFS_BLK_ALIGN = 0x0002, /** * @brief Don't add the tail end of a file to a fragment block. * * If set, the @ref sqfs_data_writer_t will always generate a final * block for a file, even if it is truncated. It will not add the * tail end to a fragment block. */ SQFS_BLK_DONT_FRAGMENT = 0x0004, /** * @brief Set by the @ref sqfs_data_writer_t on the first * block of a file. */ SQFS_BLK_FIRST_BLOCK = 0x0800, /** * @brief Set by the @ref sqfs_data_writer_t on the last * block of a file. */ SQFS_BLK_LAST_BLOCK = 0x1000, /** * @brief Set by the @ref sqfs_data_writer_t to indicate that a block * is a tail end of a file and the block. */ SQFS_BLK_IS_FRAGMENT = 0x2000, /** * @brief Set by the @ref sqfs_data_writer_t on fragment blocks that * it generates. */ SQFS_BLK_FRAGMENT_BLOCK = 0x4000, /** * @brief Set by @ref sqfs_data_writer_t if the block was * actually compressed. */ SQFS_BLK_IS_COMPRESSED = 0x8000, /** * @brief The combination of all flags that are user settable. */ SQFS_BLK_USER_SETTABLE_FLAGS = 0x0007, } E_SQFS_BLK_FLAGS; /** * @struct sqfs_block_t * * @brief Encapsulates a chunk of data to be processed by the block processor. */ struct sqfs_block_t { /** * @brief Used internally, existing value is ignored and overwritten * when enqueueing a block. */ sqfs_block_t *next; /** * @brief Used internally, existing value is ignored and overwritten * when enqueueing a block. */ sqfs_u32 sequence_number; /** * @brief Size of the data area. */ sqfs_u32 size; /** * @brief Checksum of the input data. */ sqfs_u32 checksum; /** * @brief Data block index within the inode. */ sqfs_u32 index; /** * @brief The squashfs inode related to this block. */ sqfs_inode_generic_t *inode; /** * @brief User settable flag field. * * A combination of @ref E_SQFS_BLK_FLAGS and custom, user * settable flags. */ sqfs_u32 flags; /** * @brief Raw data to be processed. */ sqfs_u8 data[]; }; #endif /* SQFS_BLOCK_H */ squashfs-tools-ng-0.8/include/sqfs/compressor.h000066400000000000000000000240571360235375500217430ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * compressor.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_COMPRESSOR_H #define SQFS_COMPRESSOR_H #include "sqfs/predef.h" #include "sqfs/super.h" /** * @file compressor.h * * @brief Contains declarations to everything related to data compression. */ /** * @interface sqfs_compressor_t * * @brief Encapsultes a compressor with a simple interface to compress or * extract chunks of data. */ struct sqfs_compressor_t { /** * @brief Destroy a compressor and free all memory used by it. * * @param cmp A pointer to a compressor object. */ void (*destroy)(sqfs_compressor_t *cmp); /** * @brief Write compressor options to disk if non-default settings * have been used. * * The options are stored in an uncompressed meta data block directly * after the super block. * * @param cmp A pointer to a compressor object. * @param file A file to write to. * * @return The number of bytes written on success, 0 means default * settings are used. A negative value is an @ref E_SQFS_ERROR * identifier. */ int (*write_options)(sqfs_compressor_t *cmp, sqfs_file_t *file); /** * @brief Read compressor options from disk. * * @param cmp A pointer to a compressor object. * @param file A file to read from. * * @return Zero on success or an @ref E_SQFS_ERROR value. */ int (*read_options)(sqfs_compressor_t *cmp, sqfs_file_t *file); /** * @brief Compress or uncompress a chunk of data. * * @param cmp A pointer to a compressor object. * @param in A pointer to the input buffer to read from. * @param size The number of bytes to read from the input and compress. * @param out The destination buffer to write the result to. * @param outsize The available space in the destination buffer. * * @return The number of bytes written to the buffer, a negative * value is an @ref E_SQFS_ERROR value. The value 0 means * the output buffer was too small when extracting or that * the result is larger than the input when compressing. */ sqfs_s32 (*do_block)(sqfs_compressor_t *cmp, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize); /** * @brief Create an exact copt of agiven compressor * * @param cmp A pointer to a compressor object. * * @return A deep copy of the given compressor. */ sqfs_compressor_t *(*create_copy)(sqfs_compressor_t *cmp); }; /** * @struct sqfs_compressor_config_t * * @brief Configuration parameters for instantiating a compressor backend. * * The unused fields MUST be set to 0. The easiest way to do this is by always * clearing the struct using memset before setting anything, or using * @ref sqfs_compressor_config_init to set defaults and then modify the struct * from there. */ struct sqfs_compressor_config_t { /** * @brief An @ref E_SQFS_COMPRESSOR identifier */ sqfs_u16 id; /** * @brief A combination of @ref SQFS_COMP_FLAG flags. */ sqfs_u16 flags; /** * @brief The intended data block size. */ sqfs_u32 block_size; /** * @brief Backend specific options for fine tuing. */ union { /** * @brief Options for the zlib compressor. */ struct { /** * @brief Compression level. Value between 1 and 9. * * Default is 9, i.e. best compression. */ sqfs_u16 level; /** * @brief Deflate window size. Value between 8 and 15. * * Default is 15, i.e. 32k window. */ sqfs_u16 window_size; sqfs_u32 padd0[3]; } gzip; /** * @brief Options for the zstd compressor. */ struct { /** * @brief Compression level. Value between 1 and 22. * * Default is 15. */ sqfs_u16 level; sqfs_u16 padd0[7]; } zstd; /** * @brief Options for the lzo compressor. */ struct { /** * @brief Which variant of lzo should be used. * * An @ref SQFS_LZO_ALGORITHM value. Default is * @ref SQFS_LZO1X_999, i.e. best compression. */ sqfs_u16 algorithm; /** * @brief Compression level for @ref SQFS_LZO1X_999. * * If the selected algorithm is @ref SQFS_LZO1X_999, * this can be a value between 0 and 9. For all other * algorithms it has to be 0. * * Defaults to 9, i.e. best compression. */ sqfs_u16 level; sqfs_u32 padd0[3]; } lzo; /** * @brief Options for the xz compressor. */ struct { /** * @brief LZMA dictionary size. * * This value must either be a power of two or the sumo * of two consecutive powers of two. * * Default is setting this to the same as the * block size. */ sqfs_u32 dict_size; sqfs_u32 padd0[3]; } xz; sqfs_u64 padd0[2]; } opt; }; /** * @enum SQFS_COMP_FLAG * * @brief Flags for configuring the compressor. */ typedef enum { /** * @brief For LZ4, set this to use high compression mode. */ SQFS_COMP_FLAG_LZ4_HC = 0x0001, SQFS_COMP_FLAG_LZ4_ALL = 0x0001, /** * @brief For LZMA, set this to select the x86 BCJ filter. */ SQFS_COMP_FLAG_XZ_X86 = 0x0001, /** * @brief For LZMA, set this to select the PowerPC BCJ filter. */ SQFS_COMP_FLAG_XZ_POWERPC = 0x0002, /** * @brief For LZMA, set this to select the Itanium BCJ filter. */ SQFS_COMP_FLAG_XZ_IA64 = 0x0004, /** * @brief For LZMA, set this to select the ARM BCJ filter. */ SQFS_COMP_FLAG_XZ_ARM = 0x0008, /** * @brief For LZMA, set this to select the ARM Thumb BCJ filter. */ SQFS_COMP_FLAG_XZ_ARMTHUMB = 0x0010, /** * @brief For LZMA, set this to select the Sparc BCJ filter. */ SQFS_COMP_FLAG_XZ_SPARC = 0x0020, SQFS_COMP_FLAG_XZ_ALL = 0x003F, /** * @brief For zlib deflate, set this to try the default strategy. */ SQFS_COMP_FLAG_GZIP_DEFAULT = 0x0001, /** * @brief For zlib deflate, set this to try the "filtered" strategy. */ SQFS_COMP_FLAG_GZIP_FILTERED = 0x0002, /** * @brief For zlib deflate, set this to try the huffman only strategy. */ SQFS_COMP_FLAG_GZIP_HUFFMAN = 0x0004, /** * @brief For zlib deflate, set this to try the RLE strategy. */ SQFS_COMP_FLAG_GZIP_RLE = 0x0008, /** * @brief For zlib deflate, set this to try the fixed strategy. */ SQFS_COMP_FLAG_GZIP_FIXED = 0x0010, SQFS_COMP_FLAG_GZIP_ALL = 0x001F, /** * @brief Set this if the compressor should actually extract * instead of compress data. */ SQFS_COMP_FLAG_UNCOMPRESS = 0x8000, SQFS_COMP_FLAG_GENERIC_ALL = 0x8000, } SQFS_COMP_FLAG; /** * @enum SQFS_LZO_ALGORITHM * * @brief The available LZO algorithms. */ typedef enum { SQFS_LZO1X_1 = 0, SQFS_LZO1X_1_11 = 1, SQFS_LZO1X_1_12 = 2, SQFS_LZO1X_1_15 = 3, SQFS_LZO1X_999 = 4, } SQFS_LZO_ALGORITHM; #define SQFS_GZIP_DEFAULT_LEVEL (9) #define SQFS_GZIP_DEFAULT_WINDOW (15) #define SQFS_LZO_DEFAULT_ALG SQFS_LZO1X_999 #define SQFS_LZO_DEFAULT_LEVEL (8) #define SQFS_ZSTD_DEFAULT_LEVEL (15) #define SQFS_GZIP_MIN_LEVEL (1) #define SQFS_GZIP_MAX_LEVEL (9) #define SQFS_LZO_MIN_LEVEL (0) #define SQFS_LZO_MAX_LEVEL (9) #define SQFS_ZSTD_MIN_LEVEL (1) #define SQFS_ZSTD_MAX_LEVEL (22) #define SQFS_GZIP_MIN_WINDOW (8) #define SQFS_GZIP_MAX_WINDOW (15) #ifdef __cplusplus extern "C" { #endif /** * @brief Initialize a compressor configuration * * The detail configuration options are all initialized to the defaults for * the compressor in question. * * @param cfg A pointer to a compressor configuration to initialize * @param id The compressor id to set. * @param block_size The block size to set. * @param flags The compressor flags to set. * * @return Zero on success, an @ref E_SQFS_ERROR value if some of the options * don't make sense (e.g. unknown flags are used). */ SQFS_API int sqfs_compressor_config_init(sqfs_compressor_config_t *cfg, E_SQFS_COMPRESSOR id, size_t block_size, sqfs_u16 flags); /** * @brief Check if a specified compressor implementation is available. * * @param id An @ref E_SQFS_COMPRESSOR identifier. * * @return true if the implementation is available and can be instantiated * through @ref sqfs_compressor_create. */ SQFS_API bool sqfs_compressor_exists(E_SQFS_COMPRESSOR id); /** * @brief Create an instance of a compressor implementation. * * @param cfg A pointer to a compressor configuration. * * @return A pointer to a compressor object on success, NULL on allocation * failure or if initializing the compressor failed. */ SQFS_API sqfs_compressor_t *sqfs_compressor_create(const sqfs_compressor_config_t *cfg); /** * @brief Get the name of a compressor backend from its ID. * * This function will even resolve compressor names that are not built in, so * use @ref sqfs_compressor_exists to check if a compressor is actually * available. * * @param id An @ref E_SQFS_COMPRESSOR identifier. * * @return A string holding the name of the compressor, NULL if the compressor * ID is not known. */ SQFS_API const char *sqfs_compressor_name_from_id(E_SQFS_COMPRESSOR id); /** * @brief Get the compressor ID using just the name of the backend. * * This function will even resolve compressor names that are not built in, so * use @ref sqfs_compressor_exists to check if a compressor is actually * available. * * @param name The name of the compressor backend. * * @return A positive, @ref E_SQFS_COMPRESSOR identifier on success * or @ref SQFS_ERROR_UNSUPPORTED if the backend is unknown. */ SQFS_API int sqfs_compressor_id_from_name(const char *name); #ifdef __cplusplus } #endif #endif /* SQFS_COMPRESSOR_H */ squashfs-tools-ng-0.8/include/sqfs/data_reader.h000066400000000000000000000120331360235375500217710ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * data_reader.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_DATA_READER_H #define SQFS_DATA_READER_H #include "sqfs/predef.h" /** * @file data_reader.h * * @brief Contains declarations for the @ref sqfs_data_reader_t. */ /** * @struct sqfs_data_reader_t * * @brief Abstracts access to data blocks stored in a SquashFS image. * * A SquashFS image can contain a series of file data blocks between the * super block and the inode table. Blocks may or may not be compressed. * Data chunks that are smaller than the block size indicated by the super * block (such as the final chunk of a file or an entire file that is smaller * than a signle block) can be grouped in a single fragment block. * * Regular file inodes referre to the location of the first block and store a * sequence of block sizes for all consequitve blocks, as well as a fragment * index and fragment offset which is resolved through a fragment table. * * The data reader abstracts all of this away in a simple interface that allows * reading file data through an inode description and a location in the file. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Create a data reader instance. * * @memberof sqfs_data_reader_t * * @param file A file interface through which to access the * underlying filesystem image. * @param block_size The data block size from the super block. * @param cmp A compressor to use for uncompressing blocks read from disk. * * @return A pointer to a new data reader object. NULL means * allocation failure. */ SQFS_API sqfs_data_reader_t *sqfs_data_reader_create(sqfs_file_t *file, size_t block_size, sqfs_compressor_t *cmp); /** * @brief Destroy a data reader instance and free all memory used by it. * * @memberof sqfs_data_reader_t * * @param data A pointer to a data reader object. */ SQFS_API void sqfs_data_reader_destroy(sqfs_data_reader_t *data); /** * @brief Read and decode the fragment table from disk. * * @memberof sqfs_data_reader_t * * @param data A pointer to a data reader object. * @param super A pointer to the super block. * * @return Zero on succcess, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_reader_load_fragment_table(sqfs_data_reader_t *data, const sqfs_super_t *super); /** * @brief Get the tail end of a file. * * @memberof sqfs_data_reader_t * * @param data A pointer to a data reader object. * @param inode A pointer to the inode describing the file. * @param out Returns a pointer to the tail block of the file. * * @return Zero on succcess, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, sqfs_block_t **out); /** * @brief Get a full sized data block of a file by block index. * * @memberof sqfs_data_reader_t * * @param data A pointer to a data reader object. * @param inode A pointer to the inode describing the file. * @param index The block index in the inodes block list. * @param out Returns a pointer to the data block. * * @return Zero on succcess, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_reader_get_block(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, size_t index, sqfs_block_t **out); /** * @brief A simple UNIX-read-like function to read data from a file. * * @memberof sqfs_data_reader_t * * This function acts like the read system call in a Unix-like OS. It takes * care of reading accross data blocks and fragment internally, using a * data and fragment block cache. * * @param data A pointer to a data reader object. * @param inode A pointer to the inode describing the file. * @param offset An arbitrary byte offset into the uncompressed file. * @param buffer Returns the data read from the file. * @param size The number of uncompressed bytes to read from the given offset. * * @return The number of bytes read on succcess, zero if attempting to read * past the end of the file and a negative @ref E_SQFS_ERROR value * on failure. */ SQFS_API sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, sqfs_u64 offset, void *buffer, sqfs_u32 size); #ifdef __cplusplus } #endif #endif /* SQFS_DATA_READER_H */ squashfs-tools-ng-0.8/include/sqfs/data_writer.h000066400000000000000000000254701360235375500220540ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * data_writer.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SFQS_DATA_WRITER_H #define SFQS_DATA_WRITER_H #include "sqfs/predef.h" /** * @file data_writer.h * * @brief Contains declarations for the data block processor. */ /** * @struct sqfs_data_writer_t * * @brief Abstracts generating of file data and fragment blocks. * * This data structure provides a simple begin/append/end interface * to generate file data blocks (see @ref sqfs_data_writer_begin_file, * @ref sqfs_data_writer_append and @ref sqfs_data_writer_end respectively). * * Internally it takes care of partitioning data in the correct block sizes, * adding tail-ens to fragment blocks, compressing the data, deduplicating data * and finally writing it to disk. */ /** * @struct sqfs_block_hooks_t * * @brief A set of hooks for tapping into the data writer. * * This structure can be registered with an @ref sqfs_data_writer_t and * contains function pointers that will be called during various stages * when writing data to disk. * * The callbacks can not only be used for accounting but may also write extra * data to the output file or make modifications to the blocks before they are * writtien. * * The callbacks can be individually set to NULL to disable them. */ struct sqfs_block_hooks_t { /** * @brief Set this to the size of the struct. * * This is required for future expandabillity while maintaining ABI * compatibillity. At the current time, the implementation of * @ref sqfs_data_writer_set_hooks rejects any hook struct where this * isn't the exact size. If new hooks are added in the future, the * struct grows and the future implementation can tell by the size * whether the application uses the new version or the old one. */ size_t size; /** * @brief Gets called before writing a block to disk. * * If this is not NULL, it gets called before a block is written to * disk. If the block has the @ref SQFS_BLK_ALIGN flag set, the * function is called before padding the file. * * The function may modify the block itself or write data to the file. * which is taken into account when padding the file. * * @param user A user pointer. * @param block The block that is about to be written. * @param file The file that the block will be written to. */ void (*pre_block_write)(void *user, sqfs_block_t *block, sqfs_file_t *file); /** * @brief Gets called after writing a block to disk. * * If this is not NULL, it gets called after a block is written to * disk. If the block has the @ref SQFS_BLK_ALIGN flag set, the * function is called before padding the file. * * Modifying the block is rather pointless, but the function may * write data to the file which is taken into account when padding * the file. * * @param user A user pointer. * @param block The block that is about to be written. * @param file The file that the block was written to. */ void (*post_block_write)(void *user, const sqfs_block_t *block, sqfs_file_t *file); /** * @brief Gets called before storing a fragment in a fragment block. * * The function can modify the block before it is stored. * * @param user A user pointer. * @param block The data chunk that is about to be merged into the * fragment block. */ void (*pre_fragment_store)(void *user, sqfs_block_t *block); /** * @brief Gets called if block deduplication managed to get * rid of the data blocks of a file. * * @param user A user pointer. * @param count The number of blocks that have been erased. * @param bytes The number of bytes that have been erased. Includes * potential padding before and after the end. */ void (*notify_blocks_erased)(void *user, size_t count, sqfs_u64 bytes); /** * @brief Gets called before throwing away a fragment that turned out * to be a duplicate. * * @param user A user pointer. * @param block The data chunk that is about to be merged into the * fragment block. */ void (*notify_fragment_discard)(void *user, const sqfs_block_t *block); /** * @brief Gets called before writing a block of padding bytes to disk. * * @param user A user pointer. * @param block The padding bytes that are about to be written. * @param count The number of padding bytes in the block. */ void (*prepare_padding)(void *user, sqfs_u8 *block, size_t count); }; #ifdef __cplusplus extern "C" { #endif /** * @brief Create a data block writer. * * @memberof sqfs_data_writer_t * * @param max_block_size The maximum size of a data block. Required for the * internal scratch buffer used for compressing data. * @param cmp A pointer to a compressor. If multiple worker threads are used, * the deep copy function of the compressor is used to create * several instances that don't interfere with each other. * @param num_workers The number of worker threads to create. * @param max_backlog The maximum number of blocks currently in flight. When * trying to add more, enqueueing blocks until the in-flight * block count drops below the threshold. * @param devblksz File can optionally be allgined to device block size. This * specifies the desired alignment. * @param file The output file to write the finished blocks to. * * @return A pointer to a data writer object on success, NULL on allocation * failure or on failure to create and initialize the worker threads. */ SQFS_API sqfs_data_writer_t *sqfs_data_writer_create(size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file); /** * @brief Destroy a data writer and free all memory used by it. * * @memberof sqfs_data_writer_t * * @param proc A pointer to a data writer object. */ SQFS_API void sqfs_data_writer_destroy(sqfs_data_writer_t *proc); /** * @brief Start writing a file. * * @memberof sqfs_data_writer_t * * After calling this function, call @ref sqfs_data_writer_append repeatedly to * add data to the file. Finally call @ref sqfs_data_writer_end_file when you * are done. After writing all files, use @ref sqfs_data_writer_finish to wait * until all blocks that are still in flight are done and written to disk. * * The specified inode pointer is kept internally and updated with the * compressed block sizes and final destinations of the file and possible * fragment. You need to make sure it has enough backing-store for all blocks * to come. Furthermore, since there can still be blocks in-flight even after * calling @ref sqfs_data_writer_end_file, the data in the inode may still * change. The only point at which the data writer is guarnteed to not touch * them anymore is after @ref sqfs_data_writer_finish has returned. * * @param proc A pointer to a data writer object. * @param inode The regular file inode representing the file. The data writer * internally updates it while writing blocks to disk. * @param flags A combination of @ref E_SQFS_BLK_FLAGS that can be used to * micro manage how the data is processed. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_writer_begin_file(sqfs_data_writer_t *proc, sqfs_inode_generic_t *inode, sqfs_u32 flags); /** * @brief Append data to the current file. * * @memberof sqfs_data_writer_t * * Call this after @ref sqfs_data_writer_begin_file to add data to a file. * * @param proc A pointer to a data writer object. * @param data A pointer to a buffer to read data from. * @param size How many bytes should be copied out of the given * buffer and written to disk. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_writer_append(sqfs_data_writer_t *proc, const void *data, size_t size); /** * @brief Stop writing the current file and flush everything that is * buffered internally. * * @memberof sqfs_data_writer_t * * The counter part to @ref sqfs_data_writer_begin_file. * * Even after calling this, there might still be data blocks in-flight. * Use @ref sqfs_data_writer_finish when you are done writing files to force * the remaining blocks to be processed and written to disk. * * @param proc A pointer to a data writer object. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_writer_end_file(sqfs_data_writer_t *proc); /** * @brief Wait for the in-flight data blocks to finish and finally flush the * current fragment block. * * @memberof sqfs_data_writer_t * * @param proc A pointer to a block processor object. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. The failure * return value can either be an error encountered during enqueueing, * processing or writing to disk. */ SQFS_API int sqfs_data_writer_finish(sqfs_data_writer_t *proc); /** * @brief Write the completed fragment table to disk. * * @memberof sqfs_data_writer_t * * Call this after producing the inode and directory table to generate * the fragment table for the squashfs image. * * @param proc A pointer to a data writer object. * @param super A pointer to a super block to write information about the * fragment table to. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_data_writer_write_fragment_table(sqfs_data_writer_t *proc, sqfs_super_t *super); /** * @brief Register a set of hooks to be invoked when writing blocks to disk. * * @memberof sqfs_data_writer_t * * @param proc A pointer to a data writer object. * @param user_ptr A user pointer to pass to the callbacks. * @param hooks A structure containing the hooks. * * @return Zero on success, @ref SQFS_ERROR_UNSUPPORTED if the size field of * the hooks doesn't match any size knwon to the library. */ SQFS_API int sqfs_data_writer_set_hooks(sqfs_data_writer_t *proc, void *user_ptr, const sqfs_block_hooks_t *hooks); #ifdef __cplusplus } #endif #endif /* SFQS_DATA_WRITER_H */ squashfs-tools-ng-0.8/include/sqfs/dir.h000066400000000000000000000065771360235375500203340ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * dir.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_DIR_H #define SQFS_DIR_H #include "sqfs/predef.h" /** * @file dir.h * * @brief Contains on-disk data structures for the directory table and * declarations for the @ref sqfs_dir_writer_t. */ #define SQFS_MAX_DIR_ENT 256 /** * @struct sqfs_dir_header_t * * @brief On-disk data structure of a directory header * * See @ref sqfs_dir_writer_t for an overview on how SquashFS stores * directories on disk. */ struct sqfs_dir_header_t { /** * @brief The number of @ref sqfs_dir_entry_t entries that are * following. * * This value is stored off by one and the total count must not * exceed 256. */ sqfs_u32 count; /** * @brief The location of the meta data block containing the inodes for * the entries that follow, relative to the start of the inode * table. */ sqfs_u32 start_block; /** * @brief The inode number of the first entry. */ sqfs_u32 inode_number; }; /** * @struct sqfs_dir_entry_t * * @brief On-disk data structure of a directory entry. Many of these * follow a single @ref sqfs_dir_header_t. * * See @ref sqfs_dir_writer_t for an overview on how SquashFS stores * directories on disk. */ struct sqfs_dir_entry_t { /** * @brief An offset into the uncompressed meta data block containing * the coresponding inode. */ sqfs_u16 offset; /** * @brief Signed difference of the inode number from the one * in the @ref sqfs_dir_header_t. */ sqfs_s16 inode_diff; /** * @brief The @ref E_SQFS_INODE_TYPE value for the inode that this * entry represents. */ sqfs_u16 type; /** * @brief The size of the entry name * * This value is stored off-by-one. */ sqfs_u16 size; /** * @brief The name of the directory entry (no trailing null-byte). */ sqfs_u8 name[]; }; /** * @struct sqfs_dir_index_t * * @brief On-disk data structure of a directory index. A series of those * can follow an @ref sqfs_inode_dir_ext_t. * * See @ref sqfs_dir_writer_t for an overview on how SquashFS stores * directories on disk. */ struct sqfs_dir_index_t { /** * @brief Linear byte offset into the decompressed directory listing. */ sqfs_u32 index; /** * @brief Location of the meta data block, relative to the directory * table start. */ sqfs_u32 start_block; /** * @brief Size of the name of the first entry after the header. * * This value is stored off-by-one. */ sqfs_u32 size; /** * @brief Name of the name of the first entry after the header. * * No trailing null-byte. */ sqfs_u8 name[]; }; #endif /* SQFS_DIR_H */ squashfs-tools-ng-0.8/include/sqfs/dir_reader.h000066400000000000000000000232651360235375500216470ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * dir_reader.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_DIR_READER_H #define SQFS_DIR_READER_H #include "sqfs/predef.h" /** * @file dir_reader.h * * @brief Contains declarations for the @ref sqfs_dir_reader_t */ /** * @struct sqfs_dir_reader_t * * @brief Abstracts reading of directory entries * * SquashFS stores directory listings and inode structures separated from * each other in meta data blocks. * * The sqfs_dir_reader_t abstracts access to the filesystem tree in a SquashFS * through a fairly simple interface. It keeps two meta data readers internally * for reading directory listings and inodes. Externally, it offers a few * simple functions for iterating over the contents of a directory that * completely take care of fetching/decoding headers and sifting through the * multi level hierarchie used for storing them on disk. * * See @ref sqfs_dir_writer_t for an overview on how directory entries are * stored in SquashFS. * * The reader also abstracts easy access to the underlying inodes, allowing * direct access to the inode referred to by a directory entry. */ /** * @enum E_SQFS_TREE_FILTER_FLAGS * * @brief Filter flags for @ref sqfs_dir_reader_get_full_hierarchy */ typedef enum { /** * @brief Omit device special files from the final tree. */ SQFS_TREE_NO_DEVICES = 0x01, /** * @brief Omit socket files from the final tree. */ SQFS_TREE_NO_SOCKETS = 0x02, /** * @brief Omit named pipes from the final tree. */ SQFS_TREE_NO_FIFO = 0x04, /** * @brief Omit symbolic links from the final tree. */ SQFS_TREE_NO_SLINKS = 0x08, /** * @brief Omit empty directories from the final tree. * * If a directory is not empty on-disk, but ends up empty after * applying all the other filter rules, it is also omitted. */ SQFS_TREE_NO_EMPTY = 0x10, /** * @brief Do not recurse into sub directories. * * If the start node is a directory, the tree deserializer will still * recurse into it, but it will not go beyond that. */ SQFS_TREE_NO_RECURSE = 0x20, /** * @brief Store the list of parent nodes all the way to the target node * * When traversing towards the selected node, also collect the chain * of parent nodes with the subtree stored at the end. */ SQFS_TREE_STORE_PARENTS = 0x40, SQFS_TREE_ALL_FLAGS = 0x7F, } E_SQFS_TREE_FILTER_FLAGS; /** * @struct sqfs_tree_node_t * * @brief Encapsulates a node in the filesystem tree read by * @ref sqfs_dir_reader_get_full_hierarchy. */ struct sqfs_tree_node_t { /** * @brief Pointer to parent, NULL for the root node */ sqfs_tree_node_t *parent; /** * @brief For directories, a linked list of children. */ sqfs_tree_node_t *children; /** * @brief Linked list next pointer for children list. */ sqfs_tree_node_t *next; /** * @brief Inode representing this element in the tree. */ sqfs_inode_generic_t *inode; /** * @brief Resolved 32 bit user ID from the inode */ sqfs_u32 uid; /** * @brief Resolved 32 bit group ID from the inode */ sqfs_u32 gid; /** * @brief null-terminated entry name. */ sqfs_u8 name[]; }; #ifdef __cplusplus extern "C" { #endif /** * @brief Create a directory reader. * * @memberof sqfs_dir_reader_t * * @param super A pointer to the super block. Kept internally an used for * resolving table positions. * @param cmp A compressor to use for unpacking meta data blocks. * @param file The input file to read from. * * @return A new directory reader on success, NULL on allocation failure. */ SQFS_API sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super, sqfs_compressor_t *cmp, sqfs_file_t *file); /** * @brief Cleanup a directory reader and free all its memory. * * @memberof sqfs_dir_reader_t */ SQFS_API void sqfs_dir_reader_destroy(sqfs_dir_reader_t *rd); /** * @brief Navigate a directory reader to the location of a directory * represented by an inode. * * @memberof sqfs_dir_reader_t * * This function seeks to the meta data block containing the directory * listing that the given inode referes to and resets the internal state. * After that, consequtive cals to @ref sqfs_dir_reader_read can be made * to iterate over the directory contents. * * @param rd A pointer to a directory reader. * @param inode An directory or extended directory inode. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd, const sqfs_inode_generic_t *inode); /** * @brief Reset a directory reader back to the beginning of the listing. * * @memberof sqfs_dir_reader_t * * @param rd A pointer to a directory reader. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_rewind(sqfs_dir_reader_t *rd); /** * @brief Seek through the current directory listing to locate an * entry by name. * * @memberof sqfs_dir_reader_t * * @param rd A pointer to a directory reader. * @param name The name of the entry to find. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_find(sqfs_dir_reader_t *rd, const char *name); /** * @brief Read a directory entry and advance the internal position indicator * to the next one. * * @memberof sqfs_dir_reader_t * * Call this function repeatedly to iterate over a directory listing. It * returns a positive number to indicate that it couldn't fetch any more data * because the end of the listing was reached. A negative value indicates an * error. * * After calling this function, you can use @ref sqfs_dir_reader_get_inode to * read the full inode structure that the current entry referes to. * * @param rd A pointer to a directory reader. * @param out Returns a pointer to a directory entry on success that can be * freed with a single free call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure, a positive * number if the end of the current directory listing has been reached. */ SQFS_API int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_entry_t **out); /** * @brief Read the inode that the current directory entry points to. * * @memberof sqfs_dir_reader_t * * @param rd A pointer to a directory reader. * @param out Returns a pointer to a generic inode that can be freed with a * single free call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd, sqfs_inode_generic_t **inode); /** * @brief Read the root inode using the location given by the super block. * * @memberof sqfs_dir_reader_t * * @param rd A pointer to a directory reader. * @param out Returns a pointer to a generic inode that can be freed with a * single free call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd, sqfs_inode_generic_t **inode); /** * @brief Find an inode through path traversal from the root node downwards. * * @memberof sqfs_dir_reader_t * * @param rd A pointer to a directory reader. * @param path A path to resolve into an inode. Forward or backward slashes can * be used to separate path components. Resolving '.' or '..' is * not supported. * @param out Returns a pointer to a generic inode that can be freed with a * single free call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_find_by_path(sqfs_dir_reader_t *rd, const char *path, sqfs_inode_generic_t **out); /** * @brief High level helper function for deserializing the entire file system * hierarchy into an in-memory tree structure. * * @memberof sqfs_dir_reader_t * * This function internally navigates to a specified inode using * @ref sqfs_dir_reader_find_by_path and starting from that recursively * deserializes the entire hierarchy into a tree structure holding all inodes. * * @param rd A pointer to a directory reader. * @param path A path to resolve into an inode. Forward or backward slashes can * be used to separate path components. Resolving '.' or '..' is * not supported. Can be set to NULL to get the root inode. * @param flags A combination of @ref E_SQFS_TREE_FILTER_FLAGS flags. * @param out Returns the top most tree node. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd, const sqfs_id_table_t *idtbl, const char *path, sqfs_u32 flags, sqfs_tree_node_t **out); /** * @brief Recursively destroy a tree of @ref sqfs_tree_node_t nodes * * This function can be used to clean up after * @ref sqfs_dir_reader_get_full_hierarchy. * * @param root A pointer to the root node. */ SQFS_API void sqfs_dir_tree_destroy(sqfs_tree_node_t *root); #ifdef __cplusplus } #endif #endif /* SQFS_DIR_READER_H */ squashfs-tools-ng-0.8/include/sqfs/dir_writer.h000066400000000000000000000241571360235375500217220ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * dir_writer.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_DIR_WRITER_H #define SQFS_DIR_WRITER_H #include "sqfs/predef.h" /** * @file dir_writer.h * * @brief Contains declarations for the @ref sqfs_dir_writer_t. */ /** * @struct sqfs_dir_writer_t * * @brief Abstracts generating of directory entries * * SquashFS stores directory entries and inodes separated from each other. The * inodes are stored in a series of meta data blocks before another series of * meta data blocks that contain the directory entries. Directory inodes point * to meta data block (and offset) where its contents are listed and the * entries in turn point back to the inodes that represent them. * * There are some rules to this. Directory entries have to be written in * ASCIIbetical ordering. Up to 256 entries are preceeded by a header. The * entries use delta encoding for inode numbers and block locations relative to * the header, so every time the inodes cross a meta data block boundary, if * the difference in inode number gets too large, or if the entry count would * exceed 256, a new header has to be emitted. Even if the inode pointed to is * an extended type, the entry in the header still has to indicate the base * type. * * In addtion to that, extended directory inodes can contain an index for * faster lookup. The index points to each header and requires a new header to * be emitted if the entries cross a block boundary. * * The dir writer takes care of all of this and provides a simple interface for * adding entries. Internally it fills data into a meta data writer and * generates an index that it can, on request, write to another meta data * writer used for inodes. */ /** * @enum SQFS_DIR_WRITER_CREATE_FLAGS * * @brief Flags that can be set for @ref sqfs_dir_writer_create */ typedef enum { /** * @brief Record all inode locations to create an export table. * * For NFS export support, SquashFS needs an extra table that maps * inode numbers directly to on-disk locations. * * Since the @ref sqfs_dir_writer_t "sees" all inode numbers and * coresponding locations and easily create such a table. * * If this flag is set for @ref sqfs_dir_writer_create, the result * directory wrter collects such a table which it can then write to * disk using @ref sqfs_dir_writer_write_export_table. */ SQFS_DIR_WRITER_CREATE_EXPORT_TABLE = 0x01, SQFS_DIR_WRITER_CREATE_ALL_FLAGS = 0x01 } SQFS_DIR_WRITER_CREATE_FLAGS; #ifdef __cplusplus extern "C" { #endif /** * @brief Create a directory writer. * * @memberof sqfs_dir_writer_t * * @param dm A pointer to a meta data writer that the generated directory * entries should be written to. * @param flags A combination of @ref SQFS_DIR_WRITER_CREATE_FLAGS. * * @return A pointer to a directory writer on success, NULL on * allocation failure or if flags has unknown flags set. */ SQFS_API sqfs_dir_writer_t *sqfs_dir_writer_create(sqfs_meta_writer_t *dm, sqfs_u32 flags); /** * @brief Destroy a directory writer and free all its memory. * * @memberof sqfs_dir_writer_t * * @param writer A pointer to a directory writer object. */ SQFS_API void sqfs_dir_writer_destroy(sqfs_dir_writer_t *writer); /** * @brief Begin writing a directory, i.e. reset and initialize all internal * state neccessary. * * @memberof sqfs_dir_writer_t * * @param writer A pointer to a directory writer object. * @param flags A currently unused flag field. Must be set to 0. * * @return Zero on success, a @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_writer_begin(sqfs_dir_writer_t *writer, sqfs_u32 flags); /** * @brief Add add a directory entry. * * @memberof sqfs_dir_writer_t * * @param writer A pointer to a directory writer object. * @param name The name of the directory entry. * @param inode_num The inode number of the entry. * @param inode_ref A reference to the inode, i.e. the meta data block offset * is stored in bits 16 to 48 and the lower 16 bit hold an * offset into the block. * @param mode A file mode, i.e. type and permission bits from which the entry * type is derived internally. * * @return Zero on success, a @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_writer_add_entry(sqfs_dir_writer_t *writer, const char *name, sqfs_u32 inode_num, sqfs_u64 inode_ref, sqfs_u16 mode); /** * @brief Finish writing a directory listing and write everything out to the * meta data writer. * * @memberof sqfs_dir_writer_t * * @param writer A pointer to a directory writer object. * * @return Zero on success, a @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_writer_end(sqfs_dir_writer_t *writer); /** * @brief Get the total, uncompressed size of the last written * directory in bytes. * * @memberof sqfs_dir_writer_t * * Call this function after @ref sqfs_dir_writer_end to get the uncompressed * size of the directory listing that is required for the directory inodes. * And also to determine which kind of directory inode to create. * * @param writer A pointer to a directory writer object. * * @return The size of the entire, uncompressed listing in bytes. */ SQFS_API size_t sqfs_dir_writer_get_size(const sqfs_dir_writer_t *writer); /** * @brief Get the numer of entries written to the last directory. * * @memberof sqfs_dir_writer_t * * Call this function after @ref sqfs_dir_writer_end to get the total * number of entries written to the directory. * * @param writer A pointer to a directory writer object. * * @return The number of entries in the directory. */ SQFS_API size_t sqfs_dir_writer_get_entry_count(const sqfs_dir_writer_t *writer); /** * @brief Get the location of the last written directory. * * @memberof sqfs_dir_writer_t * * Call this function after @ref sqfs_dir_writer_end to get the location of * the directory listing that is required for the directory inodes. * * @param writer A pointer to a directory writer object. * * @return A meta data reference, i.e. bits 16 to 48 contain the block start * and the lower 16 bit an offset into the uncompressed block. */ SQFS_API sqfs_u64 sqfs_dir_writer_get_dir_reference(const sqfs_dir_writer_t *writer); /** * @brief Get the size of the index of the last written directory. * * @memberof sqfs_dir_writer_t * * Call this function after @ref sqfs_dir_writer_end to get the size of * the directory index that is required for extended directory inodes. * * @param writer A pointer to a directory writer object. * * @return The number of index entries. */ SQFS_API size_t sqfs_dir_writer_get_index_size(const sqfs_dir_writer_t *writer); /** * @brief Helper function for creating an inode from the last directory. * * @memberof sqfs_dir_writer_t * * Call this function after @ref sqfs_dir_writer_end to create a bare bones * inode structure for the directory. The directory information is filled in * completely and the type is set, the rest of the basic information such as * permission bits, owner and timestamp is left untouched. * * If the generated inode is an extended directory inode, you can use another * convenience function called @ref sqfs_dir_writer_write_index to write the * index meta data after writing the inode itself. * * @param writer A pointer to a directory writer object. * @param hlinks The number of hard links pointing to the directory. * @param xattr If set to something other than 0xFFFFFFFF, an extended * directory inode is created with xattr index set. * @param parent_ino The inode number of the parent directory. * * @return A generic inode or NULL on allocation failure. */ SQFS_API sqfs_inode_generic_t *sqfs_dir_writer_create_inode(const sqfs_dir_writer_t *writer, size_t hlinks, sqfs_u32 xattr, sqfs_u32 parent_ino); /** * @brief Write an export table to a SquashFS image. * * @memberof sqfs_dir_writer_t * * If the @ref sqfs_dir_writer_t was created with the * @ref SQFS_DIR_WRITER_CREATE_EXPORT_TABLE flag set, it has an internal table * that maps all inode numbers to inode references. After writing the fragment * table, this function can be used to write this inode mapping table for NFS * export support. * * It is safe to call this function if the writer has been created without the * flag. In this case, it is simply a noop. * * In theory, the writer "sees" the entire directory tree and for each entry, * the inode number and on-disk location, so it can build this table. The only * inode it never sees is the root inode, so that information has to be passed * to this function to add it to the table just before writing it to disk. * * @param writer A pointer to a directory writer object. * @param file The ouput file to write the table to. * @param cmp The compressor to use to compress the table. * @param root_inode_num The inode number of the root inode. * @param root_inode_ref An inode reference for the root inode. * @param super A pointer to the super block. Location of the export table and * the exportable flag are set. * * @return Zero on success, a @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_dir_writer_write_export_table(sqfs_dir_writer_t *writer, sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u32 root_inode_num, sqfs_u64 root_inode_ref, sqfs_super_t *super); #ifdef __cplusplus } #endif #endif /* SQFS_DIR_WRITER_H */ squashfs-tools-ng-0.8/include/sqfs/error.h000066400000000000000000000074611360235375500207000ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * error.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_ERROR_H #define SQFS_ERROR_H /** * @file error.h * * @brief Contains the @ref E_SQFS_ERROR enumerator. */ /** * @enum E_SQFS_ERROR * * @brief Error codes that can be returned by various libsquashfs functions. */ typedef enum { /** * @brief Allocation using malloc or calloc failed (returned NULL). */ SQFS_ERROR_ALLOC = -1, /** * @brief Generic I/O error if a file read or write operation failed. */ SQFS_ERROR_IO = -2, /** * @brief Generic compressor error returned if compressing data failed * (some kind of internal error) or extracting failed (typically * means the data is corrupted). */ SQFS_ERROR_COMPRESSOR = -3, /** * @brief An internal error of the "this wasn't supposed to happen" * kind that cannot easily be mapped to something usefull. */ SQFS_ERROR_INTERNAL = -4, /** * @brief Attempted to read an on-disk data structure that appears to * be corrupted, i.e. contains obvious non-sense values. */ SQFS_ERROR_CORRUPTED = -5, /** * @brief Attempted to use an unsupported feature (e.g. an unknown * compressor or xattr type). */ SQFS_ERROR_UNSUPPORTED = -6, /** * @brief Attempted to read a data structure into memory would * overflow the addressable memory. Usually indicates a * corrupted or maliciously manipulated SquashFS filesystem. */ SQFS_ERROR_OVERFLOW = -7, /** * @brief Attempted to perform an out-of-bounds read. If this happens * when following a reference stored in a data structure, it * usually indicates a corrupted or maliciously manipulated * SquashFS filesystem. */ SQFS_ERROR_OUT_OF_BOUNDS = -8, /** * @brief Specific error when reading the super block. * * Could not find the magic. */ SFQS_ERROR_SUPER_MAGIC = -9, /** * @brief Specific error when reading the super block. * * The version indicated be the filesystem is not supported. */ SFQS_ERROR_SUPER_VERSION = -10, /** * @brief Specific error when reading or initializing the super block. * * The block size specified is either not a power of 2, or outside the * legal range (4k to 1M). */ SQFS_ERROR_SUPER_BLOCK_SIZE = -11, /** * @brief Expected a directory (inode), found something else instead. * * Generated when trying to resolve a path but a part of the the path * turned out to not be a directory. Also generated when trying to * read directory entries from something that isn't a directory. */ SQFS_ERROR_NOT_DIR = -12, /** * @brief A specified path, or a part of it, does not exist. */ SQFS_ERROR_NO_ENTRY = -13, /** * @brief Detected a hard link loop while walking a filesystem tree. */ SQFS_ERROR_LINK_LOOP = -14, /** * @brief Tried to perform an file operation on something that isn't * a regular file or a regular file inode. */ SQFS_ERROR_NOT_FILE = -15, /** * @brief An invalid argument was passed to a library function. */ SQFS_ERROR_ARG_INVALID = -16, } E_SQFS_ERROR; #endif /* SQFS_ERROR_H */ squashfs-tools-ng-0.8/include/sqfs/id_table.h000066400000000000000000000075671360235375500213210ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * id_table.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_ID_TABLE_H #define SQFS_ID_TABLE_H #include "sqfs/predef.h" /** * @file id_table.h * * @brief Contains declarations for the @ref sqfs_id_table_t data structure. */ /** * @struct sqfs_id_table_t * * @brief A simple data structure that encapsulates ID to index mapping for * user and group IDs. * * SquashFS does not store user and group IDs in inodes directly. Instead, it * collects the unique 32 bit IDs in a table with at most 64k entries and * stores a 16 bit index into the inode. This allows SquashFS to only have 16 * bit UID/GID entries in the inodes but actually have 32 bit UIDs/GIDs under * the hood (at least 64k selected ones). */ #ifdef __cplusplus extern "C" { #endif /** * @brief Create an ID table object. * * @memberof sqfs_id_table_t * * @return A pointer to an ID table object, NULL on allocation failure. */ SQFS_API sqfs_id_table_t *sqfs_id_table_create(void); /** * @brief Destroy an ID table object and free all memory used by it. * * @memberof sqfs_id_table_t * * @param tbl A pointer to an ID table object. */ SQFS_API void sqfs_id_table_destroy(sqfs_id_table_t *tbl); /** * @brief Resolve a 32 bit ID to a unique 16 bit index. * * @memberof sqfs_id_table_t * * @param tbl A pointer to an ID table object. * @param id The ID to resolve. * @param out Returns the unique table index. * * @return Zero on success, an @ref E_SQFS_ERROR on failure. */ SQFS_API int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, sqfs_u32 id, sqfs_u16 *out); /** * @brief Write an ID table to disk. * * @memberof sqfs_id_table_t * * @param tbl A pointer to an ID table object. * @param file The underlying file to append the table to. * @param super A pointer to a super block in which to store the ID table * start location. * @param cmp A compressor to use to compress the ID table. * * @return Zero on success, an @ref E_SQFS_ERROR on failure. */ SQFS_API int sqfs_id_table_write(sqfs_id_table_t *tbl, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); /** * @brief Read an ID table from disk. * * @memberof sqfs_id_table_t * * @param tbl A pointer to an ID table object. * @param file The underlying file to read the table from. * @param super A pointer to a super block from which to get * the ID table location. * @param cmp A compressor to use to extract compressed table blocks. * * @return Zero on success, an @ref E_SQFS_ERROR on failure. */ SQFS_API int sqfs_id_table_read(sqfs_id_table_t *tbl, sqfs_file_t *file, const sqfs_super_t *super, sqfs_compressor_t *cmp); /** * @brief Resolve a 16 bit index to a 32 bit ID. * * @memberof sqfs_id_table_t * * @param tbl A pointer to an ID table object. * @param index The table index to resolve. * @param out Returns the underlying 32 bit ID that the index maps to. * * @return Zero on success, an @ref E_SQFS_ERROR on failure. */ SQFS_API int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, sqfs_u16 index, sqfs_u32 *out); #ifdef __cplusplus } #endif #endif /* SQFS_ID_TABLE_H */ squashfs-tools-ng-0.8/include/sqfs/inode.h000066400000000000000000000425361360235375500206470ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * inode.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_INODE_H #define SQFS_INODE_H #include "sqfs/predef.h" /** * @file inode.h * * @brief Contains on-disk data structures used for inodes. */ /** * @enum E_SQFS_INODE_TYPE * * @brief Used by @ref sqfs_inode_t to identify the inode type. */ typedef enum { SQFS_INODE_DIR = 1, SQFS_INODE_FILE = 2, SQFS_INODE_SLINK = 3, SQFS_INODE_BDEV = 4, SQFS_INODE_CDEV = 5, SQFS_INODE_FIFO = 6, SQFS_INODE_SOCKET = 7, SQFS_INODE_EXT_DIR = 8, SQFS_INODE_EXT_FILE = 9, SQFS_INODE_EXT_SLINK = 10, SQFS_INODE_EXT_BDEV = 11, SQFS_INODE_EXT_CDEV = 12, SQFS_INODE_EXT_FIFO = 13, SQFS_INODE_EXT_SOCKET = 14, } E_SQFS_INODE_TYPE; /** * @enum E_SQFS_INODE_MODE * * @brief Mode bits for the @ref sqfs_inode_t mode field. * * This is basically the same that mode bits in struct stat store on Unix-like * systems. It is duplicated here for portability with non-POSIX platforms. In * case you are not familiar with Unix file permissions, a brief description * follows. * * There are 3 fields with permissions: * - of the user that owns the file * - of the group that the file belongs to * - everybody else * * Each field holds 3 bits: X, W and R meaning execute, write and read access * respectively. There are 2 special cases: On a directory, execute means * entering the directory and accessing its contents. Read and write refere * to reading or changing the list of entries. For symlinks, the permissions * are meaningless and have all bits set. * * Besides the permissions, there are 3 more bits: * - sticky * - set group id * - set user id * * Nowadays, the later two mean executing a program makes it run as the group * or user (respectively) that owns it instead of the user that actually ran * the program. On directories, the sticky bit means that its contents can only * be deleted by the actual owner, even if others have write permissions. All * other uses of those bits are obscure, historic and differ between flavours * of Unix. * * The remaining 4 bits (adding up to a total of 16) specify the type of file: * - named pipe, aka fifo * - character device * - directory * - block device * - regular file * - symlink * - socket */ typedef enum { SQFS_INODE_OTHERS_X = 00001, SQFS_INODE_OTHERS_W = 00002, SQFS_INODE_OTHERS_R = 00004, SQFS_INODE_OTHERS_MASK = 00007, SQFS_INODE_GROUP_X = 00010, SQFS_INODE_GROUP_W = 00020, SQFS_INODE_GROUP_R = 00040, SQFS_INODE_GROUP_MASK = 00070, SQFS_INODE_OWNER_X = 00100, SQFS_INODE_OWNER_W = 00200, SQFS_INODE_OWNER_R = 00400, SQFS_INODE_OWNER_MASK = 00700, SQFS_INODE_STICKY = 01000, SQFS_INODE_SET_GID = 02000, SQFS_INODE_SET_UID = 04000, SQFS_INODE_MODE_FIFO = 0010000, SQFS_INODE_MODE_CHR = 0020000, SQFS_INODE_MODE_DIR = 0040000, SQFS_INODE_MODE_BLK = 0060000, SQFS_INODE_MODE_REG = 0100000, SQFS_INODE_MODE_LNK = 0120000, SQFS_INODE_MODE_SOCK = 0140000, SQFS_INODE_MODE_MASK = 0170000, } E_SQFS_INODE_MODE; /** * @struct sqfs_inode_t * * @brief Common inode structure * * This structure holds the fields common for all inodes. Depending on the type * field, a specific inode structure follows. */ struct sqfs_inode_t { /** * @brief An @ref E_SQFS_INODE_TYPE value. */ sqfs_u16 type; /** * @brief Mode filed holding permission bits only. The type is derived * from the type field. * * This field holds a combination of @ref E_SQFS_INODE_MODE flags. */ sqfs_u16 mode; /** * @brief An index into the ID table where the owner UID is located. */ sqfs_u16 uid_idx; /** * @brief An index into the ID table where the owner GID is located. */ sqfs_u16 gid_idx; /** * @brief Last modifcation time. * * This field counts seconds (not counting leap seconds) since 00:00, * Jan 1 1970 UTC. This field is unsigned, so it expires in the year * 2106 (as opposed to 2038). */ sqfs_u32 mod_time; /** * @brief Unique inode number */ sqfs_u32 inode_number; }; /** * @struct sqfs_inode_dev_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_BDEV * or @ref SQFS_INODE_CDEV. */ struct sqfs_inode_dev_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Device number. */ sqfs_u32 devno; }; /** * @struct sqfs_inode_dev_ext_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_EXT_BDEV * or @ref SQFS_INODE_EXT_CDEV. */ struct sqfs_inode_dev_ext_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Device number. */ sqfs_u32 devno; /** * @brief Extended attribute index. */ sqfs_u32 xattr_idx; }; /** * @struct sqfs_inode_ipc_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_FIFO * or @ref SQFS_INODE_SOCKET. */ struct sqfs_inode_ipc_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; }; /** * @struct sqfs_inode_ipc_ext_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_EXT_FIFO * or @ref SQFS_INODE_EXT_SOCKET. */ struct sqfs_inode_ipc_ext_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Extended attribute index. */ sqfs_u32 xattr_idx; }; /** * @struct sqfs_inode_slink_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_SLINK. * * The declaration does not contain the flexible array member of the symlink * target because @ref sqfs_inode_generic_t would otherwies be impossible to * implement without violating the C standard. */ struct sqfs_inode_slink_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Size of the symlink target in bytes */ sqfs_u32 target_size; /*sqfs_u8 target[];*/ }; /** * @struct sqfs_inode_slink_ext_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_EXT_SLINK. * * The declaration does not contain the flexible array member of the symlink * target because it is wedged right in between the target size and the xattr * identifier. */ struct sqfs_inode_slink_ext_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Size of the symlink target in bytes */ sqfs_u32 target_size; /*sqfs_u8 target[];*/ /** * @brief Extended attribute index. */ sqfs_u32 xattr_idx; }; /** * @struct sqfs_inode_file_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_FILE. * * The declaration does not contain the flexible array member for the data * block sizes because @ref sqfs_inode_generic_t would otherwies be impossible * to implement without violating the C standard. * * For each data block, the inode is followed by a 32 bit integer that holds * the on-disk size of the compressed block in bytes and has bit number 24 * set if the block is stored uncompressed. * * If a block size is specified as zero, it is assumed to be an entire block * filled with zero bytes. */ struct sqfs_inode_file_t { /** * @brief Absolute position of the first data block. */ sqfs_u32 blocks_start; /** * @brief Index into the fragment table or 0xFFFFFFFF if unused. */ sqfs_u32 fragment_index; /** * @brief Offset into the uncompressed fragment block or 0xFFFFFFFF * if unused. */ sqfs_u32 fragment_offset; /** * @brief Total, uncompressed size of the file in bytes. */ sqfs_u32 file_size; /*sqfs_u32 block_sizes[];*/ }; /** * @struct sqfs_inode_file_ext_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_EXT_FILE. * * @copydoc sqfs_inode_file_t */ struct sqfs_inode_file_ext_t { /** * @brief Absolute position of the first data block. */ sqfs_u64 blocks_start; /** * @brief Total, uncompressed size of the file in bytes. */ sqfs_u64 file_size; /** * @brief If the file is sparse, holds the number of bytes not written * to disk because of the omitted sparse blocks. */ sqfs_u64 sparse; /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Index into the fragment table or 0xFFFFFFFF if unused. */ sqfs_u32 fragment_idx; /** * @brief Offset into the uncompressed fragment block or 0xFFFFFFFF * if unused. */ sqfs_u32 fragment_offset; /** * @brief Extended attribute index. */ sqfs_u32 xattr_idx; /*sqfs_u32 block_sizes[];*/ }; /** * @struct sqfs_inode_dir_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_DIR. */ struct sqfs_inode_dir_t { /** * @brief Offset from the directory table start to the location of the * meta data block containing the first directory header. */ sqfs_u32 start_block; /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Combined size of all directory entries and headers in bytes. */ sqfs_u16 size; /** * @brief Offset into the uncompressed start block where the header can * be found. */ sqfs_u16 offset; /** * @brief Inode number of the parent directory containing * this directory inode. */ sqfs_u32 parent_inode; }; /** * @struct sqfs_inode_dir_ext_t * * @brief Follows a @ref sqfs_inode_t if type is @ref SQFS_INODE_EXT_DIR. */ struct sqfs_inode_dir_ext_t { /** * @brief Number of hard links to this node. */ sqfs_u32 nlink; /** * @brief Combined size of all directory entries and headers in bytes. */ sqfs_u32 size; /** * @brief Offset from the directory table start to the location of the * meta data block containing the first directory header. */ sqfs_u32 start_block; /** * @brief Inode number of the parent directory containing * this directory inode. */ sqfs_u32 parent_inode; /** * @brief Number of directory index entries following the inode * * This number is stored off-by one and counts the number of * @ref sqfs_dir_index_t entries following the inode. */ sqfs_u16 inodex_count; /** * @brief Offset into the uncompressed start block where the header can * be found. */ sqfs_u16 offset; /** * @brief Extended attribute index. */ sqfs_u32 xattr_idx; }; /** * @struct sqfs_inode_generic_t * * @brief A generic inode structure that combines all others and provides * additional information. * * A few helper functions exist for working with this. For instance, * @ref sqfs_meta_reader_read_inode can read an inode from disk and assemble it * into an instance of this structure. Similarly, the * @ref sqfs_meta_writer_write_inode function can break it down into encoded, * on-disk structures and write them to disk. */ struct sqfs_inode_generic_t { /** * @brief The common fields for all inodes. */ sqfs_inode_t base; /** * @brief A pointer into the extra field holding the symlink target. * * @param This string is not null terminated. The helper functions rely * entirely on the length stored in the symlink inode. */ char *slink_target; /** * @brief A pointer into the extra field holding file blocks sizes. * * For file inodes, holds the consecutive block sizes. Bit number 24 is * set if the block is stored uncompressed. If it the size is zero, * the block is sparse. */ sqfs_u32 *block_sizes; /** * @brief For file inodes, stores the number of blocks used. */ size_t num_file_blocks; /** * @brief For extended directory inodes, stores the number of payload * bytes following for the directory index. */ size_t num_dir_idx_bytes; /** * @brief Type specific inode data. */ union { sqfs_inode_dev_t dev; sqfs_inode_dev_ext_t dev_ext; sqfs_inode_ipc_t ipc; sqfs_inode_ipc_ext_t ipc_ext; sqfs_inode_slink_t slink; sqfs_inode_slink_ext_t slink_ext; sqfs_inode_file_t file; sqfs_inode_file_ext_t file_ext; sqfs_inode_dir_t dir; sqfs_inode_dir_ext_t dir_ext; } data; /** * @brief Holds type specific extra data, such as symlink target. */ sqfs_u8 extra[]; }; #ifdef __cplusplus extern "C" { #endif /** * @brief Get the extended attribute index of an inode * * For basic inodes, this returns the inode index 0xFFFFFFFF, i.e. the * sentinel value indicating that there are no xattrs. * * @param inode A pointer to an inode. * @param out Returns the extended attribute index on success. * * @return Zero on success, an @ref SQFS_ERROR_CORRUPTED if the node has * an unknown type set. */ SQFS_API int sqfs_inode_get_xattr_index(const sqfs_inode_generic_t *inode, sqfs_u32 *out); /** * @brief Set the extended attribute index of an inode. * * For basic inodes, this function promes the inodes to extended inodes if the * index is not 0xFFFFFFFF. If the index is 0xFFFFFFFF, the function tries to * demote extended inode to a basic inode after setting the index. * * @param inode A pointer to an inode. * @param index The extended attribute index. * * @return Zero on success, an @ref SQFS_ERROR_CORRUPTED if the node has * an unknown type set. */ SQFS_API int sqfs_inode_set_xattr_index(sqfs_inode_generic_t *inode, sqfs_u32 index); /** * @brief Convert a basic inode to an extended inode. * * For inodes that already have an extended type, this is a no-op. * * @param inode A pointer to an inode. * * @return Zero on success, an @ref SQFS_ERROR_CORRUPTED if the node has * an unknown type set. */ SQFS_API int sqfs_inode_make_extended(sqfs_inode_generic_t *inode); /** * @brief Convert an extended inode to a basic inode if possible. * * For inodes that already have a basic type, this is a no-op. If the inode * has values set that the coresponding basic type doesn't support (e.g. it * has an xattr index set or a regular file which requires 64 bit size * counter), it is left as an extended type and success state is returned. * * @param inode A pointer to an inode. * * @return Zero on success, an @ref SQFS_ERROR_CORRUPTED if the node has * an unknown type set. */ SQFS_API int sqfs_inode_make_basic(sqfs_inode_generic_t *inode); /** * @brief Update the file size of a regular file inode. * * If the new size is wider than 32 bit, a basic file inode is transparently * promoted to an extended file inode. For extended inodes, if the new size * is small enough and was the only requirement for the extended type, the * node is transparently demoted to a basic file inode. * * @param inode A pointer to an inode. * @param size The new size to set. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_set_file_size(sqfs_inode_generic_t *inode, sqfs_u64 size); /** * @brief Update the location of the first data block of a regular file inode. * * If the new location is wider than 32 bit, a basic file inode is * transparently promoted to an extended file inode. For extended inodes, * if the new size is small enough and was the only requirement for the * extended type, the node is transparently demoted to a basic file inode. * * @param inode A pointer to an inode. * @param location The new location to set. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_set_file_block_start(sqfs_inode_generic_t *inode, sqfs_u64 location); /** * @brief Update the file fragment location of a regular file inode. * * @param inode A pointer to an inode. * @param index The new fragment index to set. * @param offset The new fragment offset to set. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_set_frag_location(sqfs_inode_generic_t *inode, sqfs_u32 index, sqfs_u32 offset); /** * @brief Get the file size of a regular file inode. * * @param inode A pointer to an inode. * @param size Returns the file size. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_get_file_size(const sqfs_inode_generic_t *inode, sqfs_u64 *size); /** * @brief Get the file fragment location of a regular file inode. * * @param inode A pointer to an inode. * @param index Returns the fragment index. * @param offset Returns the fragment offset. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_get_frag_location(const sqfs_inode_generic_t *inode, sqfs_u32 *index, sqfs_u32 *offset); /** * @brief Get the location of the first data block of a regular file inode. * * @param inode A pointer to an inode. * @param location Returns the location. * * @return Zero on success, @ref SQFS_ERROR_NOT_FILE if the node is * not a regular file. */ SQFS_API int sqfs_inode_get_file_block_start(const sqfs_inode_generic_t *inode, sqfs_u64 *location); #ifdef __cplusplus } #endif #endif /* SQFS_INODE_H */ squashfs-tools-ng-0.8/include/sqfs/io.h000066400000000000000000000107611360235375500201530ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * io.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_IO_H #define SQFS_IO_H #include "sqfs/predef.h" /** * @file io.h * * @brief Contains the @ref sqfs_file_t interface for abstracting file I/O */ /** * @enum E_SQFS_FILE_OPEN_FLAGS * * @brief Flags for @ref sqfs_open_file */ typedef enum { /** * @brief If set, access the file for reading only * * If not set, the file is expected to have a zero size after opening * which can be grown with successive writes to end of the file. * * Opening an existing file with this flag cleared results in failure, * unless the @ref SQFS_FILE_OPEN_OVERWRITE flag is also set. */ SQFS_FILE_OPEN_READ_ONLY = 0x01, /** * @brief If the read only flag is not set, overwrite any * existing file. * * If the file alrady exists, it is truncated to zero bytes size and * overwritten. */ SQFS_FILE_OPEN_OVERWRITE = 0x02, SQFS_FILE_OPEN_ALL_FLAGS = 0x03, } E_SQFS_FILE_OPEN_FLAGS; /** * @interface sqfs_file_t * * @brief Abstracts file I/O to make it easy to embedd SquashFS. */ struct sqfs_file_t { /** * @brief Close the file and destroy the interface implementation. * * @param file A pointer to the file object. */ void (*destroy)(sqfs_file_t *file); /** * @brief Read a chunk of data from an absolute position. * * @param file A pointer to the file object. * @param offset An absolute offset to read data from. * @param buffer A pointer to a buffer to copy the data to. * @param size The number of bytes to read from the file. * * @return Zero on success, an @ref E_SQFS_ERROR identifier on failure * that the data structures in libsquashfs that use this return * directly to the caller. */ int (*read_at)(sqfs_file_t *file, sqfs_u64 offset, void *buffer, size_t size); /** * @brief Write a chunk of data at an absolute position. * * @param file A pointer to the file object. * @param offset An absolute offset to write data to. * @param buffer A pointer to a buffer to write to the file. * @param size The number of bytes to write from the buffer. * * @return Zero on success, an @ref E_SQFS_ERROR identifier on failure * that the data structures in libsquashfs that use this return * directly to the caller. */ int (*write_at)(sqfs_file_t *file, sqfs_u64 offset, const void *buffer, size_t size); /** * @brief Get the number of bytes currently stored in the file. * * @param file A pointer to the file object. */ sqfs_u64 (*get_size)(const sqfs_file_t *file); /** * @brief Extend or shrink a file to a specified size. * * @param file A pointer to the file object. * @param size The new capacity of the file in bytes. * * @return Zero on success, an @ref E_SQFS_ERROR identifier on failure * that the data structures in libsquashfs that use this return * directly to the caller. */ int (*truncate)(sqfs_file_t *file, sqfs_u64 size); }; #ifdef __cplusplus extern "C" { #endif /** * @brief Open a file through the operating systems filesystem API * * This function internally creates an instance of a reference implementation * of the @ref sqfs_file_t interface that uses the operating systems native * API for file I/O. * * On Unix-like systems, if the open call fails, this function makes sure to * preserves the value in errno indicating the underlying problem. * * @param filename The name of the file to open. * @param flags A set of @ref E_SQFS_FILE_OPEN_FLAGS. * * @return A pointer to a file object on success, NULL on allocation failure, * failure to open the file or if an unknown flag was set. */ SQFS_API sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags); #ifdef __cplusplus } #endif #endif /* SQFS_IO_H */ squashfs-tools-ng-0.8/include/sqfs/meta_reader.h000066400000000000000000000143211360235375500220100ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * meta_reader.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_META_READER_H #define SQFS_META_READER_H #include "sqfs/predef.h" /** * @file meta_reader.h * * @brief Contains declarations for the @ref sqfs_meta_reader_t. */ /** * @struct sqfs_meta_reader_t * * @brief Abstracts reading of meta data blocks. * * SquashFS stores meta data by dividing it into fixed size (8k) chunks * that are written to disk with a small header indicating the on-disk * size and whether it is compressed or not. * * Data written to meta data blocks doesn't have to be aligned, i.e. * SquashFS doesn't care if an object is written across two blocks. * * The main task of the meta data read is to provide a simple read and seek * functions that transparently take care of fetching and uncompressing blocks * from disk and reading transparently across block boarders if required. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Create a meta data reader * * @memberof sqfs_meta_reader_t * * @param file A pointer to a file object to read from * @param cmp A compressor to use for unpacking compressed meta data blocks * @param start A lower limit for the blocks to be read. Every seek to an offset * below that is interpreted as an out-of-bounds read. * @param limit An upper limit for the blocks to read. Every seek to an offset * afer that is interpreted as an out-of-bounds read. * * @return A pointer to a meta data reader on success, NULL on * allocation failure. */ SQFS_API sqfs_meta_reader_t *sqfs_meta_reader_create(sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u64 start, sqfs_u64 limit); /** * @brief Destroy a meta data reader and free all memory used by it. * * @memberof sqfs_meta_reader_t * * @param m A pointer to a meta data reader. */ SQFS_API void sqfs_meta_reader_destroy(sqfs_meta_reader_t *m); /** * @brief Seek to a specific meta data block and offset. * * @memberof sqfs_meta_reader_t * * The underlying block is fetched from disk and uncompressed, unless it * already is the current block. * * @param m A pointer to a meta data reader. * @param block_start Absolute position where the block header can be found. * @param offset A byte offset into the uncompressed block. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, sqfs_u64 block_start, size_t offset); /** * @brief Get the current position that the next read will read from. * * @memberof sqfs_meta_reader_t * * @param m A pointer to a meta data reader. * @param block_start Absolute position where the current block is. * @param offset A byte offset into the uncompressed block. */ SQFS_API void sqfs_meta_reader_get_position(const sqfs_meta_reader_t *m, sqfs_u64 *block_start, size_t *offset); /** * @brief Read a chunk of data from a meta data reader. * * @memberof sqfs_meta_reader_t * * If the meta data reader reaches the end of the current block before filling * the destination buffer, it transparently reads the next block from disk and * uncompresses it. * * @param m A pointer to a meta data reader. * @param data A pointer to copy the data to. * @param size The numbre of bytes to read. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_reader_read(sqfs_meta_reader_t *m, void *data, size_t size); /** * @brief Read and decode a directory header from a meta data reader. * * @memberof sqfs_meta_reader_t * * This is a convenience function on to of @ref sqfs_meta_reader_read that * reads and decodes a directory header from a meta data block. * * @param m A pointer to a meta data reader. * @param hdr A pointer to a directory header to fill. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_reader_read_dir_header(sqfs_meta_reader_t *m, sqfs_dir_header_t *hdr); /** * @brief Read and decode a directory header from a meta data reader. * * @memberof sqfs_meta_reader_t * * This is a convenience function on to of @ref sqfs_meta_reader_read that * reads and decodes a directory entry. * * @param m A pointer to a meta data reader. * @param ent Returns a pointer to a directory entry. Can be released with a * single free() call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m, sqfs_dir_entry_t **ent); /** * @brief Read and decode an inode from a meta data reader. * * @memberof sqfs_meta_reader_t * * This is a convenience function on to of @ref sqfs_meta_reader_seek and * @ref sqfs_meta_reader_read that reads and decodes an inode. * * @param ir A pointer to a meta data reader. * @param super A pointer to the super block, required for figuring out the * size of file inodes. * @param block_start The meta data block to seek to for reading the inode. * @param offset A byte offset within the uncompressed block where the * inode is. * @param out Returns a pointer to an inode. Can be released with a * single free() call. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, const sqfs_super_t *super, sqfs_u64 block_start, size_t offset, sqfs_inode_generic_t **out); #ifdef __cplusplus } #endif #endif /* SQFS_META_READER_H */ squashfs-tools-ng-0.8/include/sqfs/meta_writer.h000066400000000000000000000146431360235375500220710ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * meta_writer.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_META_WRITER_H #define SQFS_META_WRITER_H #include "sqfs/predef.h" /** * @file meta_writer.h * * @brief Contains declarations for the @ref sqfs_meta_writer_t. */ /** * @struct sqfs_meta_writer_t * * @brief Abstracts generating of meta data blocks, either in memory or * directly on disk. * * SquashFS stores meta data by dividing it into fixed size (8k) chunks * that are written to disk with a small header indicating the on-disk * size and whether it is compressed or not. * * Data written to meta data blocks doesn't have to be aligned, i.e. * SquashFS doesn't care if an object is written across two blocks. * * The main task of the meta data writer is to provide a simple append * function that transparently takes care of chopping data up into blocks, * compressing the blocks and pre-pending a header. */ /** * @enum E_SQFS_META_WRITER_FLAGS * * @brief Possible flags for @ref sqfs_meta_writer_create. */ typedef enum { /** * @brief If set, keep finished blocks in memory. * * To write them to disk, explicitly call * @ref sqfs_meta_write_write_to_file. */ SQFS_META_WRITER_KEEP_IN_MEMORY = 0x01, SQFS_META_WRITER_ALL_FLAGS = 0x01, } E_SQFS_META_WRITER_FLAGS; #ifdef __cplusplus extern "C" { #endif /** * @brief Create a meta data writer. * * @memberof sqfs_meta_writer_t * * @note The meta writer internally keeps references to the pointers passed * to this function, so don't destroy them before destroying the * meta writer. * * @param file An output file to write the data to. * @param cmp A compressor to use. * @param flags A combination of @ref E_SQFS_META_WRITER_FLAGS. * * @return A pointer to a meta writer on success, NULL on allocation failure * or if an unknown flag was set. */ SQFS_API sqfs_meta_writer_t *sqfs_meta_writer_create(sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u32 flags); /** * @brief Destroy a meta data writer and free all memory used by it. * * @memberof sqfs_meta_writer_t * * @param m A pointer to a meta data writer. */ SQFS_API void sqfs_meta_writer_destroy(sqfs_meta_writer_t *m); /** * @brief Finish the current block, even if it isn't full yet. * * @memberof sqfs_meta_writer_t * * This function forces the meta writer to compress and store the block it * is currently writing to, even if it isn't full yet, and either write it * out to disk (or append it to the in memory chain if told to keep blocks * in memory). * * @param m A pointer to a meta data writer. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_writer_flush(sqfs_meta_writer_t *m); /** * @brief Finish the current block, even if it isn't full yet. * * @memberof sqfs_meta_writer_t * * This function forces reads a speicifed number of bytes from a given data * block and appends it to the meta data block that the writer is currently * working on. If the block becomes full, it is compressed, written to disk * and a new block is started that the remaining data is written to. * * @param m A pointer to a meta data writer. * @param data A pointer to a chunk of data to append to the writer. * @param size The number of data bytes to append. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_writer_append(sqfs_meta_writer_t *m, const void *data, size_t size); /** * @brief Query the current block start position and offset within the block * * @memberof sqfs_meta_writer_t * * Get the byte offset relative to the first block that the current block will * start at once it is written to disk and get the byte offset within this * block that the next call to @ref sqfs_meta_writer_append will start writing * data at. * * @param m A pointer to a meta data writer. * @param block_start Returns the offset of the current block from the first. * @param offset Returns an offset into the current block where the next write * starts. */ SQFS_API void sqfs_meta_writer_get_position(const sqfs_meta_writer_t *m, sqfs_u64 *block_start, sqfs_u32 *offset); /** * @brief Reset all internal state, including the current block start position. * * @memberof sqfs_meta_writer_t * * This functions forces the meta data writer to forget everything that * happened since it was created, so it can be recycled. * * The data written is not lost, unless it was kept in memory and never written * out to disk. */ SQFS_API void sqfs_meta_writer_reset(sqfs_meta_writer_t *m); /** * @brief Write all blocks collected in memory to disk * * @memberof sqfs_meta_writer_t * * If the meta writer was created with the flag set to store blocks in * memory instead of writing them to disk, calling this function forces * the meta writer to write out all blocks it collected so far. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_write_write_to_file(sqfs_meta_writer_t *m); /** * @brief A convenience function for encoding and writing an inode * * @memberof sqfs_meta_writer_t * * The SquashFS inode table is essentially a series of meta data blocks * containing variable sized inodes. This function takes a generic inode * structure, encodes it and writes the result to a meta data writer * using @ref sqfs_meta_writer_append internally. * * @param iw A pointer to a meta data writer. * @param n A pointer to an inode. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *iw, const sqfs_inode_generic_t *n); #ifdef __cplusplus } #endif #endif /* SQFS_META_WRITER_H */ squashfs-tools-ng-0.8/include/sqfs/predef.h000066400000000000000000000074211360235375500210100ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * predef.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_PREDEF_H #define SQFS_PREDEF_H /** * @file predef.h * * @brief Includes forward declarations of data structures, * macros and integer types. */ #include #include #include #if defined(_WIN32) || defined(__CYGWIN__) #ifdef SQFS_BUILDING_DLL #if defined(__GNUC__) || defined(__clang__) #define SQFS_API __attribute__ ((dllexport)) #else #define SQFS_API __declspec(dllexport) #endif #else #if defined(__GNUC__) || defined(__clang__) #define SQFS_API __attribute__ ((dllimport)) #else #define SQFS_API __declspec(dllimport) #endif #endif #define SQFS_INTERNAL #else #if defined(__GNUC__) || defined(__clang__) #define SQFS_API __attribute__ ((visibility ("default"))) #define SQFS_INTERNAL __attribute__ ((visibility ("hidden"))) #else #define SQFS_API #define SQFS_INTERNAL #endif #endif typedef uint8_t sqfs_u8; typedef uint16_t sqfs_u16; typedef uint32_t sqfs_u32; typedef uint64_t sqfs_u64; typedef int8_t sqfs_s8; typedef int16_t sqfs_s16; typedef int32_t sqfs_s32; typedef int64_t sqfs_s64; typedef struct sqfs_block_t sqfs_block_t; typedef struct sqfs_data_writer_t sqfs_data_writer_t; typedef struct sqfs_compressor_config_t sqfs_compressor_config_t; typedef struct sqfs_compressor_t sqfs_compressor_t; typedef struct sqfs_dir_writer_t sqfs_dir_writer_t; typedef struct sqfs_dir_reader_t sqfs_dir_reader_t; typedef struct sqfs_id_table_t sqfs_id_table_t; typedef struct sqfs_meta_reader_t sqfs_meta_reader_t; typedef struct sqfs_meta_writer_t sqfs_meta_writer_t; typedef struct sqfs_xattr_reader_t sqfs_xattr_reader_t; typedef struct sqfs_file_t sqfs_file_t; typedef struct sqfs_tree_node_t sqfs_tree_node_t; typedef struct sqfs_data_reader_t sqfs_data_reader_t; typedef struct sqfs_block_hooks_t sqfs_block_hooks_t; typedef struct sqfs_xattr_writer_t sqfs_xattr_writer_t; typedef struct sqfs_fragment_t sqfs_fragment_t; typedef struct sqfs_dir_header_t sqfs_dir_header_t; typedef struct sqfs_dir_entry_t sqfs_dir_entry_t; typedef struct sqfs_dir_index_t sqfs_dir_index_t; typedef struct sqfs_inode_t sqfs_inode_t; typedef struct sqfs_inode_dev_t sqfs_inode_dev_t; typedef struct sqfs_inode_dev_ext_t sqfs_inode_dev_ext_t; typedef struct sqfs_inode_ipc_t sqfs_inode_ipc_t; typedef struct sqfs_inode_ipc_ext_t sqfs_inode_ipc_ext_t; typedef struct sqfs_inode_slink_t sqfs_inode_slink_t; typedef struct sqfs_inode_slink_ext_t sqfs_inode_slink_ext_t; typedef struct sqfs_inode_file_t sqfs_inode_file_t; typedef struct sqfs_inode_file_ext_t sqfs_inode_file_ext_t; typedef struct sqfs_inode_dir_t sqfs_inode_dir_t; typedef struct sqfs_inode_dir_ext_t sqfs_inode_dir_ext_t; typedef struct sqfs_inode_generic_t sqfs_inode_generic_t; typedef struct sqfs_super_t sqfs_super_t; typedef struct sqfs_xattr_entry_t sqfs_xattr_entry_t; typedef struct sqfs_xattr_value_t sqfs_xattr_value_t; typedef struct sqfs_xattr_id_t sqfs_xattr_id_t; typedef struct sqfs_xattr_id_table_t sqfs_xattr_id_table_t; #endif /* SQFS_PREDEF_H */ squashfs-tools-ng-0.8/include/sqfs/super.h000066400000000000000000000205351360235375500207020ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * super.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_SUPER_H #define SQFS_SUPER_H #include "sqfs/predef.h" /** * @file super.h * * @brief Contains on-disk data structures, identifiers and functions for the * SquashFS super block. */ #define SQFS_MAGIC 0x73717368 #define SQFS_VERSION_MAJOR 4 #define SQFS_VERSION_MINOR 0 #define SQFS_DEVBLK_SIZE 4096 #define SQFS_DEFAULT_BLOCK_SIZE 131072 /** * @struct sqfs_super_t * * @brief The SquashFS super block, located at the beginning of the file system * to describe the layout of the filesystem. */ struct sqfs_super_t { /** * @brief Magic number. Must be set to SQFS_MAGIC. */ sqfs_u32 magic; /** * @brief Total number of inodes. */ sqfs_u32 inode_count; /** * @brief Last time the filesystem was modified. * * This field counts seconds (not counting leap seconds) since 00:00, * Jan 1 1970 UTC. This field is unsigned, so it expires in the year * 2106 (as opposed to 2038). */ sqfs_u32 modification_time; /** * @brief The data block size in bytes. * * Must be a power of 2, no less than 4k and not larger than 1M. */ sqfs_u32 block_size; /** * @brief The number of fragment blocks in the data area. */ sqfs_u32 fragment_entry_count; /** * @brief Identifies the compressor that has been used. * * Valid identifiers are in the @ref E_SQFS_COMPRESSOR enum. */ sqfs_u16 compression_id; /** * @brief The log2 of the block_size field for sanity checking * * Must be no less than 12 and not larger than 20. */ sqfs_u16 block_log; /** * @brief A combination of @ref E_SQFS_SUPER_FLAGS flags * * Most of the flags that can be set here are informative only. */ sqfs_u16 flags; /** * @brief The total number of unique user or group IDs. */ sqfs_u16 id_count; /** * @brief Must be @ref SQFS_VERSION_MAJOR */ sqfs_u16 version_major; /** * @brief Must be @ref SQFS_VERSION_MINOR */ sqfs_u16 version_minor; /** * @brief A reference to the root inode * * The bits 16 to 48 hold an offset that is added to inode_table_start * to get the location of the meta data block containing the inode. * The lower 16 bits hold a byte offset into the uncompressed block. */ sqfs_u64 root_inode_ref; /** * @brief Total size of the file system in bytes, not counting padding */ sqfs_u64 bytes_used; /** * @brief On-disk location of the ID table * * This value must point to a location after the directory table and * (if present) after the export and fragment tables, but before the * xattr table. */ sqfs_u64 id_table_start; /** * @brief On-disk location of the extended attribute table (if present) * * See @ref sqfs_xattr_reader_t for an overview on how SquashFS stores * extended attributes on disk. * * This value must either point to a location after the ID table, or * it must be set to 0xFFFFFFFF to indicate the table is not present. */ sqfs_u64 xattr_id_table_start; /** * @brief On-disk location of the first meta data block containing * the inodes * * This value must point to a location before the directory table. */ sqfs_u64 inode_table_start; /** * @brief On-disk location of the first meta data block containing * the directory entries * * This value must point to a location after the inode table but * before the fragment, export, ID and xattr tables. */ sqfs_u64 directory_table_start; /** * @brief On-disk location of the fragment table (if present) * * This value must either point to a location after the directory * table, but before the export, ID and xattr tables, or it must be * set to 0xFFFFFFFF to indicate that the table is not present. */ sqfs_u64 fragment_table_start; /** * @brief On-disk location of the export table (if present) * * This value must either point to a location after directory table * (and if present after the fragment table), but before the ID table, * or it must be set to 0xFFFFFFFF to indicate that the table is not * present. */ sqfs_u64 export_table_start; }; /** * @enum E_SQFS_COMPRESSOR * * @brief Set in @ref sqfs_super_t to identify the compresser used by the * filesystem. * * Most of the flags that can be set are informative only. */ typedef enum { SQFS_COMP_GZIP = 1, SQFS_COMP_LZMA = 2, SQFS_COMP_LZO = 3, SQFS_COMP_XZ = 4, SQFS_COMP_LZ4 = 5, SQFS_COMP_ZSTD = 6, SQFS_COMP_MIN = 1, SQFS_COMP_MAX = 6, } E_SQFS_COMPRESSOR; /** * @enum E_SQFS_SUPER_FLAGS * * @brief Flags that can be set in @ref sqfs_super flags field. */ typedef enum { /** * @brief Set to indicate that meta data blocks holding the inodes are * stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_INODES = 0x0001, /** * @brief Set to indicate that all data blocks are stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_DATA = 0x0002, /** * @brief Set to indicate that all fragment blocks are stored * uncompressed. */ SQFS_FLAG_UNCOMPRESSED_FRAGMENTS = 0x0008, /** * @brief Set to indicate that there are no fragment blocks. */ SQFS_FLAG_NO_FRAGMENTS = 0x0010, /** * @brief Set to indicate that fragments have been generated for all * files that are not a multiple of the block size in size. */ SQFS_FLAG_ALWAYS_FRAGMENTS = 0x0020, /** * @brief Set to indicate that data blocks have not been deduplicated. */ SQFS_FLAG_DUPLICATES = 0x0040, /** * @brief Set to indicate that an NFS export table is present. */ SQFS_FLAG_EXPORTABLE = 0x0080, /** * @brief Set to indicate that meta data blocks holding extended * attributes are stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_XATTRS = 0x0100, /** * @brief Set to indicate that the filesystem does not * contain extended attributes. */ SQFS_FLAG_NO_XATTRS = 0x0200, /** * @brief Set to indicate that a single, uncompressed meta data block * with compressor options follows the super block. */ SQFS_FLAG_COMPRESSOR_OPTIONS = 0x0400, /** * @brief Set to indicate that meta data blocks holding the IDs are * stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_IDS = 0x0800, } E_SQFS_SUPER_FLAGS; #ifdef __cplusplus extern "C" { #endif /** * @brief Initialize the SquashFS super block. * * @memberof sqfs_super_t * * @param super A pointer to a super block structure. * @param block_size The uncompressed size of the data blocks in bytes. * @param mtime The modification time stamp to set. * @param compressor The compressor ID to set. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_init(sqfs_super_t *super, size_t block_size, sqfs_u32 mtime, E_SQFS_COMPRESSOR compressor); /** * @brief Encode and write a SquashFS super block to disk. * * @memberof sqfs_super_t * * @param super A pointer to the super block structure to write. * @param file A file object through which to access the filesystem image. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_write(const sqfs_super_t *super, sqfs_file_t *file); /** * @brief Read a SquashFS super block from disk, decode it and check the fields * * @memberof sqfs_super_t * * @param super A pointer to the super block structure to fill. * @param file A file object through which to access the filesystem image. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_read(sqfs_super_t *super, sqfs_file_t *file); #ifdef __cplusplus } #endif #endif /* SQFS_SUPER_H */ squashfs-tools-ng-0.8/include/sqfs/table.h000066400000000000000000000065051360235375500206340ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * table.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_TABLE_H #define SQFS_TABLE_H #include "sqfs/predef.h" /** * @file table.h * * @brief Contains helper functions for reading or writing tables. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Write a table to disk. * * This function takes an in-memory array, breaks it down into meta data * blocks, compresses and writes those blocks to the given output file and * then writes a raw list of 64 bit absolute locations of each meta data * block. The position of the location list is returned through a pointer. * * @param file The output file to write to. * @param cmp A compressor to use for compressing the meta data blocks. * @param data A pointer to a array to divide into blocks and write to disk. * @param table_size The size of the input array in bytes. * @param start Returns the absolute position of the location list. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_write_table(sqfs_file_t *file, sqfs_compressor_t *cmp, const void *data, size_t table_size, sqfs_u64 *start); /** * @brief Read a table from a SquashFS filesystem. * * This function takes an absolute position and an array size as input. It * then computes the number of meta data blocks required to store this array * and reads that many 64 bit integers from the given start location. Each * integer is interpreted as the location of a meta data block containing the * respective array chunk. * * The entire data encoded in that way is read and uncompressed into memory. * * @param file An input file to read from. * @param cmp A compressor to use for uncompressing the meta data block. * @param table_size The size of the entire array in bytes. * @param location The absolute position of the location list. * @param lower_limit The lowest "sane" position at which to expect a meta * data block. Anything less than that is interpreted * as an out-of-bounds read. * @param upper_limit The highest "sane" position at which to expect a meta * data block. Anything after that is interpreted as an * out-of-bounds read. * @param out Returns a pointer to the table in memory. * * @return Zero on success, an @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_read_table(sqfs_file_t *file, sqfs_compressor_t *cmp, size_t table_size, sqfs_u64 location, sqfs_u64 lower_limit, sqfs_u64 upper_limit, void **out); #ifdef __cplusplus } #endif #endif /* SQFS_TABLE_H */ squashfs-tools-ng-0.8/include/sqfs/xattr.h000066400000000000000000000116621360235375500207070ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xattr.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_XATTR_H #define SQFS_XATTR_H #include "sqfs/predef.h" /** * @file xattr.h * * @brief Contains on-disk data structures for storing extended attributes. */ /** * @enum E_SQFS_XATTR_TYPE * * Used by @ref sqfs_xattr_entry_t to encodes the xattr prefix. */ typedef enum { SQFS_XATTR_USER = 0, SQFS_XATTR_TRUSTED = 1, SQFS_XATTR_SECURITY = 2, SQFS_XATTR_FLAG_OOL = 0x100, SQFS_XATTR_PREFIX_MASK = 0xFF, } E_SQFS_XATTR_TYPE; /** * @struct sqfs_xattr_entry_t * * @brief On-disk data structure that holds a single xattr key * * See @ref sqfs_xattr_reader_t for an overview how SquashFS stores extended * attributes on disk. */ struct sqfs_xattr_entry_t { /** * @brief Encodes the prefix of the key * * A @ref E_SQFS_XATTR_TYPE value. If the @ref SQFS_XATTR_FLAG_OOL is * set, the value that follows is not actually a string but a 64 bit * reference to the location where the value is actually stored. */ sqfs_u16 type; /** * @brief The size in bytes of the suffix string that follows */ sqfs_u16 size; sqfs_u8 key[]; }; /** * @struct sqfs_xattr_value_t * * @brief On-disk data structure that holds a single xattr value * * See @ref sqfs_xattr_reader_t for an overview how SquashFS stores extended * attributes on disk. */ struct sqfs_xattr_value_t { /** * @brief The exact size in bytes of the value that follows */ sqfs_u32 size; sqfs_u8 value[]; }; /** * @struct sqfs_xattr_id_t * * @brief On-disk data structure that describes a set of key-value pairs * * See @ref sqfs_xattr_reader_t for an overview how SquashFS stores extended * attributes on disk. */ struct sqfs_xattr_id_t { /** * @brief Location of the first key-value pair * * This is a reference, i.e. the bits 16 to 48 hold an offset that is * added to xattr_table_start from @ref sqfs_xattr_id_table_t to get * the location of a meta data block that contains the first key-value * pair. The lower 16 bits store an offset into the uncompressed meta * data block. */ sqfs_u64 xattr; /** * @brief Number of consecutive key-value pairs */ sqfs_u32 count; /** * @brief Total size of the uncompressed key-value pairs in bytes, * including data structures used to encode them. */ sqfs_u32 size; }; /** * @struct sqfs_xattr_id_table_t * * @brief On-disk data structure that the super block points to * * Indicates the locations of the xattr key-value pairs and descriptor array. * See @ref sqfs_xattr_reader_t for an overview how SquashFS stores extended * attributes on disk. */ struct sqfs_xattr_id_table_t { /** * @brief The location of the first meta data block holding the key * value pairs. */ sqfs_u64 xattr_table_start; /** * @brief The total number of descriptors (@ref sqfs_xattr_id_t) */ sqfs_u32 xattr_ids; /** * @brief Unused, alwayas set this to 0 when writing! */ sqfs_u32 unused; /** * @brief Holds the locations of the meta data blocks that contain the * @ref sqfs_xattr_id_t descriptor array. */ sqfs_u64 locations[]; }; #ifdef __cplusplus extern "C" { #endif /** * @brief Resolve an xattr identifier to the coresponding prefix * * Like many file systems, SquashFS stores xattrs be cutting off the common * prefix of the key string and storing an enumerator instead to save memory. * * This function takes an @ref E_SQFS_XATTR_TYPE identifier and returns the * coresponding prefix string, including the '.' at the end that separates * the prefix from the rest of the key. */ SQFS_API const char *sqfs_get_xattr_prefix(E_SQFS_XATTR_TYPE id); /** * @brief Resolve an xattr prefix into an identifier * * Like many file systems, SquashFS stores xattrs be cutting off the common * prefix of the key string and storing an enumerator instead to save memory. * * This function takes a key and finds the enumerator value that represents * its prefix. An error value is returned if the given prefix isn't supported. * * @return On success an @ref E_SQFS_XATTR_TYPE. If not supported, the * @ref SQFS_ERROR_UNSUPPORTED error code. */ SQFS_API int sqfs_get_xattr_prefix_id(const char *key); #ifdef __cplusplus } #endif #endif /* SQFS_XATTR_H */ squashfs-tools-ng-0.8/include/sqfs/xattr_reader.h000066400000000000000000000165301360235375500222300ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xattr_reader.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_XATTR_READER_H #define SQFS_XATTR_READER_H #include "sqfs/predef.h" /** * @file xattr_reader.h * * @brief Contains declarations for the @ref sqfs_xattr_reader_t. */ /** * @struct sqfs_xattr_reader_t * * @brief Abstracts read access to extended attributes in a SquashFS filesystem * * SquashFS stores extended attributes using multiple levels of indirection. * First of all, the key-value pairs of each inode (that has extended * attributes) are deduplicated and stored consecutively in meta data blocks. * Furthermore, a value can be stored out-of-band, i.e. it holds a reference to * another location from which the value has to be read. * * For each unique set of key-value pairs, a descriptor object is generated * that holds the location of the first pair, the number of pairs and the total * size used on disk. The array of descriptor objects is stored in multiple * meta data blocks. Each inode that has extended attributes holds a 32 bit * index into the descriptor array. * * The third layer of indirection is yet another table that points to the * locations of the previous two tables. Its location is in turn stored in * the super block. * * The sqfs_xattr_reader_t data structure takes care of the low level details * of loading and parsing the data. * * After creating an instance using @ref sqfs_xattr_reader_create, simply call * @ref sqfs_xattr_reader_load_locations to load and parse all of the location * tables. Then use @ref sqfs_xattr_reader_get_desc to resolve a 32 bit index * from an inode to a descriptor structure. Use @ref sqfs_xattr_reader_seek_kv * to point the reader to the start of the key-value pairs and the call * @ref sqfs_xattr_reader_read_key and @ref sqfs_xattr_reader_read_value * consecutively to read and decode each key-value pair. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Create an xattr reader * * @memberof sqfs_xattr_reader_t * * This function creates an object that abstracts away read only access to * the extended attributes in a SquashFS filesystem. * * After creating a reader and before using it, call * @ref sqfs_xattr_reader_load_locations to load and parse the location * information required to look up xattr key-value pairs. * * All pointers passed to this function are stored internally for later use. * Do not destroy any of the pointed to objects before destroying the xattr * reader. * * @param file A pointer to a file object that contains the SquashFS filesystem * @param super A pointer to the SquashFS super block required to find the * location tables. * @param cmp A pointer to a compressor used to uncompress the loaded meta data * blocks. * * @return A pointer to a new xattr reader instance on success, NULL on * allocation failure. */ SQFS_API sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); /** * @brief Destroy an xattr reader and free all memory used by it * * @memberof sqfs_xattr_reader_t * * @param xr A pointer to an xattr reader instance */ SQFS_API void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr); /** * @brief Load the locations of the xattr meta data blocks into memory * * @memberof sqfs_xattr_reader_t * * This function must be called explicitly after an xattr reader has been * created to load the actual location table from disk. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr); /** * @brief Resolve an xattr index from an inode to an xattr description * * @memberof sqfs_xattr_reader_t * * This function takes an xattr index from an extended inode type and resolves * it to a descriptor that points to location of the key-value pairs and * indicates how many key-value pairs to read from there. * * @param xr A pointer to an xattr reader instance * @param idx The xattr index to resolve * @param desc Used to return the description * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, sqfs_u32 idx, sqfs_xattr_id_t *desc); /** * @brief Resolve an xattr index from an inode to an xattr description * * @memberof sqfs_xattr_reader_t * * This function takes an xattr descriptor object and seeks to the meta data * block containing the key-value pairs. The individual pairs can then be read * using consecutive calls to @ref sqfs_xattr_reader_read_key and * @ref sqfs_xattr_reader_read_value. * * @param xr A pointer to an xattr reader instance * @param desc The descriptor holding the location of the key-value pairs * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr, const sqfs_xattr_id_t *desc); /** * @brief Read the next xattr key * * @memberof sqfs_xattr_reader_t * * After setting the start position using @ref sqfs_xattr_reader_seek_kv, this * function reads and decodes an xattr key and advances the internal position * indicator to the location after the key. The value can then be read using * using @ref sqfs_xattr_reader_read_value. After reading the value, the next * key can be read by calling this function again. * * @param xr A pointer to an xattr reader instance * @param key_out Used to return the decoded key. The underlying memory can be * released using a single free() call. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr, sqfs_xattr_entry_t **key_out); /** * @brief Read the xattr value belonging to the last read key * * @memberof sqfs_xattr_reader_t * * After calling @ref sqfs_xattr_reader_read_key, this function can read and * decode the asociated value. The internal location indicator is then advanced * past the key to the next value, so @ref sqfs_xattr_reader_read_key can be * called again to read the next key. * * @param xr A pointer to an xattr reader instance. * @param key A pointer to the decoded key object. * @param val_out Used to return the decoded value. The underlying memory can * be released using a single free() call. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, const sqfs_xattr_entry_t *key, sqfs_xattr_value_t **val_out); #ifdef __cplusplus } #endif #endif /* SQFS_XATTR_READER_H */ squashfs-tools-ng-0.8/include/sqfs/xattr_writer.h000066400000000000000000000114211360235375500222740ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xattr_writer.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program 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 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 Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_XATRR_WRITER_H #define SQFS_XATRR_WRITER_H #include "sqfs/predef.h" /** * @file xattr_writer.h * * @brief Contains declarations for the @ref sqfs_xattr_writer_t. */ /** * @struct sqfs_xattr_writer_t * * @brief Abstracts writing of extended attributes to a SquashFS filesystem. * * This data structure provides a simple, abstract interface to recording * extended attributes that hads out 32 bit tokens required for inodes to * refere to them. * * Use @ref sqfs_xattr_writer_begin to start a block of key-value pairs, then * add the individual pairs with @ref sqfs_xattr_writer_add and finaly use * @ref sqfs_xattr_writer_end which returns the required token. * * Finally, use @ref sqfs_xattr_writer_flush to have the extended attributes * written to disk. * * The writer internally takes care of propper deduplication and packaging * everything up in compressed meta data blocks in the multi-level hierarchy * used by SquashFS. See @ref sqfs_xattr_reader_t for a brief overview on how * SquashFS stores extended attributes. */ #ifdef __cplusplus extern "C" { #endif /** * @brief Create an xattr writer instance. * * @memberof sqfs_xattr_writer_t * * @return A pointer to a new xattr writer, NULL on allocation failure. */ SQFS_API sqfs_xattr_writer_t *sqfs_xattr_writer_create(void); /** * @brief Destroy an xattr writer instance and free all memory it used. * * @memberof sqfs_xattr_writer_t * * @param xwr A pointer to an xattr writer instance. */ SQFS_API void sqfs_xattr_writer_destroy(sqfs_xattr_writer_t *xwr); /** * @brief Begin recording a block of key-value pairs. * * @memberof sqfs_xattr_writer_t * * Use @ref sqfs_xattr_writer_add to add the individual pairs. Call * @ref sqfs_xattr_writer_end when you are done. * * @param xwr A pointer to an xattr writer instance. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_writer_begin(sqfs_xattr_writer_t *xwr); /** * @brief Add a key-value pair to the current block. * * @memberof sqfs_xattr_writer_t * * @param xwr A pointer to an xattr writer instance. * @param key The xattr key string. * @param value The associated value to store. * @param size The size of the value blob. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_writer_add(sqfs_xattr_writer_t *xwr, const char *key, const void *value, size_t size); /** * @brief Finish a generating a key-value block. * * @memberof sqfs_xattr_writer_t * * This function internally takes care of deduplicating the current block * and generates the coresponding 32 bit xattr token used by SquashFS inodes. * The token it returns can be one it returned previously if the block turns * out to be a duplicate of a previous block. * * @param xwr A pointer to an xattr writer instance. * @param out Returns an ID that has to be set to the inode that the block of * key-value pairs belongs to. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_writer_end(sqfs_xattr_writer_t *xwr, sqfs_u32 *out); /** * @brief Write all recorded key-value pairs to disk. * * @memberof sqfs_xattr_writer_t * * This function takes care of generating the extended attribute tables * used by SquashFS. Call it after you are donew with all other meta data * tables, since SquashFS requires it to be the very last thing in the * file system. * * @param xwr A pointer to an xattr writer instance. * @param file The output file to write the tables to. * @param super The super block to update with the table locations and flags. * @param cmp The compressor to user to compress the tables. * * @return Zero on success, a negative @ref E_SQFS_ERROR value on failure. */ SQFS_API int sqfs_xattr_writer_flush(sqfs_xattr_writer_t *xwr, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); #ifdef __cplusplus } #endif #endif /* SQFS_XATRR_WRITER_H */ squashfs-tools-ng-0.8/include/tar.h000066400000000000000000000071311360235375500173530ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef TAR_H #define TAR_H #include "config.h" #include "compat.h" #include #include #include typedef struct sparse_map_t { struct sparse_map_t *next; sqfs_u64 offset; sqfs_u64 count; } sparse_map_t; typedef struct { char name[100]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char typeflag; char linkname[100]; char magic[6]; char version[2]; char uname[32]; char gname[32]; char devmajor[8]; char devminor[8]; union { struct { char prefix[155]; char padding[12]; } posix; struct { char atime[12]; char ctime[12]; char offset[12]; char deprecated[4]; char unused; struct { char offset[12]; char numbytes[12]; } sparse[4]; char isextended; char realsize[12]; char padding[17]; } gnu; } tail; } tar_header_t; typedef struct { struct { char offset[12]; char numbytes[12]; } sparse[21]; char isextended; char padding[7]; } gnu_sparse_t; typedef struct tar_xattr_t { struct tar_xattr_t *next; char *key; sqfs_u8 *value; size_t value_len; char data[]; } tar_xattr_t; typedef struct { struct stat sb; char *name; char *link_target; sparse_map_t *sparse; sqfs_u64 actual_size; sqfs_u64 record_size; bool unknown_record; bool is_hard_link; tar_xattr_t *xattr; /* broken out since struct stat could contain 32 bit values on 32 bit systems. */ sqfs_s64 mtime; } tar_header_decoded_t; #define TAR_TYPE_FILE '0' #define TAR_TYPE_LINK '1' #define TAR_TYPE_SLINK '2' #define TAR_TYPE_CHARDEV '3' #define TAR_TYPE_BLOCKDEV '4' #define TAR_TYPE_DIR '5' #define TAR_TYPE_FIFO '6' #define TAR_TYPE_GNU_SLINK 'K' #define TAR_TYPE_GNU_PATH 'L' #define TAR_TYPE_GNU_SPARSE 'S' #define TAR_TYPE_PAX 'x' #define TAR_MAGIC "ustar" #define TAR_VERSION "00" #define TAR_MAGIC_OLD "ustar " #define TAR_VERSION_OLD " " #define TAR_RECORD_SIZE (512) /* Returns < 0 on failure, > 0 if cannot encode, 0 on success. Prints error/warning messages to stderr. The counter is an incremental record counter used if additional headers need to be generated. */ int write_tar_header(FILE *fp, const struct stat *sb, const char *name, const char *slink_target, const tar_xattr_t *xattr, unsigned int counter); int write_hard_link(FILE *fp, const struct stat *sb, const char *name, const char *target, unsigned int counter); /* calcuate and skip the zero padding */ int skip_padding(FILE *fp, sqfs_u64 size); /* round up to block size and skip the entire entry */ int skip_entry(FILE *fp, sqfs_u64 size); int read_header(FILE *fp, tar_header_decoded_t *out); void clear_header(tar_header_decoded_t *hdr); /* Write zero bytes to an output file to padd it to the tar record size. Returns 0 on success. On failure, prints error message to stderr. */ int padd_file(FILE *fp, sqfs_u64 size); /* A wrapper around the read() system call. It retries the read if it is interrupted by a signal or less than the desired size was read. Returns 0 on success. Writes to stderr on failure using 'errstr' as a perror style error prefix. */ int read_retry(const char *errstr, FILE *fp, void *buffer, size_t size); /* A wrapper around the write() system call. It retries the write if it is interrupted by a signal or only part of the data was written. Returns 0 on success. Writes to stderr on failure using 'errstr' as a perror style error prefix. */ int write_retry(const char *errstr, FILE *fp, const void *data, size_t size); #endif /* TAR_H */ squashfs-tools-ng-0.8/lib/000077500000000000000000000000001360235375500155355ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/common/000077500000000000000000000000001360235375500170255ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/common/Makemodule.am000066400000000000000000000012441360235375500214300ustar00rootroot00000000000000libcommon_a_SOURCES = lib/common/serialize_fstree.c lib/common/statistics.c libcommon_a_SOURCES += lib/common/inode_stat.c lib/common/hardlink.c libcommon_a_SOURCES += lib/common/print_version.c lib/common/data_reader_dump.c libcommon_a_SOURCES += lib/common/compress.c lib/common/comp_opt.c libcommon_a_SOURCES += lib/common/data_writer.c include/common.h libcommon_a_SOURCES += lib/common/get_path.c lib/common/io_stdin.c libcommon_a_SOURCES += lib/common/writer.c lib/common/perror.c libcommon_a_SOURCES += lib/common/mkdir_p.c libcommon_a_CFLAGS = $(AM_CFLAGS) $(LZO_CFLAGS) if WITH_LZO libcommon_a_SOURCES += lib/common/comp_lzo.c endif noinst_LIBRARIES += libcommon.a squashfs-tools-ng-0.8/lib/common/comp_lzo.c000066400000000000000000000135121360235375500210150ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * comp_lzo.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "common.h" #include #include #include #include #define LZO_MAX_SIZE(size) (size + (size / 16) + 64 + 3) #define LZO_NUM_ALGS (sizeof(lzo_algs) / sizeof(lzo_algs[0])) typedef int (*lzo_cb_t)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); static const struct { lzo_cb_t compress; size_t bufsize; } lzo_algs[] = { [SQFS_LZO1X_1] = { .compress = lzo1x_1_compress, .bufsize = LZO1X_1_MEM_COMPRESS, }, [SQFS_LZO1X_1_11] = { .compress = lzo1x_1_11_compress, .bufsize = LZO1X_1_11_MEM_COMPRESS, }, [SQFS_LZO1X_1_12] = { .compress = lzo1x_1_12_compress, .bufsize = LZO1X_1_12_MEM_COMPRESS, }, [SQFS_LZO1X_1_15] = { .compress = lzo1x_1_15_compress, .bufsize = LZO1X_1_15_MEM_COMPRESS, }, [SQFS_LZO1X_999] = { .compress = lzo1x_999_compress, .bufsize = LZO1X_999_MEM_COMPRESS, }, }; typedef struct { sqfs_compressor_t base; int algorithm; int level; size_t buf_size; size_t work_size; sqfs_u8 buffer[]; } lzo_compressor_t; typedef struct { sqfs_u32 algorithm; sqfs_u32 level; } lzo_options_t; static int lzo_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; sqfs_u8 buffer[sizeof(lzo_options_t) + 2]; lzo_options_t opt; int ret; if (lzo->algorithm == SQFS_LZO_DEFAULT_ALG && lzo->level == SQFS_LZO_DEFAULT_LEVEL) { return 0; } opt.algorithm = htole32(lzo->algorithm); if (lzo->algorithm == SQFS_LZO1X_999) { opt.level = htole32(lzo->level); } else { opt.level = 0; } *((sqfs_u16 *)buffer) = htole16(0x8000 | sizeof(opt)); memcpy(buffer + 2, &opt, sizeof(opt)); ret = file->write_at(file, sizeof(sqfs_super_t), buffer, sizeof(buffer)); return ret ? ret : (int)sizeof(buffer); } static int lzo_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; sqfs_u8 buffer[sizeof(lzo_options_t) + 2]; lzo_options_t opt; int ret; ret = file->read_at(file, sizeof(sqfs_super_t), buffer, sizeof(buffer)); if (ret) return ret; if (le16toh(*((sqfs_u16 *)buffer)) != (0x8000 | sizeof(opt))) return SQFS_ERROR_CORRUPTED; memcpy(&opt, buffer + 2, sizeof(opt)); lzo->algorithm = le32toh(opt.algorithm); lzo->level = le32toh(opt.level); switch(lzo->algorithm) { case SQFS_LZO1X_1: case SQFS_LZO1X_1_11: case SQFS_LZO1X_1_12: case SQFS_LZO1X_1_15: if (lzo->level != 0) return SQFS_ERROR_UNSUPPORTED; break; case SQFS_LZO1X_999: if (lzo->level < 1 || lzo->level > 9) return SQFS_ERROR_UNSUPPORTED; break; default: return SQFS_ERROR_UNSUPPORTED; } return 0; } static sqfs_s32 lzo_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; void *scratch; lzo_uint len; int ret; if (size >= 0x7FFFFFFF) return 0; scratch = lzo->buffer + lzo->work_size; len = lzo->buf_size - lzo->work_size; if (lzo->algorithm == SQFS_LZO1X_999 && lzo->level != SQFS_LZO_DEFAULT_LEVEL) { ret = lzo1x_999_compress_level(in, size, scratch, &len, lzo->buffer, NULL, 0, 0, lzo->level); } else { ret = lzo_algs[lzo->algorithm].compress(in, size, scratch, &len, lzo->buffer); } if (ret != LZO_E_OK) return SQFS_ERROR_COMPRESSOR; if (len < size && len <= outsize) { memcpy(out, scratch, len); return len; } return 0; } static sqfs_s32 lzo_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; lzo_uint len = outsize; int ret; if (outsize >= 0x7FFFFFFF) return 0; ret = lzo1x_decompress_safe(in, size, out, &len, lzo->buffer); if (ret != LZO_E_OK) return SQFS_ERROR_COMPRESSOR; return len; } static sqfs_compressor_t *lzo_create_copy(sqfs_compressor_t *cmp) { lzo_compressor_t *other = (lzo_compressor_t *)cmp; lzo_compressor_t *lzo; lzo = calloc(1, sizeof(*lzo) + other->buf_size); if (lzo == NULL) return NULL; memcpy(lzo, other, sizeof(*lzo)); return (sqfs_compressor_t *)lzo; } static void lzo_destroy(sqfs_compressor_t *base) { free(base); } sqfs_compressor_t *lzo_compressor_create(const sqfs_compressor_config_t *cfg) { sqfs_compressor_t *base; lzo_compressor_t *lzo; size_t scratch_size; if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) return NULL; if (cfg->opt.lzo.algorithm >= LZO_NUM_ALGS || lzo_algs[cfg->opt.lzo.algorithm].compress == NULL) { return NULL; } if (cfg->opt.lzo.algorithm == SQFS_LZO1X_999) { if (cfg->opt.lzo.level > SQFS_LZO_MAX_LEVEL) return NULL; } else if (cfg->opt.lzo.level != 0) { return NULL; } /* XXX: liblzo does not do bounds checking internally, we need our own internal scratch buffer at worst case size... */ if (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) { scratch_size = 0; } else { scratch_size = cfg->block_size; if (scratch_size < SQFS_META_BLOCK_SIZE) scratch_size = SQFS_META_BLOCK_SIZE; scratch_size = LZO_MAX_SIZE(scratch_size); } /* ...in addition to the LZO work space buffer of course */ scratch_size += lzo_algs[cfg->opt.lzo.algorithm].bufsize; lzo = calloc(1, sizeof(*lzo) + scratch_size); base = (sqfs_compressor_t *)lzo; if (lzo == NULL) return NULL; lzo->algorithm = cfg->opt.lzo.algorithm; lzo->level = cfg->opt.lzo.level; lzo->buf_size = scratch_size; lzo->work_size = lzo_algs[cfg->opt.lzo.algorithm].bufsize; base->destroy = lzo_destroy; base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ? lzo_uncomp_block : lzo_comp_block; base->write_options = lzo_write_options; base->read_options = lzo_read_options; base->create_copy = lzo_create_copy; return base; } squashfs-tools-ng-0.8/lib/common/comp_opt.c000066400000000000000000000206421360235375500210150ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * comp_opt.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include #include typedef struct { const char *name; sqfs_u16 flag; } flag_t; static const flag_t gzip_flags[] = { { "default", SQFS_COMP_FLAG_GZIP_DEFAULT }, { "filtered", SQFS_COMP_FLAG_GZIP_FILTERED }, { "huffman", SQFS_COMP_FLAG_GZIP_HUFFMAN }, { "rle", SQFS_COMP_FLAG_GZIP_RLE }, { "fixed", SQFS_COMP_FLAG_GZIP_FIXED }, }; static const flag_t xz_flags[] = { { "x86", SQFS_COMP_FLAG_XZ_X86 }, { "powerpc", SQFS_COMP_FLAG_XZ_POWERPC }, { "ia64", SQFS_COMP_FLAG_XZ_IA64 }, { "arm", SQFS_COMP_FLAG_XZ_ARM }, { "armthumb", SQFS_COMP_FLAG_XZ_ARMTHUMB }, { "sparc", SQFS_COMP_FLAG_XZ_SPARC }, }; static const flag_t lz4_flags[] = { { "hc", SQFS_COMP_FLAG_LZ4_HC }, }; static const char *lzo_algs[] = { [SQFS_LZO1X_1] = "lzo1x_1", [SQFS_LZO1X_1_11] = "lzo1x_1_11", [SQFS_LZO1X_1_12] = "lzo1x_1_12", [SQFS_LZO1X_1_15] = "lzo1x_1_15", [SQFS_LZO1X_999] = "lzo1x_999", }; static int set_flag(sqfs_compressor_config_t *cfg, const char *name, const flag_t *flags, size_t num_flags) { size_t i; for (i = 0; i < num_flags; ++i) { if (strcmp(flags[i].name, name) == 0) { cfg->flags |= flags[i].flag; return 0; } } return -1; } static int find_lzo_alg(sqfs_compressor_config_t *cfg, const char *name) { size_t i; for (i = 0; i < sizeof(lzo_algs) / sizeof(lzo_algs[0]); ++i) { if (strcmp(lzo_algs[i], name) == 0) { cfg->opt.lzo.algorithm = i; return 0; } } return -1; } static int get_size_value(const char *value, sqfs_u32 *out, sqfs_u32 block_size) { int i; for (i = 0; isdigit(value[i]) && i < 9; ++i) ; if (i < 1 || i > 9) return -1; *out = atol(value); switch (value[i]) { case '\0': break; case 'm': case 'M': *out <<= 20; break; case 'k': case 'K': *out <<= 10; break; case '%': *out = (*out * block_size) / 100; break; default: return -1; } return 0; } enum { OPT_WINDOW = 0, OPT_LEVEL, OPT_ALG, OPT_DICT, }; static char *const token[] = { [OPT_WINDOW] = (char *)"window", [OPT_LEVEL] = (char *)"level", [OPT_ALG] = (char *)"algorithm", [OPT_DICT] = (char *)"dictsize", NULL }; int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, E_SQFS_COMPRESSOR id, size_t block_size, char *options) { size_t num_flags = 0, min_level = 0, max_level = 0, level; const flag_t *flags = NULL; char *subopts, *value; int i, opt; if (sqfs_compressor_config_init(cfg, id, block_size, 0)) return -1; if (options == NULL) return 0; switch (cfg->id) { case SQFS_COMP_GZIP: min_level = SQFS_GZIP_MIN_LEVEL; max_level = SQFS_GZIP_MAX_LEVEL; flags = gzip_flags; num_flags = sizeof(gzip_flags) / sizeof(gzip_flags[0]); break; case SQFS_COMP_LZO: min_level = SQFS_LZO_MIN_LEVEL; max_level = SQFS_LZO_MAX_LEVEL; break; case SQFS_COMP_ZSTD: min_level = SQFS_ZSTD_MIN_LEVEL; max_level = SQFS_ZSTD_MAX_LEVEL; break; case SQFS_COMP_XZ: flags = xz_flags; num_flags = sizeof(xz_flags) / sizeof(xz_flags[0]); break; case SQFS_COMP_LZ4: flags = lz4_flags; num_flags = sizeof(lz4_flags) / sizeof(lz4_flags[0]); break; default: break; } subopts = options; while (*subopts != '\0') { opt = getsubopt(&subopts, token, &value); switch (opt) { case OPT_WINDOW: if (cfg->id != SQFS_COMP_GZIP) goto fail_opt; if (value == NULL) goto fail_value; for (i = 0; isdigit(value[i]); ++i) ; if (i < 1 || i > 3 || value[i] != '\0') goto fail_window; cfg->opt.gzip.window_size = atoi(value); if (cfg->opt.gzip.window_size < SQFS_GZIP_MIN_WINDOW || cfg->opt.gzip.window_size > SQFS_GZIP_MAX_WINDOW) goto fail_window; break; case OPT_LEVEL: if (value == NULL) goto fail_value; for (i = 0; isdigit(value[i]) && i < 3; ++i) ; if (i < 1 || i > 3 || value[i] != '\0') goto fail_level; level = atoi(value); if (level < min_level || level > max_level) goto fail_level; switch (cfg->id) { case SQFS_COMP_GZIP: cfg->opt.gzip.level = level; break; case SQFS_COMP_LZO: cfg->opt.lzo.level = level; break; case SQFS_COMP_ZSTD: cfg->opt.zstd.level = level; break; default: goto fail_opt; } break; case OPT_ALG: if (cfg->id != SQFS_COMP_LZO) goto fail_opt; if (value == NULL) goto fail_value; if (find_lzo_alg(cfg, value)) goto fail_lzo_alg; break; case OPT_DICT: if (cfg->id != SQFS_COMP_XZ) goto fail_opt; if (value == NULL) goto fail_value; if (get_size_value(value, &cfg->opt.xz.dict_size, cfg->block_size)) { goto fail_dict; } break; default: if (set_flag(cfg, value, flags, num_flags)) goto fail_opt; break; } } return 0; fail_lzo_alg: fprintf(stderr, "Unknown lzo variant '%s'.\n", value); return -1; fail_window: fputs("Window size must be a number between 8 and 15.\n", stderr); return -1; fail_level: fprintf(stderr, "Compression level must be a number between " PRI_SZ " and " PRI_SZ ".\n", min_level, max_level); return -1; fail_opt: fprintf(stderr, "Unknown compressor option '%s'.\n", value); return -1; fail_value: fprintf(stderr, "Missing value for compressor option '%s'.\n", token[opt]); return -1; fail_dict: fputs("Dictionary size must be a number with the optional " "suffix 'm','k' or '%'.\n", stderr); return -1; } typedef void (*compressor_help_fun_t)(void); static void gzip_print_help(void) { size_t i; printf( "Available options for gzip compressor:\n" "\n" " level= Compression level. Value from 1 to 9.\n" " Defaults to %d.\n" " window= Deflate compression window size. Value from 8 to 15.\n" " Defaults to %d.\n" "\n" "In additon to the options, one or more strategies can be specified.\n" "If multiple stratgies are provided, the one yielding the best compression\n" "ratio will be used.\n" "\n" "The following strategies are available:\n", SQFS_GZIP_DEFAULT_LEVEL, SQFS_GZIP_DEFAULT_WINDOW); for (i = 0; i < sizeof(gzip_flags) / sizeof(gzip_flags[0]); ++i) printf("\t%s\n", gzip_flags[i].name); } static void lz4_print_help(void) { fputs("Available options for lz4 compressor:\n" "\n" " hc If present, use slower but better compressing\n" " variant of lz4.\n" "\n", stdout); } static void lzo_print_help(void) { size_t i; fputs("Available options for lzo compressor:\n" "\n" " algorithm= Specify the variant of lzo to use.\n" " Defaults to 'lzo1x_999'.\n" " level= For lzo1x_999, the compression level.\n" " Value from 1 to 9. Defaults to 8.\n" " Ignored if algorithm is not lzo1x_999.\n" "\n" "Available algorithms:\n", stdout); for (i = 0; i < sizeof(lzo_algs) / sizeof(lzo_algs[0]); ++i) printf("\t%s\n", lzo_algs[i]); } static void xz_print_help(void) { size_t i; fputs( "Available options for xz compressor:\n" "\n" " dictsize= Dictionary size. Either a value in bytes or a\n" " percentage of the block size. Defaults to 100%.\n" " The suffix '%' indicates a percentage. 'K' and 'M'\n" " can also be used for kibi and mebi bytes\n" " respecitively.\n" "\n" "In additon to the options, one or more bcj filters can be specified.\n" "If multiple filters are provided, the one yielding the best compression\n" "ratio will be used.\n" "\n" "The following filters are available:\n", stdout); for (i = 0; i < sizeof(xz_flags) / sizeof(xz_flags[0]); ++i) printf("\t%s\n", xz_flags[i].name); } static void zstd_print_help(void) { printf("Available options for zstd compressor:\n" "\n" " level= Set compression level. Defaults to %d.\n" " Maximum is %d.\n" "\n", SQFS_ZSTD_DEFAULT_LEVEL, SQFS_ZSTD_MAX_LEVEL); } static const compressor_help_fun_t helpfuns[SQFS_COMP_MAX + 1] = { [SQFS_COMP_GZIP] = gzip_print_help, [SQFS_COMP_XZ] = xz_print_help, [SQFS_COMP_LZO] = lzo_print_help, [SQFS_COMP_LZ4] = lz4_print_help, [SQFS_COMP_ZSTD] = zstd_print_help, }; void compressor_print_help(E_SQFS_COMPRESSOR id) { if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX) return; if (helpfuns[id] == NULL) return; helpfuns[id](); } squashfs-tools-ng-0.8/lib/common/compress.c000066400000000000000000000015241360235375500210260ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * compress.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" E_SQFS_COMPRESSOR compressor_get_default(void) { if (sqfs_compressor_exists(SQFS_COMP_XZ)) return SQFS_COMP_XZ; if (sqfs_compressor_exists(SQFS_COMP_ZSTD)) return SQFS_COMP_ZSTD; return SQFS_COMP_GZIP; } void compressor_print_available(void) { bool have_compressor; int i; fputs("Available compressors:\n", stdout); for (i = SQFS_COMP_MIN; i <= SQFS_COMP_MAX; ++i) { have_compressor = sqfs_compressor_exists(i); #ifdef WITH_LZO if (i == SQFS_COMP_LZO) have_compressor = true; #endif if (have_compressor) printf("\t%s\n", sqfs_compressor_name_from_id(i)); } printf("\nDefault compressor: %s\n", sqfs_compressor_name_from_id(compressor_get_default())); } squashfs-tools-ng-0.8/lib/common/data_reader_dump.c000066400000000000000000000036471360235375500224630ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * data_reader_dump.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include #include static int append_block(FILE *fp, const sqfs_block_t *blk) { const unsigned char *ptr = blk->data; size_t ret, size = blk->size; while (size > 0) { if (ferror(fp)) { fputs("writing data block: error writing to file\n", stderr); } if (feof(fp)) { fputs("writing data block: unexpected end of file\n", stderr); } ret = fwrite(ptr, 1, size, fp); ptr += ret; size -= ret; } return 0; } int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, FILE *fp, size_t block_size, bool allow_sparse) { sqfs_block_t *blk; sqfs_u64 filesz; size_t i, diff; int err; sqfs_inode_get_file_size(inode, &filesz); #if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L) if (allow_sparse) { int fd = fileno(fp); if (ftruncate(fd, filesz)) goto fail_sparse; } #else allow_sparse = false; #endif for (i = 0; i < inode->num_file_blocks; ++i) { diff = (filesz < block_size) ? filesz : block_size; if (SQFS_IS_SPARSE_BLOCK(inode->block_sizes[i]) && allow_sparse) { if (fseek(fp, diff, SEEK_CUR) < 0) goto fail_sparse; } else { err = sqfs_data_reader_get_block(data, inode, i, &blk); if (err) { sqfs_perror(name, "reading data block", err); return -1; } err = append_block(fp, blk); free(blk); if (err) return -1; } filesz -= diff; } if (filesz > 0) { err = sqfs_data_reader_get_fragment(data, inode, &blk); if (err) { sqfs_perror(name, "reading fragment block", err); return -1; } if (append_block(fp, blk)) { free(blk); return -1; } free(blk); } return 0; fail_sparse: perror("creating sparse output file"); return -1; } squashfs-tools-ng-0.8/lib/common/data_writer.c000066400000000000000000000021741360235375500215020ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * data_writer.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" static sqfs_u8 buffer[4096]; int write_data_from_file(const char *filename, sqfs_data_writer_t *data, sqfs_inode_generic_t *inode, sqfs_file_t *file, int flags) { sqfs_u64 filesz, offset; size_t diff; int ret; ret = sqfs_data_writer_begin_file(data, inode, flags); if (ret) { sqfs_perror(filename, "beginning file data blocks", ret); return -1; } sqfs_inode_get_file_size(inode, &filesz); for (offset = 0; offset < filesz; offset += diff) { if (filesz - offset > sizeof(buffer)) { diff = sizeof(buffer); } else { diff = filesz - offset; } ret = file->read_at(file, offset, buffer, diff); if (ret) { sqfs_perror(filename, "reading file range", ret); return -1; } ret = sqfs_data_writer_append(data, buffer, diff); if (ret) { sqfs_perror(filename, "packing file data", ret); return -1; } } ret = sqfs_data_writer_end_file(data); if (ret) { sqfs_perror(filename, "finishing file data", ret); return -1; } return 0; } squashfs-tools-ng-0.8/lib/common/get_path.c000066400000000000000000000014301360235375500207620ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * get_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include char *sqfs_tree_node_get_path(const sqfs_tree_node_t *node) { const sqfs_tree_node_t *it; char *str, *ptr; size_t len = 0; if (node->parent == NULL) return strdup("/"); for (it = node; it != NULL && it->parent != NULL; it = it->parent) { len += strlen((const char *)it->name) + 1; } str = malloc(len + 1); if (str == NULL) return NULL; ptr = str + len; *ptr = '\0'; for (it = node; it != NULL && it->parent != NULL; it = it->parent) { len = strlen((const char *)it->name); ptr -= len; memcpy(ptr, (const char *)it->name, len); *(--ptr) = '/'; } return str; } squashfs-tools-ng-0.8/lib/common/hardlink.c000066400000000000000000000040121360235375500207620ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * hardlink.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include static size_t count_nodes(const sqfs_tree_node_t *n) { size_t count = n->children == NULL ? 1 : 0; for (n = n->children; n != NULL; n = n->next) count += count_nodes(n); return count; } static size_t map_nodes(const sqfs_tree_node_t **list, const sqfs_tree_node_t *n, size_t idx) { if (n->children == NULL) list[idx++] = n; for (n = n->children; n != NULL; n = n->next) idx = map_nodes(list, n, idx); return idx; } int sqfs_tree_find_hard_links(const sqfs_tree_node_t *root, sqfs_hard_link_t **out) { sqfs_hard_link_t *hardlinks = NULL, *lnk = NULL; const sqfs_tree_node_t **list = NULL; size_t i, j, count; const char *name; bool is_dup; count = count_nodes(root); list = malloc(sizeof(list[0]) * count); if (list == NULL) goto fail; map_nodes(list, root, 0); for (i = 0; i < count; ++i) { name = (const char *)list[i]->name; if (!is_filename_sane(name, false)) continue; is_dup = false; for (j = 0; j < i; ++j) { if (list[j]->inode->base.inode_number == list[i]->inode->base.inode_number) { name = (const char *)list[j]->name; if (!is_filename_sane(name, false)) continue; is_dup = true; break; } } if (is_dup) { lnk = calloc(1, sizeof(*lnk)); if (lnk == NULL) goto fail; lnk->inode_number = list[j]->inode->base.inode_number; lnk->target = sqfs_tree_node_get_path(list[j]); if (lnk->target == NULL) goto fail; if (canonicalize_name(lnk->target) == 0) { lnk->next = hardlinks; hardlinks = lnk; } else { free(lnk->target); free(lnk); } } } *out = hardlinks; return 0; fail: perror("detecting hard links in file system tree"); free(lnk); while (hardlinks != NULL) { lnk = hardlinks; hardlinks = hardlinks->next; free(lnk->target); free(lnk); } free(list); return -1; } squashfs-tools-ng-0.8/lib/common/inode_stat.c000066400000000000000000000040201360235375500213160ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * inode_stat.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include int inode_stat(const sqfs_tree_node_t *node, struct stat *sb) { memset(sb, 0, sizeof(*sb)); sb->st_mode = node->inode->base.mode; sb->st_uid = node->uid; sb->st_gid = node->gid; sb->st_atime = node->inode->base.mod_time; sb->st_mtime = node->inode->base.mod_time; sb->st_ctime = node->inode->base.mod_time; sb->st_ino = node->inode->base.inode_number; sb->st_nlink = 1; sb->st_blksize = 512; switch (node->inode->base.type) { case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: sb->st_rdev = node->inode->data.dev.devno; sb->st_nlink = node->inode->data.dev.nlink; break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: sb->st_rdev = node->inode->data.dev_ext.devno; sb->st_nlink = node->inode->data.dev_ext.nlink; break; case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: sb->st_nlink = node->inode->data.ipc.nlink; break; case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: sb->st_nlink = node->inode->data.ipc_ext.nlink; break; case SQFS_INODE_SLINK: sb->st_size = node->inode->data.slink.target_size; sb->st_nlink = node->inode->data.slink.nlink; break; case SQFS_INODE_EXT_SLINK: sb->st_size = node->inode->data.slink_ext.target_size; sb->st_nlink = node->inode->data.slink_ext.nlink; break; case SQFS_INODE_FILE: sb->st_size = node->inode->data.file.file_size; break; case SQFS_INODE_EXT_FILE: sb->st_size = node->inode->data.file_ext.file_size; sb->st_nlink = node->inode->data.file_ext.nlink; break; case SQFS_INODE_DIR: sb->st_size = node->inode->data.dir.size; sb->st_nlink = node->inode->data.dir.nlink; break; case SQFS_INODE_EXT_DIR: sb->st_size = node->inode->data.dir_ext.size; sb->st_nlink = node->inode->data.dir_ext.nlink; break; } sb->st_blocks = sb->st_size / sb->st_blksize; if (sb->st_size % sb->st_blksize) sb->st_blocks += 1; return 0; } squashfs-tools-ng-0.8/lib/common/io_stdin.c000066400000000000000000000065111360235375500210040ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * io_stdin.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include typedef struct { sqfs_file_t base; const sparse_map_t *map; sqfs_u64 offset; sqfs_u64 size; FILE *fp; } sqfs_file_stdinout_t; static void stdinout_destroy(sqfs_file_t *base) { free(base); } static sqfs_u64 stdinout_get_size(const sqfs_file_t *base) { return ((const sqfs_file_stdinout_t *)base)->size; } static int stdinout_truncate(sqfs_file_t *base, sqfs_u64 size) { (void)base; (void)size; return SQFS_ERROR_IO; } static int stdin_read_at(sqfs_file_t *base, sqfs_u64 offset, void *buffer, size_t size) { sqfs_file_stdinout_t *file = (sqfs_file_stdinout_t *)base; size_t temp_size = 0; sqfs_u8 *temp = NULL; sqfs_u64 diff; size_t ret; if (offset < file->offset) return SQFS_ERROR_IO; if (offset > file->offset) { temp_size = 1024; temp = alloca(temp_size); } if (offset >= file->size || (offset + size) > file->size) return SQFS_ERROR_OUT_OF_BOUNDS; while (size > 0) { if (ferror(file->fp)) return SQFS_ERROR_IO; if (feof(file->fp)) return SQFS_ERROR_OUT_OF_BOUNDS; if (offset > file->offset) { diff = file->offset - offset; diff = diff > (sqfs_u64)temp_size ? temp_size : diff; ret = fread(temp, 1, diff, file->fp); } else { ret = fread(buffer, 1, size, file->fp); } if (offset <= file->offset) { buffer = (char *)buffer + ret; size -= ret; offset += ret; } file->offset += ret; } return 0; } static int stdin_read_condensed(sqfs_file_t *base, sqfs_u64 offset, void *buffer, size_t size) { sqfs_file_stdinout_t *file = (sqfs_file_stdinout_t *)base; sqfs_u64 poffset = 0, src_start; size_t dst_start, diff, count; const sparse_map_t *it; int err; memset(buffer, 0, size); for (it = file->map; it != NULL; it = it->next) { if (it->offset + it->count <= offset) { poffset += it->count; continue; } if (it->offset >= offset + size) { poffset += it->count; continue; } count = size; if (offset + count >= it->offset + it->count) count = it->offset + it->count - offset; if (it->offset < offset) { diff = offset - it->offset; src_start = poffset + diff; dst_start = 0; count -= diff; } else if (it->offset > offset) { diff = it->offset - offset; src_start = poffset; dst_start = diff; } else { src_start = poffset; dst_start = 0; } err = stdin_read_at(base, src_start, (char *)buffer + dst_start, count); if (err) return err; poffset += it->count; } return 0; } static int stdin_write_at(sqfs_file_t *base, sqfs_u64 offset, const void *buffer, size_t size) { (void)base; (void)offset; (void)buffer; (void)size; return SQFS_ERROR_IO; } sqfs_file_t *sqfs_get_stdin_file(FILE *fp, const sparse_map_t *map, sqfs_u64 size) { sqfs_file_stdinout_t *file = calloc(1, sizeof(*file)); sqfs_file_t *base = (sqfs_file_t *)file; if (file == NULL) return NULL; file->size = size; file->map = map; file->fp = fp; base->destroy = stdinout_destroy; base->write_at = stdin_write_at; base->get_size = stdinout_get_size; base->truncate = stdinout_truncate; if (map == NULL) { base->read_at = stdin_read_at; } else { base->read_at = stdin_read_condensed; } return base; } squashfs-tools-ng-0.8/lib/common/mkdir_p.c000066400000000000000000000054161360235375500206240ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mkdir_p.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include #include #ifdef _WIN32 /* Supported paths: - :\ - \\\\ - \\?\:\ - \\?\UNC\\\ - Relative path not starting with '\' */ static WCHAR *skip_unc_path(WCHAR *ptr) { /* server */ if (*ptr == '\0' || *ptr == '\\') return NULL; while (*ptr != '\0' && *ptr != '\\') ++ptr; if (*(ptr++) != '\\') return NULL; /* share */ if (*ptr == '\0' || *ptr == '\\') return NULL; while (*ptr != '\0' && *ptr != '\\') ++ptr; return (*ptr == '\\') ? (ptr + 1) : ptr; } static WCHAR *skip_prefix(WCHAR *ptr) { if (isalpha(ptr[0]) && ptr[1] == ':' && ptr[2] == '\\') return ptr + 3; if (ptr[0] == '\\' && ptr[1] == '\\') { if (ptr[2] == '?') { if (ptr[3] != '\\') return NULL; ptr += 4; if ((ptr[0] == 'u' || ptr[0] == 'U') && (ptr[1] == 'n' || ptr[1] == 'N') && (ptr[2] == 'c' || ptr[2] == 'C') && ptr[3] == '\\') { ptr += 4; return skip_unc_path(ptr); } if (isalpha(ptr[0]) && ptr[1] == ':' && ptr[2] == '\\') return ptr + 3; return NULL; } return skip_unc_path(ptr); } if (ptr[0] == '\\') return NULL; return ptr; } int mkdir_p(const char *path) { WCHAR *wpath, *ptr, *end; DWORD error; bool done; wpath = path_to_windows(path); if (wpath == NULL) return -1; ptr = skip_prefix(wpath); if (ptr == NULL) { fprintf(stderr, "Illegal or unsupported path: %s\n", path); goto fail; } while (*ptr != '\0') { if (*ptr == '\\') { ++ptr; continue; } for (end = ptr; *end != '\0' && *end != '\\'; ++end) ++end; if (*end == '\\') { done = false; *end = '\0'; } else { done = true; } if (!CreateDirectoryW(wpath, NULL)) { error = GetLastError(); if (error != ERROR_ALREADY_EXISTS) { fprintf(stderr, "Creating %s: %ld\n", path, error); goto fail; } } if (!done) { *end = '\\'; ptr = end + 1; } } free(wpath); return 0; fail: free(wpath); return -1; } #else int mkdir_p(const char *path) { size_t i, len; char *buffer; while (path[0] == '/' && path[1] == '/') ++path; if (*path == '\0' || (path[0] == '/' && path[1] == '\0')) return 0; len = strlen(path) + 1; buffer = alloca(len); for (i = 0; i < len; ++i) { if (i > 0 && (path[i] == '/' || path[i] == '\0')) { buffer[i] = '\0'; if (mkdir(buffer, 0755) != 0) { if (errno != EEXIST) { fprintf(stderr, "mkdir %s: %s\n", buffer, strerror(errno)); return -1; } } } buffer[i] = path[i]; } return 0; } #endif squashfs-tools-ng-0.8/lib/common/perror.c000066400000000000000000000031431360235375500205030ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * print_version.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include void sqfs_perror(const char *file, const char *action, int error_code) { const char *errstr; switch (error_code) { case SQFS_ERROR_ALLOC: errstr = "out of memory"; break; case SQFS_ERROR_IO: errstr = "I/O error"; break; case SQFS_ERROR_COMPRESSOR: errstr = "internal compressor error"; break; case SQFS_ERROR_INTERNAL: errstr = "internal error"; break; case SQFS_ERROR_CORRUPTED: errstr = "data corrupted"; break; case SQFS_ERROR_UNSUPPORTED: errstr = "unknown or not supported"; break; case SQFS_ERROR_OVERFLOW: errstr = "numeric overflow"; break; case SQFS_ERROR_OUT_OF_BOUNDS: errstr = "location out of bounds"; break; case SFQS_ERROR_SUPER_MAGIC: errstr = "wrong magic value in super block"; break; case SFQS_ERROR_SUPER_VERSION: errstr = "wrong squashfs version in super block"; break; case SQFS_ERROR_SUPER_BLOCK_SIZE: errstr = "invalid block size specified in super block"; break; case SQFS_ERROR_NOT_DIR: errstr = "target is not a directory"; break; case SQFS_ERROR_NO_ENTRY: errstr = "no such file or directory"; break; case SQFS_ERROR_LINK_LOOP: errstr = "hard link loop detected"; break; case SQFS_ERROR_NOT_FILE: errstr = "target is not a file"; break; case SQFS_ERROR_ARG_INVALID: errstr = "invalid argument"; break; default: errstr = "libsquashfs returned an unknown error code"; break; } fprintf(stderr, "%s: %s: %s.\n", file, action, errstr); } squashfs-tools-ng-0.8/lib/common/print_version.c000066400000000000000000000013321360235375500220710ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * print_version.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #define LICENSE_SHORT "GPLv3+" #define LICENSE_LONG "GNU GPL version 3 or later" #define LICENSE_URL "https://gnu.org/licenses/gpl.html" static const char *version_string = "%s (%s) %s\n" "Copyright (c) 2019 David Oberhollenzer et al\n" "License " LICENSE_SHORT ": " LICENSE_LONG " <" LICENSE_URL ">.\n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n"; void print_version(const char *progname) { printf(version_string, progname, PACKAGE_NAME, PACKAGE_VERSION); } squashfs-tools-ng-0.8/lib/common/serialize_fstree.c000066400000000000000000000106401360235375500225310ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * serialize_fstree.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #include #include static sqfs_inode_generic_t *tree_node_to_inode(tree_node_t *node) { sqfs_inode_generic_t *inode; size_t extra = 0; if (S_ISLNK(node->mode)) extra = strlen(node->data.target); inode = calloc(1, sizeof(*inode) + extra); if (inode == NULL) { perror("creating inode"); return NULL; } switch (node->mode & S_IFMT) { case S_IFSOCK: inode->base.type = SQFS_INODE_SOCKET; inode->data.ipc.nlink = node->link_count; break; case S_IFIFO: inode->base.type = SQFS_INODE_FIFO; inode->data.ipc.nlink = node->link_count; break; case S_IFLNK: inode->base.type = SQFS_INODE_SLINK; inode->data.slink.nlink = node->link_count; inode->data.slink.target_size = extra; inode->slink_target = (char *)inode->extra; memcpy(inode->extra, node->data.target, extra); break; case S_IFBLK: inode->base.type = SQFS_INODE_BDEV; inode->data.dev.nlink = node->link_count; inode->data.dev.devno = node->data.devno; break; case S_IFCHR: inode->base.type = SQFS_INODE_CDEV; inode->data.dev.nlink = node->link_count; inode->data.dev.devno = node->data.devno; break; default: assert(0); } return inode; } static sqfs_inode_generic_t *write_dir_entries(const char *filename, sqfs_dir_writer_t *dirw, tree_node_t *node) { sqfs_u32 xattr, parent_inode; sqfs_inode_generic_t *inode; tree_node_t *it, *tgt; int ret; ret = sqfs_dir_writer_begin(dirw, 0); if (ret) goto fail; for (it = node->data.dir.children; it != NULL; it = it->next) { if (it->mode == FSTREE_MODE_HARD_LINK_RESOLVED) { tgt = it->data.target_node; } else { tgt = it; } ret = sqfs_dir_writer_add_entry(dirw, it->name, tgt->inode_num, tgt->inode_ref, tgt->mode); if (ret) goto fail; } ret = sqfs_dir_writer_end(dirw); if (ret) goto fail; xattr = node->xattr_idx; parent_inode = (node->parent == NULL) ? 0 : node->parent->inode_num; inode = sqfs_dir_writer_create_inode(dirw, 0, xattr, parent_inode); if (inode == NULL) { ret = SQFS_ERROR_ALLOC; goto fail; } if (inode->base.type == SQFS_INODE_DIR) { inode->data.dir.nlink = node->link_count; } else { inode->data.dir_ext.nlink = node->link_count; } return inode; fail: sqfs_perror(filename, "recoding directory entries", ret); return NULL; } static int serialize_tree_node(const char *filename, sqfs_writer_t *wr, tree_node_t *n) { sqfs_inode_generic_t *inode; sqfs_u32 offset; sqfs_u64 block; int ret; if (S_ISDIR(n->mode)) { inode = write_dir_entries(filename, wr->dirwr, n); ret = SQFS_ERROR_INTERNAL; } else if (S_ISREG(n->mode)) { inode = n->data.file.user_ptr; n->data.file.user_ptr = NULL; ret = SQFS_ERROR_INTERNAL; if (inode->base.type == SQFS_INODE_FILE && n->link_count > 1) { sqfs_inode_make_extended(inode); inode->data.file_ext.nlink = n->link_count; } else { inode->data.file_ext.nlink = n->link_count; } } else { inode = tree_node_to_inode(n); ret = SQFS_ERROR_ALLOC; } if (inode == NULL) return ret; inode->base.mode = n->mode; inode->base.mod_time = n->mod_time; inode->base.inode_number = n->inode_num; sqfs_inode_set_xattr_index(inode, n->xattr_idx); ret = sqfs_id_table_id_to_index(wr->idtbl, n->uid, &inode->base.uid_idx); if (ret) goto out; ret = sqfs_id_table_id_to_index(wr->idtbl, n->gid, &inode->base.gid_idx); if (ret) goto out; sqfs_meta_writer_get_position(wr->im, &block, &offset); n->inode_ref = (block << 16) | offset; ret = sqfs_meta_writer_write_inode(wr->im, inode); out: free(inode); return ret; } int sqfs_serialize_fstree(const char *filename, sqfs_writer_t *wr) { size_t i; int ret; wr->super.inode_table_start = wr->outfile->get_size(wr->outfile); for (i = 0; i < wr->fs.unique_inode_count; ++i) { ret = serialize_tree_node(filename, wr, wr->fs.inodes[i]); if (ret) goto out; } ret = sqfs_meta_writer_flush(wr->im); if (ret) goto out; ret = sqfs_meta_writer_flush(wr->dm); if (ret) goto out; wr->super.root_inode_ref = wr->fs.root->inode_ref; wr->super.directory_table_start = wr->outfile->get_size(wr->outfile); ret = sqfs_meta_write_write_to_file(wr->dm); if (ret) goto out; ret = 0; out: if (ret) sqfs_perror(filename, "storing filesystem tree", ret); return ret; } squashfs-tools-ng-0.8/lib/common/statistics.c000066400000000000000000000046171360235375500213730ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * statistics.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include static void post_block_write(void *user, const sqfs_block_t *block, sqfs_file_t *file) { data_writer_stats_t *stats = user; (void)file; if (block->size == 0) return; if (block->flags & SQFS_BLK_FRAGMENT_BLOCK) { stats->frag_blocks_written += 1; } else { stats->blocks_written += 1; } stats->bytes_written += block->size; } static void pre_fragment_store(void *user, sqfs_block_t *block) { data_writer_stats_t *stats = user; (void)block; stats->frag_count += 1; } static void notify_blocks_erased(void *user, size_t count, sqfs_u64 bytes) { data_writer_stats_t *stats = user; stats->bytes_written -= bytes; stats->blocks_written -= count; stats->duplicate_blocks += count; } static void notify_fragment_discard(void *user, const sqfs_block_t *block) { data_writer_stats_t *stats = user; (void)block; stats->frag_dup += 1; } static const sqfs_block_hooks_t hooks = { .size = sizeof(hooks), .post_block_write = post_block_write, .pre_fragment_store = pre_fragment_store, .notify_blocks_erased = notify_blocks_erased, .notify_fragment_discard = notify_fragment_discard, }; void register_stat_hooks(sqfs_data_writer_t *data, data_writer_stats_t *stats) { sqfs_data_writer_set_hooks(data, stats, &hooks); } void sqfs_print_statistics(sqfs_super_t *super, data_writer_stats_t *stats) { size_t ratio; if (stats->bytes_written > 0) { ratio = (100 * stats->bytes_written) / stats->bytes_read; } else { ratio = 100; } fputs("---------------------------------------------------\n", stdout); printf("Input files processed: " PRI_SZ"\n", stats->file_count); printf("Data blocks actually written: " PRI_SZ "\n", stats->blocks_written); printf("Fragment blocks written: " PRI_SZ "\n", stats->frag_blocks_written); printf("Duplicate data blocks omitted: " PRI_SZ "\n", stats->duplicate_blocks); printf("Sparse blocks omitted: " PRI_SZ "\n", stats->sparse_blocks); printf("Fragments actually written: " PRI_SZ "\n", stats->frag_count); printf("Duplicated fragments omitted: " PRI_SZ"\n", stats->frag_dup); printf("Total number of inodes: %u\n", super->inode_count); printf("Number of unique group/user IDs: %u\n", super->id_count); printf("Data compression ratio: " PRI_SZ "%%\n", ratio); } squashfs-tools-ng-0.8/lib/common/writer.c000066400000000000000000000150021360235375500205030ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * writer.c * * Copyright (C) 2019 David Oberhollenzer */ #include "common.h" #include #include #ifdef HAVE_SYS_SYSINFO_H #include static size_t os_get_num_jobs(void) { int nprocs; nprocs = get_nprocs_conf(); return nprocs < 1 ? 1 : nprocs; } #else static size_t os_get_num_jobs(void) { return 1; } #endif static int padd_sqfs(sqfs_file_t *file, sqfs_u64 size, size_t blocksize) { size_t padd_sz = size % blocksize; int status = -1; sqfs_u8 *buffer; if (padd_sz == 0) return 0; padd_sz = blocksize - padd_sz; buffer = calloc(1, padd_sz); if (buffer == NULL) goto fail_errno; if (file->write_at(file, file->get_size(file), buffer, padd_sz)) { goto fail_errno; } status = 0; out: free(buffer); return status; fail_errno: perror("padding output file to block size"); goto out; } void sqfs_writer_cfg_init(sqfs_writer_cfg_t *cfg) { memset(cfg, 0, sizeof(*cfg)); cfg->num_jobs = os_get_num_jobs(); cfg->block_size = SQFS_DEFAULT_BLOCK_SIZE; cfg->devblksize = SQFS_DEVBLK_SIZE; cfg->comp_id = compressor_get_default(); } int sqfs_writer_init(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *wrcfg) { sqfs_compressor_config_t cfg; int ret, flags; if (compressor_cfg_init_options(&cfg, wrcfg->comp_id, wrcfg->block_size, wrcfg->comp_extra)) { return -1; } sqfs->outfile = sqfs_open_file(wrcfg->filename, wrcfg->outmode); if (sqfs->outfile == NULL) { perror(wrcfg->filename); return -1; } if (fstree_init(&sqfs->fs, wrcfg->fs_defaults)) goto fail_file; sqfs->cmp = sqfs_compressor_create(&cfg); #ifdef WITH_LZO if (cfg.id == SQFS_COMP_LZO) { if (sqfs->cmp != NULL) sqfs->cmp->destroy(sqfs->cmp); sqfs->cmp = lzo_compressor_create(&cfg); } #endif if (sqfs->cmp == NULL) { fputs("Error creating compressor\n", stderr); goto fail_fs; } ret = sqfs_super_init(&sqfs->super, wrcfg->block_size, sqfs->fs.defaults.st_mtime, wrcfg->comp_id); if (ret) { sqfs_perror(wrcfg->filename, "initializing super block", ret); goto fail_cmp; } ret = sqfs_super_write(&sqfs->super, sqfs->outfile); if (ret) { sqfs_perror(wrcfg->filename, "writing super block", ret); goto fail_cmp; } ret = sqfs->cmp->write_options(sqfs->cmp, sqfs->outfile); if (ret < 0) { sqfs_perror(wrcfg->filename, "writing compressor options", ret); goto fail_cmp; } if (ret > 0) sqfs->super.flags |= SQFS_FLAG_COMPRESSOR_OPTIONS; sqfs->data = sqfs_data_writer_create(sqfs->super.block_size, sqfs->cmp, wrcfg->num_jobs, wrcfg->max_backlog, wrcfg->devblksize, sqfs->outfile); if (sqfs->data == NULL) { perror("creating data block processor"); goto fail_cmp; } memset(&sqfs->stats, 0, sizeof(sqfs->stats)); register_stat_hooks(sqfs->data, &sqfs->stats); sqfs->idtbl = sqfs_id_table_create(); if (sqfs->idtbl == NULL) { sqfs_perror(wrcfg->filename, "creating ID table", SQFS_ERROR_ALLOC); goto fail_data; } if (!wrcfg->no_xattr) { sqfs->xwr = sqfs_xattr_writer_create(); if (sqfs->xwr == NULL) { sqfs_perror(wrcfg->filename, "creating xattr writer", SQFS_ERROR_ALLOC); goto fail_id; } } sqfs->im = sqfs_meta_writer_create(sqfs->outfile, sqfs->cmp, 0); if (sqfs->im == NULL) { fputs("Error creating inode meta data writer.\n", stderr); goto fail_xwr; } sqfs->dm = sqfs_meta_writer_create(sqfs->outfile, sqfs->cmp, SQFS_META_WRITER_KEEP_IN_MEMORY); if (sqfs->dm == NULL) { fputs("Error creating directory meta data writer.\n", stderr); goto fail_im; } flags = 0; if (wrcfg->exportable) flags |= SQFS_DIR_WRITER_CREATE_EXPORT_TABLE; sqfs->dirwr = sqfs_dir_writer_create(sqfs->dm, flags); if (sqfs->dirwr == NULL) { fputs("Error creating directory table writer.\n", stderr); goto fail_dm; } return 0; fail_dm: sqfs_meta_writer_destroy(sqfs->dm); fail_im: sqfs_meta_writer_destroy(sqfs->im); fail_xwr: if (sqfs->xwr != NULL) sqfs_xattr_writer_destroy(sqfs->xwr); fail_id: sqfs_id_table_destroy(sqfs->idtbl); fail_data: sqfs_data_writer_destroy(sqfs->data); fail_cmp: sqfs->cmp->destroy(sqfs->cmp); fail_fs: fstree_cleanup(&sqfs->fs); fail_file: sqfs->outfile->destroy(sqfs->outfile); return -1; } int sqfs_writer_finish(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *cfg) { int ret; if (!cfg->quiet) fputs("Waiting for remaining data blocks...\n", stdout); ret = sqfs_data_writer_finish(sqfs->data); if (ret) { sqfs_perror(cfg->filename, "finishing data blocks", ret); return -1; } if (!cfg->quiet) fputs("Writing inodes and directories...\n", stdout); sqfs->super.inode_count = sqfs->fs.unique_inode_count; if (sqfs_serialize_fstree(cfg->filename, sqfs)) return -1; if (!cfg->quiet) fputs("Writing fragment table...\n", stdout); ret = sqfs_data_writer_write_fragment_table(sqfs->data, &sqfs->super); if (ret) { sqfs_perror(cfg->filename, "writing fragment table", ret); return -1; } if (cfg->exportable) { if (!cfg->quiet) fputs("Writing export table...\n", stdout); ret = sqfs_dir_writer_write_export_table(sqfs->dirwr, sqfs->outfile, sqfs->cmp, sqfs->fs.root->inode_num, sqfs->fs.root->inode_ref, &sqfs->super); if (ret) return -1; } if (!cfg->quiet) fputs("Writing ID table...\n", stdout); ret = sqfs_id_table_write(sqfs->idtbl, sqfs->outfile, &sqfs->super, sqfs->cmp); if (ret) { sqfs_perror(cfg->filename, "writing ID table", ret); return -1; } if (!cfg->no_xattr) { if (!cfg->quiet) fputs("Writing extended attributes...\n", stdout); ret = sqfs_xattr_writer_flush(sqfs->xwr, sqfs->outfile, &sqfs->super, sqfs->cmp); if (ret) { sqfs_perror(cfg->filename, "writing extended attributes", ret); return -1; } } sqfs->super.bytes_used = sqfs->outfile->get_size(sqfs->outfile); ret = sqfs_super_write(&sqfs->super, sqfs->outfile); if (ret) { sqfs_perror(cfg->filename, "updating super block", ret); return -1; } if (padd_sqfs(sqfs->outfile, sqfs->super.bytes_used, cfg->devblksize)) { return -1; } if (!cfg->quiet) sqfs_print_statistics(&sqfs->super, &sqfs->stats); return 0; } void sqfs_writer_cleanup(sqfs_writer_t *sqfs) { if (sqfs->xwr != NULL) sqfs_xattr_writer_destroy(sqfs->xwr); sqfs_dir_writer_destroy(sqfs->dirwr); sqfs_meta_writer_destroy(sqfs->dm); sqfs_meta_writer_destroy(sqfs->im); sqfs_id_table_destroy(sqfs->idtbl); sqfs_data_writer_destroy(sqfs->data); sqfs->cmp->destroy(sqfs->cmp); fstree_cleanup(&sqfs->fs); sqfs->outfile->destroy(sqfs->outfile); } squashfs-tools-ng-0.8/lib/compat/000077500000000000000000000000001360235375500170205ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/compat/Makemodule.am000066400000000000000000000004231360235375500214210ustar00rootroot00000000000000libcompat_a_SOURCES = lib/compat/getline.c lib/compat/getsubopt.c libcompat_a_SOURCES += lib/compat/strndup.c lib/compat/mockups.c libcompat_a_SOURCES += lib/compat/chdir.c include/compat.h libcompat_a_SOURCES += lib/compat/path_to_windows.c noinst_LIBRARIES += libcompat.a squashfs-tools-ng-0.8/lib/compat/chdir.c000066400000000000000000000010141360235375500202510ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * chdir.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #ifdef _WIN32 #include int chdir(const char *path) { WCHAR *wpath; int ret; wpath = path_to_windows(path); if (wpath == NULL) return -1; if (!SetCurrentDirectoryW(wpath)) { fprintf(stderr, "Switching to directory '%s': %ld\n", path, GetLastError()); ret = -1; } else { ret = 0; } free(wpath); return ret; } #endif squashfs-tools-ng-0.8/lib/compat/getline.c000066400000000000000000000015741360235375500206220ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * getline.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #include #include #ifndef HAVE_GETLINE ssize_t getline(char **line, size_t *n, FILE *fp) { size_t new_cap, len = 0, cap = 0; char *buffer = NULL, *new; int c; if (feof(fp) || ferror(fp)) return -1; do { c = fgetc(fp); if (ferror(fp)) return -1; if (c == EOF) c = '\n'; if (len == cap) { new_cap = cap ? cap * 2 : 32; new = realloc(buffer, new_cap); if (new == NULL) return -1; buffer = new; cap = new_cap; } buffer[len++] = c; } while (c != '\n'); if (len == cap) { new = realloc(buffer, cap ? cap * 2 : 32); if (new == NULL) return -1; buffer = new; } buffer[len] = '\0'; *line = buffer; *n = len; return len; } #endif squashfs-tools-ng-0.8/lib/compat/getsubopt.c000066400000000000000000000013111360235375500211740ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * getsubopt.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #include #include #ifndef HAVE_GETSUBOPT int getsubopt(char **opt, char *const *keys, char **val) { char *str = *opt; size_t i, len; *val = NULL; *opt = strchr(str, ','); if (*opt == NULL) { *opt = str + strlen(str); } else { *(*opt)++ = '\0'; } for (i = 0; keys[i]; ++i) { len = strlen(keys[i]); if (strncmp(keys[i], str, len) != 0) continue; if (str[len] != '=' && str[len] != '\0') continue; if (str[len] == '=') *val = str + len + 1; return i; } return -1; } #endif squashfs-tools-ng-0.8/lib/compat/mockups.c000066400000000000000000000016761360235375500206570ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mockups.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #ifdef _WIN32 int fchownat(int dirfd, const char *path, int uid, int gid, int flags) { if (dirfd != AT_FDCWD) { fputs("[FIXME] fchownat stub only supports AT_FDCWD!\n", stderr); return -1; } if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { fputs("[FIXME] fchownat stub used with an unknown flag!\n", stderr); return -1; } (void)path; (void)uid; (void)gid; return 0; } int fchmodat(int dirfd, const char *path, int mode, int flags) { if (dirfd != AT_FDCWD) { fputs("[FIXME] fchmodat stub only supports AT_FDCWD!\n", stderr); return -1; } if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { fputs("[FIXME] fchmodat stub used with an unknown flag!\n", stderr); return -1; } (void)path; (void)mode; return 0; } #endif squashfs-tools-ng-0.8/lib/compat/path_to_windows.c000066400000000000000000000015671360235375500224050ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * path_to_windows.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #include #include #if defined(_WIN32) || defined(__WINDOWS__) WCHAR *path_to_windows(const char *input) { WCHAR *wpath, *ptr; DWORD length; length = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); if (length <= 0) { fprintf(stderr, "Converting UTF-8 path to UTF-16: %ld\n", GetLastError()); return NULL; } wpath = calloc(sizeof(wpath[0]), length + 1); if (wpath == NULL) { fprintf(stderr, "Converting UTF-8 path to UTF-16: out of memory\n"); return NULL; } MultiByteToWideChar(CP_UTF8, 0, input, -1, wpath, length + 1); wpath[length] = '\0'; for (ptr = wpath; *ptr != '\0'; ++ptr) { if (*ptr == '/') *ptr = '\\'; } return wpath; } #endif squashfs-tools-ng-0.8/lib/compat/strndup.c000066400000000000000000000007461360235375500206720ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * strndup.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "compat.h" #include #include #ifndef HAVE_STRNDUP char *strndup(const char *str, size_t max_len) { size_t len = 0; char *out; while (len < max_len && str[len] != '\0') ++len; out = malloc(len + 1); if (out != NULL) { memcpy(out, str, len); out[len] = '\0'; } return out; } #endif squashfs-tools-ng-0.8/lib/fstree/000077500000000000000000000000001360235375500170255ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/fstree/Makemodule.am000066400000000000000000000012161360235375500214270ustar00rootroot00000000000000libfstree_a_SOURCES = lib/fstree/fstree.c lib/fstree/fstree_from_file.c libfstree_a_SOURCES += lib/fstree/fstree_sort.c lib/fstree/hardlink.c libfstree_a_SOURCES += lib/fstree/post_process.c lib/fstree/get_path.c libfstree_a_SOURCES += lib/fstree/mknode.c libfstree_a_SOURCES += lib/fstree/add_by_path.c lib/fstree/get_by_path.c libfstree_a_SOURCES += include/fstree.h lib/fstree/internal.h libfstree_a_SOURCES += lib/fstree/source_date_epoch.c libfstree_a_SOURCES += lib/fstree/canonicalize_name.c libfstree_a_SOURCES += lib/fstree/filename_sane.c libfstree_a_CFLAGS = $(AM_CFLAGS) libfstree_a_CPPFLAGS = $(AM_CPPFLAGS) noinst_LIBRARIES += libfstree.a squashfs-tools-ng-0.8/lib/fstree/add_by_path.c000066400000000000000000000021001360235375500214200ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * add_by_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include tree_node_t *fstree_add_generic(fstree_t *fs, const char *path, const struct stat *sb, const char *extra) { tree_node_t *child, *parent; const char *name; parent = fstree_get_node_by_path(fs, fs->root, path, true, true); if (parent == NULL) return NULL; name = strrchr(path, '/'); name = (name == NULL ? path : (name + 1)); child = parent->data.dir.children; while (child != NULL && strcmp(child->name, name) != 0) child = child->next; if (child != NULL) { if (!S_ISDIR(child->mode) || !S_ISDIR(sb->st_mode) || !child->data.dir.created_implicitly) { errno = EEXIST; return NULL; } child->uid = sb->st_uid; child->gid = sb->st_gid; child->mode = sb->st_mode; child->mod_time = sb->st_mtime; child->data.dir.created_implicitly = false; return child; } return fstree_mknode(parent, name, strlen(name), extra, sb); } squashfs-tools-ng-0.8/lib/fstree/canonicalize_name.c000066400000000000000000000020211360235375500226230ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * canonicalize_name.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" static void normalize_slashes(char *filename) { char *dst = filename, *src = filename; while (*src == '/' || *src == '\\') ++src; while (*src != '\0') { if (*src == '/' || *src == '\\') { while (*src == '/' || *src == '\\') ++src; if (*src == '\0') break; *(dst++) = '/'; } else { *(dst++) = *(src++); } } *dst = '\0'; } int canonicalize_name(char *filename) { char *dst = filename, *src = filename; normalize_slashes(filename); while (*src != '\0') { if (src[0] == '.') { if (src[1] == '\0') break; if (src[1] == '/') { src += 2; continue; } if (src[1] == '.' && (src[2] == '/' || src[2] == '\0')) return -1; } while (*src != '\0' && *src != '/') *(dst++) = *(src++); if (*src == '/') *(dst++) = *(src++); } *dst = '\0'; normalize_slashes(filename); return 0; } squashfs-tools-ng-0.8/lib/fstree/filename_sane.c000066400000000000000000000031571360235375500217650ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * filename_sane.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) #ifdef _MSC_VER #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif static const char *bad_names[] = { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", }; static bool is_allowed_by_os(const char *name) { size_t len, i; for (i = 0; i < sizeof(bad_names) / sizeof(bad_names[0]); ++i) { len = strlen(bad_names[i]); if (strncasecmp(name, bad_names[i], len) != 0) continue; if (name[len] == '\0') return false; if (name[len] == '.' && strchr(name + len + 1, '.') == NULL) return false; } return true; } #else static bool is_allowed_by_os(const char *name) { (void)name; return true; } #endif bool is_filename_sane(const char *name, bool check_os_specific) { if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) return false; if (check_os_specific && !is_allowed_by_os(name)) return false; while (*name != '\0') { if (*name == '/' || *name == '\\') return false; #if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) if (check_os_specific) { if (*name == '<' || *name == '>' || *name == ':') return false; if (*name == '"' || *name == '|' || *name == '?') return false; if (*name == '*' || *name <= 31) return false; } #endif ++name; } return true; } squashfs-tools-ng-0.8/lib/fstree/fstree.c000066400000000000000000000046341360235375500204700ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree.c * * Copyright (C) 2019 David Oberhollenzer */ #include "internal.h" #include #include #include enum { DEF_UID = 0, DEF_GID, DEF_MODE, DEF_MTIME, }; static const char *defaults[] = { [DEF_UID] = "uid", [DEF_GID] = "gid", [DEF_MODE] = "mode", [DEF_MTIME] = "mtime", NULL }; static int process_defaults(struct stat *sb, char *subopts) { char *value; long lval; int i; while (*subopts != '\0') { i = getsubopt(&subopts, (char *const *)defaults, &value); if (value == NULL) { fprintf(stderr, "Missing value for option %s\n", defaults[i]); return -1; } switch (i) { case DEF_UID: lval = strtol(value, NULL, 0); if (lval < 0) goto fail_uv; if (lval > (long)INT32_MAX) goto fail_ov; sb->st_uid = lval; break; case DEF_GID: lval = strtol(value, NULL, 0); if (lval < 0) goto fail_uv; if (lval > (long)INT32_MAX) goto fail_ov; sb->st_gid = lval; break; case DEF_MODE: lval = strtol(value, NULL, 0); if (lval < 0) goto fail_uv; if (lval > 07777) goto fail_ov; sb->st_mode = S_IFDIR | (sqfs_u16)lval; break; case DEF_MTIME: lval = strtol(value, NULL, 0); if (lval < 0) goto fail_uv; if (lval > (long)INT32_MAX) goto fail_ov; sb->st_mtime = lval; break; default: fprintf(stderr, "Unknown option '%s'\n", value); return -1; } } return 0; fail_uv: fprintf(stderr, "%s: value must be positive\n", defaults[i]); return -1; fail_ov: fprintf(stderr, "%s: value too large\n", defaults[i]); return -1; } static void free_recursive(tree_node_t *n) { tree_node_t *it; if (S_ISDIR(n->mode)) { while (n->data.dir.children != NULL) { it = n->data.dir.children; n->data.dir.children = it->next; free_recursive(it); } } free(n); } int fstree_init(fstree_t *fs, char *defaults) { memset(fs, 0, sizeof(*fs)); fs->defaults.st_mode = S_IFDIR | 0755; fs->defaults.st_blksize = 512; fs->defaults.st_mtime = get_source_date_epoch(); if (defaults != NULL && process_defaults(&fs->defaults, defaults) != 0) return -1; fs->root = fstree_mknode(NULL, "", 0, NULL, &fs->defaults); if (fs->root == NULL) { perror("initializing file system tree"); return -1; } return 0; } void fstree_cleanup(fstree_t *fs) { free_recursive(fs->root); free(fs->inodes); memset(fs, 0, sizeof(*fs)); } squashfs-tools-ng-0.8/lib/fstree/fstree_from_file.c000066400000000000000000000143771360235375500225170ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_from_file.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include #include #include static int add_generic(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *sb, const char *extra) { if (fstree_add_generic(fs, path, sb, extra) == NULL) { fprintf(stderr, "%s: " PRI_SZ ": %s: %s\n", filename, line_num, path, strerror(errno)); return -1; } return 0; } static int add_device(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *sb, const char *extra) { unsigned int maj, min; char c; if (sscanf(extra, "%c %u %u", &c, &maj, &min) != 3) { fprintf(stderr, "%s: " PRI_SZ ": " "expected ' major minor'\n", filename, line_num); return -1; } if (c == 'c' || c == 'C') { sb->st_mode |= S_IFCHR; } else if (c == 'b' || c == 'B') { sb->st_mode |= S_IFBLK; } else { fprintf(stderr, "%s: " PRI_SZ ": unknown device type '%c'\n", filename, line_num, c); return -1; } sb->st_rdev = makedev(maj, min); return add_generic(fs, filename, line_num, path, sb, NULL); } static int add_file(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *basic, const char *extra) { if (extra == NULL || *extra == '\0') extra = path; return add_generic(fs, filename, line_num, path, basic, extra); } static int add_hard_link(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *basic, const char *extra) { (void)basic; if (fstree_add_hard_link(fs, path, extra) == NULL) { fprintf(stderr, "%s: " PRI_SZ ": %s\n", filename, line_num, strerror(errno)); return -1; } return 0; } static const struct { const char *keyword; unsigned int mode; bool need_extra; int (*callback)(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *sb, const char *extra); } file_list_hooks[] = { { "dir", S_IFDIR, false, add_generic }, { "slink", S_IFLNK, true, add_generic }, { "link", 0, true, add_hard_link }, { "nod", 0, true, add_device }, { "pipe", S_IFIFO, false, add_generic }, { "sock", S_IFSOCK, false, add_generic }, { "file", S_IFREG, false, add_file }, }; #define NUM_HOOKS (sizeof(file_list_hooks) / sizeof(file_list_hooks[0])) static void trim_line(char *line) { size_t i; for (i = 0; isspace(line[i]); ++i) ; if (line[i] == '#') { line[0] = '\0'; return; } if (i > 0) memmove(line, line + i, strlen(line + i) + 1); i = strlen(line); while (i > 0 && isspace(line[i - 1])) --i; line[i] = '\0'; } static int handle_line(fstree_t *fs, const char *filename, size_t line_num, char *line) { const char *extra = NULL, *msg = NULL; char keyword[16], *path, *ptr; unsigned int x; struct stat sb; size_t i; memset(&sb, 0, sizeof(sb)); sb.st_mtime = fs->defaults.st_mtime; /* isolate keyword */ for (i = 0; isalpha(line[i]); ++i) ; if (i >= sizeof(keyword) || i == 0 || !isspace(line[i])) goto fail_ent; memcpy(keyword, line, i); keyword[i] = '\0'; while (isspace(line[i])) ++i; /* isolate path */ path = line + i; if (*path == '"') { ptr = path; ++i; while (line[i] != '\0' && line[i] != '"') { if (line[i] == '\\' && (line[i + 1] == '"' || line[i + 1] == '\\')) { *(ptr++) = line[i + 1]; i += 2; } else { *(ptr++) = line[i++]; } } if (line[i] != '"' || !isspace(line[i + 1])) goto fail_ent; *ptr = '\0'; ++i; } else { while (line[i] != '\0' && !isspace(line[i])) ++i; if (!isspace(line[i])) goto fail_ent; line[i++] = '\0'; } while (isspace(line[i])) ++i; if (canonicalize_name(path) || *path == '\0') goto fail_ent; /* mode */ if (!isdigit(line[i])) goto fail_mode; for (; isdigit(line[i]); ++i) { if (line[i] > '7') goto fail_mode; sb.st_mode = (sb.st_mode << 3) | (line[i] - '0'); if (sb.st_mode > 07777) goto fail_mode_bits; } if (!isspace(line[i])) goto fail_ent; while (isspace(line[i])) ++i; /* uid */ if (!isdigit(line[i])) goto fail_uid_gid; for (; isdigit(line[i]); ++i) { x = line[i] - '0'; if (sb.st_uid > (0xFFFFFFFF - x) / 10) goto fail_ent; sb.st_uid = sb.st_uid * 10 + x; } if (!isspace(line[i])) goto fail_ent; while (isspace(line[i])) ++i; /* gid */ if (!isdigit(line[i])) goto fail_uid_gid; for (; isdigit(line[i]); ++i) { x = line[i] - '0'; if (sb.st_gid > (0xFFFFFFFF - x) / 10) goto fail_ent; sb.st_gid = sb.st_gid * 10 + x; } /* extra */ if (isspace(line[i])) { while (isspace(line[i])) ++i; if (line[i] != '\0') extra = line + i; } /* forward to callback */ for (i = 0; i < NUM_HOOKS; ++i) { if (strcmp(file_list_hooks[i].keyword, keyword) == 0) { if (file_list_hooks[i].need_extra && extra == NULL) goto fail_no_extra; sb.st_mode |= file_list_hooks[i].mode; return file_list_hooks[i].callback(fs, filename, line_num, path, &sb, extra); } } fprintf(stderr, "%s: " PRI_SZ ": unknown entry type '%s'.\n", filename, line_num, keyword); return -1; fail_no_extra: fprintf(stderr, "%s: " PRI_SZ ": missing argument for %s.\n", filename, line_num, keyword); return -1; fail_uid_gid: msg = "uid & gid must be decimal numbers"; goto out_desc; fail_mode: msg = "mode must be an octal number"; goto out_desc; fail_mode_bits: msg = "you can only set the permission bits in the mode"; goto out_desc; fail_ent: msg = "error in entry description"; goto out_desc; out_desc: fprintf(stderr, "%s: " PRI_SZ ": %s.\n", filename, line_num, msg); fputs("expected: []\n", stderr); return -1; } int fstree_from_file(fstree_t *fs, const char *filename, FILE *fp) { size_t n, line_num = 0; ssize_t ret; char *line; for (;;) { line = NULL; n = 0; errno = 0; ret = getline(&line, &n, fp); ++line_num; if (ret < 0) { if (errno == 0) { free(line); break; } perror(filename); goto fail_line; } trim_line(line); if (line[0] == '\0') { free(line); continue; } if (handle_line(fs, filename, line_num, line)) goto fail_line; free(line); } return 0; fail_line: free(line); return -1; } squashfs-tools-ng-0.8/lib/fstree/fstree_sort.c000066400000000000000000000022131360235375500215260ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_sort.c * * Copyright (C) 2019 David Oberhollenzer * Copyright (C) 2019 Zachary Dremann */ #include "internal.h" #include static tree_node_t *merge(tree_node_t *lhs, tree_node_t *rhs) { tree_node_t *it; tree_node_t *head = NULL; tree_node_t **next_ptr = &head; while (lhs != NULL && rhs != NULL) { if (strcmp(lhs->name, rhs->name) <= 0) { it = lhs; lhs = lhs->next; } else { it = rhs; rhs = rhs->next; } *next_ptr = it; next_ptr = &it->next; } it = (lhs != NULL ? lhs : rhs); *next_ptr = it; return head; } tree_node_t *tree_node_list_sort(tree_node_t *head) { tree_node_t *it, *half, *prev; it = half = prev = head; while (it != NULL) { prev = half; half = half->next; it = it->next; if (it != NULL) { it = it->next; } } // half refers to the (count/2)'th element ROUNDED UP. // It will be null therefore only in the empty and the // single element list if (half == NULL) { return head; } prev->next = NULL; return merge(tree_node_list_sort(head), tree_node_list_sort(half)); } squashfs-tools-ng-0.8/lib/fstree/get_by_path.c000066400000000000000000000024101360235375500214530ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * get_by_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include static tree_node_t *child_by_name(tree_node_t *root, const char *name, size_t len) { tree_node_t *n = root->data.dir.children; while (n != NULL) { if (strncmp(n->name, name, len) == 0 && n->name[len] == '\0') break; n = n->next; } return n; } tree_node_t *fstree_get_node_by_path(fstree_t *fs, tree_node_t *root, const char *path, bool create_implicitly, bool stop_at_parent) { const char *end; tree_node_t *n; size_t len; while (*path != '\0') { while (*path == '/') ++path; if (!S_ISDIR(root->mode)) { errno = ENOTDIR; return NULL; } end = strchr(path, '/'); if (end == NULL) { if (stop_at_parent) break; len = strlen(path); } else { len = end - path; } n = child_by_name(root, path, len); if (n == NULL) { if (!create_implicitly) { errno = ENOENT; return NULL; } n = fstree_mknode(root, path, len, NULL, &fs->defaults); if (n == NULL) return NULL; n->data.dir.created_implicitly = true; } root = n; path = path + len; } return root; } squashfs-tools-ng-0.8/lib/fstree/get_path.c000066400000000000000000000013451360235375500207670ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * get_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include char *fstree_get_path(tree_node_t *node) { tree_node_t *it; char *str, *ptr; size_t len = 0; if (node->parent == NULL) return strdup("/"); for (it = node; it != NULL && it->parent != NULL; it = it->parent) { len += strlen(it->name) + 1; } str = malloc(len + 1); if (str == NULL) return NULL; ptr = str + len; *ptr = '\0'; for (it = node; it != NULL && it->parent != NULL; it = it->parent) { len = strlen(it->name); ptr -= len; memcpy(ptr, it->name, len); *(--ptr) = '/'; } return str; } squashfs-tools-ng-0.8/lib/fstree/hardlink.c000066400000000000000000000024621360235375500207710ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * hardlink.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path, const char *target) { struct stat sb; tree_node_t *n; memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFLNK | 0777; n = fstree_add_generic(fs, path, &sb, target); if (n != NULL) { if (canonicalize_name(n->data.target)) { free(n); errno = EINVAL; return NULL; } n->mode = FSTREE_MODE_HARD_LINK; } return n; } int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node) { tree_node_t *start = node; while (node->mode == FSTREE_MODE_HARD_LINK || node->mode == FSTREE_MODE_HARD_LINK_RESOLVED) { if (node->mode == FSTREE_MODE_HARD_LINK_RESOLVED) { node = node->data.target_node; } else { node = fstree_get_node_by_path(fs, fs->root, node->data.target, false, false); if (node == NULL) return -1; } if (node == start) { errno = EMLINK; return -1; } } if (S_ISDIR(node->mode)) { errno = EPERM; return -1; } start->mode = FSTREE_MODE_HARD_LINK_RESOLVED; start->data.target_node = node; node->link_count += 1; return 0; } squashfs-tools-ng-0.8/lib/fstree/internal.h000066400000000000000000000011041360235375500210060ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * internal.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef FSTREE_INTERNAL_H #define FSTREE_INTERNAL_H #include "config.h" #include "fstree.h" /* ASCIIbetically sort a linked list of tree nodes */ tree_node_t *tree_node_list_sort(tree_node_t *head); /* If the environment variable SOURCE_DATE_EPOCH is set to a parsable number that fits into an unsigned 32 bit value, return its value. Otherwise, default to 0. */ sqfs_u32 get_source_date_epoch(void); #endif /* FSTREE_INTERNAL_H */ squashfs-tools-ng-0.8/lib/fstree/mknode.c000066400000000000000000000026321360235375500204510ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mknode.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include tree_node_t *fstree_mknode(tree_node_t *parent, const char *name, size_t name_len, const char *extra, const struct stat *sb) { tree_node_t *n; size_t size; char *ptr; if (S_ISLNK(sb->st_mode) && extra == NULL) { errno = EINVAL; return NULL; } size = sizeof(tree_node_t) + name_len + 1; if (extra != NULL) size += strlen(extra) + 1; n = calloc(1, size); if (n == NULL) return NULL; if (parent != NULL) { n->next = parent->data.dir.children; parent->data.dir.children = n; n->parent = parent; } n->xattr_idx = 0xFFFFFFFF; n->uid = sb->st_uid; n->gid = sb->st_gid; n->mode = sb->st_mode; n->mod_time = sb->st_mtime; n->link_count = 1; n->name = (char *)n->payload; memcpy(n->name, name, name_len); if (extra != NULL) { ptr = n->name + name_len + 1; strcpy(ptr, extra); } else { ptr = NULL; } switch (sb->st_mode & S_IFMT) { case S_IFREG: n->data.file.input_file = ptr; break; case S_IFLNK: n->mode = S_IFLNK | 0777; n->data.target = ptr; break; case S_IFBLK: case S_IFCHR: n->data.devno = sb->st_rdev; break; case S_IFDIR: n->link_count = 2; break; } if (parent != NULL) parent->link_count += 1; return n; } squashfs-tools-ng-0.8/lib/fstree/post_process.c000066400000000000000000000100231360235375500217100ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * post_process.c * * Copyright (C) 2019 David Oberhollenzer */ #include "internal.h" #include #include #include #include #include static void alloc_inode_num_dfs(fstree_t *fs, tree_node_t *root) { bool has_subdirs = false; tree_node_t *it; for (it = root->data.dir.children; it != NULL; it = it->next) { if (S_ISDIR(it->mode)) { has_subdirs = true; break; } } if (has_subdirs) { for (it = root->data.dir.children; it != NULL; it = it->next) { if (S_ISDIR(it->mode)) alloc_inode_num_dfs(fs, it); } } for (it = root->data.dir.children; it != NULL; it = it->next) { if (it->mode != FSTREE_MODE_HARD_LINK_RESOLVED) { it->inode_num = fs->unique_inode_count + 1; fs->unique_inode_count += 1; } } } static int resolve_hard_links_dfs(fstree_t *fs, tree_node_t *n) { tree_node_t *it; if (n->mode == FSTREE_MODE_HARD_LINK) { if (fstree_resolve_hard_link(fs, n)) goto fail_link; assert(n->mode == FSTREE_MODE_HARD_LINK_RESOLVED); it = n->data.target_node; if (S_ISDIR(it->mode) && it->data.dir.visited) goto fail_link_loop; } else if (S_ISDIR(n->mode)) { n->data.dir.visited = true; for (it = n->data.dir.children; it != NULL; it = it->next) { if (resolve_hard_links_dfs(fs, it)) return -1; } n->data.dir.visited = false; } return 0; fail_link: { char *path = fstree_get_path(n); fprintf(stderr, "Resolving hard link '%s' -> '%s': %s\n", path == NULL ? n->name : path, n->data.target, strerror(errno)); free(path); } return -1; fail_link_loop: { char *npath = fstree_get_path(n); char *tpath = fstree_get_path(it); fprintf(stderr, "Hard link loop detected in '%s' -> '%s'\n", npath == NULL ? n->name : npath, tpath == NULL ? it->name : tpath); free(npath); free(tpath); } return -1; } static void sort_recursive(tree_node_t *n) { n->data.dir.children = tree_node_list_sort(n->data.dir.children); for (n = n->data.dir.children; n != NULL; n = n->next) { if (S_ISDIR(n->mode)) sort_recursive(n); } } static file_info_t *file_list_dfs(tree_node_t *n) { if (S_ISREG(n->mode)) { n->data.file.next = NULL; return &n->data.file; } if (S_ISDIR(n->mode)) { file_info_t *list = NULL, *last = NULL; for (n = n->data.dir.children; n != NULL; n = n->next) { if (list == NULL) { list = file_list_dfs(n); if (list == NULL) continue; last = list; } else { last->next = file_list_dfs(n); } while (last->next != NULL) last = last->next; } return list; } return NULL; } static void map_inodes_dfs(fstree_t *fs, tree_node_t *n) { if (n->mode == FSTREE_MODE_HARD_LINK_RESOLVED) return; fs->inodes[n->inode_num - 1] = n; if (S_ISDIR(n->mode)) { for (n = n->data.dir.children; n != NULL; n = n->next) map_inodes_dfs(fs, n); } } static void reorder_hard_links(fstree_t *fs) { size_t i, j, tgt_idx; tree_node_t *it, *tgt; for (i = 0; i < fs->unique_inode_count; ++i) { if (!S_ISDIR(fs->inodes[i]->mode)) continue; it = fs->inodes[i]->data.dir.children; for (; it != NULL; it = it->next) { if (it->mode != FSTREE_MODE_HARD_LINK_RESOLVED) continue; tgt = it->data.target_node; tgt_idx = tgt->inode_num - 1; if (tgt_idx <= i) continue; /* TODO ? */ assert(!S_ISDIR(tgt->mode)); for (j = tgt_idx; j > i; --j) { fs->inodes[j] = fs->inodes[j - 1]; fs->inodes[j]->inode_num += 1; } fs->inodes[i] = tgt; tgt->inode_num = i + 1; ++i; } } } int fstree_post_process(fstree_t *fs) { sort_recursive(fs->root); if (resolve_hard_links_dfs(fs, fs->root)) return -1; fs->unique_inode_count = 0; alloc_inode_num_dfs(fs, fs->root); fs->root->inode_num = fs->unique_inode_count + 1; fs->unique_inode_count += 1; fs->inodes = calloc(sizeof(fs->inodes[0]), fs->unique_inode_count); if (fs->inodes == NULL) { perror("Allocating inode list"); return -1; } map_inodes_dfs(fs, fs->root); reorder_hard_links(fs); fs->files = file_list_dfs(fs->root); return 0; } squashfs-tools-ng-0.8/lib/fstree/source_date_epoch.c000066400000000000000000000014701360235375500226460ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * source_date_epoch.c * * Copyright (C) 2019 David Oberhollenzer */ #include "internal.h" #include #include #include sqfs_u32 get_source_date_epoch(void) { const char *str, *ptr; sqfs_u32 x, tval = 0; str = getenv("SOURCE_DATE_EPOCH"); if (str == NULL || *str == '\0') return 0; for (ptr = str; *ptr != '\0'; ++ptr) { if (!isdigit(*ptr)) goto fail_nan; x = (*ptr) - '0'; if (tval > (UINT32_MAX - x) / 10) goto fail_ov; tval = tval * 10 + x; } return tval; fail_ov: fprintf(stderr, "WARNING: SOURCE_DATE_EPOCH=%s does not fit into " "32 bit integer\n", str); return 0; fail_nan: fprintf(stderr, "WARNING: SOURCE_DATE_EPOCH=%s is not a positive " "number\n", str); return 0; } squashfs-tools-ng-0.8/lib/sqfs/000077500000000000000000000000001360235375500165115ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/Makemodule.am000066400000000000000000000107251360235375500211200ustar00rootroot00000000000000LIBSQFS_HEARDS = include/sqfs/meta_writer.h \ include/sqfs/meta_reader.h include/sqfs/id_table.h \ include/sqfs/compressor.h include/sqfs/data_writer.h \ include/sqfs/super.h include/sqfs/inode.h \ include/sqfs/dir.h include/sqfs/xattr.h \ include/sqfs/table.h include/sqfs/predef.h \ include/sqfs/error.h include/sqfs/dir_reader.h \ include/sqfs/dir_writer.h include/sqfs/io.h \ include/sqfs/data_reader.h include/sqfs/block.h \ include/sqfs/xattr_reader.h include/sqfs/xattr_writer.h libsquashfs_la_SOURCES = $(LIBSQFS_HEARDS) lib/sqfs/id_table.c lib/sqfs/super.c libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/xattr.c libsquashfs_la_SOURCES += lib/sqfs/write_table.c lib/sqfs/meta_writer.c libsquashfs_la_SOURCES += lib/sqfs/read_super.c lib/sqfs/meta_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_inode.c lib/sqfs/write_inode.c libsquashfs_la_SOURCES += lib/sqfs/dir_writer.c lib/sqfs/xattr_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_table.c lib/sqfs/comp/compressor.c libsquashfs_la_SOURCES += lib/sqfs/comp/internal.h lib/sqfs/xattr_writer.c libsquashfs_la_SOURCES += lib/sqfs/dir_reader.c lib/sqfs/read_tree.c libsquashfs_la_SOURCES += lib/sqfs/inode.c lib/sqfs/data_writer/fragment.c libsquashfs_la_SOURCES += lib/sqfs/write_super.c lib/sqfs/data_writer/block.c libsquashfs_la_SOURCES += lib/sqfs/data_writer/internal.h lib/sqfs/data_reader.c libsquashfs_la_SOURCES += lib/sqfs/data_writer/common.c libsquashfs_la_SOURCES += lib/sqfs/data_writer/fileapi.c libsquashfs_la_SOURCES += lib/sqfs/str_table.c lib/sqfs/str_table.h libsquashfs_la_SOURCES += lib/sqfs/alloc.c lib/sqfs/util.h libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS) libsquashfs_la_LDFLAGS = $(AM_LDFLAGS) libsquashfs_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) libsquashfs_la_CFLAGS += $(XZ_CFLAGS) $(LZ4_CFLAGS) libsquashfs_la_CFLAGS += $(ZSTD_CFLAGS) $(PTHREAD_CFLAGS) libsquashfs_la_LIBADD = $(XZ_LIBS) $(ZLIB_LIBS) $(LZ4_LIBS) libsquashfs_la_LIBADD += $(ZSTD_LIBS) $(PTHREAD_LIBS) if WINDOWS libsquashfs_la_SOURCES += lib/sqfs/win32/io_file.c libsquashfs_la_CFLAGS += -DWINVER=0x0600 -D_WIN32_WINNT=0x0600 libsquashfs_la_CFLAGS += -Wc,-static-libgcc libsquashfs_la_LDFLAGS += -no-undefined -avoid-version else libsquashfs_la_SOURCES += lib/sqfs/unix/io_file.c endif if HAVE_PTHREAD libsquashfs_la_SOURCES += lib/sqfs/data_writer/winpthread.c libsquashfs_la_CPPFLAGS += -DWITH_PTHREAD else if WINDOWS libsquashfs_la_SOURCES += lib/sqfs/data_writer/winpthread.c else libsquashfs_la_SOURCES += lib/sqfs/data_writer/serial.c endif endif if WITH_GZIP libsquashfs_la_SOURCES += lib/sqfs/comp/gzip.c libsquashfs_la_CPPFLAGS += -DWITH_GZIP if WITH_OWN_ZLIB libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/adler32.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/deflate.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/deflate.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inffast.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inffast.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inffixed.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inflate.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inflate.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/zconf.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/trees.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inftrees.c libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/inftrees.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/zlib.h lib/sqfs/comp/zlib/trees.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/zutil.c lib/sqfs/comp/zlib/zutil.h libsquashfs_la_SOURCES += lib/sqfs/comp/zlib/crc32.c lib/sqfs/comp/zlib/crc32.h libsquashfs_la_CPPFLAGS += -I$(top_srcdir)/lib/sqfs/comp/zlib -DZLIB_CONST=1 libsquashfs_la_CPPFLAGS += -DNO_GZCOMPRESS=1 -DNO_GZIP=1 -DHAVE_MEMCPY=1 endif endif if WITH_XZ libsquashfs_la_SOURCES += lib/sqfs/comp/xz.c libsquashfs_la_SOURCES += lib/sqfs/comp/lzma.c libsquashfs_la_CPPFLAGS += -DWITH_XZ endif if WITH_LZ4 libsquashfs_la_SOURCES += lib/sqfs/comp/lz4.c libsquashfs_la_CPPFLAGS += -DWITH_LZ4 if WITH_OWN_LZ4 libsquashfs_la_CPPFLAGS += -I$(top_srcdir)/lib/sqfs/comp/lz4 -DLZ4_HEAPMODE=1 libsquashfs_la_SOURCES += lib/sqfs/comp/lz4/lz4.c lib/sqfs/comp/lz4/lz4.h libsquashfs_la_SOURCES += lib/sqfs/comp/lz4/lz4hc.c lib/sqfs/comp/lz4/lz4hc.h endif endif if WITH_ZSTD libsquashfs_la_SOURCES += lib/sqfs/comp/zstd.c libsquashfs_la_CPPFLAGS += -DWITH_ZSTD endif sqfsincludedir = $(includedir)/sqfs sqfsinclude_HEADERS = $(LIBSQFS_HEARDS) lib_LTLIBRARIES += libsquashfs.la pkgconfig_DATA += lib/sqfs/libsquashfs0.pc EXTRA_DIST += lib/sqfs/comp/lz4/README lib/sqfs/comp/zlib/README squashfs-tools-ng-0.8/lib/sqfs/alloc.c000066400000000000000000000011651360235375500177520ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * alloc.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "util.h" #include #include void *alloc_flex(size_t base_size, size_t item_size, size_t nmemb) { size_t size; if (SZ_MUL_OV(nmemb, item_size, &size) || SZ_ADD_OV(base_size, size, &size)) { errno = EOVERFLOW; return NULL; } return calloc(1, size); } void *alloc_array(size_t item_size, size_t nmemb) { size_t size; if (SZ_MUL_OV(nmemb, item_size, &size)) { errno = EOVERFLOW; return NULL; } return calloc(1, size); } squashfs-tools-ng-0.8/lib/sqfs/comp/000077500000000000000000000000001360235375500174475ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/comp/compressor.c000066400000000000000000000072501360235375500220130ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * compressor.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include "internal.h" typedef sqfs_compressor_t *(*compressor_fun_t) (const sqfs_compressor_config_t *cfg); static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = { #ifdef WITH_GZIP [SQFS_COMP_GZIP] = gzip_compressor_create, #endif #ifdef WITH_XZ [SQFS_COMP_XZ] = xz_compressor_create, [SQFS_COMP_LZMA] = lzma_compressor_create, #endif #ifdef WITH_LZ4 [SQFS_COMP_LZ4] = lz4_compressor_create, #endif #ifdef WITH_ZSTD [SQFS_COMP_ZSTD] = zstd_compressor_create, #endif }; static const char *names[] = { [SQFS_COMP_GZIP] = "gzip", [SQFS_COMP_LZMA] = "lzma", [SQFS_COMP_LZO] = "lzo", [SQFS_COMP_XZ] = "xz", [SQFS_COMP_LZ4] = "lz4", [SQFS_COMP_ZSTD] = "zstd", }; int sqfs_generic_write_options(sqfs_file_t *file, const void *data, size_t size) { sqfs_u8 buffer[size + 2]; int ret; *((sqfs_u16 *)buffer) = htole16(0x8000 | size); memcpy(buffer + 2, data, size); ret = file->write_at(file, sizeof(sqfs_super_t), buffer, sizeof(buffer)); if (ret) return ret; return sizeof(buffer); } int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size) { sqfs_u8 buffer[size + 2]; int ret; ret = file->read_at(file, sizeof(sqfs_super_t), buffer, sizeof(buffer)); if (ret) return ret; if (le16toh(*((sqfs_u16 *)buffer)) != (0x8000 | size)) return SQFS_ERROR_CORRUPTED; memcpy(data, buffer + 2, size); return 0; } bool sqfs_compressor_exists(E_SQFS_COMPRESSOR id) { if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX) return false; return (compressors[id] != NULL); } sqfs_compressor_t *sqfs_compressor_create(const sqfs_compressor_config_t *cfg) { sqfs_u8 padd0[sizeof(cfg->opt)]; int ret; if (cfg == NULL || cfg->id < SQFS_COMP_MIN || cfg->id > SQFS_COMP_MAX) return NULL; if (compressors[cfg->id] == NULL) return NULL; memset(padd0, 0, sizeof(padd0)); switch (cfg->id) { case SQFS_COMP_XZ: ret = memcmp(cfg->opt.xz.padd0, padd0, sizeof(cfg->opt.xz.padd0)); break; case SQFS_COMP_LZO: ret = memcmp(cfg->opt.lzo.padd0, padd0, sizeof(cfg->opt.lzo.padd0)); break; case SQFS_COMP_ZSTD: ret = memcmp(cfg->opt.zstd.padd0, padd0, sizeof(cfg->opt.zstd.padd0)); break; case SQFS_COMP_GZIP: ret = memcmp(cfg->opt.gzip.padd0, padd0, sizeof(cfg->opt.gzip.padd0)); break; default: ret = memcmp(cfg->opt.padd0, padd0, sizeof(cfg->opt.padd0)); break; } if (ret != 0) return NULL; return compressors[cfg->id](cfg); } const char *sqfs_compressor_name_from_id(E_SQFS_COMPRESSOR id) { if (id < 0 || (size_t)id >= sizeof(names) / sizeof(names[0])) return NULL; return names[id]; } int sqfs_compressor_id_from_name(const char *name) { size_t i; for (i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { if (names[i] != NULL && strcmp(names[i], name) == 0) return i; } return SQFS_ERROR_UNSUPPORTED; } int sqfs_compressor_config_init(sqfs_compressor_config_t *cfg, E_SQFS_COMPRESSOR id, size_t block_size, sqfs_u16 flags) { memset(cfg, 0, sizeof(*cfg)); cfg->id = id; cfg->flags = flags; cfg->block_size = block_size; switch (id) { case SQFS_COMP_GZIP: cfg->opt.gzip.level = SQFS_GZIP_DEFAULT_LEVEL; cfg->opt.gzip.window_size = SQFS_GZIP_DEFAULT_WINDOW; break; case SQFS_COMP_LZO: cfg->opt.lzo.algorithm = SQFS_LZO_DEFAULT_ALG; cfg->opt.lzo.level = SQFS_LZO_DEFAULT_LEVEL; break; case SQFS_COMP_ZSTD: cfg->opt.zstd.level = SQFS_ZSTD_DEFAULT_LEVEL; break; case SQFS_COMP_XZ: cfg->opt.xz.dict_size = block_size; break; default: break; } return 0; } squashfs-tools-ng-0.8/lib/sqfs/comp/gzip.c000066400000000000000000000142771360235375500205770ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * gzip.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include #include #include #include "internal.h" typedef struct { sqfs_u32 level; sqfs_u16 window; sqfs_u16 strategies; } gzip_options_t; typedef struct { sqfs_compressor_t base; z_stream strm; bool compress; size_t block_size; gzip_options_t opt; } gzip_compressor_t; static void gzip_destroy(sqfs_compressor_t *base) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; if (gzip->compress) { deflateEnd(&gzip->strm); } else { inflateEnd(&gzip->strm); } free(gzip); } static int gzip_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; gzip_options_t opt; if (gzip->opt.level == SQFS_GZIP_DEFAULT_LEVEL && gzip->opt.window == SQFS_GZIP_DEFAULT_WINDOW && gzip->opt.strategies == 0) { return 0; } opt.level = htole32(gzip->opt.level); opt.window = htole16(gzip->opt.window); opt.strategies = htole16(gzip->opt.strategies); return sqfs_generic_write_options(file, &opt, sizeof(opt)); } static int gzip_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; gzip_options_t opt; int ret; ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; gzip->opt.level = le32toh(opt.level); gzip->opt.window = le16toh(opt.window); gzip->opt.strategies = le16toh(opt.strategies); if (gzip->opt.level < 1 || gzip->opt.level > 9) return SQFS_ERROR_UNSUPPORTED; if (gzip->opt.window < 8 || gzip->opt.window > 15) return SQFS_ERROR_UNSUPPORTED; if (gzip->opt.strategies & ~SQFS_COMP_FLAG_GZIP_ALL) return SQFS_ERROR_UNSUPPORTED; return 0; } static int flag_to_zlib_strategy(int flag) { switch (flag) { case SQFS_COMP_FLAG_GZIP_DEFAULT: return Z_DEFAULT_STRATEGY; case SQFS_COMP_FLAG_GZIP_FILTERED: return Z_FILTERED; case SQFS_COMP_FLAG_GZIP_HUFFMAN: return Z_HUFFMAN_ONLY; case SQFS_COMP_FLAG_GZIP_RLE: return Z_RLE; case SQFS_COMP_FLAG_GZIP_FIXED: return Z_FIXED; } return 0; } static int find_strategy(gzip_compressor_t *gzip, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { int ret, strategy, selected = Z_DEFAULT_STRATEGY; size_t i, length, minlength = 0; for (i = 0x01; i & SQFS_COMP_FLAG_GZIP_ALL; i <<= 1) { if ((gzip->opt.strategies & i) == 0) continue; ret = deflateReset(&gzip->strm); if (ret != Z_OK) return SQFS_ERROR_COMPRESSOR; strategy = flag_to_zlib_strategy(i); gzip->strm.next_in = (void *)in; gzip->strm.avail_in = size; gzip->strm.next_out = out; gzip->strm.avail_out = outsize; ret = deflateParams(&gzip->strm, gzip->opt.level, strategy); if (ret != Z_OK) return SQFS_ERROR_COMPRESSOR; ret = deflate(&gzip->strm, Z_FINISH); if (ret == Z_STREAM_END) { length = gzip->strm.total_out; if (minlength == 0 || length < minlength) { minlength = length; selected = strategy; } } else if (ret != Z_OK && ret != Z_BUF_ERROR) { return SQFS_ERROR_COMPRESSOR; } } return selected; } static sqfs_s32 gzip_do_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; int ret, strategy = 0; size_t written; if (size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; if (gzip->compress && gzip->opt.strategies != 0) { strategy = find_strategy(gzip, in, size, out, outsize); if (strategy < 0) return strategy; } if (gzip->compress) { ret = deflateReset(&gzip->strm); } else { ret = inflateReset(&gzip->strm); } if (ret != Z_OK) return SQFS_ERROR_COMPRESSOR; gzip->strm.next_in = (void *)in; gzip->strm.avail_in = size; gzip->strm.next_out = out; gzip->strm.avail_out = outsize; if (gzip->compress && gzip->opt.strategies != 0) { ret = deflateParams(&gzip->strm, gzip->opt.level, strategy); if (ret != Z_OK) return SQFS_ERROR_COMPRESSOR; } if (gzip->compress) { ret = deflate(&gzip->strm, Z_FINISH); } else { ret = inflate(&gzip->strm, Z_FINISH); } if (ret == Z_STREAM_END) { written = gzip->strm.total_out; if (gzip->compress && written >= size) return 0; return written; } if (ret != Z_OK && ret != Z_BUF_ERROR) return SQFS_ERROR_COMPRESSOR; return 0; } static sqfs_compressor_t *gzip_create_copy(sqfs_compressor_t *cmp) { gzip_compressor_t *gzip = malloc(sizeof(*gzip)); int ret; if (gzip == NULL) return NULL; memcpy(gzip, cmp, sizeof(*gzip)); memset(&gzip->strm, 0, sizeof(gzip->strm)); if (gzip->compress) { ret = deflateInit2(&gzip->strm, gzip->opt.level, Z_DEFLATED, gzip->opt.window, 8, Z_DEFAULT_STRATEGY); } else { ret = inflateInit(&gzip->strm); } if (ret != Z_OK) { free(gzip); return NULL; } return (sqfs_compressor_t *)gzip; } sqfs_compressor_t *gzip_compressor_create(const sqfs_compressor_config_t *cfg) { gzip_compressor_t *gzip; sqfs_compressor_t *base; int ret; if (cfg->flags & ~(SQFS_COMP_FLAG_GZIP_ALL | SQFS_COMP_FLAG_GENERIC_ALL)) { return NULL; } if (cfg->opt.gzip.level < SQFS_GZIP_MIN_LEVEL || cfg->opt.gzip.level > SQFS_GZIP_MAX_LEVEL) { return NULL; } if (cfg->opt.gzip.window_size < SQFS_GZIP_MIN_WINDOW || cfg->opt.gzip.window_size > SQFS_GZIP_MAX_WINDOW) { return NULL; } gzip = calloc(1, sizeof(*gzip)); base = (sqfs_compressor_t *)gzip; if (gzip == NULL) return NULL; gzip->opt.level = cfg->opt.gzip.level; gzip->opt.window = cfg->opt.gzip.window_size; gzip->opt.strategies = cfg->flags & SQFS_COMP_FLAG_GZIP_ALL; gzip->compress = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) == 0; gzip->block_size = cfg->block_size; base->do_block = gzip_do_block; base->destroy = gzip_destroy; base->write_options = gzip_write_options; base->read_options = gzip_read_options; base->create_copy = gzip_create_copy; if (gzip->compress) { ret = deflateInit2(&gzip->strm, cfg->opt.gzip.level, Z_DEFLATED, cfg->opt.gzip.window_size, 8, Z_DEFAULT_STRATEGY); } else { ret = inflateInit(&gzip->strm); } if (ret != Z_OK) { free(gzip); return NULL; } return base; } squashfs-tools-ng-0.8/lib/sqfs/comp/internal.h000066400000000000000000000020141360235375500214310ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * internal.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef INTERNAL_H #define INTERNAL_H #include "config.h" #include "sqfs/predef.h" #include "sqfs/compressor.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "../util.h" SQFS_INTERNAL int sqfs_generic_write_options(sqfs_file_t *file, const void *data, size_t size); SQFS_INTERNAL int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size); SQFS_INTERNAL sqfs_compressor_t *xz_compressor_create(const sqfs_compressor_config_t *cfg); SQFS_INTERNAL sqfs_compressor_t *gzip_compressor_create(const sqfs_compressor_config_t *cfg); SQFS_INTERNAL sqfs_compressor_t *lz4_compressor_create(const sqfs_compressor_config_t *cfg); SQFS_INTERNAL sqfs_compressor_t *zstd_compressor_create(const sqfs_compressor_config_t *cfg); SQFS_INTERNAL sqfs_compressor_t *lzma_compressor_create(const sqfs_compressor_config_t *cfg); #endif /* INTERNAL_H */ squashfs-tools-ng-0.8/lib/sqfs/comp/lz4.c000066400000000000000000000056541360235375500203360ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * lz4.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include #include #include #include "internal.h" typedef struct { sqfs_compressor_t base; bool high_compression; } lz4_compressor_t; typedef struct { sqfs_u32 version; sqfs_u32 flags; } lz4_options; #define LZ4LEGACY 1 static int lz4_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { lz4_compressor_t *lz4 = (lz4_compressor_t *)base; lz4_options opt = { .version = htole32(LZ4LEGACY), .flags = htole32(lz4->high_compression ? SQFS_COMP_FLAG_LZ4_HC : 0), }; return sqfs_generic_write_options(file, &opt, sizeof(opt)); } static int lz4_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { lz4_options opt; int ret; (void)base; ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; opt.version = le32toh(opt.version); opt.flags = le32toh(opt.flags); if (opt.version != LZ4LEGACY) return SQFS_ERROR_UNSUPPORTED; return 0; } static sqfs_s32 lz4_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { lz4_compressor_t *lz4 = (lz4_compressor_t *)base; int ret; if (size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; if (lz4->high_compression) { ret = LZ4_compress_HC((void *)in, (void *)out, size, outsize, LZ4HC_CLEVEL_MAX); } else { ret = LZ4_compress_default((void *)in, (void *)out, size, outsize); } if (ret < 0) return SQFS_ERROR_COMPRESSOR; return ret; } static sqfs_s32 lz4_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { int ret; (void)base; if (outsize >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; ret = LZ4_decompress_safe((void *)in, (void *)out, size, outsize); if (ret < 0) return SQFS_ERROR_COMPRESSOR; return ret; } static sqfs_compressor_t *lz4_create_copy(sqfs_compressor_t *cmp) { lz4_compressor_t *lz4 = malloc(sizeof(*lz4)); if (lz4 == NULL) return NULL; memcpy(lz4, cmp, sizeof(*lz4)); return (sqfs_compressor_t *)lz4; } static void lz4_destroy(sqfs_compressor_t *base) { free(base); } sqfs_compressor_t *lz4_compressor_create(const sqfs_compressor_config_t *cfg) { sqfs_compressor_t *base; lz4_compressor_t *lz4; if (cfg->flags & ~(SQFS_COMP_FLAG_LZ4_ALL | SQFS_COMP_FLAG_GENERIC_ALL)) { return NULL; } lz4 = calloc(1, sizeof(*lz4)); base = (sqfs_compressor_t *)lz4; if (lz4 == NULL) return NULL; lz4->high_compression = (cfg->flags & SQFS_COMP_FLAG_LZ4_HC) != 0; base->destroy = lz4_destroy; base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ? lz4_uncomp_block : lz4_comp_block; base->write_options = lz4_write_options; base->read_options = lz4_read_options; base->create_copy = lz4_create_copy; return base; } squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/000077500000000000000000000000001360235375500201605ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/README000066400000000000000000000011041360235375500210340ustar00rootroot00000000000000This source has been extracted from the lz4 release tarball, version 1.9.2 released on August 20th, 2019. The source code originates from the "lib" subdirectory. The license is included in the subdirectory licenses/LZ4.txt in the tools-ng subdirectory of the squashfs-tools-ng source package. The following modifications have been made: - Always define LZ4LIB_API and LZ4LIB_STATIC_API to set default visibility to hidden, so the LZ4 functions aren't exported from libsquashfs. - Remove the streaming functions and most of the functions that aren't used by libsquashfs. squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/lz4.c000066400000000000000000002141331360235375500210410ustar00rootroot00000000000000/* LZ4 - Fast LZ compression algorithm Copyright (C) 2011-present, 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 : - LZ4 homepage : http://www.lz4.org - LZ4 source repository : https://github.com/lz4/lz4 */ /*-************************************ * Tuning parameters **************************************/ /* * LZ4_HEAPMODE : * Select how default compression functions will allocate memory for their hash table, * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). */ #ifndef LZ4_HEAPMODE # define LZ4_HEAPMODE 0 #endif /* * ACCELERATION_DEFAULT : * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 */ #define ACCELERATION_DEFAULT 1 /*-************************************ * CPU Feature Detection **************************************/ /* LZ4_FORCE_MEMORY_ACCESS * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. * The below switch allow to select different access method for improved performance. * Method 0 (default) : use `memcpy()`. Safe and portable. * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. * Method 2 : direct access. This method is portable but violate C standard. * It can generate buggy code on targets which assembly generation depends on alignment. * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally */ # if defined(__GNUC__) && \ ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \ || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) # define LZ4_FORCE_MEMORY_ACCESS 2 # elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) # define LZ4_FORCE_MEMORY_ACCESS 1 # endif #endif /* * LZ4_FORCE_SW_BITCOUNT * Define this parameter if your target system or compiler does not support hardware bit count */ #if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */ # define LZ4_FORCE_SW_BITCOUNT #endif /*-************************************ * Dependency **************************************/ /* * LZ4_SRC_INCLUDED: * Amalgamation flag, whether lz4.c is included */ #ifndef LZ4_SRC_INCLUDED # define LZ4_SRC_INCLUDED 1 #endif #ifndef LZ4_STATIC_LINKING_ONLY #define LZ4_STATIC_LINKING_ONLY #endif #ifndef LZ4_DISABLE_DEPRECATE_WARNINGS #define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */ #endif #define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */ #include "lz4.h" /* see also "memory routines" below */ /*-************************************ * Compiler Options **************************************/ #ifdef _MSC_VER /* Visual Studio */ # include # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ #endif /* _MSC_VER */ #ifndef LZ4_FORCE_INLINE # ifdef _MSC_VER /* Visual Studio */ # define LZ4_FORCE_INLINE static __forceinline # else # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # ifdef __GNUC__ # define LZ4_FORCE_INLINE static inline __attribute__((always_inline)) # else # define LZ4_FORCE_INLINE static inline # endif # else # define LZ4_FORCE_INLINE static # endif /* __STDC_VERSION__ */ # endif /* _MSC_VER */ #endif /* LZ4_FORCE_INLINE */ /* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8, * together with a simple 8-byte copy loop as a fall-back path. * However, this optimization hurts the decompression speed by >30%, * because the execution does not go to the optimized loop * for typical compressible data, and all of the preamble checks * before going to the fall-back path become useless overhead. * This optimization happens only with the -O3 flag, and -O2 generates * a simple 8-byte copy loop. * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8 * functions are annotated with __attribute__((optimize("O2"))), * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute * of LZ4_wildCopy8 does not affect the compression speed. */ #if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__) # define LZ4_FORCE_O2_GCC_PPC64LE __attribute__((optimize("O2"))) # define LZ4_FORCE_O2_INLINE_GCC_PPC64LE __attribute__((optimize("O2"))) LZ4_FORCE_INLINE #else # define LZ4_FORCE_O2_GCC_PPC64LE # define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static #endif #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) # define expect(expr,value) (__builtin_expect ((expr),(value)) ) #else # define expect(expr,value) (expr) #endif #ifndef likely #define likely(expr) expect((expr) != 0, 1) #endif #ifndef unlikely #define unlikely(expr) expect((expr) != 0, 0) #endif /*-************************************ * Memory routines **************************************/ #include /* malloc, calloc, free */ #define ALLOC(s) malloc(s) #define ALLOC_AND_ZERO(s) calloc(1,s) #define FREEMEM(p) free(p) #include /* memset, memcpy */ #define MEM_INIT(p,v,s) memset((p),(v),(s)) /*-************************************ * Common Constants **************************************/ #define MINMATCH 4 #define WILDCOPYLENGTH 8 #define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ #define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ #define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */ #define FASTLOOP_SAFE_DISTANCE 64 static const int LZ4_minLength = (MFLIMIT+1); #define KB *(1 <<10) #define MB *(1 <<20) #define GB *(1U<<30) #define LZ4_DISTANCE_ABSOLUTE_MAX 65535 #if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX) /* max supported by LZ4 format */ # error "LZ4_DISTANCE_MAX is too big : must be <= 65535" #endif #define ML_BITS 4 #define ML_MASK ((1U<=1) # include #else # ifndef assert # define assert(condition) ((void)0) # endif #endif #define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) # include static int g_debuglog_enable = 1; # define DEBUGLOG(l, ...) { \ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ fprintf(stderr, __FILE__ ": "); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, " \n"); \ } } #else # define DEBUGLOG(l, ...) {} /* disabled */ #endif /*-************************************ * Types **************************************/ #if defined(__cplusplus) || (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; typedef uintptr_t uptrval; #else typedef unsigned char BYTE; typedef unsigned short U16; typedef unsigned int U32; typedef signed int S32; typedef unsigned long long U64; typedef size_t uptrval; /* generally true, except OpenVMS-64 */ #endif #if defined(__x86_64__) typedef U64 reg_t; /* 64-bits in x32 mode */ #else typedef size_t reg_t; /* 32-bits in x32 mode */ #endif typedef enum { notLimited = 0, limitedOutput = 1, fillOutput = 2 } limitedOutput_directive; /*-************************************ * Reading and writing into memory **************************************/ static unsigned LZ4_isLittleEndian(void) { const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; } #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) /* lie to the compiler about data alignment; use with caution */ static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ /* currently only defined for gcc and icc */ typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } #else /* safe and portable access using memcpy() */ static U16 LZ4_read16(const void* memPtr) { U16 val; memcpy(&val, memPtr, sizeof(val)); return val; } static U32 LZ4_read32(const void* memPtr) { U32 val; memcpy(&val, memPtr, sizeof(val)); return val; } static reg_t LZ4_read_ARCH(const void* memPtr) { reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; } static void LZ4_write16(void* memPtr, U16 value) { memcpy(memPtr, &value, sizeof(value)); } static void LZ4_write32(void* memPtr, U32 value) { memcpy(memPtr, &value, sizeof(value)); } #endif /* LZ4_FORCE_MEMORY_ACCESS */ static U16 LZ4_readLE16(const void* memPtr) { if (LZ4_isLittleEndian()) { return LZ4_read16(memPtr); } else { const BYTE* p = (const BYTE*)memPtr; return (U16)((U16)p[0] + (p[1]<<8)); } } static void LZ4_writeLE16(void* memPtr, U16 value) { if (LZ4_isLittleEndian()) { LZ4_write16(memPtr, value); } else { BYTE* p = (BYTE*)memPtr; p[0] = (BYTE) value; p[1] = (BYTE)(value>>8); } } /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ LZ4_FORCE_O2_INLINE_GCC_PPC64LE void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; BYTE* const e = (BYTE*)dstEnd; do { memcpy(d,s,8); d+=8; s+=8; } while (d= 16. */ LZ4_FORCE_O2_INLINE_GCC_PPC64LE void LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; BYTE* const e = (BYTE*)dstEnd; do { memcpy(d,s,16); memcpy(d+16,s+16,16); d+=32; s+=32; } while (d= dstPtr + MINMATCH * - there is at least 8 bytes available to write after dstEnd */ LZ4_FORCE_O2_INLINE_GCC_PPC64LE void LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) { BYTE v[8]; assert(dstEnd >= dstPtr + MINMATCH); LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */ switch(offset) { case 1: memset(v, *srcPtr, 8); break; case 2: memcpy(v, srcPtr, 2); memcpy(&v[2], srcPtr, 2); memcpy(&v[4], &v[0], 4); break; case 4: memcpy(v, srcPtr, 4); memcpy(&v[4], srcPtr, 4); break; default: LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset); return; } memcpy(dstPtr, v, 8); dstPtr += 8; while (dstPtr < dstEnd) { memcpy(dstPtr, v, 8); dstPtr += 8; } } #endif /*-************************************ * Common functions **************************************/ static unsigned LZ4_NbCommonBytes (reg_t val) { if (LZ4_isLittleEndian()) { if (sizeof(val)==8) { # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanForward64( &r, (U64)val ); return (int)(r>>3); # elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_ctzll((U64)val) >> 3; # else static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; # endif } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r; _BitScanForward( &r, (U32)val ); return (int)(r>>3); # elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_ctz((U32)val) >> 3; # else static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; # endif } } else /* Big Endian CPU */ { if (sizeof(val)==8) { /* 64-bits */ # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse64( &r, val ); return (unsigned)(r>>3); # elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_clzll((U64)val) >> 3; # else static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits. Just to avoid some static analyzer complaining about shift by 32 on 32-bits target. Note that this code path is never triggered in 32-bits mode. */ unsigned r; if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; } if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } r += (!val); return r; # endif } else /* 32 bits */ { # if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse( &r, (unsigned long)val ); return (unsigned)(r>>3); # elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (unsigned)__builtin_clz((U32)val) >> 3; # else unsigned r; if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } r += (!val); return r; # endif } } } #define STEPSIZE sizeof(reg_t) LZ4_FORCE_INLINE unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) { const BYTE* const pStart = pIn; if (likely(pIn < pInLimit-(STEPSIZE-1))) { reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; } else { return LZ4_NbCommonBytes(diff); } } while (likely(pIn < pInLimit-(STEPSIZE-1))) { reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } pIn += LZ4_NbCommonBytes(diff); return (unsigned)(pIn - pStart); } if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } if ((pIn compression run slower on incompressible data */ /*-************************************ * Local Structures and types **************************************/ typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t; /** * This enum distinguishes several different modes of accessing previous * content in the stream. * * - noDict : There is no preceding content. * - withPrefix64k : Table entries up to ctx->dictSize before the current blob * blob being compressed are valid and refer to the preceding * content (of length ctx->dictSize), which is available * contiguously preceding in memory the content currently * being compressed. * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere * else in memory, starting at ctx->dictionary with length * ctx->dictSize. * - usingDictCtx : Like usingExtDict, but everything concerning the preceding * content is in a separate context, pointed to by * ctx->dictCtx. ctx->dictionary, ctx->dictSize, and table * entries in the current context that refer to positions * preceding the beginning of the current compression are * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx * ->dictSize describe the location and size of the preceding * content, and matches are found by looking in the ctx * ->dictCtx->hashTable. */ typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive; typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; /*-************************************ * Local Utils **************************************/ int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } /*-****************************** * Compression functions ********************************/ static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) { if (tableType == byU16) return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); else return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); } static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) { const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; if (LZ4_isLittleEndian()) { const U64 prime5bytes = 889523592379ULL; return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); } else { const U64 prime8bytes = 11400714785074694791ULL; return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); } } LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) { if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); return LZ4_hash4(LZ4_read32(p), tableType); } static void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType) { switch (tableType) { default: /* fallthrough */ case clearedTable: { /* illegal! */ assert(0); return; } case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; } case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; } case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; } } } static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType) { switch (tableType) { default: /* fallthrough */ case clearedTable: /* fallthrough */ case byPtr: { /* illegal! */ assert(0); return; } case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; } case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; } } } static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) { switch (tableType) { case clearedTable: { /* illegal! */ assert(0); return; } case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } } } LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) { U32 const h = LZ4_hashPosition(p, tableType); LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); } /* LZ4_getIndexOnHash() : * Index of match position registered in hash table. * hash position must be calculated by using base+index, or dictBase+index. * Assumption 1 : only valid if tableType == byU32 or byU16. * Assumption 2 : h is presumed valid (within limits of hash table) */ static U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType) { LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2); if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; assert(h < (1U << (LZ4_MEMORY_USAGE-2))); return hashTable[h]; } if (tableType == byU16) { const U16* const hashTable = (const U16*) tableBase; assert(h < (1U << (LZ4_MEMORY_USAGE-1))); return hashTable[h]; } assert(0); return 0; /* forbidden case */ } static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase) { if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; } { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ } LZ4_FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, const void* tableBase, tableType_t tableType, const BYTE* srcBase) { U32 const h = LZ4_hashPosition(p, tableType); return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); } LZ4_FORCE_INLINE void LZ4_prepareTable(LZ4_stream_t_internal* const cctx, const int inputSize, const tableType_t tableType) { /* If compression failed during the previous step, then the context * is marked as dirty, therefore, it has to be fully reset. */ if (cctx->dirty) { DEBUGLOG(5, "LZ4_prepareTable: Full reset for %p", cctx); MEM_INIT(cctx, 0, sizeof(LZ4_stream_t_internal)); return; } /* If the table hasn't been used, it's guaranteed to be zeroed out, and is * therefore safe to use no matter what mode we're in. Otherwise, we figure * out if it's safe to leave as is or whether it needs to be reset. */ if (cctx->tableType != clearedTable) { assert(inputSize >= 0); if (cctx->tableType != tableType || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU) || ((tableType == byU32) && cctx->currentOffset > 1 GB) || tableType == byPtr || inputSize >= 4 KB) { DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx); MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE); cctx->currentOffset = 0; cctx->tableType = clearedTable; } else { DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)"); } } /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back, is faster * than compressing without a gap. However, compressing with * currentOffset == 0 is faster still, so we preserve that case. */ if (cctx->currentOffset != 0 && tableType == byU32) { DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset"); cctx->currentOffset += 64 KB; } /* Finally, clear history */ cctx->dictCtx = NULL; cctx->dictionary = NULL; cctx->dictSize = 0; } /** LZ4_compress_generic() : inlined, to ensure branches are decided at compilation time */ LZ4_FORCE_INLINE int LZ4_compress_generic( LZ4_stream_t_internal* const cctx, const char* const source, char* const dest, const int inputSize, int *inputConsumed, /* only written when outputDirective == fillOutput */ const int maxOutputSize, const limitedOutput_directive outputDirective, const tableType_t tableType, const dict_directive dictDirective, const dictIssue_directive dictIssue, const int acceleration) { int result; const BYTE* ip = (const BYTE*) source; U32 const startIndex = cctx->currentOffset; const BYTE* base = (const BYTE*) source - startIndex; const BYTE* lowLimit; const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx; const BYTE* const dictionary = dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary; const U32 dictSize = dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize; const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */ int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */ const BYTE* const dictEnd = dictionary + dictSize; const BYTE* anchor = (const BYTE*) source; const BYTE* const iend = ip + inputSize; const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1; const BYTE* const matchlimit = iend - LASTLITERALS; /* the dictCtx currentOffset is indexed on the start of the dictionary, * while a dictionary in the current context precedes the currentOffset */ const BYTE* dictBase = (dictDirective == usingDictCtx) ? dictionary + dictSize - dictCtx->currentOffset : dictionary + dictSize - startIndex; BYTE* op = (BYTE*) dest; BYTE* const olimit = op + maxOutputSize; U32 offset = 0; U32 forwardH; DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType); /* If init conditions are not met, we don't have to mark stream * as having dirty context, since no action was taken yet */ if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported inputSize, too large (or negative) */ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */ if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */ assert(acceleration >= 1); lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0); /* Update context state */ if (dictDirective == usingDictCtx) { /* Subsequent linked blocks can't use the dictionary. */ /* Instead, they use the block we just compressed. */ cctx->dictCtx = NULL; cctx->dictSize = (U32)inputSize; } else { cctx->dictSize += (U32)inputSize; } cctx->currentOffset += (U32)inputSize; cctx->tableType = (U16)tableType; if (inputSizehashTable, tableType, base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ for ( ; ; ) { const BYTE* match; BYTE* token; const BYTE* filledIp; /* Find a match */ if (tableType == byPtr) { const BYTE* forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { U32 const h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; assert(ip < mflimitPlusOne); match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); } while ( (match+LZ4_DISTANCE_MAX < ip) || (LZ4_read32(match) != LZ4_read32(ip)) ); } else { /* byU32, byU16 */ const BYTE* forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { U32 const h = forwardH; U32 const current = (U32)(forwardIp - base); U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); assert(matchIndex <= current); assert(forwardIp - base < (ptrdiff_t)(2 GB - 1)); ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; assert(ip < mflimitPlusOne); if (dictDirective == usingDictCtx) { if (matchIndex < startIndex) { /* there was no match, try the dictionary */ assert(tableType == byU32); matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); match = dictBase + matchIndex; matchIndex += dictDelta; /* make dictCtx index comparable with current context */ lowLimit = dictionary; } else { match = base + matchIndex; lowLimit = (const BYTE*)source; } } else if (dictDirective==usingExtDict) { if (matchIndex < startIndex) { DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex); assert(startIndex - matchIndex >= MINMATCH); match = dictBase + matchIndex; lowLimit = dictionary; } else { match = base + matchIndex; lowLimit = (const BYTE*)source; } } else { /* single continuous memory segment */ match = base + matchIndex; } forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); DEBUGLOG(7, "candidate at pos=%u (offset=%u \n", matchIndex, current - matchIndex); if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } /* match outside of valid area */ assert(matchIndex < current); if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX)) && (matchIndex+LZ4_DISTANCE_MAX < current)) { continue; } /* too far */ assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* match now expected within distance */ if (LZ4_read32(match) == LZ4_read32(ip)) { if (maybe_extMem) offset = current - matchIndex; break; /* match found */ } } while(1); } /* Catch up */ filledIp = ip; while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } /* Encode Literals */ { unsigned const litLength = (unsigned)(ip - anchor); token = op++; if ((outputDirective == limitedOutput) && /* Check output buffer overflow */ (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) { return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ } if ((outputDirective == fillOutput) && (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) { op--; goto _last_literals; } if (litLength >= RUN_MASK) { int len = (int)(litLength - RUN_MASK); *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } else *token = (BYTE)(litLength< olimit)) { /* the match was too close to the end, rewind and go to last literals */ op = token; goto _last_literals; } /* Encode Offset */ if (maybe_extMem) { /* static test */ DEBUGLOG(6, " with offset=%u (ext if > %i)", offset, (int)(ip - (const BYTE*)source)); assert(offset <= LZ4_DISTANCE_MAX && offset > 0); LZ4_writeLE16(op, (U16)offset); op+=2; } else { DEBUGLOG(6, " with offset=%u (same segment)", (U32)(ip - match)); assert(ip-match <= LZ4_DISTANCE_MAX); LZ4_writeLE16(op, (U16)(ip - match)); op+=2; } /* Encode MatchLength */ { unsigned matchCode; if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx) && (lowLimit==dictionary) /* match within extDict */ ) { const BYTE* limit = ip + (dictEnd-match); assert(dictEnd > match); if (limit > matchlimit) limit = matchlimit; matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); ip += (size_t)matchCode + MINMATCH; if (ip==limit) { unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit); matchCode += more; ip += more; } DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH); } else { matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); ip += (size_t)matchCode + MINMATCH; DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH); } if ((outputDirective) && /* Check output buffer overflow */ (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) { if (outputDirective == fillOutput) { /* Match description too long : reduce it */ U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255; ip -= matchCode - newMatchCode; assert(newMatchCode < matchCode); matchCode = newMatchCode; if (unlikely(ip <= filledIp)) { /* We have already filled up to filledIp so if ip ends up less than filledIp * we have positions in the hash table beyond the current position. This is * a problem if we reuse the hash table. So we have to remove these positions * from the hash table. */ const BYTE* ptr; DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip)); for (ptr = ip; ptr <= filledIp; ++ptr) { U32 const h = LZ4_hashPosition(ptr, tableType); LZ4_clearHash(h, cctx->hashTable, tableType); } } } else { assert(outputDirective == limitedOutput); return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ } } if (matchCode >= ML_MASK) { *token += ML_MASK; matchCode -= ML_MASK; LZ4_write32(op, 0xFFFFFFFF); while (matchCode >= 4*255) { op+=4; LZ4_write32(op, 0xFFFFFFFF); matchCode -= 4*255; } op += matchCode / 255; *op++ = (BYTE)(matchCode % 255); } else *token += (BYTE)(matchCode); } /* Ensure we have enough space for the last literals. */ assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit)); anchor = ip; /* Test end of chunk */ if (ip >= mflimitPlusOne) break; /* Fill table */ LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); /* Test next position */ if (tableType == byPtr) { match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); LZ4_putPosition(ip, cctx->hashTable, tableType, base); if ( (match+LZ4_DISTANCE_MAX >= ip) && (LZ4_read32(match) == LZ4_read32(ip)) ) { token=op++; *token=0; goto _next_match; } } else { /* byU32, byU16 */ U32 const h = LZ4_hashPosition(ip, tableType); U32 const current = (U32)(ip-base); U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); assert(matchIndex < current); if (dictDirective == usingDictCtx) { if (matchIndex < startIndex) { /* there was no match, try the dictionary */ matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); match = dictBase + matchIndex; lowLimit = dictionary; /* required for match length counter */ matchIndex += dictDelta; } else { match = base + matchIndex; lowLimit = (const BYTE*)source; /* required for match length counter */ } } else if (dictDirective==usingExtDict) { if (matchIndex < startIndex) { match = dictBase + matchIndex; lowLimit = dictionary; /* required for match length counter */ } else { match = base + matchIndex; lowLimit = (const BYTE*)source; /* required for match length counter */ } } else { /* single memory segment */ match = base + matchIndex; } LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); assert(matchIndex < current); if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1) && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current)) && (LZ4_read32(match) == LZ4_read32(ip)) ) { token=op++; *token=0; if (maybe_extMem) offset = current - matchIndex; DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i", (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source)); goto _next_match; } } /* Prepare next loop */ forwardH = LZ4_hashPosition(++ip, tableType); } _last_literals: /* Encode Last Literals */ { size_t lastRun = (size_t)(iend - anchor); if ( (outputDirective) && /* Check output buffer overflow */ (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) { if (outputDirective == fillOutput) { /* adapt lastRun to fill 'dst' */ assert(olimit >= op); lastRun = (size_t)(olimit-op) - 1; lastRun -= (lastRun+240)/255; } else { assert(outputDirective == limitedOutput); return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ } } if (lastRun >= RUN_MASK) { size_t accumulator = lastRun - RUN_MASK; *op++ = RUN_MASK << ML_BITS; for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; *op++ = (BYTE) accumulator; } else { *op++ = (BYTE)(lastRun< 0); return result; } int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; assert(ctx != NULL); if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (inputSize < LZ4_64Klimit) { return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration); } else { const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); } } else { if (inputSize < LZ4_64Klimit) { return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); } else { const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration); } } } static int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { int result; #if (LZ4_HEAPMODE) LZ4_stream_t* ctxPtr = ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ if (ctxPtr == NULL) return 0; #else LZ4_stream_t ctx; LZ4_stream_t* const ctxPtr = &ctx; #endif result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); #if (LZ4_HEAPMODE) FREEMEM(ctxPtr); #endif return result; } int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputSize) { return LZ4_compress_fast(src, dst, srcSize, maxOutputSize, 1); } /*-****************************** * Streaming functions ********************************/ #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : it reports an aligment of 8-bytes, while actually aligning LZ4_stream_t on 4 bytes. */ static size_t LZ4_stream_t_alignment(void) { struct { char c; LZ4_stream_t t; } t_a; return sizeof(t_a) - sizeof(t_a.t); } #endif LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) { DEBUGLOG(5, "LZ4_initStream"); if (buffer == NULL) { return NULL; } if (size < sizeof(LZ4_stream_t)) { return NULL; } #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : it reports an aligment of 8-bytes, while actually aligning LZ4_stream_t on 4 bytes. */ if (((size_t)buffer) & (LZ4_stream_t_alignment() - 1)) { return NULL; } /* alignment check */ #endif MEM_INIT(buffer, 0, sizeof(LZ4_stream_t)); return (LZ4_stream_t*)buffer; } /*-******************************* * Decompression functions ********************************/ typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; #undef MIN #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) /* Read the variable-length literal or match length. * * ip - pointer to use as input. * lencheck - end ip. Return an error if ip advances >= lencheck. * loop_check - check ip >= lencheck in body of loop. Returns loop_error if so. * initial_check - check ip >= lencheck before start of loop. Returns initial_error if so. * error (output) - error code. Should be set to 0 before call. */ typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error; LZ4_FORCE_INLINE unsigned read_variable_length(const BYTE**ip, const BYTE* lencheck, int loop_check, int initial_check, variable_length_error* error) { unsigned length = 0; unsigned s; if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */ *error = initial_error; return length; } do { s = **ip; (*ip)++; length += s; if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */ *error = loop_error; return length; } } while (s==255); return length; } /*! LZ4_decompress_generic() : * This generic decompression function covers all use cases. * It shall be instantiated several times, using different sets of directives. * Note that it is important for performance that this function really get inlined, * in order to remove useless branches during compilation optimization. */ LZ4_FORCE_INLINE int LZ4_decompress_generic( const char* const src, char* const dst, int srcSize, int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */ endCondition_directive endOnInput, /* endOnOutputSize, endOnInputSize */ earlyEnd_directive partialDecoding, /* full, partial */ dict_directive dict, /* noDict, withPrefix64k, usingExtDict */ const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */ const BYTE* const dictStart, /* only if dict==usingExtDict */ const size_t dictSize /* note : = 0 if noDict */ ) { if (src == NULL) { return -1; } { const BYTE* ip = (const BYTE*) src; const BYTE* const iend = ip + srcSize; BYTE* op = (BYTE*) dst; BYTE* const oend = op + outputSize; BYTE* cpy; const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize; const int safeDecode = (endOnInput==endOnInputSize); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); /* Set up the "end" pointers for the shortcut. */ const BYTE* const shortiend = iend - (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/; const BYTE* const shortoend = oend - (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/; const BYTE* match; size_t offset; unsigned token; size_t length; DEBUGLOG(5, "LZ4_decompress_generic (srcSize:%i, dstSize:%i)", srcSize, outputSize); /* Special cases */ assert(lowPrefix <= op); if ((endOnInput) && (unlikely(outputSize==0))) { /* Empty output buffer */ if (partialDecoding) return 0; return ((srcSize==1) && (*ip==0)) ? 0 : -1; } if ((!endOnInput) && (unlikely(outputSize==0))) { return (*ip==0 ? 1 : -1); } if ((endOnInput) && unlikely(srcSize==0)) { return -1; } /* Currently the fast loop shows a regression on qualcomm arm chips. */ #if LZ4_FAST_DEC_LOOP if ((oend - op) < FASTLOOP_SAFE_DISTANCE) { DEBUGLOG(6, "skip fast decode loop"); goto safe_decode; } /* Fast loop : decode sequences as long as output < iend-FASTLOOP_SAFE_DISTANCE */ while (1) { /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */ assert(oend - op >= FASTLOOP_SAFE_DISTANCE); if (endOnInput) { assert(ip < iend); } token = *ip++; length = token >> ML_BITS; /* literal length */ assert(!endOnInput || ip <= iend); /* ip < iend before the increment */ /* decode literal length */ if (length == RUN_MASK) { variable_length_error error = ok; length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error); if (error == initial_error) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ /* copy literals */ cpy = op+length; LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); if (endOnInput) { /* LZ4_decompress_safe() */ if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; } LZ4_wildCopy32(op, ip, cpy); } else { /* LZ4_decompress_fast() */ if (cpy>oend-8) { goto safe_literal_copy; } LZ4_wildCopy8(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : * it doesn't know input length, and only relies on end-of-block properties */ } ip += length; op = cpy; } else { cpy = op+length; if (endOnInput) { /* LZ4_decompress_safe() */ DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length); /* We don't need to check oend, since we check it once for each loop below */ if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; } /* Literals can only be 14, but hope compilers optimize if we copy by a register size */ memcpy(op, ip, 16); } else { /* LZ4_decompress_fast() */ /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : * it doesn't know input length, and relies on end-of-block properties */ memcpy(op, ip, 8); if (length > 8) { memcpy(op+8, ip+8, 8); } } ip += length; op = cpy; } /* get offset */ offset = LZ4_readLE16(ip); ip+=2; match = op - offset; assert(match <= op); /* get matchlength */ length = token & ML_MASK; if (length == ML_MASK) { variable_length_error error = ok; if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error); if (error != ok) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */ length += MINMATCH; if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { goto safe_match_copy; } } else { length += MINMATCH; if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { goto safe_match_copy; } /* Fastpath check: Avoids a branch in LZ4_wildCopy32 if true */ if ((dict == withPrefix64k) || (match >= lowPrefix)) { if (offset >= 8) { assert(match >= lowPrefix); assert(match <= op); assert(op + 18 <= oend); memcpy(op, match, 8); memcpy(op+8, match+8, 8); memcpy(op+16, match+16, 2); op += length; continue; } } } if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ /* match starting within external dictionary */ if ((dict==usingExtDict) && (match < lowPrefix)) { if (unlikely(op+length > oend-LASTLITERALS)) { if (partialDecoding) { length = MIN(length, (size_t)(oend-op)); /* reach end of buffer */ } else { goto _output_error; /* end-of-block condition violated */ } } if (length <= (size_t)(lowPrefix-match)) { /* match fits entirely within external dictionary : just copy */ memmove(op, dictEnd - (lowPrefix-match), length); op += length; } else { /* match stretches into both external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix - match); size_t const restSize = length - copySize; memcpy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) { *op++ = *copyFrom++; } } else { memcpy(op, lowPrefix, restSize); op += restSize; } } continue; } /* copy match within block */ cpy = op + length; assert((op <= oend) && (oend-op >= 32)); if (unlikely(offset<16)) { LZ4_memcpy_using_offset(op, match, cpy, offset); } else { LZ4_wildCopy32(op, match, cpy); } op = cpy; /* wildcopy correction */ } safe_decode: #endif /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */ while (1) { token = *ip++; length = token >> ML_BITS; /* literal length */ assert(!endOnInput || ip <= iend); /* ip < iend before the increment */ /* A two-stage shortcut for the most common case: * 1) If the literal length is 0..14, and there is enough space, * enter the shortcut and copy 16 bytes on behalf of the literals * (in the fast mode, only 8 bytes can be safely copied this way). * 2) Further if the match length is 4..18, copy 18 bytes in a similar * manner; but we ensure that there's enough space in the output for * those 18 bytes earlier, upon entering the shortcut (in other words, * there is a combined check for both stages). */ if ( (endOnInput ? length != RUN_MASK : length <= 8) /* strictly "less than" on input, to re-enter the loop with at least one byte */ && likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend)) ) { /* Copy the literals */ memcpy(op, ip, endOnInput ? 16 : 8); op += length; ip += length; /* The second stage: prepare for match copying, decode full info. * If it doesn't work out, the info won't be wasted. */ length = token & ML_MASK; /* match length */ offset = LZ4_readLE16(ip); ip += 2; match = op - offset; assert(match <= op); /* check overflow */ /* Do not deal with overlapping matches. */ if ( (length != ML_MASK) && (offset >= 8) && (dict==withPrefix64k || match >= lowPrefix) ) { /* Copy the match. */ memcpy(op + 0, match + 0, 8); memcpy(op + 8, match + 8, 8); memcpy(op +16, match +16, 2); op += length + MINMATCH; /* Both stages worked, load the next token. */ continue; } /* The second stage didn't work out, but the info is ready. * Propel it right to the point of match copying. */ goto _copy_match; } /* decode literal length */ if (length == RUN_MASK) { variable_length_error error = ok; length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error); if (error == initial_error) { goto _output_error; } if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ } /* copy literals */ cpy = op+length; #if LZ4_FAST_DEC_LOOP safe_literal_copy: #endif LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); if ( ((endOnInput) && ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) ) || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) { /* We've either hit the input parsing restriction or the output parsing restriction. * If we've hit the input parsing condition then this must be the last sequence. * If we've hit the output parsing condition then we are either using partialDecoding * or we've hit the output parsing condition. */ if (partialDecoding) { /* Since we are partial decoding we may be in this block because of the output parsing * restriction, which is not valid since the output buffer is allowed to be undersized. */ assert(endOnInput); /* If we're in this block because of the input parsing condition, then we must be on the * last sequence (or invalid), so we must check that we exactly consume the input. */ if ((ip+length>iend-(2+1+LASTLITERALS)) && (ip+length != iend)) { goto _output_error; } assert(ip+length <= iend); /* We are finishing in the middle of a literals segment. * Break after the copy. */ if (cpy > oend) { cpy = oend; assert(op<=oend); length = (size_t)(oend-op); } assert(ip+length <= iend); } else { /* We must be on the last sequence because of the parsing limitations so check * that we exactly regenerate the original size (must be exact when !endOnInput). */ if ((!endOnInput) && (cpy != oend)) { goto _output_error; } /* We must be on the last sequence (or invalid) because of the parsing limitations * so check that we exactly consume the input and don't overrun the output buffer. */ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) { goto _output_error; } } memmove(op, ip, length); /* supports overlapping memory regions, which only matters for in-place decompression scenarios */ ip += length; op += length; /* Necessarily EOF when !partialDecoding. When partialDecoding * it is EOF if we've either filled the output buffer or hit * the input parsing restriction. */ if (!partialDecoding || (cpy == oend) || (ip == iend)) { break; } } else { LZ4_wildCopy8(op, ip, cpy); /* may overwrite up to WILDCOPYLENGTH beyond cpy */ ip += length; op = cpy; } /* get offset */ offset = LZ4_readLE16(ip); ip+=2; match = op - offset; /* get matchlength */ length = token & ML_MASK; _copy_match: if (length == ML_MASK) { variable_length_error error = ok; length += read_variable_length(&ip, iend - LASTLITERALS + 1, endOnInput, 0, &error); if (error != ok) goto _output_error; if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ } length += MINMATCH; #if LZ4_FAST_DEC_LOOP safe_match_copy: #endif if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */ /* match starting within external dictionary */ if ((dict==usingExtDict) && (match < lowPrefix)) { if (unlikely(op+length > oend-LASTLITERALS)) { if (partialDecoding) length = MIN(length, (size_t)(oend-op)); else goto _output_error; /* doesn't respect parsing restriction */ } if (length <= (size_t)(lowPrefix-match)) { /* match fits entirely within external dictionary : just copy */ memmove(op, dictEnd - (lowPrefix-match), length); op += length; } else { /* match stretches into both external dictionary and current block */ size_t const copySize = (size_t)(lowPrefix - match); size_t const restSize = length - copySize; memcpy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ BYTE* const endOfMatch = op + restSize; const BYTE* copyFrom = lowPrefix; while (op < endOfMatch) *op++ = *copyFrom++; } else { memcpy(op, lowPrefix, restSize); op += restSize; } } continue; } assert(match >= lowPrefix); /* copy match within block */ cpy = op + length; /* partialDecoding : may end anywhere within the block */ assert(op<=oend); if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { size_t const mlen = MIN(length, (size_t)(oend-op)); const BYTE* const matchEnd = match + mlen; BYTE* const copyEnd = op + mlen; if (matchEnd > op) { /* overlap copy */ while (op < copyEnd) { *op++ = *match++; } } else { memcpy(op, match, mlen); } op = copyEnd; if (op == oend) { break; } continue; } if (unlikely(offset<8)) { LZ4_write32(op, 0); /* silence msan warning when offset==0 */ op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; match += inc32table[offset]; memcpy(op+4, match, 4); match -= dec64table[offset]; } else { memcpy(op, match, 8); match += 8; } op += 8; if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1); if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ if (op < oCopyLimit) { LZ4_wildCopy8(op, match, oCopyLimit); match += oCopyLimit - op; op = oCopyLimit; } while (op < cpy) { *op++ = *match++; } } else { memcpy(op, match, 8); if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } } op = cpy; /* wildcopy correction */ } /* end of decoding */ if (endOnInput) { return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ } else { return (int) (((const char*)ip)-src); /* Nb of input bytes read */ } /* Overflow error detected */ _output_error: return (int) (-(((const char*)ip)-src))-1; } } /*===== Instantiate the API decoding functions. =====*/ LZ4_FORCE_O2_GCC_PPC64LE int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, decode_full_block, noDict, (BYTE*)dest, NULL, 0); } #endif /* LZ4_COMMONDEFS_ONLY */ squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/lz4.h000066400000000000000000000344701360235375500210520ustar00rootroot00000000000000/* * LZ4 - Fast LZ compression algorithm * Header File * Copyright (C) 2011-present, 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 : - LZ4 homepage : http://www.lz4.org - LZ4 source repository : https://github.com/lz4/lz4 */ #if defined (__cplusplus) extern "C" { #endif #ifndef LZ4_H_2983827168210 #define LZ4_H_2983827168210 /* --- Dependency --- */ #include /* size_t */ /** Introduction LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core, scalable with multi-cores CPU. It features an extremely fast decoder, with speed in multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. The LZ4 compression library provides in-memory compression and decompression functions. It gives full buffer control to user. Compression can be done in: - a single step (described as Simple Functions) - a single step, reusing a context (described in Advanced Functions) - unbounded multiple steps (described as Streaming compression) lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md). Decompressing such a compressed block requires additional metadata. Exact metadata depends on exact decompression function. For the typical case of LZ4_decompress_safe(), metadata includes block's compressed size, and maximum bound of decompressed size. Each application is free to encode and pass such metadata in whichever way it wants. lz4.h only handle blocks, it can not generate Frames. Blocks are different from Frames (doc/lz4_Frame_format.md). Frames bundle both blocks and metadata in a specified manner. Embedding metadata is required for compressed data to be self-contained and portable. Frame format is delivered through a companion API, declared in lz4frame.h. The `lz4` CLI can only manage frames. */ /*^*************************************************************** * Export parameters *****************************************************************/ /* * LZ4_DLL_EXPORT : * Enable exporting of functions when building a Windows DLL * LZ4LIB_VISIBILITY : * Control library symbols visibility. */ #ifndef LZ4LIB_VISIBILITY # if defined(__GNUC__) && (__GNUC__ >= 4) # define LZ4LIB_VISIBILITY __attribute__ ((visibility ("hidden"))) # else # define LZ4LIB_VISIBILITY # endif #endif #define LZ4LIB_API LZ4LIB_VISIBILITY /*------ Version ------*/ #define LZ4_QUOTE(str) #str #define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) #define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /*-************************************ * Tuning parameter **************************************/ /*! * LZ4_MEMORY_USAGE : * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Increasing memory usage improves compression ratio. * Reduced memory usage may improve speed, thanks to better cache locality. * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ #ifndef LZ4_MEMORY_USAGE # define LZ4_MEMORY_USAGE 14 #endif /*-************************************ * Simple Functions **************************************/ /*! LZ4_compress_default() : * Compresses 'srcSize' bytes from buffer 'src' * into already allocated 'dst' buffer of size 'dstCapacity'. * Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize). * It also runs faster, so it's a recommended setting. * If the function cannot compress 'src' into a more limited 'dst' budget, * compression stops *immediately*, and the function result is zero. * In which case, 'dst' content is undefined (invalid). * srcSize : max supported value is LZ4_MAX_INPUT_SIZE. * dstCapacity : size of buffer 'dst' (which must be already allocated) * @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity) * or 0 if compression fails * Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer). */ LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity); /*! LZ4_decompress_safe() : * compressedSize : is the exact complete size of the compressed block. * dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size. * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) * If destination buffer is not large enough, decoding will stop and output an error code (negative value). * If the source stream is detected malformed, the function will stop decoding and return a negative result. * Note 1 : This function is protected against malicious data packets : * it will never writes outside 'dst' buffer, nor read outside 'source' buffer, * even if the compressed block is maliciously modified to order the decoder to do these actions. * In such case, the decoder stops immediately, and considers the compressed block malformed. * Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them. * The implementation is free to send / store / derive this information in whichever way is most beneficial. * If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead. */ LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity); /*-************************************ * Advanced Functions **************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ #define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) /*! LZ4_compressBound() : Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) This function is primarily useful for memory allocation purposes (destination buffer size). Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize) inputSize : max supported value is LZ4_MAX_INPUT_SIZE return : maximum output size in a "worst case" scenario or 0, if input size is incorrect (too large or negative) */ LZ4LIB_API int LZ4_compressBound(int inputSize); /*! LZ4_compress_fast_extState() : * Same as LZ4_compress_fast(), using an externally allocated memory space for its state. * Use LZ4_sizeofState() to know how much memory must be allocated, * and allocate it on 8-bytes boundaries (using `malloc()` typically). * Then, provide this buffer as `void* state` to compression function. */ LZ4LIB_API int LZ4_sizeofState(void); LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); /*-********************************************* * Streaming Compression Functions ***********************************************/ typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ /*-********************************************** * Streaming Decompression Functions * Bufferless synchronous API ************************************************/ typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */ #endif /* LZ4_H_2983827168210 */ /*^************************************* * !!!!!! STATIC LINKING ONLY !!!!!! ***************************************/ /*-**************************************************************************** * Experimental section * * Symbols declared in this section must be considered unstable. Their * signatures or semantics may change, or they may be removed altogether in the * future. They are therefore only safe to depend on when the caller is * statically linked against the library. * * To protect against unsafe usage, not only are the declarations guarded, * the definitions are hidden by default * when building LZ4 as a shared/dynamic library. * * In order to access these declarations, * define LZ4_STATIC_LINKING_ONLY in your application * before including LZ4's headers. * * In order to make their implementations accessible dynamically, you must * define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library. ******************************************************************************/ #ifdef LZ4_STATIC_LINKING_ONLY #ifndef LZ4_STATIC_3504398509 #define LZ4_STATIC_3504398509 #define LZ4LIB_STATIC_API LZ4LIB_API #ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */ # define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */ #endif #endif /* LZ4_STATIC_3504398509 */ #endif /* LZ4_STATIC_LINKING_ONLY */ #ifndef LZ4_H_98237428734687 #define LZ4_H_98237428734687 /*-************************************************************ * PRIVATE DEFINITIONS ************************************************************** * Do not use these definitions directly. * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. * Accessing members will expose code to API and/or ABI break in future versions of the library. **************************************************************/ #define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) #define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) #define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) #include typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; struct LZ4_stream_t_internal { uint32_t hashTable[LZ4_HASH_SIZE_U32]; uint32_t currentOffset; uint16_t dirty; uint16_t tableType; const uint8_t* dictionary; const LZ4_stream_t_internal* dictCtx; uint32_t dictSize; }; typedef struct { const uint8_t* externalDict; size_t extDictSize; const uint8_t* prefixEnd; size_t prefixSize; } LZ4_streamDecode_t_internal; #else typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; struct LZ4_stream_t_internal { unsigned int hashTable[LZ4_HASH_SIZE_U32]; unsigned int currentOffset; unsigned short dirty; unsigned short tableType; const unsigned char* dictionary; const LZ4_stream_t_internal* dictCtx; unsigned int dictSize; }; typedef struct { const unsigned char* externalDict; const unsigned char* prefixEnd; size_t extDictSize; size_t prefixSize; } LZ4_streamDecode_t_internal; #endif /*! LZ4_stream_t : * information structure to track an LZ4 stream. * LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. * The structure definition can be convenient for static allocation * (on stack, or as part of larger structure). * Init this structure with LZ4_initStream() before first use. * note : only use this definition in association with static linking ! * this definition is not API/ABI safe, and may change in a future version. */ #define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4 + ((sizeof(void*)==16) ? 4 : 0) /*AS-400*/ ) #define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) union LZ4_stream_u { unsigned long long table[LZ4_STREAMSIZE_U64]; LZ4_stream_t_internal internal_donotuse; } ; /* previously typedef'd to LZ4_stream_t */ /*! LZ4_initStream() : v1.9.0+ * An LZ4_stream_t structure must be initialized at least once. * This is automatically done when invoking LZ4_createStream(), * but it's not when the structure is simply declared on stack (for example). * * Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. * It can also initialize any arbitrary buffer of sufficient size, * and will @return a pointer of proper type upon initialization. * * Note : initialization fails if size and alignment conditions are not respected. * In which case, the function will @return NULL. * Note2: An LZ4_stream_t structure guarantees correct alignment and size. * Note3: Before v1.9.0, use LZ4_resetStream() instead */ LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); /*! LZ4_streamDecode_t : * information structure to track an LZ4 stream during decompression. * init this structure using LZ4_setStreamDecode() before first use. * note : only use in association with static linking ! * this definition is not API/ABI safe, * and may change in a future version ! */ #define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ ) #define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) union LZ4_streamDecode_u { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; LZ4_streamDecode_t_internal internal_donotuse; } ; /* previously typedef'd to LZ4_streamDecode_t */ #endif /* LZ4_H_98237428734687 */ #if defined (__cplusplus) } #endif squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/lz4hc.c000066400000000000000000001572151360235375500213630ustar00rootroot00000000000000/* LZ4 HC - High Compression Mode of LZ4 Copyright (C) 2011-2017, 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 : - LZ4 source repository : https://github.com/lz4/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c */ /* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */ /* ************************************* * Tuning Parameter ***************************************/ /*! HEAPMODE : * Select how default compression function will allocate workplace memory, * in stack (0:fastest), or in heap (1:requires malloc()). * Since workplace is rather large, heap mode is recommended. */ #ifndef LZ4HC_HEAPMODE # define LZ4HC_HEAPMODE 1 #endif /*=== Dependency ===*/ #define LZ4_HC_STATIC_LINKING_ONLY #include "lz4hc.h" /*=== Common LZ4 definitions ===*/ #if defined(__GNUC__) # pragma GCC diagnostic ignored "-Wunused-function" #endif #if defined (__clang__) # pragma clang diagnostic ignored "-Wunused-function" #endif /*=== Enums ===*/ typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive; #define LZ4_COMMONDEFS_ONLY #ifndef LZ4_SRC_INCLUDED #include "lz4.c" /* LZ4_count, constants, mem */ #endif /*=== Constants ===*/ #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH) #define LZ4_OPT_NUM (1<<12) /*=== Macros ===*/ #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG)) #define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */ #define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */ /* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */ #define UPDATABLE(ip, op, anchor) &ip, &op, &anchor static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); } /************************************** * HC Compression **************************************/ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) { MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable)); MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); } static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) { uptrval startingOffset = (uptrval)(hc4->end - hc4->base); if (startingOffset > 1 GB) { LZ4HC_clearTables(hc4); startingOffset = 0; } startingOffset += 64 KB; hc4->nextToUpdate = (U32) startingOffset; hc4->base = start - startingOffset; hc4->end = start; hc4->dictBase = start - startingOffset; hc4->dictLimit = (U32) startingOffset; hc4->lowLimit = (U32) startingOffset; } /* Update chains up to ip (excluded) */ LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip) { U16* const chainTable = hc4->chainTable; U32* const hashTable = hc4->hashTable; const BYTE* const base = hc4->base; U32 const target = (U32)(ip - base); U32 idx = hc4->nextToUpdate; while (idx < target) { U32 const h = LZ4HC_hashPtr(base+idx); size_t delta = idx - hashTable[h]; if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX; DELTANEXTU16(chainTable, idx) = (U16)delta; hashTable[h] = idx; idx++; } hc4->nextToUpdate = target; } /** LZ4HC_countBack() : * @return : negative value, nb of common bytes before ip/match */ LZ4_FORCE_INLINE int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match, const BYTE* const iMin, const BYTE* const mMin) { int back = 0; int const min = (int)MAX(iMin - ip, mMin - match); assert(min <= 0); assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31)); assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31)); while ( (back > min) && (ip[back-1] == match[back-1]) ) back--; return back; } #if defined(_MSC_VER) # define LZ4HC_rotl32(x,r) _rotl(x,r) #else # define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r))) #endif static U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern) { size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3; if (bitsToRotate == 0) return pattern; return LZ4HC_rotl32(pattern, (int)bitsToRotate); } /* LZ4HC_countPattern() : * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */ static unsigned LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32) { const BYTE* const iStart = ip; reg_t const pattern = (sizeof(pattern)==8) ? (reg_t)pattern32 + (((reg_t)pattern32) << 32) : pattern32; while (likely(ip < iEnd-(sizeof(pattern)-1))) { reg_t const diff = LZ4_read_ARCH(ip) ^ pattern; if (!diff) { ip+=sizeof(pattern); continue; } ip += LZ4_NbCommonBytes(diff); return (unsigned)(ip - iStart); } if (LZ4_isLittleEndian()) { reg_t patternByte = pattern; while ((ip>= 8; } } else { /* big endian */ U32 bitOffset = (sizeof(pattern)*8) - 8; while (ip < iEnd) { BYTE const byte = (BYTE)(pattern >> bitOffset); if (*ip != byte) break; ip ++; bitOffset -= 8; } } return (unsigned)(ip - iStart); } /* LZ4HC_reverseCountPattern() : * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) * read using natural platform endianess */ static unsigned LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern) { const BYTE* const iStart = ip; while (likely(ip >= iLow+4)) { if (LZ4_read32(ip-4) != pattern) break; ip -= 4; } { const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianess */ while (likely(ip>iLow)) { if (ip[-1] != *bytePtr) break; ip--; bytePtr--; } } return (unsigned)(iStart - ip); } /* LZ4HC_protectDictEnd() : * Checks if the match is in the last 3 bytes of the dictionary, so reading the * 4 byte MINMATCH would overflow. * @returns true if the match index is okay. */ static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex) { return ((U32)((dictLimit - 1) - matchIndex) >= 3); } typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e; typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e; LZ4_FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch ( LZ4HC_CCtx_internal* hc4, const BYTE* const ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit, int longest, const BYTE** matchpos, const BYTE** startpos, const int maxNbAttempts, const int patternAnalysis, const int chainSwap, const dictCtx_directive dict, const HCfavor_e favorDecSpeed) { U16* const chainTable = hc4->chainTable; U32* const HashTable = hc4->hashTable; const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx; const BYTE* const base = hc4->base; const U32 dictLimit = hc4->dictLimit; const BYTE* const lowPrefixPtr = base + dictLimit; const U32 ipIndex = (U32)(ip - base); const U32 lowestMatchIndex = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX; const BYTE* const dictBase = hc4->dictBase; int const lookBackLength = (int)(ip-iLowLimit); int nbAttempts = maxNbAttempts; U32 matchChainPos = 0; U32 const pattern = LZ4_read32(ip); U32 matchIndex; repeat_state_e repeat = rep_untested; size_t srcPatternLength = 0; DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch"); /* First Match */ LZ4HC_Insert(hc4, ip); matchIndex = HashTable[LZ4HC_hashPtr(ip)]; DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)", matchIndex, lowestMatchIndex); while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) { int matchLength=0; nbAttempts--; assert(matchIndex < ipIndex); if (favorDecSpeed && (ipIndex - matchIndex < 8)) { /* do nothing */ } else if (matchIndex >= dictLimit) { /* within current Prefix */ const BYTE* const matchPtr = base + matchIndex; assert(matchPtr >= lowPrefixPtr); assert(matchPtr < ip); assert(longest >= 1); if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) { if (LZ4_read32(matchPtr) == pattern) { int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, lowPrefixPtr) : 0; matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); matchLength -= back; if (matchLength > longest) { longest = matchLength; *matchpos = matchPtr + back; *startpos = ip + back; } } } } else { /* lowestMatchIndex <= matchIndex < dictLimit */ const BYTE* const matchPtr = dictBase + matchIndex; if (LZ4_read32(matchPtr) == pattern) { const BYTE* const dictStart = dictBase + hc4->lowLimit; int back = 0; const BYTE* vLimit = ip + (dictLimit - matchIndex); if (vLimit > iHighLimit) vLimit = iHighLimit; matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; if ((ip+matchLength == vLimit) && (vLimit < iHighLimit)) matchLength += LZ4_count(ip+matchLength, lowPrefixPtr, iHighLimit); back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0; matchLength -= back; if (matchLength > longest) { longest = matchLength; *matchpos = base + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */ *startpos = ip + back; } } } if (chainSwap && matchLength==longest) { /* better match => select a better chain */ assert(lookBackLength==0); /* search forward only */ if (matchIndex + (U32)longest <= ipIndex) { int const kTrigger = 4; U32 distanceToNextMatch = 1; int const end = longest - MINMATCH + 1; int step = 1; int accel = 1 << kTrigger; int pos; for (pos = 0; pos < end; pos += step) { U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos); step = (accel++ >> kTrigger); if (candidateDist > distanceToNextMatch) { distanceToNextMatch = candidateDist; matchChainPos = (U32)pos; accel = 1 << kTrigger; } } if (distanceToNextMatch > 1) { if (distanceToNextMatch > matchIndex) break; /* avoid overflow */ matchIndex -= distanceToNextMatch; continue; } } } { U32 const distNextMatch = DELTANEXTU16(chainTable, matchIndex); if (patternAnalysis && distNextMatch==1 && matchChainPos==0) { U32 const matchCandidateIdx = matchIndex-1; /* may be a repeated pattern */ if (repeat == rep_untested) { if ( ((pattern & 0xFFFF) == (pattern >> 16)) & ((pattern & 0xFF) == (pattern >> 24)) ) { repeat = rep_confirmed; srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern); } else { repeat = rep_not; } } if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex) && LZ4HC_protectDictEnd(dictLimit, matchCandidateIdx) ) { const int extDict = matchCandidateIdx < dictLimit; const BYTE* const matchPtr = (extDict ? dictBase : base) + matchCandidateIdx; if (LZ4_read32(matchPtr) == pattern) { /* good candidate */ const BYTE* const dictStart = dictBase + hc4->lowLimit; const BYTE* const iLimit = extDict ? dictBase + dictLimit : iHighLimit; size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern); if (extDict && matchPtr + forwardPatternLength == iLimit) { U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern); forwardPatternLength += LZ4HC_countPattern(lowPrefixPtr, iHighLimit, rotatedPattern); } { const BYTE* const lowestMatchPtr = extDict ? dictStart : lowPrefixPtr; size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern); size_t currentSegmentLength; if (!extDict && matchPtr - backLength == lowPrefixPtr && hc4->lowLimit < dictLimit) { U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern); backLength += LZ4HC_reverseCountPattern(dictBase + dictLimit, dictStart, rotatedPattern); } /* Limit backLength not go further than lowestMatchIndex */ backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex); assert(matchCandidateIdx - backLength >= lowestMatchIndex); currentSegmentLength = backLength + forwardPatternLength; /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */ if ( (currentSegmentLength >= srcPatternLength) /* current pattern segment large enough to contain full srcPatternLength */ && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */ U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength; /* best position, full pattern, might be followed by more match */ if (LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) matchIndex = newMatchIndex; else { /* Can only happen if started in the prefix */ assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); matchIndex = dictLimit; } } else { U32 const newMatchIndex = matchCandidateIdx - (U32)backLength; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */ if (!LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) { assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); matchIndex = dictLimit; } else { matchIndex = newMatchIndex; if (lookBackLength==0) { /* no back possible */ size_t const maxML = MIN(currentSegmentLength, srcPatternLength); if ((size_t)longest < maxML) { assert(base + matchIndex < ip); if (ip - (base+matchIndex) > LZ4_DISTANCE_MAX) break; assert(maxML < 2 GB); longest = (int)maxML; *matchpos = base + matchIndex; /* virtual pos, relative to ip, to retrieve offset */ *startpos = ip; } { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex); if (distToNextPattern > matchIndex) break; /* avoid overflow */ matchIndex -= distToNextPattern; } } } } } continue; } } } } /* PA optimization */ /* follow current chain */ matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos); } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */ if ( dict == usingDictCtxHc && nbAttempts && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) { size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base); U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; assert(dictEndOffset <= 1 GB); matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset; while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) { const BYTE* const matchPtr = dictCtx->base + dictMatchIndex; if (LZ4_read32(matchPtr) == pattern) { int mlt; int back = 0; const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex); if (vLimit > iHighLimit) vLimit = iHighLimit; mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->base + dictCtx->dictLimit) : 0; mlt -= back; if (mlt > longest) { longest = mlt; *matchpos = base + matchIndex + back; *startpos = ip + back; } } { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex); dictMatchIndex -= nextOffset; matchIndex -= nextOffset; } } } return longest; } LZ4_FORCE_INLINE int LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */ const BYTE* const ip, const BYTE* const iLimit, const BYTE** matchpos, const int maxNbAttempts, const int patternAnalysis, const dictCtx_directive dict) { const BYTE* uselessPtr = ip; /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), * but this won't be the case here, as we define iLowLimit==ip, * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, matchpos, &uselessPtr, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio); } /* LZ4HC_encodeSequence() : * @return : 0 if ok, * 1 if buffer issue detected */ LZ4_FORCE_INLINE int LZ4HC_encodeSequence ( const BYTE** ip, BYTE** op, const BYTE** anchor, int matchLength, const BYTE* const match, limitedOutput_directive limit, BYTE* oend) { size_t length; BYTE* const token = (*op)++; #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6) static const BYTE* start = NULL; static U32 totalCost = 0; U32 const pos = (start==NULL) ? 0 : (U32)(*anchor - start); U32 const ll = (U32)(*ip - *anchor); U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0; U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0; U32 const cost = 1 + llAdd + ll + 2 + mlAdd; if (start==NULL) start = *anchor; /* only works for single segment */ /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */ DEBUGLOG(6, "pos:%7u -- literals:%3u, match:%4i, offset:%5u, cost:%3u + %u", pos, (U32)(*ip - *anchor), matchLength, (U32)(*ip-match), cost, totalCost); totalCost += cost; #endif /* Encode Literal length */ length = (size_t)(*ip - *anchor); if ((limit) && ((*op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */ if (length >= RUN_MASK) { size_t len = length - RUN_MASK; *token = (RUN_MASK << ML_BITS); for(; len >= 255 ; len -= 255) *(*op)++ = 255; *(*op)++ = (BYTE)len; } else { *token = (BYTE)(length << ML_BITS); } /* Copy Literals */ LZ4_wildCopy8(*op, *anchor, (*op) + length); *op += length; /* Encode Offset */ assert( (*ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */ LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2; /* Encode MatchLength */ assert(matchLength >= MINMATCH); length = (size_t)matchLength - MINMATCH; if ((limit) && (*op + (length / 255) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */ if (length >= ML_MASK) { *token += ML_MASK; length -= ML_MASK; for(; length >= 510 ; length -= 510) { *(*op)++ = 255; *(*op)++ = 255; } if (length >= 255) { length -= 255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; } else { *token += (BYTE)(length); } /* Prepare next loop */ *ip += matchLength; *anchor = *ip; return 0; } LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( LZ4HC_CCtx_internal* const ctx, const char* const source, char* const dest, int* srcSizePtr, int const maxOutputSize, unsigned maxNbAttempts, const limitedOutput_directive limit, const dictCtx_directive dict ) { const int inputSize = *srcSizePtr; const int patternAnalysis = (maxNbAttempts > 128); /* levels 9+ */ const BYTE* ip = (const BYTE*) source; const BYTE* anchor = ip; const BYTE* const iend = ip + inputSize; const BYTE* const mflimit = iend - MFLIMIT; const BYTE* const matchlimit = (iend - LASTLITERALS); BYTE* optr = (BYTE*) dest; BYTE* op = (BYTE*) dest; BYTE* oend = op + maxOutputSize; int ml0, ml, ml2, ml3; const BYTE* start0; const BYTE* ref0; const BYTE* ref = NULL; const BYTE* start2 = NULL; const BYTE* ref2 = NULL; const BYTE* start3 = NULL; const BYTE* ref3 = NULL; /* init */ *srcSizePtr = 0; if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ /* Main Loop */ while (ip <= mflimit) { ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict); if (ml encode ML1 */ optr = op; if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; continue; } if (start0 < ip) { /* first match was skipped at least once */ if (start2 < ip + ml0) { /* squeezing ML1 between ML0(original ML1) and ML2 */ ip = start0; ref = ref0; ml = ml0; /* restore initial ML1 */ } } /* Here, start0==ip */ if ((start2 - ip) < 3) { /* First Match too small : removed */ ml = ml2; ip = start2; ref =ref2; goto _Search2; } _Search3: /* At this stage, we have : * ml2 > ml1, and * ip1+3 <= ip2 (usually < ip1+ml1) */ if ((start2 - ip) < OPTIMAL_ML) { int correction; int new_ml = ml; if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; correction = new_ml - (int)(start2 - ip); if (correction > 0) { start2 += correction; ref2 += correction; ml2 -= correction; } } /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */ if (start2 + ml2 <= mflimit) { ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio); } else { ml3 = ml2; } if (ml3 == ml2) { /* No better match => encode ML1 and ML2 */ /* ip & ref are known; Now for ml */ if (start2 < ip+ml) ml = (int)(start2 - ip); /* Now, encode 2 sequences */ optr = op; if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; ip = start2; optr = op; if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) goto _dest_overflow; continue; } if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */ if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ if (start2 < ip+ml) { int correction = (int)(ip+ml - start2); start2 += correction; ref2 += correction; ml2 -= correction; if (ml2 < MINMATCH) { start2 = start3; ref2 = ref3; ml2 = ml3; } } optr = op; if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; ip = start3; ref = ref3; ml = ml3; start0 = start2; ref0 = ref2; ml0 = ml2; goto _Search2; } start2 = start3; ref2 = ref3; ml2 = ml3; goto _Search3; } /* * OK, now we have 3 ascending matches; * let's write the first one ML1. * ip & ref are known; Now decide ml. */ if (start2 < ip+ml) { if ((start2 - ip) < OPTIMAL_ML) { int correction; if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; correction = ml - (int)(start2 - ip); if (correction > 0) { start2 += correction; ref2 += correction; ml2 -= correction; } } else { ml = (int)(start2 - ip); } } optr = op; if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; /* ML2 becomes ML1 */ ip = start2; ref = ref2; ml = ml2; /* ML3 becomes ML2 */ start2 = start3; ref2 = ref3; ml2 = ml3; /* let's find a new ML3 */ goto _Search3; } _last_literals: /* Encode Last Literals */ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */ size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255; size_t const totalSize = 1 + litLength + lastRunSize; if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ if (limit && (op + totalSize > oend)) { if (limit == limitedOutput) return 0; /* Check output limit */ /* adapt lastRunSize to fill 'dest' */ lastRunSize = (size_t)(oend - op) - 1; litLength = (lastRunSize + 255 - RUN_MASK) / 255; lastRunSize -= litLength; } ip = anchor + lastRunSize; if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK; *op++ = (RUN_MASK << ML_BITS); for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255; *op++ = (BYTE) accumulator; } else { *op++ = (BYTE)(lastRunSize << ML_BITS); } memcpy(op, anchor, lastRunSize); op += lastRunSize; } /* End */ *srcSizePtr = (int) (((const char*)ip) - source); return (int) (((char*)op)-dest); _dest_overflow: if (limit == fillOutput) { op = optr; /* restore correct out pointer */ goto _last_literals; } return 0; } static int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx, const char* const source, char* dst, int* srcSizePtr, int dstCapacity, int const nbSearches, size_t sufficient_len, const limitedOutput_directive limit, int const fullUpdate, const dictCtx_directive dict, HCfavor_e favorDecSpeed); LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( LZ4HC_CCtx_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, int const dstCapacity, int cLevel, const limitedOutput_directive limit, const dictCtx_directive dict ) { typedef enum { lz4hc, lz4opt } lz4hc_strat_e; typedef struct { lz4hc_strat_e strat; U32 nbSearches; U32 targetLength; } cParams_t; static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = { { lz4hc, 2, 16 }, /* 0, unused */ { lz4hc, 2, 16 }, /* 1, unused */ { lz4hc, 2, 16 }, /* 2, unused */ { lz4hc, 4, 16 }, /* 3 */ { lz4hc, 8, 16 }, /* 4 */ { lz4hc, 16, 16 }, /* 5 */ { lz4hc, 32, 16 }, /* 6 */ { lz4hc, 64, 16 }, /* 7 */ { lz4hc, 128, 16 }, /* 8 */ { lz4hc, 256, 16 }, /* 9 */ { lz4opt, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/ { lz4opt, 512,128 }, /*11 */ { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ }; DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d)", ctx, src, *srcSizePtr); if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ ctx->end += *srcSizePtr; if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */ cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel); { cParams_t const cParam = clTable[cLevel]; HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio; int result; if (cParam.strat == lz4hc) { result = LZ4HC_compress_hashChain(ctx, src, dst, srcSizePtr, dstCapacity, cParam.nbSearches, limit, dict); } else { assert(cParam.strat == lz4opt); result = LZ4HC_compress_optimal(ctx, src, dst, srcSizePtr, dstCapacity, (int)cParam.nbSearches, cParam.targetLength, limit, cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */ dict, favor); } if (result <= 0) ctx->dirty = 1; return result; } } static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock); static int LZ4HC_compress_generic_noDictCtx ( LZ4HC_CCtx_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, int const dstCapacity, int cLevel, limitedOutput_directive limit ) { assert(ctx->dictCtx == NULL); return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx); } static int LZ4HC_compress_generic_dictCtx ( LZ4HC_CCtx_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, int const dstCapacity, int cLevel, limitedOutput_directive limit ) { const size_t position = (size_t)(ctx->end - ctx->base) - ctx->lowLimit; assert(ctx->dictCtx != NULL); if (position >= 64 KB) { ctx->dictCtx = NULL; return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); } else if (position == 0 && *srcSizePtr > 4 KB) { memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal)); LZ4HC_setExternalDict(ctx, (const BYTE *)src); ctx->compressionLevel = (short)cLevel; return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); } else { return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, usingDictCtxHc); } } static int LZ4HC_compress_generic ( LZ4HC_CCtx_internal* const ctx, const char* const src, char* const dst, int* const srcSizePtr, int const dstCapacity, int cLevel, limitedOutput_directive limit ) { if (ctx->dictCtx == NULL) { return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); } else { return LZ4HC_compress_generic_dictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); } } int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); } #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : * it reports an aligment of 8-bytes, * while actually aligning LZ4_streamHC_t on 4 bytes. */ static size_t LZ4_streamHC_t_alignment(void) { struct { char c; LZ4_streamHC_t t; } t_a; return sizeof(t_a) - sizeof(t_a.t); } #endif /* state is presumed correctly initialized, * in which case its size and alignment have already been validate */ static int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : * it reports an aligment of 8-bytes, * while actually aligning LZ4_streamHC_t on 4 bytes. */ assert(((size_t)state & (LZ4_streamHC_t_alignment() - 1)) == 0); /* check alignment */ #endif if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */ LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel); LZ4HC_init_internal (ctx, (const BYTE*)src); if (dstCapacity < LZ4_compressBound(srcSize)) return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput); else return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, notLimited); } int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); if (ctx==NULL) return 0; /* init failure */ return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel); } int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) { #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); #else LZ4_streamHC_t state; LZ4_streamHC_t* const statePtr = &state; #endif int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel); #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 FREEMEM(statePtr); #endif return cSize; } /* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */ int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel) { LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); if (ctx==NULL) return 0; /* init failure */ LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source); LZ4_setCompressionLevel(ctx, cLevel); return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, fillOutput); } /************************************** * Streaming Functions **************************************/ LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) { LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer; if (buffer == NULL) return NULL; if (size < sizeof(LZ4_streamHC_t)) return NULL; #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 : * it reports an aligment of 8-bytes, * while actually aligning LZ4_streamHC_t on 4 bytes. */ if (((size_t)buffer) & (LZ4_streamHC_t_alignment() - 1)) return NULL; /* alignment check */ #endif /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", LZ4_streamHCPtr, (unsigned)size); /* end-base will trigger a clearTable on starting compression */ LZ4_streamHCPtr->internal_donotuse.end = (const BYTE *)(ptrdiff_t)-1; LZ4_streamHCPtr->internal_donotuse.base = NULL; LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0; LZ4_streamHCPtr->internal_donotuse.dirty = 0; LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); return LZ4_streamHCPtr; } /* just a stub */ void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); if (LZ4_streamHCPtr->internal_donotuse.dirty) { LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); } else { /* preserve end - base : can trigger clearTable's threshold */ LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.base; LZ4_streamHCPtr->internal_donotuse.base = NULL; LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; } LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr, compressionLevel); if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT; if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX; LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel; } /* compression */ static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock) { DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock); if (ctxPtr->end >= ctxPtr->base + ctxPtr->dictLimit + 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ /* Only one memory segment for extDict, so any previous extDict is lost at this stage */ ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base); ctxPtr->dictBase = ctxPtr->base; ctxPtr->base = newBlock - ctxPtr->dictLimit; ctxPtr->end = newBlock; ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */ /* cannot reference an extDict and a dictCtx at the same time */ ctxPtr->dictCtx = NULL; } /* ================================================ * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX]) * ===============================================*/ typedef struct { int price; int off; int mlen; int litlen; } LZ4HC_optimal_t; /* price in bytes */ LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen) { int price = litlen; assert(litlen >= 0); if (litlen >= (int)RUN_MASK) price += 1 + ((litlen-(int)RUN_MASK) / 255); return price; } /* requires mlen >= MINMATCH */ LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen) { int price = 1 + 2 ; /* token + 16-bit offset */ assert(litlen >= 0); assert(mlen >= MINMATCH); price += LZ4HC_literalsPrice(litlen); if (mlen >= (int)(ML_MASK+MINMATCH)) price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255); return price; } typedef struct { int off; int len; } LZ4HC_match_t; LZ4_FORCE_INLINE LZ4HC_match_t LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx, const BYTE* ip, const BYTE* const iHighLimit, int minLen, int nbSearches, const dictCtx_directive dict, const HCfavor_e favorDecSpeed) { LZ4HC_match_t match = { 0 , 0 }; const BYTE* matchPtr = NULL; /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), * but this won't be the case here, as we define iLowLimit==ip, * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ int matchLength = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &matchPtr, &ip, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed); if (matchLength <= minLen) return match; if (favorDecSpeed) { if ((matchLength>18) & (matchLength<=36)) matchLength=18; /* favor shortcut */ } match.len = matchLength; match.off = (int)(ip-matchPtr); return match; } static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, const char* const source, char* dst, int* srcSizePtr, int dstCapacity, int const nbSearches, size_t sufficient_len, const limitedOutput_directive limit, int const fullUpdate, const dictCtx_directive dict, const HCfavor_e favorDecSpeed) { #define TRAILING_LITERALS 3 LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */ const BYTE* ip = (const BYTE*) source; const BYTE* anchor = ip; const BYTE* const iend = ip + *srcSizePtr; const BYTE* const mflimit = iend - MFLIMIT; const BYTE* const matchlimit = iend - LASTLITERALS; BYTE* op = (BYTE*) dst; BYTE* opSaved = (BYTE*) dst; BYTE* oend = op + dstCapacity; /* init */ DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity); *srcSizePtr = 0; if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1; /* Main Loop */ assert(ip - anchor < LZ4_MAX_INPUT_SIZE); while (ip <= mflimit) { int const llen = (int)(ip - anchor); int best_mlen, best_off; int cur, last_match_pos = 0; LZ4HC_match_t const firstMatch = LZ4HC_FindLongerMatch(ctx, ip, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed); if (firstMatch.len==0) { ip++; continue; } if ((size_t)firstMatch.len > sufficient_len) { /* good enough solution : immediate encoding */ int const firstML = firstMatch.len; const BYTE* const matchPos = ip - firstMatch.off; opSaved = op; if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) /* updates ip, op and anchor */ goto _dest_overflow; continue; } /* set prices for first positions (literals) */ { int rPos; for (rPos = 0 ; rPos < MINMATCH ; rPos++) { int const cost = LZ4HC_literalsPrice(llen + rPos); opt[rPos].mlen = 1; opt[rPos].off = 0; opt[rPos].litlen = llen + rPos; opt[rPos].price = cost; DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup", rPos, cost, opt[rPos].litlen); } } /* set prices using initial match */ { int mlen = MINMATCH; int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */ int const offset = firstMatch.off; assert(matchML < LZ4_OPT_NUM); for ( ; mlen <= matchML ; mlen++) { int const cost = LZ4HC_sequencePrice(llen, mlen); opt[mlen].mlen = mlen; opt[mlen].off = offset; opt[mlen].litlen = llen; opt[mlen].price = cost; DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i) -- initial setup", mlen, cost, mlen); } } last_match_pos = firstMatch.len; { int addLit; for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) { opt[last_match_pos+addLit].mlen = 1; /* literal */ opt[last_match_pos+addLit].off = 0; opt[last_match_pos+addLit].litlen = addLit; opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit); DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit); } } /* check further positions */ for (cur = 1; cur < last_match_pos; cur++) { const BYTE* const curPtr = ip + cur; LZ4HC_match_t newMatch; if (curPtr > mflimit) break; DEBUGLOG(7, "rPos:%u[%u] vs [%u]%u", cur, opt[cur].price, opt[cur+1].price, cur+1); if (fullUpdate) { /* not useful to search here if next position has same (or lower) cost */ if ( (opt[cur+1].price <= opt[cur].price) /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */ && (opt[cur+MINMATCH].price < opt[cur].price + 3/*min seq price*/) ) continue; } else { /* not useful to search here if next position has same (or lower) cost */ if (opt[cur+1].price <= opt[cur].price) continue; } DEBUGLOG(7, "search at rPos:%u", cur); if (fullUpdate) newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed); else /* only test matches of minimum length; slightly faster, but misses a few bytes */ newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, last_match_pos - cur, nbSearches, dict, favorDecSpeed); if (!newMatch.len) continue; if ( ((size_t)newMatch.len > sufficient_len) || (newMatch.len + cur >= LZ4_OPT_NUM) ) { /* immediate encoding */ best_mlen = newMatch.len; best_off = newMatch.off; last_match_pos = cur + 1; goto encode; } /* before match : set price with literals at beginning */ { int const baseLitlen = opt[cur].litlen; int litlen; for (litlen = 1; litlen < MINMATCH; litlen++) { int const price = opt[cur].price - LZ4HC_literalsPrice(baseLitlen) + LZ4HC_literalsPrice(baseLitlen+litlen); int const pos = cur + litlen; if (price < opt[pos].price) { opt[pos].mlen = 1; /* literal */ opt[pos].off = 0; opt[pos].litlen = baseLitlen+litlen; opt[pos].price = price; DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", pos, price, opt[pos].litlen); } } } /* set prices using match at position = cur */ { int const matchML = newMatch.len; int ml = MINMATCH; assert(cur + newMatch.len < LZ4_OPT_NUM); for ( ; ml <= matchML ; ml++) { int const pos = cur + ml; int const offset = newMatch.off; int price; int ll; DEBUGLOG(7, "testing price rPos %i (last_match_pos=%i)", pos, last_match_pos); if (opt[cur].mlen == 1) { ll = opt[cur].litlen; price = ((cur > ll) ? opt[cur - ll].price : 0) + LZ4HC_sequencePrice(ll, ml); } else { ll = 0; price = opt[cur].price + LZ4HC_sequencePrice(0, ml); } assert((U32)favorDecSpeed <= 1); if (pos > last_match_pos+TRAILING_LITERALS || price <= opt[pos].price - (int)favorDecSpeed) { DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i)", pos, price, ml); assert(pos < LZ4_OPT_NUM); if ( (ml == matchML) /* last pos of last match */ && (last_match_pos < pos) ) last_match_pos = pos; opt[pos].mlen = ml; opt[pos].off = offset; opt[pos].litlen = ll; opt[pos].price = price; } } } /* complete following positions with literals */ { int addLit; for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) { opt[last_match_pos+addLit].mlen = 1; /* literal */ opt[last_match_pos+addLit].off = 0; opt[last_match_pos+addLit].litlen = addLit; opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit); DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit); } } } /* for (cur = 1; cur <= last_match_pos; cur++) */ assert(last_match_pos < LZ4_OPT_NUM + TRAILING_LITERALS); best_mlen = opt[last_match_pos].mlen; best_off = opt[last_match_pos].off; cur = last_match_pos - best_mlen; encode: /* cur, last_match_pos, best_mlen, best_off must be set */ assert(cur < LZ4_OPT_NUM); assert(last_match_pos >= 1); /* == 1 when only one candidate */ DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos); { int candidate_pos = cur; int selected_matchLength = best_mlen; int selected_offset = best_off; while (1) { /* from end to beginning */ int const next_matchLength = opt[candidate_pos].mlen; /* can be 1, means literal */ int const next_offset = opt[candidate_pos].off; DEBUGLOG(7, "pos %i: sequence length %i", candidate_pos, selected_matchLength); opt[candidate_pos].mlen = selected_matchLength; opt[candidate_pos].off = selected_offset; selected_matchLength = next_matchLength; selected_offset = next_offset; if (next_matchLength > candidate_pos) break; /* last match elected, first match to encode */ assert(next_matchLength > 0); /* can be 1, means literal */ candidate_pos -= next_matchLength; } } /* encode all recorded sequences in order */ { int rPos = 0; /* relative position (to ip) */ while (rPos < last_match_pos) { int const ml = opt[rPos].mlen; int const offset = opt[rPos].off; if (ml == 1) { ip++; rPos++; continue; } /* literal; note: can end up with several literals, in which case, skip them */ rPos += ml; assert(ml >= MINMATCH); assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX)); opSaved = op; if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) /* updates ip, op and anchor */ goto _dest_overflow; } } } /* while (ip <= mflimit) */ _last_literals: /* Encode Last Literals */ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */ size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255; size_t const totalSize = 1 + litLength + lastRunSize; if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ if (limit && (op + totalSize > oend)) { if (limit == limitedOutput) return 0; /* Check output limit */ /* adapt lastRunSize to fill 'dst' */ lastRunSize = (size_t)(oend - op) - 1; litLength = (lastRunSize + 255 - RUN_MASK) / 255; lastRunSize -= litLength; } ip = anchor + lastRunSize; if (lastRunSize >= RUN_MASK) { size_t accumulator = lastRunSize - RUN_MASK; *op++ = (RUN_MASK << ML_BITS); for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255; *op++ = (BYTE) accumulator; } else { *op++ = (BYTE)(lastRunSize << ML_BITS); } memcpy(op, anchor, lastRunSize); op += lastRunSize; } /* End */ *srcSizePtr = (int) (((const char*)ip) - source); return (int) ((char*)op-dst); _dest_overflow: if (limit == fillOutput) { op = opSaved; /* restore correct out pointer */ goto _last_literals; } return 0; } squashfs-tools-ng-0.8/lib/sqfs/comp/lz4/lz4hc.h000066400000000000000000000317761360235375500213730ustar00rootroot00000000000000/* LZ4 HC - High Compression Mode of LZ4 Header File Copyright (C) 2011-2017, 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 : - LZ4 source repository : https://github.com/lz4/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c */ #ifndef LZ4_HC_H_19834876238432 #define LZ4_HC_H_19834876238432 #if defined (__cplusplus) extern "C" { #endif /* --- Dependency --- */ /* note : lz4hc requires lz4.h/lz4.c for compilation */ #include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */ /* --- Useful constants --- */ #define LZ4HC_CLEVEL_MIN 3 #define LZ4HC_CLEVEL_DEFAULT 9 #define LZ4HC_CLEVEL_OPT_MIN 10 #define LZ4HC_CLEVEL_MAX 12 /*-************************************ * Block Compression **************************************/ /*! LZ4_compress_HC() : * Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm. * `dst` must be already allocated. * Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h") * Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h") * `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work. * Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX. * @return : the number of bytes written into 'dst' * or 0 if compression fails. */ LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel); /* Note : * Decompression functions are provided within "lz4.h" (BSD license) */ /*! LZ4_compress_HC_extStateHC() : * Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`. * `state` size is provided by LZ4_sizeofStateHC(). * Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly). */ LZ4LIB_API int LZ4_sizeofStateHC(void); LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); /*! LZ4_compress_HC_destSize() : v1.9.0+ * Will compress as much data as possible from `src` * to fit into `targetDstSize` budget. * Result is provided in 2 parts : * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize) * or 0 if compression fails. * `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src` */ LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int compressionLevel); /*-************************************ * Streaming Compression * Bufferless synchronous API **************************************/ typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */ /* These functions compress data in successive blocks of any size, using previous blocks as dictionary, to improve compression ratio. One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks. There is an exception for ring buffers, which can be smaller than 64 KB. Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue(). Before starting compression, state must be allocated and properly initialized. LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT. Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream) or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental). LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once, which is automatically the case when state is created using LZ4_createStreamHC(). After reset, a first "fictional block" can be designated as initial dictionary, using LZ4_loadDictHC() (Optional). Invoke LZ4_compress_HC_continue() to compress each successive block. The number of blocks is unlimited. Previous input blocks, including initial dictionary when present, must remain accessible and unmodified during compression. It's allowed to update compression level anytime between blocks, using LZ4_setCompressionLevel() (experimental). 'dst' buffer should be sized to handle worst case scenarios (see LZ4_compressBound(), it ensures compression success). In case of failure, the API does not guarantee recovery, so the state _must_ be reset. To ensure compression success whenever `dst` buffer size cannot be made >= LZ4_compressBound(), consider using LZ4_compress_HC_continue_destSize(). Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks, it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC(). Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB) After completing a streaming compression, it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state, just by resetting it, using LZ4_resetStreamHC_fast(). */ LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */ /*^********************************************** * !!!!!! STATIC LINKING ONLY !!!!!! ***********************************************/ /*-****************************************************************** * PRIVATE DEFINITIONS : * Do not use these definitions directly. * They are merely exposed to allow static allocation of `LZ4_streamHC_t`. * Declare an `LZ4_streamHC_t` directly, rather than any type below. * Even then, only do so in the context of static linking, as definitions may change between versions. ********************************************************************/ #define LZ4HC_DICTIONARY_LOGSIZE 16 #define LZ4HC_MAXD (1<= 199901L) /* C99 */) #include typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal; struct LZ4HC_CCtx_internal { uint32_t hashTable[LZ4HC_HASHTABLESIZE]; uint16_t chainTable[LZ4HC_MAXD]; const uint8_t* end; /* next block here to continue on current prefix */ const uint8_t* base; /* All index relative to this position */ const uint8_t* dictBase; /* alternate base for extDict */ uint32_t dictLimit; /* below that point, need extDict */ uint32_t lowLimit; /* below that point, no more dict */ uint32_t nextToUpdate; /* index from which to continue dictionary update */ short compressionLevel; int8_t favorDecSpeed; /* favor decompression speed if this flag set, otherwise, favor compression ratio */ int8_t dirty; /* stream has to be fully reset if this flag is set */ const LZ4HC_CCtx_internal* dictCtx; }; #else typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal; struct LZ4HC_CCtx_internal { unsigned int hashTable[LZ4HC_HASHTABLESIZE]; unsigned short chainTable[LZ4HC_MAXD]; const unsigned char* end; /* next block here to continue on current prefix */ const unsigned char* base; /* All index relative to this position */ const unsigned char* dictBase; /* alternate base for extDict */ unsigned int dictLimit; /* below that point, need extDict */ unsigned int lowLimit; /* below that point, no more dict */ unsigned int nextToUpdate; /* index from which to continue dictionary update */ short compressionLevel; char favorDecSpeed; /* favor decompression speed if this flag set, otherwise, favor compression ratio */ char dirty; /* stream has to be fully reset if this flag is set */ const LZ4HC_CCtx_internal* dictCtx; }; #endif /* Do not use these definitions directly ! * Declare or allocate an LZ4_streamHC_t instead. */ #define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56 + ((sizeof(void*)==16) ? 56 : 0) /* AS400*/ ) /* 262200 or 262256*/ #define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t)) union LZ4_streamHC_u { size_t table[LZ4_STREAMHCSIZE_SIZET]; LZ4HC_CCtx_internal internal_donotuse; }; /* previously typedef'd to LZ4_streamHC_t */ /* LZ4_streamHC_t : * This structure allows static allocation of LZ4 HC streaming state. * This can be used to allocate statically, on state, or as part of a larger structure. * * Such state **must** be initialized using LZ4_initStreamHC() before first use. * * Note that invoking LZ4_initStreamHC() is not required when * the state was created using LZ4_createStreamHC() (which is recommended). * Using the normal builder, a newly created state is automatically initialized. * * Static allocation shall only be used in combination with static linking. */ /* LZ4_initStreamHC() : v1.9.0+ * Required before first use of a statically allocated LZ4_streamHC_t. * Before v1.9.0 : use LZ4_resetStreamHC() instead */ LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size); #if defined (__cplusplus) } #endif #endif /* LZ4_HC_H_19834876238432 */ /*-************************************************** * !!!!! STATIC LINKING ONLY !!!!! * Following definitions are considered experimental. * They should not be linked from DLL, * as there is no guarantee of API stability yet. * Prototypes will be promoted to "stable" status * after successfull usage in real-life scenarios. ***************************************************/ #ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */ #ifndef LZ4_HC_SLO_098092834 #define LZ4_HC_SLO_098092834 #define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */ #include "lz4.h" #if defined (__cplusplus) extern "C" { #endif /*! LZ4_setCompressionLevel() : v1.8.0+ (experimental) * It's possible to change compression level * between successive invocations of LZ4_compress_HC_continue*() * for dynamic adaptation. */ LZ4LIB_STATIC_API void LZ4_setCompressionLevel( LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel); /*! LZ4_resetStreamHC_fast() : v1.9.0+ * When an LZ4_streamHC_t is known to be in a internally coherent state, * it can often be prepared for a new compression with almost no work, only * sometimes falling back to the full, expensive reset that is always required * when the stream is in an indeterminate state (i.e., the reset performed by * LZ4_resetStreamHC()). * * LZ4_streamHCs are guaranteed to be in a valid state when: * - returned from LZ4_createStreamHC() * - reset by LZ4_resetStreamHC() * - memset(stream, 0, sizeof(LZ4_streamHC_t)) * - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast() * - the stream was in a valid state and was then used in any compression call * that returned success * - the stream was in an indeterminate state and was used in a compression * call that fully reset the state (LZ4_compress_HC_extStateHC()) and that * returned success * * Note: * A stream that was last used in a compression call that returned an error * may be passed to this function. However, it will be fully reset, which will * clear any existing history and settings from the context. */ LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast( LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel); #if defined (__cplusplus) } #endif #endif /* LZ4_HC_SLO_098092834 */ #endif /* LZ4_HC_STATIC_LINKING_ONLY */ squashfs-tools-ng-0.8/lib/sqfs/comp/lzma.c000066400000000000000000000103271360235375500205610ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * lzma.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include #include #include "internal.h" #define LZMA_SIZE_OFFSET (5) #define LZMA_SIZE_BYTES (8) #define LZMA_HEADER_SIZE (13) #define LZMA_DEFAULT_LEVEL (5) #define MEMLIMIT (32 * 1024 * 1024) typedef struct { sqfs_compressor_t base; size_t block_size; } lzma_compressor_t; static int lzma_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { (void)base; (void)file; return 0; } static int lzma_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { (void)base; (void)file; return SQFS_ERROR_UNSUPPORTED; } static sqfs_s32 lzma_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { lzma_compressor_t *lzma = (lzma_compressor_t *)base; lzma_stream strm = LZMA_STREAM_INIT; lzma_options_lzma opt; int ret; if (outsize < LZMA_HEADER_SIZE || size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; lzma_lzma_preset(&opt, LZMA_DEFAULT_LEVEL); opt.dict_size = lzma->block_size; if (lzma_alone_encoder(&strm, &opt) != LZMA_OK) { lzma_end(&strm); return SQFS_ERROR_COMPRESSOR; } strm.next_out = out; strm.avail_out = outsize; strm.next_in = in; strm.avail_in = size; ret = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if (ret != LZMA_STREAM_END) return ret == LZMA_OK ? 0 : SQFS_ERROR_COMPRESSOR; if (strm.total_out > size) return 0; out[LZMA_SIZE_OFFSET ] = size & 0xFF; out[LZMA_SIZE_OFFSET + 1] = (size >> 8) & 0xFF; out[LZMA_SIZE_OFFSET + 2] = (size >> 16) & 0xFF; out[LZMA_SIZE_OFFSET + 3] = (size >> 24) & 0xFF; out[LZMA_SIZE_OFFSET + 4] = 0; out[LZMA_SIZE_OFFSET + 5] = 0; out[LZMA_SIZE_OFFSET + 6] = 0; out[LZMA_SIZE_OFFSET + 7] = 0; return strm.total_out; } static sqfs_s32 lzma_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { sqfs_u8 lzma_header[LZMA_HEADER_SIZE]; lzma_stream strm = LZMA_STREAM_INIT; size_t hdrsize; int ret; (void)base; if (size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; if (size < sizeof(lzma_header)) return SQFS_ERROR_CORRUPTED; hdrsize = (size_t)in[LZMA_SIZE_OFFSET] | ((size_t)in[LZMA_SIZE_OFFSET + 1] << 8) | ((size_t)in[LZMA_SIZE_OFFSET + 2] << 16) | ((size_t)in[LZMA_SIZE_OFFSET + 3] << 24); if (hdrsize > outsize) return 0; if (lzma_alone_decoder(&strm, MEMLIMIT) != LZMA_OK) { lzma_end(&strm); return SQFS_ERROR_COMPRESSOR; } memcpy(lzma_header, in, sizeof(lzma_header)); memset(lzma_header + LZMA_SIZE_OFFSET, 0xFF, LZMA_SIZE_BYTES); strm.next_out = out; strm.avail_out = outsize; strm.next_in = lzma_header; strm.avail_in = sizeof(lzma_header); ret = lzma_code(&strm, LZMA_RUN); if (ret != LZMA_OK || strm.avail_in != 0) { lzma_end(&strm); return SQFS_ERROR_COMPRESSOR; } strm.next_in = in + sizeof(lzma_header); strm.avail_in = size - sizeof(lzma_header); ret = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if (ret != LZMA_STREAM_END && ret != LZMA_OK) return SQFS_ERROR_COMPRESSOR; if (ret == LZMA_OK) { if (strm.total_out < hdrsize || strm.avail_in != 0) return 0; } return hdrsize; } static sqfs_compressor_t *lzma_create_copy(sqfs_compressor_t *cmp) { lzma_compressor_t *copy = malloc(sizeof(*copy)); if (copy != NULL) memcpy(copy, cmp, sizeof(*copy)); return (sqfs_compressor_t *)copy; } static void lzma_destroy(sqfs_compressor_t *base) { free(base); } sqfs_compressor_t *lzma_compressor_create(const sqfs_compressor_config_t *cfg) { sqfs_compressor_t *base; lzma_compressor_t *lzma; if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) return NULL; lzma = calloc(1, sizeof(*lzma)); base = (sqfs_compressor_t *)lzma; if (lzma == NULL) return NULL; lzma->block_size = cfg->block_size; if (lzma->block_size < SQFS_META_BLOCK_SIZE) lzma->block_size = SQFS_META_BLOCK_SIZE; base->destroy = lzma_destroy; base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ? lzma_uncomp_block : lzma_comp_block; base->write_options = lzma_write_options; base->read_options = lzma_read_options; base->create_copy = lzma_create_copy; return base; } squashfs-tools-ng-0.8/lib/sqfs/comp/xz.c000066400000000000000000000120431360235375500202540ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xz.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include #include #include "internal.h" typedef struct { sqfs_compressor_t base; size_t block_size; size_t dict_size; int flags; } xz_compressor_t; typedef struct { sqfs_u32 dict_size; sqfs_u32 flags; } xz_options_t; static bool is_dict_size_valid(size_t size) { size_t x = size & (size - 1); if (x == 0) return true; return size == (x | (x >> 1)); } static int xz_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { xz_compressor_t *xz = (xz_compressor_t *)base; xz_options_t opt; if (xz->flags == 0 && xz->dict_size == xz->block_size) return 0; opt.dict_size = htole32(xz->dict_size); opt.flags = htole32(xz->flags); return sqfs_generic_write_options(file, &opt, sizeof(opt)); } static int xz_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { xz_compressor_t *xz = (xz_compressor_t *)base; xz_options_t opt; int ret; ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; opt.dict_size = le32toh(opt.dict_size); opt.flags = le32toh(opt.flags); if (!is_dict_size_valid(opt.dict_size)) return SQFS_ERROR_CORRUPTED; if (opt.flags & ~SQFS_COMP_FLAG_XZ_ALL) return SQFS_ERROR_UNSUPPORTED; xz->flags = opt.flags; xz->dict_size = opt.dict_size; return 0; } static sqfs_s32 compress(xz_compressor_t *xz, lzma_vli filter, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { lzma_filter filters[5]; lzma_options_lzma opt; size_t written = 0; lzma_ret ret; int i = 0; if (lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT)) return SQFS_ERROR_COMPRESSOR; opt.dict_size = xz->dict_size; if (filter != LZMA_VLI_UNKNOWN) { filters[i].id = filter; filters[i].options = NULL; ++i; } filters[i].id = LZMA_FILTER_LZMA2; filters[i].options = &opt; ++i; filters[i].id = LZMA_VLI_UNKNOWN; filters[i].options = NULL; ++i; ret = lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL, in, size, out, &written, outsize); if (ret == LZMA_OK) return (written >= size) ? 0 : written; if (ret != LZMA_BUF_ERROR) return SQFS_ERROR_COMPRESSOR; return 0; } static lzma_vli flag_to_vli(int flag) { switch (flag) { case SQFS_COMP_FLAG_XZ_X86: return LZMA_FILTER_X86; case SQFS_COMP_FLAG_XZ_POWERPC: return LZMA_FILTER_POWERPC; case SQFS_COMP_FLAG_XZ_IA64: return LZMA_FILTER_IA64; case SQFS_COMP_FLAG_XZ_ARM: return LZMA_FILTER_ARM; case SQFS_COMP_FLAG_XZ_ARMTHUMB: return LZMA_FILTER_ARMTHUMB; case SQFS_COMP_FLAG_XZ_SPARC: return LZMA_FILTER_SPARC; } return LZMA_VLI_UNKNOWN; } static sqfs_s32 xz_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { xz_compressor_t *xz = (xz_compressor_t *)base; lzma_vli filter, selected = LZMA_VLI_UNKNOWN; sqfs_s32 ret, smallest; size_t i; if (size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; ret = compress(xz, LZMA_VLI_UNKNOWN, in, size, out, outsize); if (ret < 0 || xz->flags == 0) return ret; smallest = ret; for (i = 1; i & SQFS_COMP_FLAG_XZ_ALL; i <<= 1) { if ((xz->flags & i) == 0) continue; filter = flag_to_vli(i); ret = compress(xz, filter, in, size, out, outsize); if (ret < 0) return ret; if (ret > 0 && (smallest == 0 || ret < smallest)) { smallest = ret; selected = filter; } } if (smallest == 0) return 0; return compress(xz, selected, in, size, out, outsize); } static sqfs_s32 xz_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { sqfs_u64 memlimit = 32 * 1024 * 1024; size_t dest_pos = 0; size_t src_pos = 0; lzma_ret ret; (void)base; if (outsize >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, in, &src_pos, size, out, &dest_pos, outsize); if (ret == LZMA_OK && size == src_pos) return dest_pos; return SQFS_ERROR_COMPRESSOR; } static sqfs_compressor_t *xz_create_copy(sqfs_compressor_t *cmp) { xz_compressor_t *xz = malloc(sizeof(*xz)); if (xz == NULL) return NULL; memcpy(xz, cmp, sizeof(*xz)); return (sqfs_compressor_t *)xz; } static void xz_destroy(sqfs_compressor_t *base) { free(base); } sqfs_compressor_t *xz_compressor_create(const sqfs_compressor_config_t *cfg) { sqfs_compressor_t *base; xz_compressor_t *xz; if (cfg->flags & ~(SQFS_COMP_FLAG_GENERIC_ALL | SQFS_COMP_FLAG_XZ_ALL)) { return NULL; } if (!is_dict_size_valid(cfg->opt.xz.dict_size)) return NULL; xz = calloc(1, sizeof(*xz)); base = (sqfs_compressor_t *)xz; if (xz == NULL) return NULL; xz->flags = cfg->flags; xz->dict_size = cfg->opt.xz.dict_size; xz->block_size = cfg->block_size; base->destroy = xz_destroy; base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ? xz_uncomp_block : xz_comp_block; base->write_options = xz_write_options; base->read_options = xz_read_options; base->create_copy = xz_create_copy; return base; } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/000077500000000000000000000000001360235375500204075ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/README000066400000000000000000000154441360235375500212770ustar00rootroot00000000000000Changes made for inclusion in libsquashfs: NOTE: THE SOURCE CODE IN THIS DIRECTORY IS NOT THE ORIGINAL ZLIB SOURCE CODE! A number of things were removed for inclusion in libsquashfs, part of the squashfs-tools-ng package. The original package that the source code in this directory is based on is the zlib-1.2.11 source tar ball obtained from http://zlib.net/ on October 16, 2017. An attempt has been made at removing the entire build system, samples, tests, documentation, 3rd party contributions, gzip support and various utility functions. The following sub-directories were removed with all there contents: amiga/ contrib/ doc/ examples/ msdos/ nintendods/ old/ os400/ qnx/ test/ watcom/ win32/ The following source files were removed in their entirety: gzread.c gzclose.c gzwrite.c gzguts.h gzlib.c gzguts.h compress.c uncompr.c infback.c The following source files were modified (modifications marked with a comment in the source): zutil.c inflate.c deflate.c inftrees.c zconf.h zutil.h The following additional files were removed in their entirety: ChangeLog CMakeLists.txt configure FAQ INDEX Makefile Makefile.in make_vms.com treebuild.xml zconf.h.cmakein zconf.h.in zlib.3 zlib.3.pdf zlib.map zlib.pc.cmakein zlib.pc.in zlib2ansi The following additional files were modified: README A copy of the zlib license is included in licenses/zlib.txt in the root directory of the squashfs-tools-ng source package. Rest of the original README follows: ------------------------------------------------------------------------------- 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. squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/adler32.c000066400000000000000000000121241360235375500220070ustar00rootroot00000000000000/* 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); } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/crc32.c000066400000000000000000000333451360235375500214770ustar00rootroot00000000000000/* 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); } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/crc32.h000066400000000000000000000735421360235375500215070ustar00rootroot00000000000000/* 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 } }; squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/deflate.c000066400000000000000000002322741360235375500221710ustar00rootroot00000000000000/* 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" /* XXX: Not original zlib source code. The following 2 lines were commented out by David Oberhollenzer for use in in libsquashfs. 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; } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/deflate.h000066400000000000000000000315361360235375500221740ustar00rootroot00000000000000/* 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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inffast.c000066400000000000000000000312621360235375500222110ustar00rootroot00000000000000/* 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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inffast.h000066400000000000000000000006531360235375500222160ustar00rootroot00000000000000/* 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)); squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inffixed.h000066400000000000000000000142741360235375500223640ustar00rootroot00000000000000 /* 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} }; squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inflate.c000066400000000000000000001542361360235375500222100ustar00rootroot00000000000000/* 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. */ /* XXX: Not original zlib source code. Various "fall-through" comments were added to the big-ass switch block below by David Oberhollenzer for use in libsquashfs. */ 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; /* fall-through */ case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; /* fall-through */ case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; /* fall-through */ 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; /* fall-through */ case COPY_: state->mode = COPY; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ case LEN_: state->mode = LEN; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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; /* fall-through */ 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); } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inflate.h000066400000000000000000000147321360235375500222110ustar00rootroot00000000000000/* 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 */ }; squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inftrees.c000066400000000000000000000315321360235375500223760ustar00rootroot00000000000000/* 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 /* XXX: Not original zlib source code. The following 2 lines were commented out by David Oberhollenzer for use in in libsquashfs. 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; } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/inftrees.h000066400000000000000000000055601360235375500224050ustar00rootroot00000000000000/* 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)); squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/trees.c000066400000000000000000001253611360235375500217050ustar00rootroot00000000000000/* 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 } squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/trees.h000066400000000000000000000204301360235375500217010ustar00rootroot00000000000000/* 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 }; squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/zconf.h000066400000000000000000000343561360235375500217120ustar00rootroot00000000000000/* 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 /* XXX: Not original zlib source code. The definitions of ZEXTERN, ZEXPORT and ZEXPORTVA were removed and replaced with the following below by David Oberhollenzer for use in in libsquashfs. */ #ifndef ZEXTERN # if (defined(__GNUC__) || defined(__clang__)) && !defined(_WIN32) # define ZEXTERN __attribute__ ((visibility ("hidden"))) # else # define ZEXTERN # endif #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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/zlib.h000066400000000000000000002737571360235375500215450ustar00rootroot00000000000000/* 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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/zutil.c000066400000000000000000000164341360235375500217320ustar00rootroot00000000000000/* 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" /* XXX: Not original zlib source code. The following 3 lines were commented out by David Oberhollenzer for use in in libsquashfs. #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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zlib/zutil.h000066400000000000000000000164651360235375500217430ustar00rootroot00000000000000/* 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 /* XXX: Not original zlib source code. The definition of ZLIB_INTRENAL was changed by David Oberhollenzer for use in in libsquashfs. */ #if (defined(__GNUC__) || defined(__clang__)) && !defined(_WIN32) # 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; /* XXX: Not original zlib source code. The visibility of z_errmsg was changed to internal by David Oberhollenzer for use in in libsquashfs. */ extern ZLIB_INTERNAL 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 */ squashfs-tools-ng-0.8/lib/sqfs/comp/zstd.c000066400000000000000000000060351360235375500206030ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * zstd.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include #include #include #include #include #include "internal.h" typedef struct { sqfs_compressor_t base; ZSTD_CCtx *zctx; int level; } zstd_compressor_t; typedef struct { sqfs_u32 level; } zstd_options_t; static int zstd_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { zstd_compressor_t *zstd = (zstd_compressor_t *)base; zstd_options_t opt; if (zstd->level == SQFS_ZSTD_DEFAULT_LEVEL) return 0; opt.level = htole32(zstd->level); return sqfs_generic_write_options(file, &opt, sizeof(opt)); } static int zstd_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { zstd_options_t opt; int ret; (void)base; ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; opt.level = le32toh(opt.level); return 0; } static sqfs_s32 zstd_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { zstd_compressor_t *zstd = (zstd_compressor_t *)base; size_t ret; if (size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; ret = ZSTD_compressCCtx(zstd->zctx, out, outsize, in, size, zstd->level); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) return 0; return SQFS_ERROR_COMPRESSOR; } return ret < size ? ret : 0; } static sqfs_s32 zstd_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in, sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) { size_t ret; (void)base; if (outsize >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; ret = ZSTD_decompress(out, outsize, in, size); if (ZSTD_isError(ret)) return SQFS_ERROR_COMPRESSOR; return ret; } static sqfs_compressor_t *zstd_create_copy(sqfs_compressor_t *cmp) { zstd_compressor_t *zstd = malloc(sizeof(*zstd)); if (zstd == NULL) return NULL; memcpy(zstd, cmp, sizeof(*zstd)); zstd->zctx = ZSTD_createCCtx(); if (zstd->zctx == NULL) { free(zstd); return NULL; } return (sqfs_compressor_t *)zstd; } static void zstd_destroy(sqfs_compressor_t *base) { zstd_compressor_t *zstd = (zstd_compressor_t *)base; ZSTD_freeCCtx(zstd->zctx); free(zstd); } sqfs_compressor_t *zstd_compressor_create(const sqfs_compressor_config_t *cfg) { zstd_compressor_t *zstd; sqfs_compressor_t *base; if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) return NULL; if (cfg->opt.zstd.level < 1 || cfg->opt.zstd.level > ZSTD_maxCLevel()) { return NULL; } zstd = calloc(1, sizeof(*zstd)); base = (sqfs_compressor_t *)zstd; if (zstd == NULL) return NULL; zstd->zctx = ZSTD_createCCtx(); if (zstd->zctx == NULL) { free(zstd); return NULL; } base->destroy = zstd_destroy; base->do_block = cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS ? zstd_uncomp_block : zstd_comp_block; base->write_options = zstd_write_options; base->read_options = zstd_read_options; base->create_copy = zstd_create_copy; return base; } squashfs-tools-ng-0.8/lib/sqfs/data_reader.c000066400000000000000000000166531360235375500211230ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * data_reader.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/data_reader.h" #include "sqfs/compressor.h" #include "sqfs/block.h" #include "sqfs/error.h" #include "sqfs/table.h" #include "sqfs/inode.h" #include "sqfs/io.h" #include "util.h" #include #include struct sqfs_data_reader_t { sqfs_fragment_t *frag; sqfs_compressor_t *cmp; sqfs_block_t *data_block; sqfs_block_t *frag_block; sqfs_u64 current_block; sqfs_file_t *file; sqfs_u32 num_fragments; sqfs_u32 current_frag_index; sqfs_u32 block_size; sqfs_u8 scratch[]; }; static int get_block(sqfs_data_reader_t *data, sqfs_u64 off, sqfs_u32 size, size_t unpacked_size, sqfs_block_t **out) { sqfs_block_t *blk = alloc_flex(sizeof(*blk), 1, unpacked_size); sqfs_u32 on_disk_size; sqfs_s32 ret; int err; if (blk == NULL) return SQFS_ERROR_ALLOC; blk->size = unpacked_size; if (SQFS_IS_SPARSE_BLOCK(size)) { *out = blk; return 0; } on_disk_size = SQFS_ON_DISK_BLOCK_SIZE(size); if (on_disk_size > unpacked_size) { free(blk); return SQFS_ERROR_OVERFLOW; } if (SQFS_IS_BLOCK_COMPRESSED(size)) { err = data->file->read_at(data->file, off, data->scratch, on_disk_size); if (err) { free(blk); return err; } ret = data->cmp->do_block(data->cmp, data->scratch, on_disk_size, blk->data, blk->size); if (ret <= 0) err = ret < 0 ? ret : SQFS_ERROR_OVERFLOW; } else { err = data->file->read_at(data->file, off, blk->data, on_disk_size); } if (err) { free(blk); return err; } *out = blk; return 0; } static int precache_data_block(sqfs_data_reader_t *data, sqfs_u64 location, sqfs_u32 size) { int ret; if (data->data_block != NULL && data->current_block == location) return 0; free(data->data_block); data->data_block = NULL; ret = get_block(data, location, size, data->block_size, &data->data_block); if (ret < 0) { data->data_block = NULL; return -1; } data->current_block = location; return 0; } static int precache_fragment_block(sqfs_data_reader_t *data, size_t idx) { int ret; if (data->frag_block != NULL && idx == data->current_frag_index) return 0; if (idx >= data->num_fragments) return SQFS_ERROR_OUT_OF_BOUNDS; free(data->frag_block); data->frag_block = NULL; ret = get_block(data, data->frag[idx].start_offset, data->frag[idx].size, data->block_size, &data->frag_block); if (ret < 0) return -1; data->current_frag_index = idx; return 0; } sqfs_data_reader_t *sqfs_data_reader_create(sqfs_file_t *file, size_t block_size, sqfs_compressor_t *cmp) { sqfs_data_reader_t *data = alloc_flex(sizeof(*data), 1, block_size); if (data != NULL) { data->file = file; data->block_size = block_size; data->cmp = cmp; } return data; } int sqfs_data_reader_load_fragment_table(sqfs_data_reader_t *data, const sqfs_super_t *super) { void *raw_frag; size_t size; sqfs_u32 i; int ret; free(data->frag_block); free(data->frag); data->frag = NULL; data->frag_block = NULL; data->num_fragments = 0; data->current_frag_index = 0; if (super->fragment_entry_count == 0 || (super->flags & SQFS_FLAG_NO_FRAGMENTS) != 0) { return 0; } if (super->fragment_table_start >= super->bytes_used) return SQFS_ERROR_OUT_OF_BOUNDS; if (SZ_MUL_OV(sizeof(data->frag[0]), super->fragment_entry_count, &size)) { return SQFS_ERROR_OVERFLOW; } ret = sqfs_read_table(data->file, data->cmp, size, super->fragment_table_start, super->directory_table_start, super->fragment_table_start, &raw_frag); if (ret) return ret; data->num_fragments = super->fragment_entry_count; data->current_frag_index = super->fragment_entry_count; data->frag = raw_frag; for (i = 0; i < data->num_fragments; ++i) { data->frag[i].size = le32toh(data->frag[i].size); data->frag[i].start_offset = le64toh(data->frag[i].start_offset); } return 0; } void sqfs_data_reader_destroy(sqfs_data_reader_t *data) { free(data->data_block); free(data->frag_block); free(data->frag); free(data); } int sqfs_data_reader_get_block(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, size_t index, sqfs_block_t **out) { size_t i, unpacked_size; sqfs_u64 off, filesz; sqfs_inode_get_file_block_start(inode, &off); sqfs_inode_get_file_size(inode, &filesz); if (index >= inode->num_file_blocks) return SQFS_ERROR_OUT_OF_BOUNDS; for (i = 0; i < index; ++i) { off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i]); filesz -= data->block_size; } unpacked_size = filesz < data->block_size ? filesz : data->block_size; return get_block(data, off, inode->block_sizes[index], unpacked_size, out); } int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, sqfs_block_t **out) { sqfs_u32 frag_idx, frag_off, frag_sz; sqfs_block_t *blk; sqfs_u64 filesz; sqfs_inode_get_file_size(inode, &filesz); sqfs_inode_get_frag_location(inode, &frag_idx, &frag_off); if (inode->num_file_blocks * data->block_size >= filesz) { *out = NULL; return 0; } frag_sz = filesz % data->block_size; if (precache_fragment_block(data, frag_idx)) return -1; if (frag_off + frag_sz > data->block_size) return -1; blk = alloc_flex(sizeof(*blk), 1, frag_sz); if (blk == NULL) return -1; blk->size = frag_sz; memcpy(blk->data, (char *)data->frag_block->data + frag_off, frag_sz); *out = blk; return 0; } sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, sqfs_u64 offset, void *buffer, sqfs_u32 size) { sqfs_u32 frag_idx, frag_off, diff, total = 0; sqfs_u64 off, filesz; char *ptr; size_t i; if (size >= 0x7FFFFFFF) size = 0x7FFFFFFE; /* work out file location and size */ sqfs_inode_get_file_size(inode, &filesz); sqfs_inode_get_frag_location(inode, &frag_idx, &frag_off); sqfs_inode_get_file_block_start(inode, &off); /* find location of the first block */ i = 0; while (offset > data->block_size && i < inode->num_file_blocks) { off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i++]); offset -= data->block_size; if (filesz >= data->block_size) { filesz -= data->block_size; } else { filesz = 0; } } /* copy data from blocks */ while (i < inode->num_file_blocks && size > 0 && filesz > 0) { diff = data->block_size - offset; if (size < diff) diff = size; if (SQFS_IS_SPARSE_BLOCK(inode->block_sizes[i])) { memset(buffer, 0, diff); } else { if (precache_data_block(data, off, inode->block_sizes[i])) { return -1; } memcpy(buffer, (char *)data->data_block->data + offset, diff); off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i]); } if (filesz >= data->block_size) { filesz -= data->block_size; } else { filesz = 0; } ++i; offset = 0; size -= diff; total += diff; buffer = (char *)buffer + diff; } /* copy from fragment */ if (i == inode->num_file_blocks && size > 0 && filesz > 0) { if (precache_fragment_block(data, frag_idx)) return -1; if (frag_off + filesz > data->block_size) return SQFS_ERROR_OUT_OF_BOUNDS; if (offset >= filesz) return total; if (offset + size > filesz) size = filesz - offset; if (size == 0) return total; ptr = (char *)data->frag_block->data + frag_off + offset; memcpy(buffer, ptr, size); total += size; } return total; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/000077500000000000000000000000001360235375500210165ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/data_writer/block.c000066400000000000000000000106011360235375500222520ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * process_block.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" #include static int store_block_location(sqfs_data_writer_t *proc, sqfs_u64 offset, sqfs_u32 size, sqfs_u32 chksum) { size_t new_sz; void *new; if (proc->num_blocks == proc->max_blocks) { new_sz = proc->max_blocks * 2; new = realloc(proc->blocks, sizeof(proc->blocks[0]) * new_sz); if (new == NULL) return SQFS_ERROR_ALLOC; proc->blocks = new; proc->max_blocks = new_sz; } proc->blocks[proc->num_blocks].offset = offset; proc->blocks[proc->num_blocks].hash = MK_BLK_HASH(chksum, size); proc->num_blocks += 1; return 0; } static size_t deduplicate_blocks(sqfs_data_writer_t *proc, size_t count) { size_t i, j; for (i = 0; i < proc->file_start; ++i) { for (j = 0; j < count; ++j) { if (proc->blocks[i + j].hash != proc->blocks[proc->file_start + j].hash) break; } if (j == count) break; } return i; } static int align_file(sqfs_data_writer_t *proc, sqfs_block_t *blk) { sqfs_u32 chksum; void *padding; sqfs_u64 size; size_t diff; int ret; if (!(blk->flags & SQFS_BLK_ALIGN)) return 0; size = proc->file->get_size(proc->file); diff = size % proc->devblksz; if (diff == 0) return 0; padding = calloc(1, diff); if (padding == 0) return SQFS_ERROR_ALLOC; if (proc->hooks != NULL && proc->hooks->prepare_padding != NULL) proc->hooks->prepare_padding(proc->user_ptr, padding, diff); chksum = crc32(0, padding, diff); ret = proc->file->write_at(proc->file, size, padding, diff); free(padding); if (ret) return ret; return store_block_location(proc, size, diff | (1 << 24), chksum); } int process_completed_block(sqfs_data_writer_t *proc, sqfs_block_t *blk) { sqfs_u64 offset, bytes; size_t start, count; sqfs_u32 out; int err; if (proc->hooks != NULL && proc->hooks->pre_block_write != NULL) { proc->hooks->pre_block_write(proc->user_ptr, blk, proc->file); } if (blk->flags & SQFS_BLK_FIRST_BLOCK) { proc->start = proc->file->get_size(proc->file); proc->file_start = proc->num_blocks; err = align_file(proc, blk); if (err) return err; } if (blk->size != 0) { out = blk->size; if (!(blk->flags & SQFS_BLK_IS_COMPRESSED)) out |= 1 << 24; offset = proc->file->get_size(proc->file); if (blk->flags & SQFS_BLK_FRAGMENT_BLOCK) { offset = htole64(offset); proc->fragments[blk->index].start_offset = offset; proc->fragments[blk->index].pad0 = 0; proc->fragments[blk->index].size = htole32(out); } else { blk->inode->block_sizes[blk->index] = out; } err = store_block_location(proc, offset, out, blk->checksum); if (err) return err; err = proc->file->write_at(proc->file, offset, blk->data, blk->size); if (err) return err; } if (proc->hooks != NULL && proc->hooks->post_block_write != NULL) { proc->hooks->post_block_write(proc->user_ptr, blk, proc->file); } if (blk->flags & SQFS_BLK_LAST_BLOCK) { err = align_file(proc, blk); if (err) return err; count = proc->num_blocks - proc->file_start; start = deduplicate_blocks(proc, count); offset = proc->blocks[start].offset; sqfs_inode_set_file_block_start(blk->inode, offset); if (start >= proc->file_start) return 0; offset = start + count; if (offset >= proc->file_start) { count = proc->num_blocks - offset; proc->num_blocks = offset; } else { proc->num_blocks = proc->file_start; } if (proc->hooks != NULL && proc->hooks->notify_blocks_erased != NULL) { bytes = proc->file->get_size(proc->file) - proc->start; proc->hooks->notify_blocks_erased(proc->user_ptr, count, bytes); } err = proc->file->truncate(proc->file, proc->start); if (err) return err; } return 0; } int data_writer_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp, sqfs_u8 *scratch, size_t scratch_size) { ssize_t ret; if (block->size == 0) { block->checksum = 0; return 0; } block->checksum = crc32(0, block->data, block->size); if (block->flags & SQFS_BLK_IS_FRAGMENT) return 0; if (!(block->flags & SQFS_BLK_DONT_COMPRESS)) { ret = cmp->do_block(cmp, block->data, block->size, scratch, scratch_size); if (ret < 0) return ret; if (ret > 0) { memcpy(block->data, scratch, ret); block->size = ret; block->flags |= SQFS_BLK_IS_COMPRESSED; } } return 0; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/common.c000066400000000000000000000056371360235375500224650ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * common.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" void free_blk_list(sqfs_block_t *list) { sqfs_block_t *it; while (list != NULL) { it = list; list = list->next; free(it); } } int data_writer_init(sqfs_data_writer_t *proc, size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file) { proc->max_block_size = max_block_size; proc->num_workers = num_workers; proc->max_backlog = max_backlog; proc->devblksz = devblksz; proc->cmp = cmp; proc->file = file; proc->max_blocks = INIT_BLOCK_COUNT; proc->frag_list_max = INIT_BLOCK_COUNT; proc->blocks = alloc_array(sizeof(proc->blocks[0]), proc->max_blocks); if (proc->blocks == NULL) return -1; proc->frag_list = alloc_array(sizeof(proc->frag_list[0]), proc->frag_list_max); if (proc->frag_list == NULL) return -1; return 0; } void data_writer_cleanup(sqfs_data_writer_t *proc) { free_blk_list(proc->queue); free_blk_list(proc->done); free(proc->blk_current); free(proc->frag_block); free(proc->frag_list); free(proc->fragments); free(proc->blocks); free(proc); } void data_writer_store_done(sqfs_data_writer_t *proc, sqfs_block_t *blk, int status) { sqfs_block_t *it = proc->done, *prev = NULL; while (it != NULL) { if (it->sequence_number >= blk->sequence_number) break; prev = it; it = it->next; } if (prev == NULL) { blk->next = proc->done; proc->done = blk; } else { blk->next = prev->next; prev->next = blk; } if (status != 0 && proc->status == 0) proc->status = status; } sqfs_block_t *data_writer_next_work_item(sqfs_data_writer_t *proc) { sqfs_block_t *blk; if (proc->status != 0) return NULL; blk = proc->queue; proc->queue = blk->next; blk->next = NULL; if (proc->queue == NULL) proc->queue_last = NULL; return blk; } int sqfs_data_writer_write_fragment_table(sqfs_data_writer_t *proc, sqfs_super_t *super) { sqfs_u64 start; size_t size; int ret; if (proc->num_fragments == 0) { super->fragment_entry_count = 0; super->fragment_table_start = 0xFFFFFFFFFFFFFFFFUL; super->flags &= ~SQFS_FLAG_ALWAYS_FRAGMENTS; super->flags |= SQFS_FLAG_NO_FRAGMENTS; return 0; } size = sizeof(proc->fragments[0]) * proc->num_fragments; ret = sqfs_write_table(proc->file, proc->cmp, proc->fragments, size, &start); if (ret) return ret; super->flags &= ~SQFS_FLAG_NO_FRAGMENTS; super->flags |= SQFS_FLAG_ALWAYS_FRAGMENTS; super->fragment_entry_count = proc->num_fragments; super->fragment_table_start = start; return 0; } int sqfs_data_writer_set_hooks(sqfs_data_writer_t *proc, void *user_ptr, const sqfs_block_hooks_t *hooks) { if (hooks->size != sizeof(*hooks)) return SQFS_ERROR_UNSUPPORTED; proc->hooks = hooks; proc->user_ptr = user_ptr; return 0; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/fileapi.c000066400000000000000000000100001360235375500225620ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * fileapi.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" static bool is_zero_block(unsigned char *ptr, size_t size) { return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0; } static int enqueue_block(sqfs_data_writer_t *proc, sqfs_block_t *block) { int status; while (proc->backlog > proc->max_backlog) { status = wait_completed(proc); if (status) return status; } if (proc->backlog == proc->max_backlog) proc->notify_threads = true; return append_to_work_queue(proc, block, proc->notify_threads); } static int add_sentinel_block(sqfs_data_writer_t *proc) { sqfs_block_t *blk = calloc(1, sizeof(*blk)); if (blk == NULL) return test_and_set_status(proc, SQFS_ERROR_ALLOC); blk->inode = proc->inode; blk->flags = proc->blk_flags | SQFS_BLK_LAST_BLOCK; return enqueue_block(proc, blk); } int sqfs_data_writer_begin_file(sqfs_data_writer_t *proc, sqfs_inode_generic_t *inode, sqfs_u32 flags) { if (proc->inode != NULL) return test_and_set_status(proc, SQFS_ERROR_INTERNAL); if (flags & ~SQFS_BLK_USER_SETTABLE_FLAGS) return test_and_set_status(proc, SQFS_ERROR_UNSUPPORTED); proc->inode = inode; proc->blk_flags = flags | SQFS_BLK_FIRST_BLOCK; proc->blk_index = 0; proc->blk_current = NULL; return 0; } static int flush_block(sqfs_data_writer_t *proc, sqfs_block_t *block) { block->index = proc->blk_index++; block->flags = proc->blk_flags; block->inode = proc->inode; if (is_zero_block(block->data, block->size)) { sqfs_inode_make_extended(proc->inode); proc->inode->data.file_ext.sparse += block->size; proc->inode->num_file_blocks += 1; proc->inode->block_sizes[block->index] = 0; free(block); return 0; } if (block->size < proc->max_block_size && !(block->flags & SQFS_BLK_DONT_FRAGMENT)) { block->flags |= SQFS_BLK_IS_FRAGMENT; } else { proc->inode->num_file_blocks += 1; proc->blk_flags &= ~SQFS_BLK_FIRST_BLOCK; } return enqueue_block(proc, block); } int sqfs_data_writer_append(sqfs_data_writer_t *proc, const void *data, size_t size) { size_t diff; void *new; int err; while (size > 0) { if (proc->blk_current == NULL) { new = alloc_flex(sizeof(*proc->blk_current), 1, proc->max_block_size); if (new == NULL) return test_and_set_status(proc, SQFS_ERROR_ALLOC); proc->blk_current = new; } diff = proc->max_block_size - proc->blk_current->size; if (diff == 0) { err = flush_block(proc, proc->blk_current); proc->blk_current = NULL; if (err) return err; continue; } if (diff > size) diff = size; memcpy(proc->blk_current->data + proc->blk_current->size, data, diff); size -= diff; proc->blk_current->size += diff; data = (const char *)data + diff; } if (proc->blk_current != NULL && proc->blk_current->size == proc->max_block_size) { err = flush_block(proc, proc->blk_current); proc->blk_current = NULL; return err; } return 0; } int sqfs_data_writer_end_file(sqfs_data_writer_t *proc) { int err; if (proc->inode == NULL) return test_and_set_status(proc, SQFS_ERROR_INTERNAL); if (!(proc->blk_flags & SQFS_BLK_FIRST_BLOCK)) { if (proc->blk_current != NULL && (proc->blk_flags & SQFS_BLK_DONT_FRAGMENT)) { proc->blk_flags |= SQFS_BLK_LAST_BLOCK; } else { err = add_sentinel_block(proc); if (err) return err; } } if (proc->blk_current != NULL) { err = flush_block(proc, proc->blk_current); proc->blk_current = NULL; } proc->inode = NULL; proc->blk_flags = 0; proc->blk_index = 0; return 0; } int sqfs_data_writer_finish(sqfs_data_writer_t *proc) { int status = 0; append_to_work_queue(proc, NULL, true); while (proc->backlog > 0) { status = wait_completed(proc); if (status) return status; } if (proc->frag_block != NULL) { status = append_to_work_queue(proc, proc->frag_block, true); proc->frag_block = NULL; if (status) return status; status = wait_completed(proc); } return status; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/fragment.c000066400000000000000000000060231360235375500227660ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * fragtbl.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" static int grow_fragment_table(sqfs_data_writer_t *proc) { size_t newsz; void *new; if (proc->num_fragments >= proc->max_fragments) { newsz = proc->max_fragments ? proc->max_fragments * 2 : 16; new = realloc(proc->fragments, sizeof(proc->fragments[0]) * newsz); if (new == NULL) return SQFS_ERROR_ALLOC; proc->max_fragments = newsz; proc->fragments = new; } return 0; } static int grow_deduplication_list(sqfs_data_writer_t *proc) { size_t new_sz; void *new; if (proc->frag_list_num == proc->frag_list_max) { new_sz = proc->frag_list_max * 2; new = realloc(proc->frag_list, sizeof(proc->frag_list[0]) * new_sz); if (new == NULL) return SQFS_ERROR_ALLOC; proc->frag_list = new; proc->frag_list_max = new_sz; } return 0; } static int store_fragment(sqfs_data_writer_t *proc, sqfs_block_t *frag, sqfs_u64 hash) { int err = grow_deduplication_list(proc); if (err) return err; proc->frag_list[proc->frag_list_num].index = proc->frag_block->index; proc->frag_list[proc->frag_list_num].offset = proc->frag_block->size; proc->frag_list[proc->frag_list_num].hash = hash; proc->frag_list_num += 1; sqfs_inode_set_frag_location(frag->inode, proc->frag_block->index, proc->frag_block->size); if (proc->hooks != NULL && proc->hooks->pre_fragment_store != NULL) { proc->hooks->pre_fragment_store(proc->user_ptr, frag); } memcpy(proc->frag_block->data + proc->frag_block->size, frag->data, frag->size); proc->frag_block->flags |= (frag->flags & SQFS_BLK_DONT_COMPRESS); proc->frag_block->size += frag->size; return 0; } int process_completed_fragment(sqfs_data_writer_t *proc, sqfs_block_t *frag, sqfs_block_t **blk_out) { sqfs_u64 hash; size_t i, size; int err; hash = MK_BLK_HASH(frag->checksum, frag->size); for (i = 0; i < proc->frag_list_num; ++i) { if (proc->frag_list[i].hash == hash) goto out_duplicate; } if (proc->frag_block != NULL) { size = proc->frag_block->size + frag->size; if (size > proc->max_block_size) { *blk_out = proc->frag_block; proc->frag_block = NULL; } } if (proc->frag_block == NULL) { size = sizeof(sqfs_block_t) + proc->max_block_size; err = grow_fragment_table(proc); if (err) goto fail; proc->frag_block = calloc(1, size); if (proc->frag_block == NULL) { err = SQFS_ERROR_ALLOC; goto fail; } proc->frag_block->index = proc->num_fragments++; proc->frag_block->flags = SQFS_BLK_FRAGMENT_BLOCK; } err = store_fragment(proc, frag, hash); if (err) goto fail; return 0; fail: free(*blk_out); *blk_out = NULL; return err; out_duplicate: sqfs_inode_set_frag_location(frag->inode, proc->frag_list[i].index, proc->frag_list[i].offset); if (proc->hooks != NULL && proc->hooks->notify_fragment_discard != NULL) { proc->hooks->notify_fragment_discard(proc->user_ptr, frag); } return 0; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/internal.h000066400000000000000000000064711360235375500230130ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * internal.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef INTERNAL_H #define INTERNAL_H #include "config.h" #include "sqfs/data_writer.h" #include "sqfs/compressor.h" #include "sqfs/inode.h" #include "sqfs/table.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "../util.h" #include #include #include #ifdef WITH_PTHREAD #include #include #elif defined(_WIN32) || defined(__WINDOWS__) #define WIN32_LEAN_AND_MEAN #include #endif #define MK_BLK_HASH(chksum, size) \ (((sqfs_u64)(size) << 32) | (sqfs_u64)(chksum)) #define INIT_BLOCK_COUNT (128) typedef struct { sqfs_u64 offset; sqfs_u64 hash; } blk_info_t; typedef struct { sqfs_u32 index; sqfs_u32 offset; sqfs_u64 hash; } frag_info_t; typedef struct compress_worker_t compress_worker_t; struct sqfs_data_writer_t { /* synchronization primitives */ #ifdef WITH_PTHREAD pthread_mutex_t mtx; pthread_cond_t queue_cond; pthread_cond_t done_cond; #elif defined(_WIN32) || defined(__WINDOWS__) CRITICAL_SECTION mtx; CONDITION_VARIABLE queue_cond; CONDITION_VARIABLE done_cond; #endif /* needs rw access by worker and main thread */ sqfs_block_t *queue; sqfs_block_t *queue_last; sqfs_block_t *done; size_t backlog; int status; /* used by main thread only */ sqfs_u32 enqueue_id; sqfs_u32 dequeue_id; unsigned int num_workers; size_t max_backlog; size_t devblksz; sqfs_file_t *file; sqfs_fragment_t *fragments; size_t num_fragments; size_t max_fragments; sqfs_u64 start; size_t file_start; size_t num_blocks; size_t max_blocks; blk_info_t *blocks; sqfs_compressor_t *cmp; sqfs_block_t *frag_block; frag_info_t *frag_list; size_t frag_list_num; size_t frag_list_max; const sqfs_block_hooks_t *hooks; void *user_ptr; bool notify_threads; /* file API */ sqfs_inode_generic_t *inode; sqfs_block_t *blk_current; sqfs_u32 blk_flags; size_t blk_index; /* used only by workers */ size_t max_block_size; #if defined(WITH_PTHREAD) || defined(_WIN32) || defined(__WINDOWS__) compress_worker_t *workers[]; #else sqfs_u8 scratch[]; #endif }; SQFS_INTERNAL int process_completed_block(sqfs_data_writer_t *proc, sqfs_block_t *block); SQFS_INTERNAL int process_completed_fragment(sqfs_data_writer_t *proc, sqfs_block_t *frag, sqfs_block_t **blk_out); SQFS_INTERNAL void free_blk_list(sqfs_block_t *list); SQFS_INTERNAL int data_writer_init(sqfs_data_writer_t *proc, size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file); SQFS_INTERNAL void data_writer_cleanup(sqfs_data_writer_t *proc); SQFS_INTERNAL void data_writer_store_done(sqfs_data_writer_t *proc, sqfs_block_t *blk, int status); SQFS_INTERNAL sqfs_block_t *data_writer_next_work_item(sqfs_data_writer_t *proc); SQFS_INTERNAL int data_writer_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp, sqfs_u8 *scratch, size_t scratch_size); SQFS_INTERNAL int test_and_set_status(sqfs_data_writer_t *proc, int status); SQFS_INTERNAL int append_to_work_queue(sqfs_data_writer_t *proc, sqfs_block_t *block, bool notify_threads); SQFS_INTERNAL int wait_completed(sqfs_data_writer_t *proc); #endif /* INTERNAL_H */ squashfs-tools-ng-0.8/lib/sqfs/data_writer/serial.c000066400000000000000000000033621360235375500224450ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * serial.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" sqfs_data_writer_t *sqfs_data_writer_create(size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file) { sqfs_data_writer_t *proc; proc = alloc_flex(sizeof(*proc), 1, max_block_size); if (proc == NULL) return NULL; if (data_writer_init(proc, max_block_size, cmp, num_workers, max_backlog, devblksz, file)) { data_writer_cleanup(proc); return NULL; } return proc; } void sqfs_data_writer_destroy(sqfs_data_writer_t *proc) { data_writer_cleanup(proc); } int test_and_set_status(sqfs_data_writer_t *proc, int status) { if (proc->status == 0) proc->status = status; return proc->status; } int append_to_work_queue(sqfs_data_writer_t *proc, sqfs_block_t *block, bool signal_threads) { sqfs_block_t *fragblk = NULL; (void)signal_threads; if (proc->status != 0 || block == NULL) { free(block); return proc->status; } if (block->flags & SQFS_BLK_IS_FRAGMENT) { block->checksum = crc32(0, block->data, block->size); proc->status = process_completed_fragment(proc, block, &fragblk); free(block); if (proc->status != 0) { free(fragblk); return proc->status; } if (fragblk == NULL) return 0; block = fragblk; } proc->status = data_writer_do_block(block, proc->cmp, proc->scratch, proc->max_block_size); if (proc->status == 0) proc->status = process_completed_block(proc, block); free(block); return proc->status; } int wait_completed(sqfs_data_writer_t *proc) { return proc->status; } squashfs-tools-ng-0.8/lib/sqfs/data_writer/winpthread.c000066400000000000000000000221411360235375500233270ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * winpthread.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "internal.h" #if defined(_WIN32) || defined(__WINDOWS__) # define LOCK(mtx) EnterCriticalSection(mtx) # define UNLOCK(mtx) LeaveCriticalSection(mtx) # define AWAIT(cond, mtx) SleepConditionVariableCS(cond, mtx, INFINITE) # define SIGNAL_ALL(cond) WakeAllConditionVariable(cond) # define THREAD_EXIT_SUCCESS 0 # define THREAD_TYPE DWORD WINAPI # define THREAD_ARG LPVOID # define THREAD_HANDLE HANDLE #else # define LOCK(mtx) pthread_mutex_lock(mtx) # define UNLOCK(mtx) pthread_mutex_unlock(mtx) # define AWAIT(cond, mtx) pthread_cond_wait(cond, mtx) # define SIGNAL_ALL(cond) pthread_cond_broadcast(cond) # define THREAD_EXIT_SUCCESS NULL # define THREAD_TYPE void * # define THREAD_ARG void * # define THREAD_HANDLE pthread_t #endif struct compress_worker_t { sqfs_data_writer_t *shared; sqfs_compressor_t *cmp; THREAD_HANDLE thread; sqfs_u8 scratch[]; }; static THREAD_TYPE worker_proc(THREAD_ARG arg) { compress_worker_t *worker = arg; sqfs_data_writer_t *shared = worker->shared; sqfs_block_t *blk = NULL; int status = 0; for (;;) { LOCK(&shared->mtx); if (blk != NULL) { data_writer_store_done(shared, blk, status); SIGNAL_ALL(&shared->done_cond); } while (shared->queue == NULL && shared->status == 0) AWAIT(&shared->queue_cond, &shared->mtx); blk = data_writer_next_work_item(shared); UNLOCK(&shared->mtx); if (blk == NULL) break; status = data_writer_do_block(blk, worker->cmp, worker->scratch, shared->max_block_size); } return THREAD_EXIT_SUCCESS; } #if defined(_WIN32) || defined(__WINDOWS__) sqfs_data_writer_t *sqfs_data_writer_create(size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file) { sqfs_data_writer_t *proc; unsigned int i; if (num_workers < 1) num_workers = 1; proc = alloc_flex(sizeof(*proc), sizeof(proc->workers[0]), num_workers); if (proc == NULL) return NULL; InitializeCriticalSection(&proc->mtx); InitializeConditionVariable(&proc->queue_cond); InitializeConditionVariable(&proc->done_cond); if (data_writer_init(proc, max_block_size, cmp, num_workers, max_backlog, devblksz, file)) { goto fail; } for (i = 0; i < num_workers; ++i) { proc->workers[i] = alloc_flex(sizeof(compress_worker_t), 1, max_block_size); if (proc->workers[i] == NULL) goto fail; proc->workers[i]->shared = proc; proc->workers[i]->cmp = cmp->create_copy(cmp); if (proc->workers[i]->cmp == NULL) goto fail; proc->workers[i]->thread = CreateThread(NULL, 0, worker_proc, proc->workers[i], 0, 0); if (proc->workers[i]->thread == NULL) goto fail; } return proc; fail: sqfs_data_writer_destroy(proc); return NULL; } void sqfs_data_writer_destroy(sqfs_data_writer_t *proc) { unsigned int i; EnterCriticalSection(&proc->mtx); proc->status = -1; WakeAllConditionVariable(&proc->queue_cond); LeaveCriticalSection(&proc->mtx); for (i = 0; i < proc->num_workers; ++i) { if (proc->workers[i] == NULL) continue; if (proc->workers[i]->thread != NULL) { WaitForSingleObject(proc->workers[i]->thread, INFINITE); CloseHandle(proc->workers[i]->thread); } if (proc->workers[i]->cmp != NULL) proc->workers[i]->cmp->destroy(proc->workers[i]->cmp); free(proc->workers[i]); } DeleteCriticalSection(&proc->mtx); data_writer_cleanup(proc); } #else sqfs_data_writer_t *sqfs_data_writer_create(size_t max_block_size, sqfs_compressor_t *cmp, unsigned int num_workers, size_t max_backlog, size_t devblksz, sqfs_file_t *file) { sqfs_data_writer_t *proc; sigset_t set, oldset; unsigned int i; int ret; if (num_workers < 1) num_workers = 1; proc = alloc_flex(sizeof(*proc), sizeof(proc->workers[0]), num_workers); if (proc == NULL) return NULL; proc->mtx = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; proc->queue_cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; proc->done_cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; if (data_writer_init(proc, max_block_size, cmp, num_workers, max_backlog, devblksz, file)) { goto fail_init; } for (i = 0; i < num_workers; ++i) { proc->workers[i] = alloc_flex(sizeof(compress_worker_t), 1, max_block_size); if (proc->workers[i] == NULL) goto fail_init; proc->workers[i]->shared = proc; proc->workers[i]->cmp = cmp->create_copy(cmp); if (proc->workers[i]->cmp == NULL) goto fail_init; } sigfillset(&set); pthread_sigmask(SIG_SETMASK, &set, &oldset); for (i = 0; i < num_workers; ++i) { ret = pthread_create(&proc->workers[i]->thread, NULL, worker_proc, proc->workers[i]); if (ret != 0) goto fail_thread; } pthread_sigmask(SIG_SETMASK, &oldset, NULL); return proc; fail_thread: pthread_mutex_lock(&proc->mtx); proc->status = -1; pthread_cond_broadcast(&proc->queue_cond); pthread_mutex_unlock(&proc->mtx); for (i = 0; i < num_workers; ++i) { if (proc->workers[i]->thread > 0) { pthread_join(proc->workers[i]->thread, NULL); } } pthread_sigmask(SIG_SETMASK, &oldset, NULL); fail_init: for (i = 0; i < num_workers; ++i) { if (proc->workers[i] != NULL) { if (proc->workers[i]->cmp != NULL) { proc->workers[i]->cmp-> destroy(proc->workers[i]->cmp); } free(proc->workers[i]); } } pthread_cond_destroy(&proc->done_cond); pthread_cond_destroy(&proc->queue_cond); pthread_mutex_destroy(&proc->mtx); data_writer_cleanup(proc); return NULL; } void sqfs_data_writer_destroy(sqfs_data_writer_t *proc) { unsigned int i; pthread_mutex_lock(&proc->mtx); proc->status = -1; pthread_cond_broadcast(&proc->queue_cond); pthread_mutex_unlock(&proc->mtx); for (i = 0; i < proc->num_workers; ++i) { pthread_join(proc->workers[i]->thread, NULL); proc->workers[i]->cmp->destroy(proc->workers[i]->cmp); free(proc->workers[i]); } pthread_cond_destroy(&proc->done_cond); pthread_cond_destroy(&proc->queue_cond); pthread_mutex_destroy(&proc->mtx); data_writer_cleanup(proc); } #endif int append_to_work_queue(sqfs_data_writer_t *proc, sqfs_block_t *block, bool signal_threads) { int status; LOCK(&proc->mtx); status = proc->status; if (status != 0) goto out; if (block != NULL) { if (proc->queue_last == NULL) { proc->queue = proc->queue_last = block; } else { proc->queue_last->next = block; proc->queue_last = block; } block->sequence_number = proc->enqueue_id++; block->next = NULL; proc->backlog += 1; block = NULL; } out: if (signal_threads) SIGNAL_ALL(&proc->queue_cond); UNLOCK(&proc->mtx); free(block); return 0; } static sqfs_block_t *try_dequeue(sqfs_data_writer_t *proc) { sqfs_block_t *queue, *it, *prev; it = proc->done; prev = NULL; while (it != NULL && it->sequence_number == proc->dequeue_id) { prev = it; it = it->next; proc->dequeue_id += 1; } if (prev == NULL) { queue = NULL; } else { queue = proc->done; prev->next = NULL; proc->done = it; } return queue; } static sqfs_block_t *queue_merge(sqfs_block_t *lhs, sqfs_block_t *rhs) { sqfs_block_t *it, *head = NULL, **next_ptr = &head; while (lhs != NULL && rhs != NULL) { if (lhs->sequence_number <= rhs->sequence_number) { it = lhs; lhs = lhs->next; } else { it = rhs; rhs = rhs->next; } *next_ptr = it; next_ptr = &it->next; } it = (lhs != NULL ? lhs : rhs); *next_ptr = it; return head; } static int process_done_queue(sqfs_data_writer_t *proc, sqfs_block_t *queue) { sqfs_block_t *it, *block = NULL; int status = 0; while (queue != NULL && status == 0) { it = queue; queue = it->next; proc->backlog -= 1; if (it->flags & SQFS_BLK_IS_FRAGMENT) { block = NULL; status = process_completed_fragment(proc, it, &block); if (block != NULL && status == 0) { LOCK(&proc->mtx); proc->dequeue_id = it->sequence_number; block->sequence_number = it->sequence_number; if (proc->queue == NULL) { proc->queue = block; proc->queue_last = block; } else { block->next = proc->queue; proc->queue = block; } proc->backlog += 1; proc->done = queue_merge(queue, proc->done); SIGNAL_ALL(&proc->queue_cond); UNLOCK(&proc->mtx); queue = NULL; } else { free(block); } } else { status = process_completed_block(proc, it); } free(it); } free_blk_list(queue); return status; } int test_and_set_status(sqfs_data_writer_t *proc, int status) { LOCK(&proc->mtx); if (proc->status == 0) { proc->status = status; } else { status = proc->status; } SIGNAL_ALL(&proc->queue_cond); UNLOCK(&proc->mtx); return status; } int wait_completed(sqfs_data_writer_t *proc) { sqfs_block_t *queue; int status; LOCK(&proc->mtx); for (;;) { queue = try_dequeue(proc); status = proc->status; if (queue != NULL || status != 0) break; AWAIT(&proc->done_cond, &proc->mtx); } UNLOCK(&proc->mtx); if (status != 0) { free_blk_list(queue); return status; } status = process_done_queue(proc, queue); return status ? test_and_set_status(proc, status) : status; } squashfs-tools-ng-0.8/lib/sqfs/dir_reader.c000066400000000000000000000127521360235375500207640ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * fs_reader.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/dir_reader.h" #include "sqfs/compressor.h" #include "sqfs/super.h" #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/dir.h" #include "util.h" #include #include struct sqfs_dir_reader_t { sqfs_meta_reader_t *meta_dir; sqfs_meta_reader_t *meta_inode; const sqfs_super_t *super; sqfs_dir_header_t hdr; sqfs_u64 dir_block_start; size_t entries; size_t size; size_t start_size; sqfs_u16 dir_offset; sqfs_u16 inode_offset; }; sqfs_dir_reader_t *sqfs_dir_reader_create(const sqfs_super_t *super, sqfs_compressor_t *cmp, sqfs_file_t *file) { sqfs_dir_reader_t *rd = calloc(1, sizeof(*rd)); sqfs_u64 start, limit; if (rd == NULL) return NULL; start = super->inode_table_start; limit = super->directory_table_start; rd->meta_inode = sqfs_meta_reader_create(file, cmp, start, limit); if (rd->meta_inode == NULL) { free(rd); return NULL; } start = super->directory_table_start; limit = super->id_table_start; if (super->fragment_table_start < limit) limit = super->fragment_table_start; if (super->export_table_start < limit) limit = super->export_table_start; rd->meta_dir = sqfs_meta_reader_create(file, cmp, start, limit); if (rd->meta_dir == NULL) { sqfs_meta_reader_destroy(rd->meta_inode); free(rd); return NULL; } rd->super = super; return rd; } void sqfs_dir_reader_destroy(sqfs_dir_reader_t *rd) { sqfs_meta_reader_destroy(rd->meta_inode); sqfs_meta_reader_destroy(rd->meta_dir); free(rd); } int sqfs_dir_reader_open_dir(sqfs_dir_reader_t *rd, const sqfs_inode_generic_t *inode) { sqfs_u64 block_start; size_t size, offset; if (inode->base.type == SQFS_INODE_DIR) { size = inode->data.dir.size; offset = inode->data.dir.offset; block_start = inode->data.dir.start_block; } else if (inode->base.type == SQFS_INODE_EXT_DIR) { size = inode->data.dir_ext.size; offset = inode->data.dir_ext.offset; block_start = inode->data.dir_ext.start_block; } else { return SQFS_ERROR_NOT_DIR; } memset(&rd->hdr, 0, sizeof(rd->hdr)); rd->size = size; rd->entries = 0; if (rd->size <= sizeof(rd->hdr)) return 0; block_start += rd->super->directory_table_start; rd->dir_block_start = block_start; rd->dir_offset = offset; rd->start_size = size; return sqfs_meta_reader_seek(rd->meta_dir, block_start, offset); } int sqfs_dir_reader_read(sqfs_dir_reader_t *rd, sqfs_dir_entry_t **out) { sqfs_dir_entry_t *ent; size_t count; int err; if (!rd->entries) { if (rd->size < sizeof(rd->hdr)) return 1; err = sqfs_meta_reader_read_dir_header(rd->meta_dir, &rd->hdr); if (err) return err; rd->size -= sizeof(rd->hdr); rd->entries = rd->hdr.count + 1; } err = sqfs_meta_reader_read_dir_ent(rd->meta_dir, &ent); if (err) return err; count = sizeof(*ent) + strlen((const char *)ent->name); if (count > rd->size) { rd->size = 0; rd->entries = 0; } else { rd->size -= count; rd->entries -= 1; } rd->inode_offset = ent->offset; *out = ent; return 0; } int sqfs_dir_reader_rewind(sqfs_dir_reader_t *rd) { memset(&rd->hdr, 0, sizeof(rd->hdr)); rd->size = rd->start_size; rd->entries = 0; return sqfs_meta_reader_seek(rd->meta_dir, rd->dir_block_start, rd->dir_offset); } int sqfs_dir_reader_find(sqfs_dir_reader_t *rd, const char *name) { sqfs_dir_entry_t *ent; int ret; if (rd->size != rd->start_size) { ret = sqfs_dir_reader_rewind(rd); if (ret) return ret; } do { ret = sqfs_dir_reader_read(rd, &ent); if (ret < 0) return ret; if (ret > 0) return SQFS_ERROR_NO_ENTRY; ret = strcmp((const char *)ent->name, name); free(ent); } while (ret < 0); return ret == 0 ? 0 : SQFS_ERROR_NO_ENTRY; } int sqfs_dir_reader_get_inode(sqfs_dir_reader_t *rd, sqfs_inode_generic_t **inode) { sqfs_u64 block_start; block_start = rd->hdr.start_block; return sqfs_meta_reader_read_inode(rd->meta_inode, rd->super, block_start, rd->inode_offset, inode); } int sqfs_dir_reader_get_root_inode(sqfs_dir_reader_t *rd, sqfs_inode_generic_t **inode) { sqfs_u64 block_start = rd->super->root_inode_ref >> 16; sqfs_u16 offset = rd->super->root_inode_ref & 0xFFFF; return sqfs_meta_reader_read_inode(rd->meta_inode, rd->super, block_start, offset, inode); } int sqfs_dir_reader_find_by_path(sqfs_dir_reader_t *rd, const char *path, sqfs_inode_generic_t **out) { sqfs_inode_generic_t *inode; sqfs_dir_entry_t *ent; const char *ptr; int ret; ret = sqfs_dir_reader_get_root_inode(rd, &inode); if (ret) return ret; while (*path != '\0') { if (*path == '/' || *path == '\\') { while (*path == '/' || *path == '\\') ++path; continue; } ret = sqfs_dir_reader_open_dir(rd, inode); free(inode); if (ret) return ret; ptr = strchr(path, '/'); if (ptr == NULL) { ptr = strchr(path, '\\'); if (ptr == NULL) { for (ptr = path; *ptr != '\0'; ++ptr) ; } } do { ret = sqfs_dir_reader_read(rd, &ent); if (ret < 0) return ret; if (ret == 0) { ret = strncmp((const char *)ent->name, path, ptr - path); if (ret == 0) ret = ent->name[ptr - path]; free(ent); } } while (ret < 0); if (ret > 0) return SQFS_ERROR_NO_ENTRY; ret = sqfs_dir_reader_get_inode(rd, &inode); if (ret) return ret; path = ptr; } *out = inode; return 0; } squashfs-tools-ng-0.8/lib/sqfs/dir_writer.c000066400000000000000000000237121360235375500210340ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * dir_writer.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_writer.h" #include "sqfs/dir_writer.h" #include "sqfs/super.h" #include "sqfs/table.h" #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/dir.h" #include "util.h" #include #include typedef struct dir_entry_t { struct dir_entry_t *next; sqfs_u64 inode_ref; sqfs_u32 inode_num; sqfs_u16 type; size_t name_len; char name[]; } dir_entry_t; typedef struct index_ent_t { struct index_ent_t *next; dir_entry_t *ent; sqfs_u64 block; sqfs_u32 index; } index_ent_t; struct sqfs_dir_writer_t { dir_entry_t *list; dir_entry_t *list_end; index_ent_t *idx; index_ent_t *idx_end; sqfs_u64 dir_ref; size_t dir_size; size_t ent_count; sqfs_meta_writer_t *dm; sqfs_u64 *export_tbl; size_t export_tbl_max; size_t export_tbl_count; }; static int get_type(sqfs_u16 mode) { switch (mode & S_IFMT) { case S_IFSOCK: return SQFS_INODE_SOCKET; case S_IFIFO: return SQFS_INODE_FIFO; case S_IFLNK: return SQFS_INODE_SLINK; case S_IFBLK: return SQFS_INODE_BDEV; case S_IFCHR: return SQFS_INODE_CDEV; case S_IFDIR: return SQFS_INODE_DIR; case S_IFREG: return SQFS_INODE_FILE; } return SQFS_ERROR_UNSUPPORTED; } static void writer_reset(sqfs_dir_writer_t *writer) { dir_entry_t *ent; index_ent_t *idx; while (writer->idx != NULL) { idx = writer->idx; writer->idx = idx->next; free(idx); } while (writer->list != NULL) { ent = writer->list; writer->list = ent->next; free(ent); } writer->list_end = NULL; writer->idx_end = NULL; writer->dir_ref = 0; writer->dir_size = 0; writer->ent_count = 0; } static int add_export_table_entry(sqfs_dir_writer_t *writer, sqfs_u32 inum, sqfs_u64 iref) { size_t i, new_max; sqfs_u64 *new; if (writer->export_tbl == NULL) return 0; if (inum < 1) return SQFS_ERROR_ARG_INVALID; new_max = writer->export_tbl_max; while ((inum - 1) >= new_max) { if (SZ_MUL_OV(new_max, 2, &new_max)) return SQFS_ERROR_ALLOC; } if (new_max > writer->export_tbl_max) { if (SZ_MUL_OV(new_max, sizeof(writer->export_tbl[0]), &new_max)) return SQFS_ERROR_ALLOC; new = realloc(writer->export_tbl, new_max); if (new == NULL) return SQFS_ERROR_ALLOC; new_max /= sizeof(writer->export_tbl[0]); for (i = writer->export_tbl_max; i < new_max; ++i) new[i] = 0xFFFFFFFFFFFFFFFFUL; writer->export_tbl = new; writer->export_tbl_max = new_max; } writer->export_tbl[inum - 1] = iref; if ((inum - 1) >= writer->export_tbl_count) writer->export_tbl_count = inum; return 0; } sqfs_dir_writer_t *sqfs_dir_writer_create(sqfs_meta_writer_t *dm, sqfs_u32 flags) { sqfs_dir_writer_t *writer; if (flags & ~SQFS_DIR_WRITER_CREATE_ALL_FLAGS) return NULL; writer = calloc(1, sizeof(*writer)); if (writer == NULL) return NULL; if (flags & SQFS_DIR_WRITER_CREATE_EXPORT_TABLE) { writer->export_tbl_max = 512; writer->export_tbl = calloc(sizeof(writer->export_tbl[0]), writer->export_tbl_max); if (writer->export_tbl == NULL) { free(writer); return NULL; } memset(writer->export_tbl, 0xFF, sizeof(writer->export_tbl[0]) * writer->export_tbl_max); } writer->dm = dm; return writer; } void sqfs_dir_writer_destroy(sqfs_dir_writer_t *writer) { writer_reset(writer); free(writer->export_tbl); free(writer); } int sqfs_dir_writer_begin(sqfs_dir_writer_t *writer, sqfs_u32 flags) { sqfs_u32 offset; sqfs_u64 block; if (flags != 0) return SQFS_ERROR_UNSUPPORTED; writer_reset(writer); sqfs_meta_writer_get_position(writer->dm, &block, &offset); writer->dir_ref = (block << 16) | offset; return 0; } int sqfs_dir_writer_add_entry(sqfs_dir_writer_t *writer, const char *name, sqfs_u32 inode_num, sqfs_u64 inode_ref, sqfs_u16 mode) { dir_entry_t *ent; int type, err; type = get_type(mode); if (type < 0) return type; if (name[0] == '\0' || inode_num < 1) return SQFS_ERROR_ARG_INVALID; err = add_export_table_entry(writer, inode_num, inode_ref); if (err) return err; ent = alloc_flex(sizeof(*ent), 1, strlen(name)); if (ent == NULL) return SQFS_ERROR_ALLOC; ent->inode_ref = inode_ref; ent->inode_num = inode_num; ent->type = type; ent->name_len = strlen(name); memcpy(ent->name, name, ent->name_len); if (writer->list_end == NULL) { writer->list = writer->list_end = ent; } else { writer->list_end->next = ent; writer->list_end = ent; } writer->ent_count += 1; return 0; } static size_t get_conseq_entry_count(sqfs_u32 offset, dir_entry_t *head) { size_t size, count = 0; dir_entry_t *it; sqfs_s32 diff; size = (offset + sizeof(sqfs_dir_header_t)) % SQFS_META_BLOCK_SIZE; for (it = head; it != NULL; it = it->next) { if ((it->inode_ref >> 16) != (head->inode_ref >> 16)) break; diff = it->inode_num - head->inode_num; if (diff > 32767 || diff < -32767) break; size += sizeof(sqfs_dir_entry_t) + it->name_len; if (count > 0 && size > SQFS_META_BLOCK_SIZE) break; count += 1; if (count == SQFS_MAX_DIR_ENT) break; } return count; } static int add_header(sqfs_dir_writer_t *writer, size_t count, dir_entry_t *ref, sqfs_u64 block) { sqfs_dir_header_t hdr; index_ent_t *idx; int err; hdr.count = htole32(count - 1); hdr.start_block = htole32(ref->inode_ref >> 16); hdr.inode_number = htole32(ref->inode_num); err = sqfs_meta_writer_append(writer->dm, &hdr, sizeof(hdr)); if (err) return err; idx = calloc(1, sizeof(*idx)); if (idx == NULL) return SQFS_ERROR_ALLOC; idx->ent = ref; idx->block = block; idx->index = writer->dir_size; if (writer->idx_end == NULL) { writer->idx = writer->idx_end = idx; } else { writer->idx_end->next = idx; writer->idx_end = idx; } writer->dir_size += sizeof(hdr); return 0; } int sqfs_dir_writer_end(sqfs_dir_writer_t *writer) { dir_entry_t *it, *first; sqfs_dir_entry_t ent; sqfs_u16 *diff_u16; size_t i, count; sqfs_u32 offset; sqfs_u64 block; int err; for (it = writer->list; it != NULL; ) { sqfs_meta_writer_get_position(writer->dm, &block, &offset); count = get_conseq_entry_count(offset, it); err = add_header(writer, count, it, block); if (err) return err; first = it; for (i = 0; i < count; ++i) { ent.offset = htole16(it->inode_ref & 0x0000FFFF); ent.inode_diff = it->inode_num - first->inode_num; ent.type = htole16(it->type); ent.size = htole16(it->name_len - 1); diff_u16 = (sqfs_u16 *)&ent.inode_diff; *diff_u16 = htole16(*diff_u16); err = sqfs_meta_writer_append(writer->dm, &ent, sizeof(ent)); if (err) return err; err = sqfs_meta_writer_append(writer->dm, it->name, it->name_len); if (err) return err; writer->dir_size += sizeof(ent) + it->name_len; it = it->next; } } return 0; } size_t sqfs_dir_writer_get_size(const sqfs_dir_writer_t *writer) { return writer->dir_size; } sqfs_u64 sqfs_dir_writer_get_dir_reference(const sqfs_dir_writer_t *writer) { return writer->dir_ref; } size_t sqfs_dir_writer_get_index_size(const sqfs_dir_writer_t *writer) { size_t index_size = 0; index_ent_t *idx; for (idx = writer->idx; idx != NULL; idx = idx->next) index_size += sizeof(sqfs_dir_index_t) + idx->ent->name_len; return index_size; } size_t sqfs_dir_writer_get_entry_count(const sqfs_dir_writer_t *writer) { return writer->ent_count; } sqfs_inode_generic_t *sqfs_dir_writer_create_inode(const sqfs_dir_writer_t *writer, size_t hlinks, sqfs_u32 xattr, sqfs_u32 parent_ino) { sqfs_inode_generic_t *inode; sqfs_dir_index_t ent; sqfs_u64 start_block; sqfs_u16 block_offset; size_t index_size; index_ent_t *idx; sqfs_u8 *ptr; index_size = 0; for (idx = writer->idx; idx != NULL; idx = idx->next) index_size += sizeof(ent) + idx->ent->name_len; inode = alloc_flex(sizeof(*inode), 1, index_size); if (inode == NULL) return NULL; start_block = writer->dir_ref >> 16; block_offset = writer->dir_ref & 0xFFFF; if (xattr != 0xFFFFFFFF || start_block > 0xFFFFFFFFUL || writer->dir_size > 0xFFFF) { inode->base.type = SQFS_INODE_EXT_DIR; } else { inode->base.type = SQFS_INODE_DIR; } if (inode->base.type == SQFS_INODE_DIR) { inode->data.dir.start_block = start_block; inode->data.dir.nlink = writer->ent_count + hlinks + 2; inode->data.dir.size = writer->dir_size; inode->data.dir.offset = block_offset; inode->data.dir.parent_inode = parent_ino; } else { inode->data.dir_ext.nlink = writer->ent_count + hlinks + 2; inode->data.dir_ext.size = writer->dir_size; inode->data.dir_ext.start_block = start_block; inode->data.dir_ext.parent_inode = parent_ino; inode->data.dir_ext.offset = block_offset; inode->data.dir_ext.xattr_idx = xattr; inode->data.dir_ext.inodex_count = 0; inode->num_dir_idx_bytes = 0; for (idx = writer->idx; idx != NULL; idx = idx->next) { memset(&ent, 0, sizeof(ent)); ent.start_block = idx->block; ent.index = idx->index; ent.size = idx->ent->name_len - 1; ptr = inode->extra + inode->num_dir_idx_bytes; memcpy(ptr, &ent, sizeof(ent)); memcpy(ptr + sizeof(ent), idx->ent->name, idx->ent->name_len); inode->data.dir_ext.inodex_count += 1; inode->num_dir_idx_bytes += sizeof(ent); inode->num_dir_idx_bytes += idx->ent->name_len; } } return inode; } int sqfs_dir_writer_write_export_table(sqfs_dir_writer_t *writer, sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u32 root_inode_num, sqfs_u64 root_inode_ref, sqfs_super_t *super) { sqfs_u64 start; size_t size; int ret; ret = add_export_table_entry(writer, root_inode_num, root_inode_ref); if (ret) return 0; if (writer->export_tbl_count == 0) return 0; size = sizeof(writer->export_tbl[0]) * writer->export_tbl_count; ret = sqfs_write_table(file, cmp, writer->export_tbl, size, &start); if (ret) return ret; super->export_table_start = start; super->flags |= SQFS_FLAG_EXPORTABLE; return 0; } squashfs-tools-ng-0.8/lib/sqfs/id_table.c000066400000000000000000000056541360235375500204320ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * id_table.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/id_table.h" #include "sqfs/super.h" #include "sqfs/table.h" #include "sqfs/error.h" #include "compat.h" #include #include struct sqfs_id_table_t { sqfs_u32 *ids; size_t num_ids; size_t max_ids; }; sqfs_id_table_t *sqfs_id_table_create(void) { return calloc(1, sizeof(sqfs_id_table_t)); } void sqfs_id_table_destroy(sqfs_id_table_t *tbl) { free(tbl->ids); free(tbl); } int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, sqfs_u32 id, sqfs_u16 *out) { size_t i, sz; void *ptr; for (i = 0; i < tbl->num_ids; ++i) { if (tbl->ids[i] == id) { *out = i; return 0; } } if (tbl->num_ids == 0x10000) return SQFS_ERROR_OVERFLOW; if (tbl->num_ids == tbl->max_ids) { sz = (tbl->max_ids ? tbl->max_ids * 2 : 16); ptr = realloc(tbl->ids, sizeof(tbl->ids[0]) * sz); if (ptr == NULL) return SQFS_ERROR_ALLOC; tbl->ids = ptr; tbl->max_ids = sz; } *out = tbl->num_ids; tbl->ids[tbl->num_ids++] = id; return 0; } int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, sqfs_u16 index, sqfs_u32 *out) { if (index >= tbl->num_ids) return SQFS_ERROR_OUT_OF_BOUNDS; *out = tbl->ids[index]; return 0; } int sqfs_id_table_read(sqfs_id_table_t *tbl, sqfs_file_t *file, const sqfs_super_t *super, sqfs_compressor_t *cmp) { sqfs_u64 upper_limit, lower_limit; void *raw_ids; size_t i; int ret; if (tbl->ids != NULL) { free(tbl->ids); tbl->num_ids = 0; tbl->max_ids = 0; tbl->ids = NULL; } if (!super->id_count || super->id_table_start >= super->bytes_used) return SQFS_ERROR_CORRUPTED; upper_limit = super->id_table_start; lower_limit = super->directory_table_start; if (super->fragment_table_start > lower_limit && super->fragment_table_start < upper_limit) { lower_limit = super->fragment_table_start; } if (super->export_table_start > lower_limit && super->export_table_start < upper_limit) { lower_limit = super->export_table_start; } tbl->num_ids = super->id_count; tbl->max_ids = super->id_count; ret = sqfs_read_table(file, cmp, tbl->num_ids * sizeof(sqfs_u32), super->id_table_start, lower_limit, upper_limit, &raw_ids); if (ret) return ret; tbl->ids = raw_ids; for (i = 0; i < tbl->num_ids; ++i) tbl->ids[i] = le32toh(tbl->ids[i]); return 0; } int sqfs_id_table_write(sqfs_id_table_t *tbl, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp) { sqfs_u64 start; size_t i; int ret; for (i = 0; i < tbl->num_ids; ++i) tbl->ids[i] = htole32(tbl->ids[i]); super->id_count = tbl->num_ids; ret = sqfs_write_table(file, cmp, tbl->ids, sizeof(tbl->ids[0]) * tbl->num_ids, &start); super->id_table_start = start; for (i = 0; i < tbl->num_ids; ++i) tbl->ids[i] = le32toh(tbl->ids[i]); return ret; } squashfs-tools-ng-0.8/lib/sqfs/inode.c000066400000000000000000000201101360235375500177450ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * inode.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/inode.h" #include "sqfs/error.h" static int inverse_type[] = { [SQFS_INODE_DIR] = SQFS_INODE_EXT_DIR, [SQFS_INODE_FILE] = SQFS_INODE_EXT_FILE, [SQFS_INODE_SLINK] = SQFS_INODE_EXT_SLINK, [SQFS_INODE_BDEV] = SQFS_INODE_EXT_BDEV, [SQFS_INODE_CDEV] = SQFS_INODE_EXT_CDEV, [SQFS_INODE_FIFO] = SQFS_INODE_EXT_FIFO, [SQFS_INODE_SOCKET] = SQFS_INODE_EXT_SOCKET, [SQFS_INODE_EXT_DIR] = SQFS_INODE_DIR, [SQFS_INODE_EXT_FILE] = SQFS_INODE_FILE, [SQFS_INODE_EXT_SLINK] = SQFS_INODE_SLINK, [SQFS_INODE_EXT_BDEV] = SQFS_INODE_BDEV, [SQFS_INODE_EXT_CDEV] = SQFS_INODE_CDEV, [SQFS_INODE_EXT_FIFO] = SQFS_INODE_FIFO, [SQFS_INODE_EXT_SOCKET] = SQFS_INODE_SOCKET, }; int sqfs_inode_get_xattr_index(const sqfs_inode_generic_t *inode, sqfs_u32 *out) { switch (inode->base.type) { case SQFS_INODE_DIR: case SQFS_INODE_FILE: case SQFS_INODE_SLINK: case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: *out = 0xFFFFFFFF; break; case SQFS_INODE_EXT_DIR: *out = inode->data.dir_ext.xattr_idx; break; case SQFS_INODE_EXT_FILE: *out = inode->data.file_ext.xattr_idx; break; case SQFS_INODE_EXT_SLINK: *out = inode->data.slink_ext.xattr_idx; break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: *out = inode->data.dev_ext.xattr_idx; break; case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: *out = inode->data.ipc_ext.xattr_idx; break; default: return SQFS_ERROR_CORRUPTED; } return 0; } int sqfs_inode_set_xattr_index(sqfs_inode_generic_t *inode, sqfs_u32 index) { int err; if (index != 0xFFFFFFFF) { err = sqfs_inode_make_extended(inode); if (err) return err; } switch (inode->base.type) { case SQFS_INODE_DIR: case SQFS_INODE_FILE: case SQFS_INODE_SLINK: case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: break; case SQFS_INODE_EXT_DIR: inode->data.dir_ext.xattr_idx = index; break; case SQFS_INODE_EXT_FILE: inode->data.file_ext.xattr_idx = index; break; case SQFS_INODE_EXT_SLINK: inode->data.slink_ext.xattr_idx = index; break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: inode->data.dev_ext.xattr_idx = index; break; case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: inode->data.ipc_ext.xattr_idx = index; break; default: return SQFS_ERROR_CORRUPTED; } if (index == 0xFFFFFFFF) { err = sqfs_inode_make_basic(inode); if (err) return err; } return 0; } int sqfs_inode_make_extended(sqfs_inode_generic_t *inode) { switch (inode->base.type) { case SQFS_INODE_DIR: { sqfs_inode_dir_ext_t temp = { .nlink = inode->data.dir.nlink, .size = inode->data.dir.size, .start_block = inode->data.dir.start_block, .parent_inode = inode->data.dir.parent_inode, .inodex_count = 0, .offset = inode->data.dir.offset, .xattr_idx = 0xFFFFFFFF, }; inode->data.dir_ext = temp; break; } case SQFS_INODE_FILE: { sqfs_inode_file_ext_t temp = { .blocks_start = inode->data.file.blocks_start, .file_size = inode->data.file.file_size, .sparse = 0, .nlink = 1, .fragment_idx = inode->data.file.fragment_index, .fragment_offset = inode->data.file.fragment_offset, .xattr_idx = 0xFFFFFFFF, }; inode->data.file_ext = temp; break; } case SQFS_INODE_SLINK: inode->data.slink_ext.xattr_idx = 0xFFFFFFFF; break; case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: inode->data.dev_ext.xattr_idx = 0xFFFFFFFF; break; case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: inode->data.dev_ext.xattr_idx = 0xFFFFFFFF; break; case SQFS_INODE_EXT_DIR: case SQFS_INODE_EXT_FILE: case SQFS_INODE_EXT_SLINK: case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: return 0; default: return SQFS_ERROR_CORRUPTED; } inode->base.type = inverse_type[inode->base.type]; return 0; } int sqfs_inode_make_basic(sqfs_inode_generic_t *inode) { sqfs_u32 xattr; int err; err = sqfs_inode_get_xattr_index(inode, &xattr); if (err != 0 || xattr != 0xFFFFFFFF) return err; switch (inode->base.type) { case SQFS_INODE_DIR: case SQFS_INODE_FILE: case SQFS_INODE_SLINK: case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: return 0; case SQFS_INODE_EXT_DIR: { sqfs_inode_dir_t temp = { .start_block = inode->data.dir_ext.start_block, .nlink = inode->data.dir_ext.nlink, .size = inode->data.dir_ext.size, .offset = inode->data.dir_ext.offset, .parent_inode = inode->data.dir_ext.parent_inode, }; if (inode->data.dir_ext.size > 0x0FFFF) return 0; inode->data.dir = temp; break; } case SQFS_INODE_EXT_FILE: { sqfs_inode_file_t temp = { .blocks_start = inode->data.file_ext.blocks_start, .fragment_index = inode->data.file_ext.fragment_idx, .fragment_offset = inode->data.file_ext.fragment_offset, .file_size = inode->data.file_ext.file_size, }; if (inode->data.file_ext.blocks_start > 0x0FFFFFFFFUL) return 0; if (inode->data.file_ext.file_size > 0x0FFFFFFFFUL) return 0; if (inode->data.file_ext.sparse > 0) return 0; if (inode->data.file_ext.nlink > 1) return 0; inode->data.file = temp; break; } case SQFS_INODE_EXT_SLINK: case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: break; default: return SQFS_ERROR_CORRUPTED; } inode->base.type = inverse_type[inode->base.type]; return 0; } int sqfs_inode_set_file_size(sqfs_inode_generic_t *inode, sqfs_u64 size) { if (inode->base.type == SQFS_INODE_EXT_FILE) { inode->data.file_ext.file_size = size; if (size < 0x0FFFFFFFFUL) sqfs_inode_make_basic(inode); } else if (inode->base.type == SQFS_INODE_FILE) { if (size > 0x0FFFFFFFFUL) { sqfs_inode_make_extended(inode); inode->data.file_ext.file_size = size; } else { inode->data.file.file_size = size; } } else { return SQFS_ERROR_NOT_FILE; } return 0; } int sqfs_inode_set_frag_location(sqfs_inode_generic_t *inode, sqfs_u32 index, sqfs_u32 offset) { if (inode->base.type == SQFS_INODE_EXT_FILE) { inode->data.file_ext.fragment_idx = index; inode->data.file_ext.fragment_offset = offset; } else if (inode->base.type == SQFS_INODE_FILE) { inode->data.file.fragment_index = index; inode->data.file.fragment_offset = offset; } else { return SQFS_ERROR_NOT_FILE; } return 0; } int sqfs_inode_set_file_block_start(sqfs_inode_generic_t *inode, sqfs_u64 location) { if (inode->base.type == SQFS_INODE_EXT_FILE) { inode->data.file_ext.blocks_start = location; if (location < 0x0FFFFFFFFUL) sqfs_inode_make_basic(inode); } else if (inode->base.type == SQFS_INODE_FILE) { if (location > 0x0FFFFFFFFUL) { sqfs_inode_make_extended(inode); inode->data.file_ext.blocks_start = location; } else { inode->data.file.blocks_start = location; } } else { return SQFS_ERROR_NOT_FILE; } return 0; } int sqfs_inode_get_file_size(const sqfs_inode_generic_t *inode, sqfs_u64 *size) { if (inode->base.type == SQFS_INODE_EXT_FILE) { *size = inode->data.file_ext.file_size; } else if (inode->base.type == SQFS_INODE_FILE) { *size = inode->data.file.file_size; } else { return SQFS_ERROR_NOT_FILE; } return 0; } int sqfs_inode_get_frag_location(const sqfs_inode_generic_t *inode, sqfs_u32 *index, sqfs_u32 *offset) { if (inode->base.type == SQFS_INODE_EXT_FILE) { *index = inode->data.file_ext.fragment_idx; *offset = inode->data.file_ext.fragment_offset; } else if (inode->base.type == SQFS_INODE_FILE) { *index = inode->data.file.fragment_index; *offset = inode->data.file.fragment_offset; } else { return SQFS_ERROR_NOT_FILE; } return 0; } int sqfs_inode_get_file_block_start(const sqfs_inode_generic_t *inode, sqfs_u64 *location) { if (inode->base.type == SQFS_INODE_EXT_FILE) { *location = inode->data.file_ext.blocks_start; } else if (inode->base.type == SQFS_INODE_FILE) { *location = inode->data.file.blocks_start; } else { return SQFS_ERROR_NOT_FILE; } return 0; } squashfs-tools-ng-0.8/lib/sqfs/libsquashfs0.pc.in000066400000000000000000000004511360235375500220460ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libsquashfs Version: @PACKAGE_VERSION@ Description: A library for working with SquashFS file systems. Cflags: -I${includedir} Libs: -L${libdir} -lsquashfs @PTHREAD_LIBS@ Requires.private: @LIBSQFS_DEP_MOD@ squashfs-tools-ng-0.8/lib/sqfs/meta_reader.c000066400000000000000000000062771360235375500211410ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * meta_reader.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/compressor.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "util.h" #include #include struct sqfs_meta_reader_t { sqfs_u64 start; sqfs_u64 limit; size_t data_used; /* The location of the current block in the image */ sqfs_u64 block_offset; /* The location of the next block after the current one */ sqfs_u64 next_block; /* A byte offset into the uncompressed data of the current block */ size_t offset; /* The underlying file descriptor to read from */ sqfs_file_t *file; /* A pointer to the compressor to use for extracting data */ sqfs_compressor_t *cmp; /* The raw data read from the input file */ sqfs_u8 data[SQFS_META_BLOCK_SIZE]; /* The uncompressed data read from the input file */ sqfs_u8 scratch[SQFS_META_BLOCK_SIZE]; }; sqfs_meta_reader_t *sqfs_meta_reader_create(sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u64 start, sqfs_u64 limit) { sqfs_meta_reader_t *m = calloc(1, sizeof(*m)); if (m == NULL) return NULL; m->start = start; m->limit = limit; m->file = file; m->cmp = cmp; return m; } void sqfs_meta_reader_destroy(sqfs_meta_reader_t *m) { free(m); } int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, sqfs_u64 block_start, size_t offset) { bool compressed; sqfs_u16 header; sqfs_u32 size; sqfs_s32 ret; int err; if (block_start < m->start || block_start >= m->limit) return SQFS_ERROR_OUT_OF_BOUNDS; if (block_start == m->block_offset) { if (offset >= m->data_used) return SQFS_ERROR_OUT_OF_BOUNDS; m->offset = offset; return 0; } err = m->file->read_at(m->file, block_start, &header, 2); if (err) return err; header = le16toh(header); compressed = (header & 0x8000) == 0; size = header & 0x7FFF; if (size > sizeof(m->data)) return SQFS_ERROR_CORRUPTED; if ((block_start + 2 + size) > m->limit) return SQFS_ERROR_OUT_OF_BOUNDS; err = m->file->read_at(m->file, block_start + 2, m->data, size); if (err) return err; if (compressed) { ret = m->cmp->do_block(m->cmp, m->data, size, m->scratch, sizeof(m->scratch)); if (ret < 0) return ret; memcpy(m->data, m->scratch, ret); m->data_used = ret; } else { m->data_used = size; } if (offset >= m->data_used) return SQFS_ERROR_OUT_OF_BOUNDS; m->block_offset = block_start; m->next_block = block_start + size + 2; m->offset = offset; return 0; } void sqfs_meta_reader_get_position(const sqfs_meta_reader_t *m, sqfs_u64 *block_start, size_t *offset) { *block_start = m->block_offset; *offset = m->offset; } int sqfs_meta_reader_read(sqfs_meta_reader_t *m, void *data, size_t size) { size_t diff; int ret; while (size != 0) { diff = m->data_used - m->offset; if (diff == 0) { ret = sqfs_meta_reader_seek(m, m->next_block, 0); if (ret) return ret; diff = m->data_used; } if (diff > size) diff = size; memcpy(data, m->data + m->offset, diff); m->offset += diff; data = (char *)data + diff; size -= diff; } return 0; } squashfs-tools-ng-0.8/lib/sqfs/meta_writer.c000066400000000000000000000073661360235375500212130ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * meta_writer.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_writer.h" #include "sqfs/compressor.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "util.h" #include #include typedef struct meta_block_t { struct meta_block_t *next; /* possibly compressed data with 2 byte header */ sqfs_u8 data[SQFS_META_BLOCK_SIZE + 2]; } meta_block_t; struct sqfs_meta_writer_t { /* A byte offset into the uncompressed data of the current block */ size_t offset; /* The location of the current block in the file */ size_t block_offset; /* The underlying file descriptor to write to */ sqfs_file_t *file; /* A pointer to the compressor to use for compressing the data */ sqfs_compressor_t *cmp; /* The raw data chunk that data is appended to */ sqfs_u8 data[SQFS_META_BLOCK_SIZE]; sqfs_u32 flags; meta_block_t *list; meta_block_t *list_end; }; static int write_block(sqfs_file_t *file, meta_block_t *outblk) { size_t count = le16toh(((sqfs_u16 *)outblk->data)[0]) & 0x7FFF; sqfs_u64 off = file->get_size(file); return file->write_at(file, off, outblk->data, count + 2); } sqfs_meta_writer_t *sqfs_meta_writer_create(sqfs_file_t *file, sqfs_compressor_t *cmp, sqfs_u32 flags) { sqfs_meta_writer_t *m; if (flags & ~SQFS_META_WRITER_ALL_FLAGS) return NULL; m = calloc(1, sizeof(*m)); if (m == NULL) return NULL; m->cmp = cmp; m->file = file; m->flags = flags; return m; } void sqfs_meta_writer_destroy(sqfs_meta_writer_t *m) { meta_block_t *blk; while (m->list != NULL) { blk = m->list; m->list = blk->next; free(blk); } free(m); } int sqfs_meta_writer_flush(sqfs_meta_writer_t *m) { meta_block_t *outblk; sqfs_u32 count; sqfs_s32 ret; if (m->offset == 0) return 0; outblk = calloc(1, sizeof(*outblk)); if (outblk == NULL) return SQFS_ERROR_ALLOC; ret = m->cmp->do_block(m->cmp, m->data, m->offset, outblk->data + 2, sizeof(outblk->data) - 2); if (ret < 0) { free(outblk); return ret; } if (ret > 0) { ((sqfs_u16 *)outblk->data)[0] = htole16(ret); count = ret + 2; } else { ((sqfs_u16 *)outblk->data)[0] = htole16(m->offset | 0x8000); memcpy(outblk->data + 2, m->data, m->offset); count = m->offset + 2; } ret = 0; if (m->flags & SQFS_META_WRITER_KEEP_IN_MEMORY) { if (m->list == NULL) { m->list = outblk; } else { m->list_end->next = outblk; } m->list_end = outblk; } else { ret = write_block(m->file, outblk); free(outblk); } memset(m->data, 0, sizeof(m->data)); m->offset = 0; m->block_offset += count; return ret; } int sqfs_meta_writer_append(sqfs_meta_writer_t *m, const void *data, size_t size) { size_t diff; int ret; while (size != 0) { diff = sizeof(m->data) - m->offset; if (diff == 0) { ret = sqfs_meta_writer_flush(m); if (ret) return ret; diff = sizeof(m->data); } if (diff > size) diff = size; memcpy(m->data + m->offset, data, diff); m->offset += diff; size -= diff; data = (const char *)data + diff; } if (m->offset == sizeof(m->data)) return sqfs_meta_writer_flush(m); return 0; } void sqfs_meta_writer_get_position(const sqfs_meta_writer_t *m, sqfs_u64 *block_start, sqfs_u32 *offset) { *block_start = m->block_offset; *offset = m->offset; } void sqfs_meta_writer_reset(sqfs_meta_writer_t *m) { m->block_offset = 0; m->offset = 0; } int sqfs_meta_write_write_to_file(sqfs_meta_writer_t *m) { meta_block_t *blk; int ret; while (m->list != NULL) { blk = m->list; ret = write_block(m->file, blk); if (ret) return ret; m->list = blk->next; free(blk); } m->list_end = NULL; return 0; } squashfs-tools-ng-0.8/lib/sqfs/read_inode.c000066400000000000000000000215241360235375500207520ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * read_inode.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/error.h" #include "sqfs/super.h" #include "sqfs/inode.h" #include "sqfs/dir.h" #include "util.h" #include #include #include #define SWAB16(x) x = le16toh(x) #define SWAB32(x) x = le32toh(x) #define SWAB64(x) x = le64toh(x) static int set_mode(sqfs_inode_t *inode) { inode->mode &= ~S_IFMT; switch (inode->type) { case SQFS_INODE_SOCKET: case SQFS_INODE_EXT_SOCKET: inode->mode |= S_IFSOCK; break; case SQFS_INODE_SLINK: case SQFS_INODE_EXT_SLINK: inode->mode |= S_IFLNK; break; case SQFS_INODE_FILE: case SQFS_INODE_EXT_FILE: inode->mode |= S_IFREG; break; case SQFS_INODE_BDEV: case SQFS_INODE_EXT_BDEV: inode->mode |= S_IFBLK; break; case SQFS_INODE_DIR: case SQFS_INODE_EXT_DIR: inode->mode |= S_IFDIR; break; case SQFS_INODE_CDEV: case SQFS_INODE_EXT_CDEV: inode->mode |= S_IFCHR; break; case SQFS_INODE_FIFO: case SQFS_INODE_EXT_FIFO: inode->mode |= S_IFIFO; break; default: return SQFS_ERROR_UNSUPPORTED; } return 0; } static sqfs_u64 get_block_count(sqfs_u64 size, sqfs_u64 block_size, sqfs_u32 frag_index, sqfs_u32 frag_offset) { sqfs_u64 count = size / block_size; if ((size % block_size) != 0 && (frag_index == 0xFFFFFFFF || frag_offset == 0xFFFFFFFF)) { ++count; } return count; } static int read_inode_file(sqfs_meta_reader_t *ir, sqfs_inode_t *base, size_t block_size, sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_file_t file; sqfs_u64 i, count; int err; err = sqfs_meta_reader_read(ir, &file, sizeof(file)); if (err) return err; SWAB32(file.blocks_start); SWAB32(file.fragment_index); SWAB32(file.fragment_offset); SWAB32(file.file_size); count = get_block_count(file.file_size, block_size, file.fragment_index, file.fragment_offset); out = alloc_flex(sizeof(*out), sizeof(sqfs_u32), count); if (out == NULL) return SQFS_ERROR_ALLOC; out->base = *base; out->data.file = file; out->block_sizes = (sqfs_u32 *)out->extra; out->num_file_blocks = count; err = sqfs_meta_reader_read(ir, out->block_sizes, count * sizeof(sqfs_u32)); if (err) { free(out); return err; } for (i = 0; i < count; ++i) SWAB32(out->block_sizes[i]); *result = out; return 0; } static int read_inode_file_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, size_t block_size, sqfs_inode_generic_t **result) { sqfs_inode_file_ext_t file; sqfs_inode_generic_t *out; sqfs_u64 i, count; int err; err = sqfs_meta_reader_read(ir, &file, sizeof(file)); if (err) return err; SWAB64(file.blocks_start); SWAB64(file.file_size); SWAB64(file.sparse); SWAB32(file.nlink); SWAB32(file.fragment_idx); SWAB32(file.fragment_offset); SWAB32(file.xattr_idx); count = get_block_count(file.file_size, block_size, file.fragment_idx, file.fragment_offset); out = alloc_flex(sizeof(*out), sizeof(sqfs_u32), count); if (out == NULL) { return errno == EOVERFLOW ? SQFS_ERROR_OVERFLOW : SQFS_ERROR_ALLOC; } out->base = *base; out->data.file_ext = file; out->block_sizes = (sqfs_u32 *)out->extra; out->num_file_blocks = count; err = sqfs_meta_reader_read(ir, out->block_sizes, count * sizeof(sqfs_u32)); if (err) { free(out); return err; } for (i = 0; i < count; ++i) SWAB32(out->block_sizes[i]); *result = out; return 0; } static int read_inode_slink(sqfs_meta_reader_t *ir, sqfs_inode_t *base, sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_slink_t slink; size_t size; int err; err = sqfs_meta_reader_read(ir, &slink, sizeof(slink)); if (err) return err; SWAB32(slink.nlink); SWAB32(slink.target_size); if (SZ_ADD_OV(slink.target_size, 1, &size) || SZ_ADD_OV(sizeof(*out), size, &size)) { return SQFS_ERROR_OVERFLOW; } out = calloc(1, size); if (out == NULL) return SQFS_ERROR_ALLOC; out->slink_target = (char *)out->extra; out->base = *base; out->data.slink = slink; err = sqfs_meta_reader_read(ir, out->slink_target, slink.target_size); if (err) { free(out); return err; } *result = out; return 0; } static int read_inode_slink_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, sqfs_inode_generic_t **result) { sqfs_u32 xattr; int err; err = read_inode_slink(ir, base, result); if (err) return err; err = sqfs_meta_reader_read(ir, &xattr, sizeof(xattr)); if (err) { free(*result); return err; } (*result)->data.slink_ext.xattr_idx = le32toh(xattr); return 0; } static int read_inode_dir_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, sqfs_inode_generic_t **result) { size_t i, new_sz, index_max, index_used; sqfs_inode_generic_t *out; sqfs_inode_dir_ext_t dir; sqfs_dir_index_t ent; void *new; int err; err = sqfs_meta_reader_read(ir, &dir, sizeof(dir)); if (err) return err; SWAB32(dir.nlink); SWAB32(dir.size); SWAB32(dir.start_block); SWAB32(dir.parent_inode); SWAB16(dir.inodex_count); SWAB16(dir.offset); SWAB32(dir.xattr_idx); index_max = dir.size ? 128 : 0; index_used = 0; out = alloc_flex(sizeof(*out), 1, index_max); if (out == NULL) return SQFS_ERROR_ALLOC; out->base = *base; out->data.dir_ext = dir; if (dir.size == 0) { *result = out; return 0; } for (i = 0; i < dir.inodex_count; ++i) { err = sqfs_meta_reader_read(ir, &ent, sizeof(ent)); if (err) { free(out); return err; } SWAB32(ent.start_block); SWAB32(ent.index); SWAB32(ent.size); new_sz = index_max; while (sizeof(ent) + ent.size + 1 > new_sz - index_used) { if (SZ_MUL_OV(new_sz, 2, &new_sz)) { free(out); return SQFS_ERROR_OVERFLOW; } } if (new_sz > index_max) { new = realloc(out, sizeof(*out) + new_sz); if (new == NULL) { free(out); return SQFS_ERROR_ALLOC; } out = new; index_max = new_sz; } memcpy(out->extra + index_used, &ent, sizeof(ent)); index_used += sizeof(ent); err = sqfs_meta_reader_read(ir, out->extra + index_used, ent.size + 1); if (err) { free(out); return err; } } out->num_dir_idx_bytes = index_used; *result = out; return 0; } int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, const sqfs_super_t *super, sqfs_u64 block_start, size_t offset, sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_t inode; int err; /* read base inode */ block_start += super->inode_table_start; err = sqfs_meta_reader_seek(ir, block_start, offset); if (err) return err; err = sqfs_meta_reader_read(ir, &inode, sizeof(inode)); if (err) return err; SWAB16(inode.type); SWAB16(inode.mode); SWAB16(inode.uid_idx); SWAB16(inode.gid_idx); SWAB32(inode.mod_time); SWAB32(inode.inode_number); err = set_mode(&inode); if (err) return err; /* inode types where the size is variable */ switch (inode.type) { case SQFS_INODE_FILE: return read_inode_file(ir, &inode, super->block_size, result); case SQFS_INODE_SLINK: return read_inode_slink(ir, &inode, result); case SQFS_INODE_EXT_FILE: return read_inode_file_ext(ir, &inode, super->block_size, result); case SQFS_INODE_EXT_SLINK: return read_inode_slink_ext(ir, &inode, result); case SQFS_INODE_EXT_DIR: return read_inode_dir_ext(ir, &inode, result); default: break; } /* everything else */ out = calloc(1, sizeof(*out)); if (out == NULL) return SQFS_ERROR_ALLOC; out->base = inode; switch (inode.type) { case SQFS_INODE_DIR: err = sqfs_meta_reader_read(ir, &out->data.dir, sizeof(out->data.dir)); if (err) goto fail_free; SWAB32(out->data.dir.start_block); SWAB32(out->data.dir.nlink); SWAB16(out->data.dir.size); SWAB16(out->data.dir.offset); SWAB32(out->data.dir.parent_inode); break; case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: err = sqfs_meta_reader_read(ir, &out->data.dev, sizeof(out->data.dev)); if (err) goto fail_free; SWAB32(out->data.dev.nlink); SWAB32(out->data.dev.devno); break; case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: err = sqfs_meta_reader_read(ir, &out->data.ipc, sizeof(out->data.ipc)); if (err) goto fail_free; SWAB32(out->data.ipc.nlink); break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: err = sqfs_meta_reader_read(ir, &out->data.dev_ext, sizeof(out->data.dev_ext)); if (err) goto fail_free; SWAB32(out->data.dev_ext.nlink); SWAB32(out->data.dev_ext.devno); SWAB32(out->data.dev_ext.xattr_idx); break; case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: err = sqfs_meta_reader_read(ir, &out->data.ipc_ext, sizeof(out->data.ipc_ext)); if (err) goto fail_free; SWAB32(out->data.ipc_ext.nlink); SWAB32(out->data.ipc_ext.xattr_idx); break; default: err = SQFS_ERROR_UNSUPPORTED; goto fail_free; } *result = out; return 0; fail_free: free(out); return err; } squashfs-tools-ng-0.8/lib/sqfs/read_super.c000066400000000000000000000044251360235375500210130ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * read_super.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/super.h" #include "sqfs/error.h" #include "sqfs/io.h" #include "util.h" #include int sqfs_super_read(sqfs_super_t *super, sqfs_file_t *file) { size_t block_size = 0; sqfs_super_t temp; int i, ret; ret = file->read_at(file, 0, &temp, sizeof(temp)); if (ret) return ret; temp.magic = le32toh(temp.magic); temp.inode_count = le32toh(temp.inode_count); temp.modification_time = le32toh(temp.modification_time); temp.block_size = le32toh(temp.block_size); temp.fragment_entry_count = le32toh(temp.fragment_entry_count); temp.compression_id = le16toh(temp.compression_id); temp.block_log = le16toh(temp.block_log); temp.flags = le16toh(temp.flags); temp.id_count = le16toh(temp.id_count); temp.version_major = le16toh(temp.version_major); temp.version_minor = le16toh(temp.version_minor); temp.root_inode_ref = le64toh(temp.root_inode_ref); temp.bytes_used = le64toh(temp.bytes_used); temp.id_table_start = le64toh(temp.id_table_start); temp.xattr_id_table_start = le64toh(temp.xattr_id_table_start); temp.inode_table_start = le64toh(temp.inode_table_start); temp.directory_table_start = le64toh(temp.directory_table_start); temp.fragment_table_start = le64toh(temp.fragment_table_start); temp.export_table_start = le64toh(temp.export_table_start); if (temp.magic != SQFS_MAGIC) return SFQS_ERROR_SUPER_MAGIC; if ((temp.version_major != SQFS_VERSION_MAJOR) || (temp.version_minor != SQFS_VERSION_MINOR)) return SFQS_ERROR_SUPER_VERSION; if ((temp.block_size - 1) & temp.block_size) return SQFS_ERROR_SUPER_BLOCK_SIZE; if (temp.block_size < 4096 || temp.block_size > (1 << 20)) return SQFS_ERROR_SUPER_BLOCK_SIZE; if (temp.block_log < 12 || temp.block_log > 20) return SQFS_ERROR_CORRUPTED; block_size = 1; for (i = 0; i < temp.block_log; ++i) block_size <<= 1; if (temp.block_size != block_size) return SQFS_ERROR_CORRUPTED; if (temp.compression_id < SQFS_COMP_MIN || temp.compression_id > SQFS_COMP_MAX) return SQFS_ERROR_UNSUPPORTED; if (temp.id_count == 0) return SQFS_ERROR_CORRUPTED; memcpy(super, &temp, sizeof(temp)); return 0; } squashfs-tools-ng-0.8/lib/sqfs/read_table.c000066400000000000000000000034341360235375500207430ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * read_table.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/error.h" #include "sqfs/table.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "util.h" #include int sqfs_read_table(sqfs_file_t *file, sqfs_compressor_t *cmp, size_t table_size, sqfs_u64 location, sqfs_u64 lower_limit, sqfs_u64 upper_limit, void **out) { size_t diff, block_count, blk_idx = 0; sqfs_u64 start, *locations; sqfs_meta_reader_t *m; void *data, *ptr; int err; data = malloc(table_size); if (data == NULL) return SQFS_ERROR_ALLOC; /* restore list from image */ block_count = table_size / SQFS_META_BLOCK_SIZE; if ((table_size % SQFS_META_BLOCK_SIZE) != 0) ++block_count; locations = alloc_array(sizeof(sqfs_u64), block_count); if (locations == NULL) { err = SQFS_ERROR_ALLOC; goto fail_data; } err = file->read_at(file, location, locations, sizeof(sqfs_u64) * block_count); if (err) goto fail_idx; /* Read the actual data */ m = sqfs_meta_reader_create(file, cmp, lower_limit, upper_limit); if (m == NULL) { err = SQFS_ERROR_ALLOC; goto fail_idx; } ptr = data; while (table_size > 0) { start = le64toh(locations[blk_idx++]); err = sqfs_meta_reader_seek(m, start, 0); if (err) goto fail; diff = SQFS_META_BLOCK_SIZE; if (diff > table_size) diff = table_size; err = sqfs_meta_reader_read(m, ptr, diff); if (err) goto fail; ptr = (char *)ptr + diff; table_size -= diff; } sqfs_meta_reader_destroy(m); free(locations); *out = data; return 0; fail: sqfs_meta_reader_destroy(m); fail_idx: free(locations); fail_data: free(data); *out = NULL; return err; } squashfs-tools-ng-0.8/lib/sqfs/read_tree.c000066400000000000000000000131021360235375500206040ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * read_tree.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/dir_reader.h" #include "sqfs/compressor.h" #include "sqfs/id_table.h" #include "sqfs/super.h" #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/dir.h" #include "util.h" #include #include static int should_skip(int type, unsigned int flags) { switch (type) { case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: case SQFS_INODE_EXT_CDEV: case SQFS_INODE_EXT_BDEV: return (flags & SQFS_TREE_NO_DEVICES); case SQFS_INODE_SLINK: case SQFS_INODE_EXT_SLINK: return (flags & SQFS_TREE_NO_SLINKS); case SQFS_INODE_SOCKET: case SQFS_INODE_EXT_SOCKET: return(flags & SQFS_TREE_NO_SOCKETS); case SQFS_INODE_FIFO: case SQFS_INODE_EXT_FIFO: return (flags & SQFS_TREE_NO_FIFO); } return 0; } static bool would_be_own_parent(sqfs_tree_node_t *parent, sqfs_tree_node_t *n) { sqfs_u32 inum = n->inode->base.inode_number; while (parent != NULL) { if (parent->inode->base.inode_number == inum) return true; parent = parent->parent; } return false; } static sqfs_tree_node_t *create_node(sqfs_inode_generic_t *inode, const char *name) { sqfs_tree_node_t *n; n = alloc_flex(sizeof(*n), 1, strlen(name) + 1); if (n == NULL) return NULL; n->inode = inode; strcpy((char *)n->name, name); return n; } static int fill_dir(sqfs_dir_reader_t *dr, sqfs_tree_node_t *root, unsigned int flags) { sqfs_tree_node_t *n, *prev, **tail; sqfs_inode_generic_t *inode; sqfs_dir_entry_t *ent; int err; tail = &root->children; for (;;) { err = sqfs_dir_reader_read(dr, &ent); if (err > 0) break; if (err < 0) return err; if (should_skip(ent->type, flags)) { free(ent); continue; } err = sqfs_dir_reader_get_inode(dr, &inode); if (err) { free(ent); return err; } n = create_node(inode, (const char *)ent->name); free(ent); if (n == NULL) { free(inode); return SQFS_ERROR_ALLOC; } if (would_be_own_parent(root, n)) { free(n); free(inode); return SQFS_ERROR_LINK_LOOP; } *tail = n; tail = &n->next; n->parent = root; } n = root->children; prev = NULL; while (n != NULL) { if (n->inode->base.type == SQFS_INODE_DIR || n->inode->base.type == SQFS_INODE_EXT_DIR) { if (!(flags & SQFS_TREE_NO_RECURSE)) { err = sqfs_dir_reader_open_dir(dr, n->inode); if (err) return err; err = fill_dir(dr, n, flags); if (err) return err; } if (n->children == NULL && (flags & SQFS_TREE_NO_EMPTY)) { free(n->inode); if (prev == NULL) { root->children = root->children->next; free(n); n = root->children; } else { prev->next = n->next; free(n); n = prev->next; } continue; } } prev = n; n = n->next; } return 0; } static int resolve_ids(sqfs_tree_node_t *root, const sqfs_id_table_t *idtbl) { sqfs_tree_node_t *it; int err; for (it = root->children; it != NULL; it = it->next) resolve_ids(it, idtbl); err = sqfs_id_table_index_to_id(idtbl, root->inode->base.uid_idx, &root->uid); if (err) return err; return sqfs_id_table_index_to_id(idtbl, root->inode->base.gid_idx, &root->gid); } void sqfs_dir_tree_destroy(sqfs_tree_node_t *root) { sqfs_tree_node_t *it; while (root->children != NULL) { it = root->children; root->children = it->next; sqfs_dir_tree_destroy(it); } free(root->inode); free(root); } int sqfs_dir_reader_get_full_hierarchy(sqfs_dir_reader_t *rd, const sqfs_id_table_t *idtbl, const char *path, unsigned int flags, sqfs_tree_node_t **out) { sqfs_tree_node_t *root, *tail, *new; sqfs_inode_generic_t *inode; sqfs_dir_entry_t *ent; const char *ptr; int ret; if (flags & ~SQFS_TREE_ALL_FLAGS) return SQFS_ERROR_UNSUPPORTED; ret = sqfs_dir_reader_get_root_inode(rd, &inode); if (ret) return ret; root = tail = create_node(inode, ""); if (root == NULL) { free(inode); return SQFS_ERROR_ALLOC; } inode = NULL; while (path != NULL && *path != '\0') { if (*path == '/' || *path == '\\') { while (*path == '/' || *path == '\\') ++path; continue; } ret = sqfs_dir_reader_open_dir(rd, tail->inode); if (ret) goto fail; ptr = strchr(path, '/'); if (ptr == NULL) { ptr = strchr(path, '\\'); if (ptr == NULL) { for (ptr = path; *ptr != '\0'; ++ptr) ; } } for (;;) { ret = sqfs_dir_reader_read(rd, &ent); if (ret < 0) goto fail; if (ret > 0) { ret = SQFS_ERROR_NO_ENTRY; goto fail; } ret = strncmp((const char *)ent->name, path, ptr - path); if (ret == 0 && ent->name[ptr - path] == '\0') break; free(ent); } ret = sqfs_dir_reader_get_inode(rd, &inode); if (ret) { free(ent); goto fail; } new = create_node(inode, (const char *)ent->name); free(ent); if (new == NULL) { free(inode); ret = SQFS_ERROR_ALLOC; goto fail; } inode = NULL; path = ptr; if (flags & SQFS_TREE_STORE_PARENTS) { tail->children = new; new->parent = tail; tail = new; } else { sqfs_dir_tree_destroy(root); root = tail = new; } } if (tail->inode->base.type == SQFS_INODE_DIR || tail->inode->base.type == SQFS_INODE_EXT_DIR) { ret = sqfs_dir_reader_open_dir(rd, tail->inode); if (ret) goto fail; ret = fill_dir(rd, tail, flags); if (ret) goto fail; } ret = resolve_ids(root, idtbl); if (ret) goto fail; *out = root; return 0; fail: sqfs_dir_tree_destroy(root); return ret; } squashfs-tools-ng-0.8/lib/sqfs/readdir.c000066400000000000000000000025151360235375500202720ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * readdir.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_reader.h" #include "sqfs/error.h" #include "sqfs/dir.h" #include "compat.h" #include #include int sqfs_meta_reader_read_dir_header(sqfs_meta_reader_t *m, sqfs_dir_header_t *hdr) { int err = sqfs_meta_reader_read(m, hdr, sizeof(*hdr)); if (err) return err; hdr->count = le32toh(hdr->count); hdr->start_block = le32toh(hdr->start_block); hdr->inode_number = le32toh(hdr->inode_number); if (hdr->count > (SQFS_MAX_DIR_ENT - 1)) return SQFS_ERROR_CORRUPTED; return 0; } int sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m, sqfs_dir_entry_t **result) { sqfs_dir_entry_t ent, *out; sqfs_u16 *diff_u16; int err; err = sqfs_meta_reader_read(m, &ent, sizeof(ent)); if (err) return err; diff_u16 = (sqfs_u16 *)&ent.inode_diff; *diff_u16 = le16toh(*diff_u16); ent.offset = le16toh(ent.offset); ent.type = le16toh(ent.type); ent.size = le16toh(ent.size); out = calloc(1, sizeof(*out) + ent.size + 2); if (out == NULL) return SQFS_ERROR_ALLOC; *out = ent; err = sqfs_meta_reader_read(m, out->name, ent.size + 1); if (err) { free(out); return err; } *result = out; return 0; } squashfs-tools-ng-0.8/lib/sqfs/str_table.c000066400000000000000000000065321360235375500206420ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * str_table.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include #include #include #include "sqfs/error.h" #include "str_table.h" #include "util.h" /* R5 hash function (borrowed from reiserfs) */ static sqfs_u32 strhash(const char *s) { const signed char *str = (const signed char *)s; sqfs_u32 a = 0; while (*str != '\0') { a += *str << 4; a += *str >> 4; a *= 11; str++; } return a; } static int strings_grow(str_table_t *table) { size_t newsz; void *new; if (table->num_strings < table->max_strings) return 0; newsz = table->max_strings ? (table->max_strings * 2) : 16; new = realloc(table->strings, sizeof(table->strings[0]) * newsz); if (new == NULL) return SQFS_ERROR_ALLOC; table->strings = new; table->max_strings = newsz; return 0; } int str_table_init(str_table_t *table, size_t size) { memset(table, 0, sizeof(*table)); table->buckets = alloc_array(size, sizeof(table->buckets[0])); table->num_buckets = size; if (table->buckets == NULL) return SQFS_ERROR_ALLOC; return 0; } void str_table_cleanup(str_table_t *table) { str_bucket_t *bucket; size_t i; for (i = 0; i < table->num_buckets; ++i) { while (table->buckets[i] != NULL) { bucket = table->buckets[i]; table->buckets[i] = bucket->next; free(bucket->str); free(bucket); } } free(table->buckets); free(table->strings); memset(table, 0, sizeof(*table)); } int str_table_get_index(str_table_t *table, const char *str, size_t *idx) { str_bucket_t *bucket; sqfs_u32 hash; size_t index; int err; hash = strhash(str); index = hash % table->num_buckets; bucket = table->buckets[index]; while (bucket != NULL) { if (strcmp(bucket->str, str) == 0) { *idx = bucket->index; return 0; } bucket = bucket->next; } err = strings_grow(table); if (err) return err; bucket = calloc(1, sizeof(*bucket)); if (bucket == NULL) goto fail_oom; bucket->str = strdup(str); if (bucket->str == NULL) goto fail_oom; bucket->index = table->num_strings; table->strings[table->num_strings++] = bucket->str; *idx = bucket->index; bucket->next = table->buckets[index]; table->buckets[index] = bucket; return 0; fail_oom: free(bucket); return SQFS_ERROR_ALLOC; } const char *str_table_get_string(str_table_t *table, size_t index) { if (index >= table->num_strings) return NULL; return table->strings[index]; } static str_bucket_t *bucket_by_index(str_table_t *table, size_t index) { str_bucket_t *bucket = NULL; sqfs_u32 hash; if (index < table->num_strings) { hash = strhash(table->strings[index]); bucket = table->buckets[hash % table->num_buckets]; while (bucket != NULL && bucket->index != index) bucket = bucket->next; } return bucket; } void str_table_add_ref(str_table_t *table, size_t index) { str_bucket_t *bucket = bucket_by_index(table, index); if (bucket != NULL && bucket->refcount < ~((size_t)0)) bucket->refcount += 1; } void str_table_del_ref(str_table_t *table, size_t index) { str_bucket_t *bucket = bucket_by_index(table, index); if (bucket != NULL && bucket->refcount > 0) bucket->refcount -= 1; } size_t str_table_get_ref_count(str_table_t *table, size_t index) { str_bucket_t *bucket = bucket_by_index(table, index); return bucket != NULL ? bucket->refcount : 0; } squashfs-tools-ng-0.8/lib/sqfs/str_table.h000066400000000000000000000027011360235375500206410ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * str_table.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef STR_TABLE_H #define STR_TABLE_H #include "sqfs/predef.h" typedef struct str_bucket_t { struct str_bucket_t *next; char *str; size_t index; size_t refcount; } str_bucket_t; /* Stores strings in a hash table and assigns an incremental, unique ID to each string. Subsequent additions return the existing ID. The ID can be used for (hopefully) constant time lookup of the original string. */ typedef struct { str_bucket_t **buckets; size_t num_buckets; char **strings; size_t num_strings; size_t max_strings; } str_table_t; /* `size` is the number of hash table buckets to use internally. */ SQFS_INTERNAL int str_table_init(str_table_t *table, size_t size); SQFS_INTERNAL void str_table_cleanup(str_table_t *table); /* Resolve a string to an incremental, unique ID. */ SQFS_INTERNAL int str_table_get_index(str_table_t *table, const char *str, size_t *idx); /* Resolve a unique ID to the string it represents. Returns NULL if the ID is unknown, i.e. out of bounds. */ SQFS_INTERNAL const char *str_table_get_string(str_table_t *table, size_t index); SQFS_INTERNAL void str_table_add_ref(str_table_t *table, size_t index); SQFS_INTERNAL void str_table_del_ref(str_table_t *table, size_t index); SQFS_INTERNAL size_t str_table_get_ref_count(str_table_t *table, size_t index); #endif /* STR_TABLE_H */ squashfs-tools-ng-0.8/lib/sqfs/super.c000066400000000000000000000024151360235375500200150ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * super.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/super.h" #include "sqfs/error.h" #include int sqfs_super_init(sqfs_super_t *super, size_t block_size, sqfs_u32 mtime, E_SQFS_COMPRESSOR compressor) { unsigned int i; if (block_size & (block_size - 1)) return SQFS_ERROR_SUPER_BLOCK_SIZE; if (block_size < 4096 || block_size > (1 << 20)) return SQFS_ERROR_SUPER_BLOCK_SIZE; memset(super, 0, sizeof(*super)); super->magic = SQFS_MAGIC; super->modification_time = mtime; super->block_size = block_size; super->compression_id = compressor; super->flags = SQFS_FLAG_NO_FRAGMENTS | SQFS_FLAG_NO_XATTRS; super->version_major = SQFS_VERSION_MAJOR; super->version_minor = SQFS_VERSION_MINOR; super->bytes_used = sizeof(*super); super->id_table_start = 0xFFFFFFFFFFFFFFFFUL; super->xattr_id_table_start = 0xFFFFFFFFFFFFFFFFUL; super->inode_table_start = 0xFFFFFFFFFFFFFFFFUL; super->directory_table_start = 0xFFFFFFFFFFFFFFFFUL; super->fragment_table_start = 0xFFFFFFFFFFFFFFFFUL; super->export_table_start = 0xFFFFFFFFFFFFFFFFUL; for (i = block_size; i != 0x01; i >>= 1) super->block_log += 1; return 0; } squashfs-tools-ng-0.8/lib/sqfs/unix/000077500000000000000000000000001360235375500174745ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/unix/io_file.c000066400000000000000000000055001360235375500212460ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * io_file.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/io.h" #include "sqfs/error.h" #include #include #include #include #include typedef struct { sqfs_file_t base; sqfs_u64 size; int fd; } sqfs_file_stdio_t; static void stdio_destroy(sqfs_file_t *base) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; close(file->fd); free(file); } static int stdio_read_at(sqfs_file_t *base, sqfs_u64 offset, void *buffer, size_t size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; ssize_t ret; while (size > 0) { ret = pread(file->fd, buffer, size, offset); if (ret < 0) { if (errno == EINTR) continue; return SQFS_ERROR_IO; } if (ret == 0) return SQFS_ERROR_OUT_OF_BOUNDS; buffer = (char *)buffer + ret; size -= ret; offset += ret; } return 0; } static int stdio_write_at(sqfs_file_t *base, sqfs_u64 offset, const void *buffer, size_t size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; ssize_t ret; while (size > 0) { ret = pwrite(file->fd, buffer, size, offset); if (ret < 0) { if (errno == EINTR) continue; return SQFS_ERROR_IO; } if (ret == 0) return SQFS_ERROR_OUT_OF_BOUNDS; buffer = (const char *)buffer + ret; size -= ret; offset += ret; } if (offset >= file->size) file->size = offset; return 0; } static sqfs_u64 stdio_get_size(const sqfs_file_t *base) { const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base; return file->size; } static int stdio_truncate(sqfs_file_t *base, sqfs_u64 size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; if (ftruncate(file->fd, size)) return SQFS_ERROR_IO; file->size = size; return 0; } sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags) { sqfs_file_stdio_t *file; int open_mode, temp; sqfs_file_t *base; struct stat sb; if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) { errno = EINVAL; return NULL; } file = calloc(1, sizeof(*file)); base = (sqfs_file_t *)file; if (file == NULL) return NULL; if (flags & SQFS_FILE_OPEN_READ_ONLY) { open_mode = O_RDONLY; } else { open_mode = O_CREAT | O_RDWR; if (flags & SQFS_FILE_OPEN_OVERWRITE) { open_mode |= O_TRUNC; } else { open_mode |= O_EXCL; } } file->fd = open(filename, open_mode, 0600); if (file->fd < 0) { temp = errno; free(file); errno = temp; return NULL; } if (fstat(file->fd, &sb)) { temp = errno; close(file->fd); free(file); errno = temp; return NULL; } file->size = sb.st_size; base->destroy = stdio_destroy; base->read_at = stdio_read_at; base->write_at = stdio_write_at; base->get_size = stdio_get_size; base->truncate = stdio_truncate; return base; } squashfs-tools-ng-0.8/lib/sqfs/util.h000066400000000000000000000014371360235375500176440ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * util.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef SQFS_UTIL_H #define SQFS_UTIL_H #include "config.h" #include "sqfs/predef.h" #include "compat.h" #include /* Helper for allocating data structures with flexible array members. 'base_size' is the size of the struct itself, 'item_size' the size of a single array element and 'nmemb' the number of elements. Iternally checks for arithmetic overflows when allocating the combined thing. */ SQFS_INTERNAL void *alloc_flex(size_t base_size, size_t item_size, size_t nmemb); /* Basically the same as calloc, but *ALWAYS* does overflow checking */ SQFS_INTERNAL void *alloc_array(size_t item_size, size_t nmemb); #endif /* SQFS_UTIL_H */ squashfs-tools-ng-0.8/lib/sqfs/win32/000077500000000000000000000000001360235375500174535ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/sqfs/win32/io_file.c000066400000000000000000000064451360235375500212360ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * io_file.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/io.h" #include "sqfs/error.h" #include #define WIN32_LEAN_AND_MEAN #include typedef struct { sqfs_file_t base; sqfs_u64 size; HANDLE fd; } sqfs_file_stdio_t; static void stdio_destroy(sqfs_file_t *base) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; CloseHandle(file->fd); free(file); } static int stdio_read_at(sqfs_file_t *base, sqfs_u64 offset, void *buffer, size_t size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; DWORD actually_read; LARGE_INTEGER pos; if (offset >= file->size) return SQFS_ERROR_OUT_OF_BOUNDS; if (size == 0) return 0; if ((offset + size - 1) >= file->size) return SQFS_ERROR_OUT_OF_BOUNDS; pos.QuadPart = offset; if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN)) return SQFS_ERROR_IO; while (size > 0) { if (!ReadFile(file->fd, buffer, size, &actually_read, NULL)) return SQFS_ERROR_IO; size -= actually_read; buffer = (char *)buffer + actually_read; } return 0; } static int stdio_write_at(sqfs_file_t *base, sqfs_u64 offset, const void *buffer, size_t size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; DWORD actually_read; LARGE_INTEGER pos; if (size == 0) return 0; pos.QuadPart = offset; if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN)) return SQFS_ERROR_IO; while (size > 0) { if (!WriteFile(file->fd, buffer, size, &actually_read, NULL)) return SQFS_ERROR_IO; size -= actually_read; buffer = (char *)buffer + actually_read; offset += actually_read; if (offset > file->size) file->size = offset; } return 0; } static sqfs_u64 stdio_get_size(const sqfs_file_t *base) { const sqfs_file_stdio_t *file = (const sqfs_file_stdio_t *)base; return file->size; } static int stdio_truncate(sqfs_file_t *base, sqfs_u64 size) { sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; LARGE_INTEGER pos; pos.QuadPart = size; if (!SetFilePointerEx(file->fd, pos, NULL, FILE_BEGIN)) return SQFS_ERROR_IO; if (!SetEndOfFile(file->fd)) return SQFS_ERROR_IO; file->size = size; return 0; } sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags) { int access_flags, creation_mode; sqfs_file_stdio_t *file; LARGE_INTEGER size; sqfs_file_t *base; if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) return NULL; file = calloc(1, sizeof(*file)); base = (sqfs_file_t *)file; if (file == NULL) return NULL; if (flags & SQFS_FILE_OPEN_READ_ONLY) { access_flags = GENERIC_READ; creation_mode = OPEN_EXISTING; } else { access_flags = GENERIC_READ | GENERIC_WRITE; if (flags & SQFS_FILE_OPEN_OVERWRITE) { creation_mode = CREATE_ALWAYS; } else { creation_mode = CREATE_NEW; } } file->fd = CreateFile(filename, access_flags, 0, NULL, creation_mode, FILE_ATTRIBUTE_NORMAL, NULL); if (file->fd == INVALID_HANDLE_VALUE) { free(file); return NULL; } if (!GetFileSizeEx(file->fd, &size)) { free(file); return NULL; } file->size = size.QuadPart; base->destroy = stdio_destroy; base->read_at = stdio_read_at; base->write_at = stdio_write_at; base->get_size = stdio_get_size; base->truncate = stdio_truncate; return base; } squashfs-tools-ng-0.8/lib/sqfs/write_inode.c000066400000000000000000000127121360235375500211700ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * write_inode.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_writer.h" #include "sqfs/error.h" #include "sqfs/inode.h" #include "sqfs/dir.h" #include "compat.h" #include static int write_block_sizes(sqfs_meta_writer_t *ir, const sqfs_inode_generic_t *n) { sqfs_u32 sizes[n->num_file_blocks]; size_t i; for (i = 0; i < n->num_file_blocks; ++i) sizes[i] = htole32(n->block_sizes[i]); return sqfs_meta_writer_append(ir, sizes, sizeof(sqfs_u32) * n->num_file_blocks); } static int write_dir_index(sqfs_meta_writer_t *ir, const sqfs_u8 *data, size_t count) { sqfs_dir_index_t ent; size_t len; int err; while (count > sizeof(ent)) { memcpy(&ent, data, sizeof(ent)); data += sizeof(ent); count -= sizeof(ent); len = ent.size + 1; if (len > count) return SQFS_ERROR_CORRUPTED; ent.start_block = htole32(ent.start_block); ent.index = htole32(ent.index); ent.size = htole32(ent.size); err = sqfs_meta_writer_append(ir, &ent, sizeof(ent)); if (err) return err; err = sqfs_meta_writer_append(ir, data, len); if (err) return err; data += len; count -= len; } return 0; } int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, const sqfs_inode_generic_t *n) { sqfs_inode_t base; int ret; base.type = htole16(n->base.type); base.mode = htole16(n->base.mode & ~SQFS_INODE_MODE_MASK); base.uid_idx = htole16(n->base.uid_idx); base.gid_idx = htole16(n->base.gid_idx); base.mod_time = htole32(n->base.mod_time); base.inode_number = htole32(n->base.inode_number); ret = sqfs_meta_writer_append(ir, &base, sizeof(base)); if (ret) return ret; switch (n->base.type) { case SQFS_INODE_DIR: { sqfs_inode_dir_t dir = { .start_block = htole32(n->data.dir.start_block), .nlink = htole32(n->data.dir.nlink), .size = htole16(n->data.dir.size), .offset = htole16(n->data.dir.offset), .parent_inode = htole32(n->data.dir.parent_inode), }; return sqfs_meta_writer_append(ir, &dir, sizeof(dir)); } case SQFS_INODE_FILE: { sqfs_inode_file_t file = { .blocks_start = htole32(n->data.file.blocks_start), .fragment_index = htole32(n->data.file.fragment_index), .fragment_offset = htole32(n->data.file.fragment_offset), .file_size = htole32(n->data.file.file_size), }; ret = sqfs_meta_writer_append(ir, &file, sizeof(file)); if (ret) return ret; return n->num_file_blocks ? write_block_sizes(ir, n) : 0; } case SQFS_INODE_SLINK: { sqfs_inode_slink_t slink = { .nlink = htole32(n->data.slink.nlink), .target_size = htole32(n->data.slink.target_size), }; ret = sqfs_meta_writer_append(ir, &slink, sizeof(slink)); if (ret) return ret; return sqfs_meta_writer_append(ir, n->slink_target, n->data.slink.target_size); } case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: { sqfs_inode_dev_t dev = { .nlink = htole32(n->data.dev.nlink), .devno = htole32(n->data.dev.devno), }; return sqfs_meta_writer_append(ir, &dev, sizeof(dev)); } case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: { sqfs_inode_ipc_t ipc = { .nlink = htole32(n->data.ipc.nlink), }; return sqfs_meta_writer_append(ir, &ipc, sizeof(ipc)); } case SQFS_INODE_EXT_DIR: { sqfs_inode_dir_ext_t dir = { .nlink = htole32(n->data.dir_ext.nlink), .size = htole32(n->data.dir_ext.size), .start_block = htole32(n->data.dir_ext.start_block), .parent_inode = htole32(n->data.dir_ext.parent_inode), .inodex_count = htole16(n->data.dir_ext.inodex_count), .offset = htole16(n->data.dir_ext.offset), .xattr_idx = htole32(n->data.dir_ext.xattr_idx), }; ret = sqfs_meta_writer_append(ir, &dir, sizeof(dir)); if (ret) return ret; return write_dir_index(ir, n->extra, n->num_dir_idx_bytes); } case SQFS_INODE_EXT_FILE: { sqfs_inode_file_ext_t file = { .blocks_start = htole64(n->data.file_ext.blocks_start), .file_size = htole64(n->data.file_ext.file_size), .sparse = htole64(n->data.file_ext.sparse), .nlink = htole32(n->data.file_ext.nlink), .fragment_idx = htole32(n->data.file_ext.fragment_idx), .fragment_offset = htole32(n->data.file_ext.fragment_offset), .xattr_idx = htole32(n->data.file_ext.xattr_idx), }; ret = sqfs_meta_writer_append(ir, &file, sizeof(file)); if (ret) return ret; return n->num_file_blocks ? write_block_sizes(ir, n) : 0; } case SQFS_INODE_EXT_SLINK: { sqfs_inode_slink_t slink = { .nlink = htole32(n->data.slink_ext.nlink), .target_size = htole32(n->data.slink_ext.target_size), }; sqfs_u32 xattr = htole32(n->data.slink_ext.xattr_idx); ret = sqfs_meta_writer_append(ir, &slink, sizeof(slink)); if (ret) return ret; ret = sqfs_meta_writer_append(ir, n->slink_target, n->data.slink_ext.target_size); if (ret) return ret; return sqfs_meta_writer_append(ir, &xattr, sizeof(xattr)); } case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: { sqfs_inode_dev_ext_t dev = { .nlink = htole32(n->data.dev_ext.nlink), .devno = htole32(n->data.dev_ext.devno), .xattr_idx = htole32(n->data.dev_ext.xattr_idx), }; return sqfs_meta_writer_append(ir, &dev, sizeof(dev)); } case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: { sqfs_inode_ipc_ext_t ipc = { .nlink = htole32(n->data.ipc_ext.nlink), .xattr_idx = htole32(n->data.ipc_ext.xattr_idx), }; return sqfs_meta_writer_append(ir, &ipc, sizeof(ipc)); } } return SQFS_ERROR_UNSUPPORTED; } squashfs-tools-ng-0.8/lib/sqfs/write_super.c000066400000000000000000000026301360235375500212260ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * write_super.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/super.h" #include "sqfs/io.h" #include "compat.h" int sqfs_super_write(const sqfs_super_t *super, sqfs_file_t *file) { sqfs_super_t copy; copy.magic = htole32(super->magic); copy.inode_count = htole32(super->inode_count); copy.modification_time = htole32(super->modification_time); copy.block_size = htole32(super->block_size); copy.fragment_entry_count = htole32(super->fragment_entry_count); copy.compression_id = htole16(super->compression_id); copy.block_log = htole16(super->block_log); copy.flags = htole16(super->flags); copy.id_count = htole16(super->id_count); copy.version_major = htole16(super->version_major); copy.version_minor = htole16(super->version_minor); copy.root_inode_ref = htole64(super->root_inode_ref); copy.bytes_used = htole64(super->bytes_used); copy.id_table_start = htole64(super->id_table_start); copy.xattr_id_table_start = htole64(super->xattr_id_table_start); copy.inode_table_start = htole64(super->inode_table_start); copy.directory_table_start = htole64(super->directory_table_start); copy.fragment_table_start = htole64(super->fragment_table_start); copy.export_table_start = htole64(super->export_table_start); return file->write_at(file, 0, ©, sizeof(copy)); } squashfs-tools-ng-0.8/lib/sqfs/write_table.c000066400000000000000000000031521360235375500211570ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * write_table.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/meta_writer.h" #include "sqfs/error.h" #include "sqfs/super.h" #include "sqfs/table.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "util.h" #include int sqfs_write_table(sqfs_file_t *file, sqfs_compressor_t *cmp, const void *data, size_t table_size, sqfs_u64 *start) { size_t block_count, list_size, diff, blkidx = 0; sqfs_u64 off, *locations; sqfs_meta_writer_t *m; int ret; block_count = table_size / SQFS_META_BLOCK_SIZE; if ((table_size % SQFS_META_BLOCK_SIZE) != 0) ++block_count; locations = alloc_array(sizeof(sqfs_u64), block_count); if (locations == NULL) return SQFS_ERROR_ALLOC; /* Write actual data */ m = sqfs_meta_writer_create(file, cmp, 0); if (m == NULL) { ret = SQFS_ERROR_ALLOC; goto out_idx; } while (table_size > 0) { locations[blkidx++] = htole64(file->get_size(file)); diff = SQFS_META_BLOCK_SIZE; if (diff > table_size) diff = table_size; ret = sqfs_meta_writer_append(m, data, diff); if (ret) goto out; data = (const char *)data + diff; table_size -= diff; } ret = sqfs_meta_writer_flush(m); if (ret) goto out; /* write location list */ *start = file->get_size(file); list_size = sizeof(sqfs_u64) * block_count; off = file->get_size(file); ret = file->write_at(file, off, locations, list_size); if (ret) goto out; /* cleanup */ ret = 0; out: sqfs_meta_writer_destroy(m); out_idx: free(locations); return ret; } squashfs-tools-ng-0.8/lib/sqfs/xattr.c000066400000000000000000000017651360235375500200300ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * write_xattr.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/xattr.h" #include "sqfs/error.h" #include static const struct { const char *prefix; E_SQFS_XATTR_TYPE type; } xattr_types[] = { { "user.", SQFS_XATTR_USER }, { "trusted.", SQFS_XATTR_TRUSTED }, { "security.", SQFS_XATTR_SECURITY }, }; int sqfs_get_xattr_prefix_id(const char *key) { size_t i, len; for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) { len = strlen(xattr_types[i].prefix); if (strncmp(key, xattr_types[i].prefix, len) == 0 && strlen(key) > len) { return xattr_types[i].type; } } return SQFS_ERROR_UNSUPPORTED; } const char *sqfs_get_xattr_prefix(E_SQFS_XATTR_TYPE id) { size_t i; for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) { if (xattr_types[i].type == id) return xattr_types[i].prefix; } return NULL; } squashfs-tools-ng-0.8/lib/sqfs/xattr_reader.c000066400000000000000000000143231360235375500213440ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xattr_reader.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/xattr_reader.h" #include "sqfs/meta_reader.h" #include "sqfs/super.h" #include "sqfs/xattr.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "util.h" #include #include #include struct sqfs_xattr_reader_t { sqfs_u64 xattr_start; size_t num_id_blocks; size_t num_ids; sqfs_u64 *id_block_starts; sqfs_meta_reader_t *idrd; sqfs_meta_reader_t *kvrd; sqfs_super_t *super; sqfs_file_t *file; }; int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) { sqfs_xattr_id_table_t idtbl; size_t i; int err; if (xr->super->flags & SQFS_FLAG_NO_XATTRS) return 0; if (xr->super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) return 0; if (xr->super->xattr_id_table_start >= xr->super->bytes_used) return SQFS_ERROR_OUT_OF_BOUNDS; err = xr->file->read_at(xr->file, xr->super->xattr_id_table_start, &idtbl, sizeof(idtbl)); if (err) return err; xr->xattr_start = le64toh(idtbl.xattr_table_start); xr->num_ids = le32toh(idtbl.xattr_ids); xr->num_id_blocks = (xr->num_ids * sizeof(sqfs_xattr_id_t)) / SQFS_META_BLOCK_SIZE; if ((xr->num_ids * sizeof(sqfs_xattr_id_t)) % SQFS_META_BLOCK_SIZE) xr->num_id_blocks += 1; xr->id_block_starts = alloc_array(sizeof(sqfs_u64), xr->num_id_blocks); if (xr->id_block_starts == NULL) { if (errno == EOVERFLOW) return SQFS_ERROR_OVERFLOW; return SQFS_ERROR_ALLOC; } err = xr->file->read_at(xr->file, xr->super->xattr_id_table_start + sizeof(idtbl), xr->id_block_starts, sizeof(sqfs_u64) * xr->num_id_blocks); if (err) goto fail; for (i = 0; i < xr->num_id_blocks; ++i) { xr->id_block_starts[i] = le64toh(xr->id_block_starts[i]); if (xr->id_block_starts[i] > xr->super->bytes_used) { err = SQFS_ERROR_OUT_OF_BOUNDS; goto fail; } } return 0; fail: free(xr->id_block_starts); xr->id_block_starts = NULL; return err; } int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr, sqfs_xattr_entry_t **key_out) { sqfs_xattr_entry_t key, *out; const char *prefix; size_t plen, total; int ret; ret = sqfs_meta_reader_read(xr->kvrd, &key, sizeof(key)); if (ret) return ret; key.type = le16toh(key.type); key.size = le16toh(key.size); prefix = sqfs_get_xattr_prefix(key.type & SQFS_XATTR_PREFIX_MASK); if (prefix == NULL) return SQFS_ERROR_UNSUPPORTED; plen = strlen(prefix); if (SZ_ADD_OV(plen, key.size, &total) || SZ_ADD_OV(total, 1, &total) || SZ_ADD_OV(sizeof(*out), total, &total)) { return SQFS_ERROR_OVERFLOW; } out = calloc(1, total); if (out == NULL) return SQFS_ERROR_ALLOC; *out = key; memcpy(out->key, prefix, plen); ret = sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size); if (ret) { free(out); return ret; } *key_out = out; return 0; } int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, const sqfs_xattr_entry_t *key, sqfs_xattr_value_t **val_out) { size_t offset, new_offset, size; sqfs_xattr_value_t value, *out; sqfs_u64 ref, start, new_start; int ret; ret = sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value)); if (ret) return ret; if (key->type & SQFS_XATTR_FLAG_OOL) { ret = sqfs_meta_reader_read(xr->kvrd, &ref, sizeof(ref)); if (ret) return ret; sqfs_meta_reader_get_position(xr->kvrd, &start, &offset); new_start = xr->xattr_start + (ref >> 16); if (new_start >= xr->super->bytes_used) return SQFS_ERROR_OUT_OF_BOUNDS; new_offset = ref & 0xFFFF; if (new_offset >= SQFS_META_BLOCK_SIZE) return SQFS_ERROR_OUT_OF_BOUNDS; ret = sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset); if (ret) return ret; } value.size = le32toh(value.size); if (SZ_ADD_OV(sizeof(*out), value.size, &size) || SZ_ADD_OV(size, 1, &size)) { return SQFS_ERROR_OVERFLOW; } out = calloc(1, size); if (out == NULL) return SQFS_ERROR_ALLOC; *out = value; ret = sqfs_meta_reader_read(xr->kvrd, out->value, value.size); if (ret) goto fail; if (key->type & SQFS_XATTR_FLAG_OOL) { ret = sqfs_meta_reader_seek(xr->kvrd, start, offset); if (ret) goto fail; } *val_out = out; return 0; fail: free(out); return ret; } int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr, const sqfs_xattr_id_t *desc) { sqfs_u32 offset = desc->xattr & 0xFFFF; sqfs_u64 block = xr->xattr_start + (desc->xattr >> 16); return sqfs_meta_reader_seek(xr->kvrd, block, offset); } int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, sqfs_u32 idx, sqfs_xattr_id_t *desc) { size_t block, offset; int ret; memset(desc, 0, sizeof(*desc)); if (idx == 0xFFFFFFFF) return 0; if (xr->kvrd == NULL || xr->idrd == NULL) return idx == 0 ? 0 : SQFS_ERROR_OUT_OF_BOUNDS; if (idx >= xr->num_ids) return SQFS_ERROR_OUT_OF_BOUNDS; offset = (idx * sizeof(*desc)) % SQFS_META_BLOCK_SIZE; block = (idx * sizeof(*desc)) / SQFS_META_BLOCK_SIZE; ret = sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block], offset); if (ret) return ret; ret = sqfs_meta_reader_read(xr->idrd, desc, sizeof(*desc)); if (ret) return ret; desc->xattr = le64toh(desc->xattr); desc->count = le32toh(desc->count); desc->size = le32toh(desc->size); return 0; } void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr) { if (xr->kvrd != NULL) sqfs_meta_reader_destroy(xr->kvrd); if (xr->idrd != NULL) sqfs_meta_reader_destroy(xr->idrd); free(xr->id_block_starts); free(xr); } sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp) { sqfs_xattr_reader_t *xr = calloc(1, sizeof(*xr)); if (xr == NULL) return NULL; xr->file = file; xr->super = super; if (super->flags & SQFS_FLAG_NO_XATTRS) return xr; if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) return xr; xr->idrd = sqfs_meta_reader_create(file, cmp, super->id_table_start, super->bytes_used); if (xr->idrd == NULL) goto fail; xr->kvrd = sqfs_meta_reader_create(file, cmp, super->id_table_start, super->bytes_used); if (xr->kvrd == NULL) goto fail; return xr; fail: sqfs_xattr_reader_destroy(xr); return NULL; } squashfs-tools-ng-0.8/lib/sqfs/xattr_writer.c000066400000000000000000000314571360235375500214250ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * xattr_writer.c * * Copyright (C) 2019 David Oberhollenzer */ #define SQFS_BUILDING_DLL #include "config.h" #include "sqfs/xattr_writer.h" #include "sqfs/meta_writer.h" #include "sqfs/super.h" #include "sqfs/xattr.h" #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" #include "str_table.h" #include "util.h" #include #include #include #define XATTR_KEY_BUCKETS 31 #define XATTR_VALUE_BUCKETS 511 #define XATTR_INITIAL_PAIR_CAP 128 #define MK_PAIR(key, value) (((sqfs_u64)(key) << 32UL) | (sqfs_u64)(value)) #define GET_KEY(pair) ((pair >> 32UL) & 0x0FFFFFFFFUL) #define GET_VALUE(pair) (pair & 0x0FFFFFFFFUL) static const char *hexmap = "0123456789ABCDEF"; static char *to_base32(const void *input, size_t size) { const sqfs_u8 *in = input; char *out, *ptr; size_t i; out = malloc(2 * size + 1); if (out == NULL) return NULL; ptr = out; for (i = 0; i < size; ++i) { *(ptr++) = hexmap[ in[i] & 0x0F]; *(ptr++) = hexmap[(in[i] >> 4) & 0x0F]; } *ptr = '\0'; return out; } static void *from_base32(const char *input, size_t *size_out) { sqfs_u8 lo, hi, *out, *ptr; size_t len; len = strlen(input); *size_out = len / 2; out = malloc(*size_out); if (out == NULL) return NULL; ptr = out; while (*input != '\0') { lo = strchr(hexmap, *(input++)) - hexmap; hi = strchr(hexmap, *(input++)) - hexmap; *(ptr++) = lo | (hi << 4); } return out; } static int compare_u64(const void *a, const void *b) { sqfs_u64 lhs = *((const sqfs_u64 *)a); sqfs_u64 rhs = *((const sqfs_u64 *)b); return (lhs < rhs ? -1 : (lhs > rhs ? 1 : 0)); } typedef struct kv_block_desc_t { struct kv_block_desc_t *next; size_t start; size_t count; sqfs_u64 start_ref; size_t size_bytes; } kv_block_desc_t; struct sqfs_xattr_writer_t { str_table_t keys; str_table_t values; sqfs_u64 *kv_pairs; size_t max_pairs; size_t num_pairs; size_t kv_start; kv_block_desc_t *kv_blocks; size_t num_blocks; }; sqfs_xattr_writer_t *sqfs_xattr_writer_create(void) { sqfs_xattr_writer_t *xwr = calloc(1, sizeof(*xwr)); if (str_table_init(&xwr->keys, XATTR_KEY_BUCKETS)) goto fail_keys; if (str_table_init(&xwr->values, XATTR_VALUE_BUCKETS)) goto fail_values; xwr->max_pairs = XATTR_INITIAL_PAIR_CAP; xwr->kv_pairs = alloc_array(sizeof(xwr->kv_pairs[0]), xwr->max_pairs); if (xwr->kv_pairs == NULL) goto fail_pairs; return xwr; fail_pairs: str_table_cleanup(&xwr->values); fail_values: str_table_cleanup(&xwr->keys); fail_keys: free(xwr); return NULL; } void sqfs_xattr_writer_destroy(sqfs_xattr_writer_t *xwr) { kv_block_desc_t *blk; while (xwr->kv_blocks != NULL) { blk = xwr->kv_blocks; xwr->kv_blocks = xwr->kv_blocks->next; free(blk); } free(xwr->kv_pairs); str_table_cleanup(&xwr->values); str_table_cleanup(&xwr->keys); free(xwr); } int sqfs_xattr_writer_begin(sqfs_xattr_writer_t *xwr) { xwr->kv_start = xwr->num_pairs; return 0; } int sqfs_xattr_writer_add(sqfs_xattr_writer_t *xwr, const char *key, const void *value, size_t size) { size_t i, key_index, old_value_index, value_index, new_count; sqfs_u64 kv_pair, *new; char *value_str; int err; if (sqfs_get_xattr_prefix_id(key) < 0) return SQFS_ERROR_UNSUPPORTED; /* resolve key and value into unique, incremental IDs */ err = str_table_get_index(&xwr->keys, key, &key_index); if (err) return err; value_str = to_base32(value, size); if (value_str == NULL) return SQFS_ERROR_ALLOC; err = str_table_get_index(&xwr->values, value_str, &value_index); free(value_str); if (err) return err; str_table_add_ref(&xwr->values, value_index); if (sizeof(size_t) > sizeof(sqfs_u32)) { if (key_index > 0x0FFFFFFFFUL || value_index > 0x0FFFFFFFFUL) return SQFS_ERROR_OVERFLOW; } /* bail if already have the pair, overwrite if we have the key */ kv_pair = MK_PAIR(key_index, value_index); for (i = xwr->kv_start; i < xwr->num_pairs; ++i) { if (xwr->kv_pairs[i] == kv_pair) return 0; if (GET_KEY(xwr->kv_pairs[i]) == key_index) { old_value_index = GET_VALUE(xwr->kv_pairs[i]); str_table_del_ref(&xwr->values, old_value_index); xwr->kv_pairs[i] = kv_pair; return 0; } } /* append it to the list */ if (xwr->max_pairs == xwr->num_pairs) { new_count = xwr->max_pairs * 2; new = realloc(xwr->kv_pairs, sizeof(xwr->kv_pairs[0]) * new_count); if (new == NULL) return SQFS_ERROR_ALLOC; xwr->kv_pairs = new; xwr->max_pairs = new_count; } xwr->kv_pairs[xwr->num_pairs++] = kv_pair; return 0; } int sqfs_xattr_writer_end(sqfs_xattr_writer_t *xwr, sqfs_u32 *out) { kv_block_desc_t *blk, *blk_prev; size_t i, count, value_idx; sqfs_u32 index; int ret; count = xwr->num_pairs - xwr->kv_start; if (count == 0) { *out = 0xFFFFFFFF; return 0; } qsort(xwr->kv_pairs + xwr->kv_start, count, sizeof(xwr->kv_pairs[0]), compare_u64); blk_prev = NULL; blk = xwr->kv_blocks; index = 0; while (blk != NULL) { if (blk->count == count) { ret = memcmp(xwr->kv_pairs + blk->start, xwr->kv_pairs + xwr->kv_start, sizeof(xwr->kv_pairs[0]) * count); if (ret == 0) break; } if (index == 0xFFFFFFFF) return SQFS_ERROR_OVERFLOW; ++index; blk_prev = blk; blk = blk->next; } if (blk != NULL) { for (i = 0; i < count; ++i) { value_idx = GET_VALUE(xwr->kv_pairs[xwr->kv_start + i]); str_table_del_ref(&xwr->values, value_idx); value_idx = GET_VALUE(xwr->kv_pairs[blk->start + i]); str_table_add_ref(&xwr->values, value_idx); } xwr->num_pairs = xwr->kv_start; } else { blk = calloc(1, sizeof(*blk)); if (blk == NULL) return SQFS_ERROR_ALLOC; blk->start = xwr->kv_start; blk->count = count; if (blk_prev == NULL) { xwr->kv_blocks = blk; } else { blk_prev->next = blk; } xwr->num_blocks += 1; } *out = index; return 0; } /*****************************************************************************/ static sqfs_s32 write_key(sqfs_meta_writer_t *mw, const char *key, bool value_is_ool) { sqfs_xattr_entry_t kent; int type, err; size_t len; type = sqfs_get_xattr_prefix_id(key); assert(type >= 0); key = strchr(key, '.'); assert(key != NULL); ++key; len = strlen(key); if (value_is_ool) type |= SQFS_XATTR_FLAG_OOL; memset(&kent, 0, sizeof(kent)); kent.type = htole16(type); kent.size = htole16(len); err = sqfs_meta_writer_append(mw, &kent, sizeof(kent)); if (err) return err; err = sqfs_meta_writer_append(mw, key, len); if (err) return err; return sizeof(kent) + len; } static sqfs_s32 write_value(sqfs_meta_writer_t *mw, const char *value_str, sqfs_u64 *value_ref_out) { sqfs_xattr_value_t vent; sqfs_u32 offset; sqfs_u64 block; size_t size; void *value; int err; value = from_base32(value_str, &size); if (value == NULL) return SQFS_ERROR_ALLOC; memset(&vent, 0, sizeof(vent)); vent.size = htole32(size); sqfs_meta_writer_get_position(mw, &block, &offset); *value_ref_out = (block << 16) | (offset & 0xFFFF); err = sqfs_meta_writer_append(mw, &vent, sizeof(vent)); if (err) goto fail; err = sqfs_meta_writer_append(mw, value, size); if (err) goto fail; free(value); return sizeof(vent) + size; fail: free(value); return err; } static sqfs_s32 write_value_ool(sqfs_meta_writer_t *mw, sqfs_u64 location) { sqfs_xattr_value_t vent; sqfs_u64 ref; int err; memset(&vent, 0, sizeof(vent)); vent.size = htole32(sizeof(location)); ref = htole64(location); err = sqfs_meta_writer_append(mw, &vent, sizeof(vent)); if (err) return err; err = sqfs_meta_writer_append(mw, &ref, sizeof(ref)); if (err) return err; return sizeof(vent) + sizeof(ref); } static bool should_store_ool(const char *val_str, size_t refcount) { if (refcount < 2) return false; /* Storing in line needs this many bytes: refcount * len Storing out-of-line needs this many: len + (refcount - 1) * 8 Out-of-line prefereable iff refcount > 1 and: refcount * len > len + (refcount - 1) * 8 => refcount * len - len > (refcount - 1) * 8 => (refcount - 1) * len > (refcount - 1) * 8 => len > 8 */ return (strlen(val_str) / 2) > sizeof(sqfs_u64); } static int write_block_pairs(sqfs_xattr_writer_t *xwr, sqfs_meta_writer_t *mw, kv_block_desc_t *blk, sqfs_u64 *ool_locations) { sqfs_u32 key_idx, val_idx; const char *key_str, *value_str; sqfs_s32 diff, total = 0; size_t i, refcount; sqfs_u64 ref; for (i = 0; i < blk->count; ++i) { key_idx = GET_KEY(xwr->kv_pairs[blk->start + i]); val_idx = GET_VALUE(xwr->kv_pairs[blk->start + i]); key_str = str_table_get_string(&xwr->keys, key_idx); value_str = str_table_get_string(&xwr->values, val_idx); if (ool_locations[val_idx] == 0xFFFFFFFFFFFFFFFFUL) { diff = write_key(mw, key_str, false); if (diff < 0) return diff; total += diff; diff = write_value(mw, value_str, &ref); if (diff < 0) return diff; total += diff; refcount = str_table_get_ref_count(&xwr->values, val_idx); if (should_store_ool(value_str, refcount)) ool_locations[val_idx] = ref; } else { diff = write_key(mw, key_str, true); if (diff < 0) return diff; total += diff; diff = write_value_ool(mw, ool_locations[val_idx]); if (diff < 0) return diff; total += diff; } } return total; } static int write_kv_pairs(sqfs_xattr_writer_t *xwr, sqfs_meta_writer_t *mw) { sqfs_u64 block, *ool_locations; kv_block_desc_t *blk; sqfs_u32 offset; sqfs_s32 size; size_t i; ool_locations = alloc_array(sizeof(ool_locations[0]), xwr->values.num_strings); if (ool_locations == NULL) return SQFS_ERROR_ALLOC; for (i = 0; i < xwr->values.num_strings; ++i) ool_locations[i] = 0xFFFFFFFFFFFFFFFFUL; for (blk = xwr->kv_blocks; blk != NULL; blk = blk->next) { sqfs_meta_writer_get_position(mw, &block, &offset); blk->start_ref = (block << 16) | (offset & 0xFFFF); size = write_block_pairs(xwr, mw, blk, ool_locations); if (size < 0) { free(ool_locations); return size; } blk->size_bytes = size; } free(ool_locations); return sqfs_meta_writer_flush(mw); } static int write_id_table(sqfs_xattr_writer_t *xwr, sqfs_meta_writer_t *mw, sqfs_u64 *locations) { sqfs_xattr_id_t id_ent; kv_block_desc_t *blk; sqfs_u32 offset; sqfs_u64 block; size_t i = 0; int err; locations[i++] = 0; for (blk = xwr->kv_blocks; blk != NULL; blk = blk->next) { memset(&id_ent, 0, sizeof(id_ent)); id_ent.xattr = htole64(blk->start_ref); id_ent.count = htole32(blk->count); id_ent.size = htole32(blk->size_bytes); err = sqfs_meta_writer_append(mw, &id_ent, sizeof(id_ent)); if (err) return err; sqfs_meta_writer_get_position(mw, &block, &offset); if (block != locations[i - 1]) locations[i++] = block; } return sqfs_meta_writer_flush(mw); } static int write_location_table(sqfs_xattr_writer_t *xwr, sqfs_u64 kv_start, sqfs_file_t *file, const sqfs_super_t *super, sqfs_u64 *locations, size_t loc_count) { sqfs_xattr_id_table_t idtbl; int err; memset(&idtbl, 0, sizeof(idtbl)); idtbl.xattr_table_start = htole64(kv_start); idtbl.xattr_ids = htole32(xwr->num_blocks); err = file->write_at(file, super->xattr_id_table_start, &idtbl, sizeof(idtbl)); if (err) return err; return file->write_at(file, super->xattr_id_table_start + sizeof(idtbl), locations, sizeof(locations[0]) * loc_count); } static int alloc_location_table(sqfs_xattr_writer_t *xwr, sqfs_u64 **tbl_out, size_t *szout) { sqfs_u64 *locations; size_t size, count; if (SZ_MUL_OV(xwr->num_blocks, sizeof(sqfs_xattr_id_t), &size)) return SQFS_ERROR_OVERFLOW; count = size / SQFS_META_BLOCK_SIZE; if (size % SQFS_META_BLOCK_SIZE) ++count; locations = alloc_array(sizeof(sqfs_u64), count); if (locations == NULL) return SQFS_ERROR_ALLOC; *tbl_out = locations; *szout = count; return 0; } int sqfs_xattr_writer_flush(sqfs_xattr_writer_t *xwr, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp) { sqfs_u64 *locations = NULL, kv_start, id_start; sqfs_meta_writer_t *mw; size_t i, count; int err; if (xwr->num_pairs == 0 || xwr->num_blocks == 0) { super->xattr_id_table_start = 0xFFFFFFFFFFFFFFFFUL; super->flags |= SQFS_FLAG_NO_XATTRS; return 0; } mw = sqfs_meta_writer_create(file, cmp, 0); if (mw == NULL) return SQFS_ERROR_ALLOC; kv_start = file->get_size(file); err = write_kv_pairs(xwr, mw); if (err) goto out; sqfs_meta_writer_reset(mw); id_start = file->get_size(file); err = alloc_location_table(xwr, &locations, &count); if (err) goto out; err = write_id_table(xwr, mw, locations); if (err) goto out; super->xattr_id_table_start = file->get_size(file); super->flags &= ~SQFS_FLAG_NO_XATTRS; for (i = 0; i < count; ++i) locations[i] = htole64(locations[i] + id_start); err = write_location_table(xwr, kv_start, file, super, locations, count); out: free(locations); sqfs_meta_writer_destroy(mw); return err; } squashfs-tools-ng-0.8/lib/tar/000077500000000000000000000000001360235375500163235ustar00rootroot00000000000000squashfs-tools-ng-0.8/lib/tar/Makemodule.am000066400000000000000000000010061360235375500207220ustar00rootroot00000000000000libtar_a_SOURCES = lib/tar/read_header.c lib/tar/write_header.c lib/tar/skip.c libtar_a_SOURCES += lib/tar/number.c lib/tar/checksum.c lib/tar/cleanup.c libtar_a_SOURCES += lib/tar/read_sparse_map.c lib/tar/read_sparse_map_old.c libtar_a_SOURCES += lib/tar/base64.c lib/tar/urldecode.c lib/tar/internal.h libtar_a_SOURCES += lib/tar/padd_file.c lib/tar/read_retry.c include/tar.h libtar_a_SOURCES += lib/tar/write_retry.c libtar_a_CFLAGS = $(AM_CFLAGS) libtar_a_CPPFLAGS = $(AM_CPPFLAGS) noinst_LIBRARIES += libtar.a squashfs-tools-ng-0.8/lib/tar/base64.c000066400000000000000000000020311360235375500175470ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * base64.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" static sqfs_u8 convert(char in) { if (isupper(in)) return in - 'A'; if (islower(in)) return in - 'a' + 26; if (isdigit(in)) return in - '0' + 52; if (in == '+') return 62; if (in == '/' || in == '-') return 63; return 0; } size_t base64_decode(sqfs_u8 *out, const char *in, size_t len) { sqfs_u8 *start = out; while (len > 0) { unsigned int diff = 0, value = 0; while (diff < 4 && len > 0) { if (*in == '=' || *in == '_' || *in == '\0') { len = 0; } else { value = (value << 6) | convert(*(in++)); --len; ++diff; } } if (diff < 2) break; value <<= 6 * (4 - diff); switch (diff) { case 4: out[2] = value & 0xff; /* fall-through */ case 3: out[1] = (value >> 8) & 0xff; /* fall-through */ default: out[0] = (value >> 16) & 0xff; } out += (diff * 3) / 4; } *out = '\0'; return out - start; } squashfs-tools-ng-0.8/lib/tar/checksum.c000066400000000000000000000022111360235375500202650ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * checksum.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" static unsigned int get_checksum(const tar_header_t *hdr) { const unsigned char *header_start = (const unsigned char *)hdr; const unsigned char *chksum_start = (const unsigned char *)hdr->chksum; const unsigned char *header_end = header_start + sizeof(*hdr); const unsigned char *chksum_end = chksum_start + sizeof(hdr->chksum); const unsigned char *p; unsigned int chksum = 0; for (p = header_start; p < chksum_start; p++) chksum += *p; for (; p < chksum_end; p++) chksum += ' '; for (; p < header_end; p++) chksum += *p; return chksum; } void update_checksum(tar_header_t *hdr) { unsigned int chksum = get_checksum(hdr); sprintf(hdr->chksum, "%06o", chksum); hdr->chksum[6] = '\0'; hdr->chksum[7] = ' '; } bool is_checksum_valid(const tar_header_t *hdr) { unsigned int calculated_chksum = get_checksum(hdr); sqfs_u64 read_chksum; if (read_octal(hdr->chksum, sizeof(hdr->chksum), &read_chksum)) return 0; return read_chksum == calculated_chksum; } squashfs-tools-ng-0.8/lib/tar/cleanup.c000066400000000000000000000012221360235375500201130ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * cleanup.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" void free_sparse_list(sparse_map_t *sparse) { sparse_map_t *old; while (sparse != NULL) { old = sparse; sparse = sparse->next; free(old); } } void free_xattr_list(tar_xattr_t *list) { tar_xattr_t *old; while (list != NULL) { old = list; list = list->next; free(old); } } void clear_header(tar_header_decoded_t *hdr) { free_xattr_list(hdr->xattr); free_sparse_list(hdr->sparse); free(hdr->name); free(hdr->link_target); memset(hdr, 0, sizeof(*hdr)); } squashfs-tools-ng-0.8/lib/tar/internal.h000066400000000000000000000024531360235375500203140ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * internal.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef INTERNAL_H #define INTERNAL_H #include "config.h" #include "tar.h" #include #include #include #include enum { PAX_SIZE = 0x001, PAX_UID = 0x002, PAX_GID = 0x004, PAX_DEV_MAJ = 0x008, PAX_DEV_MIN = 0x010, PAX_NAME = 0x020, PAX_SLINK_TARGET = 0x040, PAX_MTIME = 0x100, PAX_SPARSE_SIZE = 0x400, }; enum { ETV_UNKNOWN = 0, ETV_V7_UNIX, ETV_PRE_POSIX, ETV_POSIX, }; #define TAR_MAX_SYMLINK_LEN (65536) #define TAR_MAX_PATH_LEN (65536) #define TAR_MAX_PAX_LEN (65536) int read_octal(const char *str, int digits, sqfs_u64 *out); int read_binary(const char *str, int digits, sqfs_u64 *out); int read_number(const char *str, int digits, sqfs_u64 *out); int pax_read_decimal(const char *str, sqfs_u64 *out); void update_checksum(tar_header_t *hdr); bool is_checksum_valid(const tar_header_t *hdr); sparse_map_t *read_sparse_map(const char *line); sparse_map_t *read_gnu_old_sparse(FILE *fp, tar_header_t *hdr); void free_sparse_list(sparse_map_t *sparse); void free_xattr_list(tar_xattr_t *list); size_t base64_decode(sqfs_u8 *out, const char *in, size_t len); void urldecode(char *str); #endif /* INTERNAL_H */ squashfs-tools-ng-0.8/lib/tar/number.c000066400000000000000000000032201360235375500177540ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * number.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" int read_octal(const char *str, int digits, sqfs_u64 *out) { sqfs_u64 result = 0; while (digits > 0 && isspace(*str)) { ++str; --digits; } while (digits > 0 && *str >= '0' && *str <= '7') { if (result > 0x1FFFFFFFFFFFFFFFUL) { fputs("numeric overflow parsing tar header\n", stderr); return -1; } result = (result << 3) | (*(str++) - '0'); --digits; } *out = result; return 0; } int read_binary(const char *str, int digits, sqfs_u64 *out) { sqfs_u64 x, ov, result = 0; bool first = true; while (digits > 0) { x = *((const unsigned char *)str++); --digits; if (first) { first = false; if (x == 0xFF) { result = 0xFFFFFFFFFFFFFFFFUL; } else { x &= 0x7F; result = 0; if (digits > 7 && x != 0) goto fail_ov; } } ov = (result >> 56) & 0xFF; if (ov != 0 && ov != 0xFF) goto fail_ov; result = (result << 8) | x; } *out = result; return 0; fail_ov: fputs("numeric overflow parsing tar header\n", stderr); return -1; } int read_number(const char *str, int digits, sqfs_u64 *out) { if (*((unsigned char *)str) & 0x80) return read_binary(str, digits, out); return read_octal(str, digits, out); } int pax_read_decimal(const char *str, sqfs_u64 *out) { sqfs_u64 result = 0; while (*str >= '0' && *str <= '9') { if (result > 0xFFFFFFFFFFFFFFFFUL / 10) { fputs("numeric overflow parsing pax header\n", stderr); return -1; } result = (result * 10) + (*(str++) - '0'); } *out = result; return 0; } squashfs-tools-ng-0.8/lib/tar/padd_file.c000066400000000000000000000012671360235375500204040ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * padd_file.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include int padd_file(FILE *fp, sqfs_u64 size) { size_t padd_sz = size % TAR_RECORD_SIZE; int status = -1; sqfs_u8 *buffer; if (padd_sz == 0) return 0; padd_sz = TAR_RECORD_SIZE - padd_sz; buffer = calloc(1, padd_sz); if (buffer == NULL) goto fail_errno; if (write_retry("padding output file to block size", fp, buffer, padd_sz)) { goto out; } status = 0; out: free(buffer); return status; fail_errno: perror("padding output file to block size"); goto out; } squashfs-tools-ng-0.8/lib/tar/read_header.c000066400000000000000000000267141360235375500207240ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * read_header.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" static bool is_zero_block(const tar_header_t *hdr) { const unsigned char *ptr = (const unsigned char *)hdr; return ptr[0] == '\0' && memcmp(ptr, ptr + 1, sizeof(*hdr) - 1) == 0; } static int check_version(const tar_header_t *hdr) { char buffer[sizeof(hdr->magic) + sizeof(hdr->version)]; memset(buffer, '\0', sizeof(buffer)); if (memcmp(hdr->magic, buffer, sizeof(hdr->magic)) == 0 && memcmp(hdr->version, buffer, sizeof(hdr->version)) == 0) return ETV_V7_UNIX; if (memcmp(hdr->magic, TAR_MAGIC, sizeof(hdr->magic)) == 0 && memcmp(hdr->version, TAR_VERSION, sizeof(hdr->version)) == 0) return ETV_POSIX; if (memcmp(hdr->magic, TAR_MAGIC_OLD, sizeof(hdr->magic)) == 0 && memcmp(hdr->version, TAR_VERSION_OLD, sizeof(hdr->version)) == 0) return ETV_PRE_POSIX; return ETV_UNKNOWN; } static char *record_to_memory(FILE *fp, sqfs_u64 size) { char *buffer = malloc(size + 1); if (buffer == NULL) goto fail_errno; if (read_retry("reading tar record", fp, buffer, size)) goto fail; if (skip_padding(fp, size)) goto fail; buffer[size] = '\0'; return buffer; fail_errno: perror("reading tar record"); goto fail; fail: free(buffer); return NULL; } static tar_xattr_t *mkxattr(const char *key, size_t keylen, const char *value, size_t valuelen) { tar_xattr_t *xattr; xattr = calloc(1, sizeof(*xattr) + keylen + 1 + valuelen + 1); if (xattr == NULL) return NULL; xattr->key = xattr->data; xattr->value = (sqfs_u8 *)xattr->data + keylen + 1; xattr->value_len = valuelen; memcpy(xattr->key, key, keylen); memcpy(xattr->value, value, valuelen); return xattr; } static int read_pax_header(FILE *fp, sqfs_u64 entsize, unsigned int *set_by_pax, tar_header_decoded_t *out) { sparse_map_t *sparse_last = NULL, *sparse; sqfs_u64 field, offset = 0, num_bytes = 0; char *buffer, *line, *key, *ptr, *value; sqfs_u64 i, start, len; tar_xattr_t *xattr; int digit; buffer = record_to_memory(fp, entsize); if (buffer == NULL) return -1; for (i = 0; i < entsize; i += len) { start = i; if (!isdigit(buffer[i])) goto fail_malformed; for (len = 0; i < entsize && isdigit(buffer[i]); ++i) { digit = buffer[i] - '0'; if (len > (entsize - digit) / 10) goto fail_ov; len = len * 10 + digit; } if (!isspace(buffer[i])) goto fail_malformed; while (i < entsize && isspace(buffer[i])) ++i; if (i >= entsize || (i - start) >= len) goto fail_ov; len -= i - start; if (i + len > entsize) goto fail_ov; line = buffer + i; line[len - 1] = '\0'; if (!strncmp(line, "uid=", 4)) { if (pax_read_decimal(line + 4, &field)) goto fail; out->sb.st_uid = field; *set_by_pax |= PAX_UID; } else if (!strncmp(line, "gid=", 4)) { if (pax_read_decimal(line + 4, &field)) goto fail; out->sb.st_gid = field; *set_by_pax |= PAX_GID; } else if (!strncmp(line, "path=", 5)) { free(out->name); out->name = strdup(line + 5); if (out->name == NULL) goto fail_errno; *set_by_pax |= PAX_NAME; } else if (!strncmp(line, "size=", 5)) { if (pax_read_decimal(line + 5, &out->record_size)) goto fail; *set_by_pax |= PAX_SIZE; } else if (!strncmp(line, "linkpath=", 9)) { free(out->link_target); out->link_target = strdup(line + 9); if (out->link_target == NULL) goto fail_errno; *set_by_pax |= PAX_SLINK_TARGET; } else if (!strncmp(line, "mtime=", 6)) { if (line[6] == '-') { if (pax_read_decimal(line + 7, &field)) goto fail; out->mtime = -((sqfs_s64)field); } else { if (pax_read_decimal(line + 6, &field)) goto fail; out->mtime = field; } *set_by_pax |= PAX_MTIME; } else if (!strncmp(line, "GNU.sparse.name=", 16)) { free(out->name); out->name = strdup(line + 16); if (out->name == NULL) goto fail_errno; *set_by_pax |= PAX_NAME; } else if (!strncmp(line, "GNU.sparse.map=", 15)) { free_sparse_list(out->sparse); sparse_last = NULL; out->sparse = read_sparse_map(line + 15); if (out->sparse == NULL) goto fail; } else if (!strncmp(line, "GNU.sparse.size=", 16)) { if (pax_read_decimal(line + 16, &out->actual_size)) goto fail; *set_by_pax |= PAX_SPARSE_SIZE; } else if (!strncmp(line, "GNU.sparse.offset=", 18)) { if (pax_read_decimal(line + 18, &offset)) goto fail; } else if (!strncmp(line, "GNU.sparse.numbytes=", 20)) { if (pax_read_decimal(line + 20, &num_bytes)) goto fail; sparse = calloc(1, sizeof(*sparse)); if (sparse == NULL) goto fail_errno; sparse->offset = offset; sparse->count = num_bytes; if (sparse_last == NULL) { free_sparse_list(out->sparse); out->sparse = sparse_last = sparse; } else { sparse_last->next = sparse; sparse_last = sparse; } } else if (!strncmp(line, "SCHILY.xattr.", 13)) { key = line + 13; ptr = strrchr(key, '='); if (ptr == NULL || ptr == key) continue; value = ptr + 1; xattr = mkxattr(key, ptr - key, value, len - (value - line) - 1); if (xattr == NULL) goto fail_errno; xattr->next = out->xattr; out->xattr = xattr; } else if (!strncmp(line, "LIBARCHIVE.xattr.", 17)) { key = line + 17; ptr = strrchr(key, '='); if (ptr == NULL || ptr == key) continue; value = ptr + 1; xattr = mkxattr(key, ptr - key, value, strlen(value)); if (xattr == NULL) goto fail_errno; urldecode(xattr->key); xattr->value_len = base64_decode(xattr->value, value, xattr->value_len); xattr->next = out->xattr; out->xattr = xattr; } } free(buffer); return 0; fail_malformed: fputs("Found a malformed PAX header.\n", stderr); goto fail; fail_ov: fputs("Numeric overflow in PAX header.\n", stderr); goto fail; fail_errno: perror("reading pax header"); goto fail; fail: free(buffer); return -1; } static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax, tar_header_decoded_t *out, int version) { size_t len1, len2; sqfs_u64 field; if (!(set_by_pax & PAX_NAME)) { if (hdr->tail.posix.prefix[0] != '\0' && version == ETV_POSIX) { len1 = strnlen(hdr->name, sizeof(hdr->name)); len2 = strnlen(hdr->tail.posix.prefix, sizeof(hdr->tail.posix.prefix)); out->name = malloc(len1 + 1 + len2 + 1); if (out->name != NULL) { memcpy(out->name, hdr->tail.posix.prefix, len2); out->name[len2] = '/'; memcpy(out->name + len2 + 1, hdr->name, len1); out->name[len1 + 1 + len2] = '\0'; } } else { out->name = strndup(hdr->name, sizeof(hdr->name)); } if (out->name == NULL) { perror("decoding filename"); return -1; } } if (!(set_by_pax & PAX_SIZE)) { if (read_number(hdr->size, sizeof(hdr->size), &out->record_size)) return -1; } if (!(set_by_pax & PAX_UID)) { if (read_number(hdr->uid, sizeof(hdr->uid), &field)) return -1; out->sb.st_uid = field; } if (!(set_by_pax & PAX_GID)) { if (read_number(hdr->gid, sizeof(hdr->gid), &field)) return -1; out->sb.st_gid = field; } if (!(set_by_pax & PAX_DEV_MAJ)) { if (read_number(hdr->devmajor, sizeof(hdr->devmajor), &field)) return -1; out->sb.st_rdev = makedev(field, minor(out->sb.st_rdev)); } if (!(set_by_pax & PAX_DEV_MIN)) { if (read_number(hdr->devminor, sizeof(hdr->devminor), &field)) return -1; out->sb.st_rdev = makedev(major(out->sb.st_rdev), field); } if (!(set_by_pax & PAX_MTIME)) { if (read_number(hdr->mtime, sizeof(hdr->mtime), &field)) return -1; if (field & 0x8000000000000000UL) { field = ~field + 1; out->mtime = -((sqfs_s64)field); } else { out->mtime = field; } } if (read_octal(hdr->mode, sizeof(hdr->mode), &field)) return -1; out->sb.st_mode = field & 07777; if (hdr->typeflag == TAR_TYPE_LINK || hdr->typeflag == TAR_TYPE_SLINK) { if (!(set_by_pax & PAX_SLINK_TARGET)) { out->link_target = strdup(hdr->linkname); if (out->link_target == NULL) { perror("decoding symlink target"); return -1; } } } out->unknown_record = false; switch (hdr->typeflag) { case '\0': case TAR_TYPE_FILE: case TAR_TYPE_GNU_SPARSE: out->sb.st_mode |= S_IFREG; break; case TAR_TYPE_LINK: out->is_hard_link = true; break; case TAR_TYPE_SLINK: out->sb.st_mode = S_IFLNK | 0777; break; case TAR_TYPE_CHARDEV: out->sb.st_mode |= S_IFCHR; break; case TAR_TYPE_BLOCKDEV: out->sb.st_mode |= S_IFBLK; break; case TAR_TYPE_DIR: out->sb.st_mode |= S_IFDIR; break; case TAR_TYPE_FIFO: out->sb.st_mode |= S_IFIFO; break; default: out->unknown_record = true; break; } #if SIZEOF_TIME_T < 8 if (out->mtime > (sqfs_s64)INT32_MAX) { out->sb.st_mtime = INT32_MAX; } else if (out->mtime < (sqfs_s64)INT32_MIN) { out->sb.st_mtime = INT32_MIN; } else { out->sb.st_mtime = out->mtime; } #else out->sb.st_mtime = out->mtime; #endif return 0; } int read_header(FILE *fp, tar_header_decoded_t *out) { unsigned int set_by_pax = 0; bool prev_was_zero = false; sqfs_u64 pax_size; tar_header_t hdr; int version; memset(out, 0, sizeof(*out)); for (;;) { if (read_retry("reading tar header", fp, &hdr, sizeof(hdr))) goto fail; if (is_zero_block(&hdr)) { if (prev_was_zero) goto out_eof; prev_was_zero = true; continue; } prev_was_zero = false; version = check_version(&hdr); if (version == ETV_UNKNOWN) goto fail_magic; if (!is_checksum_valid(&hdr)) goto fail_chksum; switch (hdr.typeflag) { case TAR_TYPE_GNU_SLINK: if (read_number(hdr.size, sizeof(hdr.size), &pax_size)) goto fail; if (pax_size < 1 || pax_size > TAR_MAX_SYMLINK_LEN) goto fail_slink_len; free(out->link_target); out->link_target = record_to_memory(fp, pax_size); if (out->link_target == NULL) goto fail; set_by_pax |= PAX_SLINK_TARGET; continue; case TAR_TYPE_GNU_PATH: if (read_number(hdr.size, sizeof(hdr.size), &pax_size)) goto fail; if (pax_size < 1 || pax_size > TAR_MAX_PATH_LEN) goto fail_path_len; free(out->name); out->name = record_to_memory(fp, pax_size); if (out->name == NULL) goto fail; set_by_pax |= PAX_NAME; continue; case TAR_TYPE_PAX: clear_header(out); if (read_number(hdr.size, sizeof(hdr.size), &pax_size)) goto fail; if (pax_size < 1 || pax_size > TAR_MAX_PAX_LEN) goto fail_pax_len; set_by_pax = 0; if (read_pax_header(fp, pax_size, &set_by_pax, out)) goto fail; continue; case TAR_TYPE_GNU_SPARSE: free_sparse_list(out->sparse); out->sparse = read_gnu_old_sparse(fp, &hdr); if (out->sparse == NULL) goto fail; if (read_number(hdr.tail.gnu.realsize, sizeof(hdr.tail.gnu.realsize), &out->actual_size)) goto fail; break; } break; } if (decode_header(&hdr, set_by_pax, out, version)) goto fail; if (out->sparse != NULL) { out->sb.st_size = out->actual_size; } else { out->sb.st_size = out->record_size; out->actual_size = out->record_size; } return 0; out_eof: clear_header(out); return 1; fail_slink_len: fprintf(stderr, "rejecting GNU symlink header with size %lu\n", (unsigned long)pax_size); goto fail; fail_path_len: fprintf(stderr, "rejecting GNU long path header with size %lu\n", (unsigned long)pax_size); goto fail; fail_pax_len: fprintf(stderr, "rejecting PAX header with size %lu\n", (unsigned long)pax_size); goto fail; fail_magic: fputs("input is not a ustar tar archive!\n", stderr); goto fail; fail_chksum: fputs("invalid tar header checksum!\n", stderr); goto fail; fail: clear_header(out); return -1; } squashfs-tools-ng-0.8/lib/tar/read_retry.c000066400000000000000000000011471360235375500206320ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * read_retry.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include #include #include "tar.h" int read_retry(const char *errstr, FILE *fp, void *buffer, size_t size) { size_t ret; while (size > 0) { if (ferror(fp)) { fprintf(stderr, "%s: error reading from file\n", errstr); return -1; } if (feof(fp)) { fprintf(stderr, "%s: short read\n", errstr); return -1; } ret = fread(buffer, 1, size, fp); size -= ret; buffer = (char *)buffer + ret; } return 0; } squashfs-tools-ng-0.8/lib/tar/read_sparse_map.c000066400000000000000000000017201360235375500216140ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * read_sparse_map.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" sparse_map_t *read_sparse_map(const char *line) { sparse_map_t *last = NULL, *list = NULL, *ent = NULL; do { ent = calloc(1, sizeof(*ent)); if (ent == NULL) goto fail_errno; if (pax_read_decimal(line, &ent->offset)) goto fail_format; while (isdigit(*line)) ++line; if (*(line++) != ',') goto fail_format; if (pax_read_decimal(line, &ent->count)) goto fail_format; while (isdigit(*line)) ++line; if (last == NULL) { list = last = ent; } else { last->next = ent; last = ent; } } while (*(line++) == ','); return list; fail_errno: perror("parsing GNU pax sparse file record"); goto fail; fail_format: fputs("malformed GNU pax sparse file record\n", stderr); goto fail; fail: free_sparse_list(list); free(ent); return NULL; } squashfs-tools-ng-0.8/lib/tar/read_sparse_map_old.c000066400000000000000000000035021360235375500224520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * read_sparse_map_old.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" sparse_map_t *read_gnu_old_sparse(FILE *fp, tar_header_t *hdr) { sparse_map_t *list = NULL, *end = NULL, *node; gnu_sparse_t sph; sqfs_u64 off, sz; int i; for (i = 0; i < 4; ++i) { if (!isdigit(hdr->tail.gnu.sparse[i].offset[0])) break; if (!isdigit(hdr->tail.gnu.sparse[i].numbytes[0])) break; if (read_octal(hdr->tail.gnu.sparse[i].offset, sizeof(hdr->tail.gnu.sparse[i].offset), &off)) goto fail; if (read_octal(hdr->tail.gnu.sparse[i].numbytes, sizeof(hdr->tail.gnu.sparse[i].numbytes), &sz)) goto fail; node = calloc(1, sizeof(*node)); if (node == NULL) goto fail_errno; node->offset = off; node->count = sz; if (list == NULL) { list = end = node; } else { end->next = node; end = node; } } if (hdr->tail.gnu.isextended == 0) return list; do { if (read_retry("reading GNU sparse header", fp, &sph, sizeof(sph))) { goto fail; } for (i = 0; i < 21; ++i) { if (!isdigit(sph.sparse[i].offset[0])) break; if (!isdigit(sph.sparse[i].numbytes[0])) break; if (read_octal(sph.sparse[i].offset, sizeof(sph.sparse[i].offset), &off)) goto fail; if (read_octal(sph.sparse[i].numbytes, sizeof(sph.sparse[i].numbytes), &sz)) goto fail; node = calloc(1, sizeof(*node)); if (node == NULL) goto fail_errno; node->offset = off; node->count = sz; if (list == NULL) { list = end = node; } else { end->next = node; end = node; } } } while (sph.isextended != 0); return list; fail_errno: perror("parsing GNU sparse header"); goto fail; fail: free_sparse_list(list); return NULL; } squashfs-tools-ng-0.8/lib/tar/skip.c000066400000000000000000000013371360235375500174410ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * skip.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include static int skip_bytes(FILE *fp, sqfs_u64 size) { unsigned char buffer[1024]; size_t diff; while (size != 0) { diff = sizeof(buffer); if (diff > size) diff = size; if (read_retry("reading tar record padding", fp, buffer, diff)) return -1; size -= diff; } return 0; } int skip_padding(FILE *fp, sqfs_u64 size) { size_t tail = size % 512; return tail ? skip_bytes(fp, 512 - tail) : 0; } int skip_entry(FILE *fp, sqfs_u64 size) { size_t tail = size % 512; return skip_bytes(fp, tail ? (size + 512 - tail) : size); } squashfs-tools-ng-0.8/lib/tar/urldecode.c000066400000000000000000000011311360235375500204310ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * urldecode.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" static int xdigit(int x) { if (isupper(x)) return x - 'A' + 0x0A; if (islower(x)) return x - 'a' + 0x0A; return x - '0'; } void urldecode(char *str) { unsigned char *out = (unsigned char *)str; char *in = str; int x; while (*in != '\0') { x = *(in++); if (x == '%' && isxdigit(in[0]) && isxdigit(in[1])) { x = xdigit(*(in++)) << 4; x |= xdigit(*(in++)); } *(out++) = x; } *out = '\0'; } squashfs-tools-ng-0.8/lib/tar/write_header.c000066400000000000000000000147251360235375500211420ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * write_header.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "internal.h" static void write_binary(char *dst, sqfs_u64 value, int digits) { memset(dst, 0, digits); while (digits > 0) { ((unsigned char *)dst)[digits - 1] = value & 0xFF; --digits; value >>= 8; } ((unsigned char *)dst)[0] |= 0x80; } static void write_number(char *dst, sqfs_u64 value, int digits) { sqfs_u64 mask = 0; char buffer[64]; int i; for (i = 0; i < (digits - 1); ++i) mask = (mask << 3) | 7; if (value <= mask) { sprintf(buffer, "%0*o ", digits - 1, (unsigned int)value); memcpy(dst, buffer, digits); } else if (value <= ((mask << 3) | 7)) { sprintf(buffer, "%0*o", digits, (unsigned int)value); memcpy(dst, buffer, digits); } else { write_binary(dst, value, digits); } } static void write_number_signed(char *dst, sqfs_s64 value, int digits) { sqfs_u64 neg; if (value < 0) { neg = -value; write_binary(dst, ~neg + 1, digits); } else { write_number(dst, value, digits); } } static int write_header(FILE *fp, const struct stat *sb, const char *name, const char *slink_target, int type) { int maj = 0, min = 0; sqfs_u64 size = 0; tar_header_t hdr; if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode)) { maj = major(sb->st_rdev); min = minor(sb->st_rdev); } if (S_ISREG(sb->st_mode)) size = sb->st_size; memset(&hdr, 0, sizeof(hdr)); strncpy(hdr.name, name, sizeof(hdr.name) - 1); write_number(hdr.mode, sb->st_mode & ~S_IFMT, sizeof(hdr.mode)); write_number(hdr.uid, sb->st_uid, sizeof(hdr.uid)); write_number(hdr.gid, sb->st_gid, sizeof(hdr.gid)); write_number(hdr.size, size, sizeof(hdr.size)); write_number_signed(hdr.mtime, sb->st_mtime, sizeof(hdr.mtime)); hdr.typeflag = type; if (slink_target != NULL) memcpy(hdr.linkname, slink_target, sb->st_size); memcpy(hdr.magic, TAR_MAGIC_OLD, sizeof(hdr.magic)); memcpy(hdr.version, TAR_VERSION_OLD, sizeof(hdr.version)); sprintf(hdr.uname, "%u", sb->st_uid); sprintf(hdr.gname, "%u", sb->st_gid); write_number(hdr.devmajor, maj, sizeof(hdr.devmajor)); write_number(hdr.devminor, min, sizeof(hdr.devminor)); update_checksum(&hdr); return write_retry("writing tar header record", fp, &hdr, sizeof(hdr)); } static int write_gnu_header(FILE *fp, const struct stat *orig, const char *payload, size_t payload_len, int type, const char *name) { struct stat sb; sb = *orig; sb.st_mode = S_IFREG | 0644; sb.st_size = payload_len; if (write_header(fp, &sb, name, NULL, type)) return -1; if (write_retry("writing GNU extension header", fp, payload, payload_len)) { return -1; } return padd_file(fp, payload_len); } static size_t num_digits(size_t num) { size_t i = 1; while (num > 10) { num /= 10; ++i; } return i; } static int write_schily_xattr(FILE *fp, const struct stat *orig, const char *name, const tar_xattr_t *xattr) { static const char *prefix = "SCHILY.xattr."; size_t len, total_size = 0; const tar_xattr_t *it; struct stat sb; for (it = xattr; it != NULL; it = it->next) { len = strlen(prefix) + strlen(it->key) + it->value_len + 2; total_size += num_digits(len) + 1 + len; } sb = *orig; sb.st_mode = S_IFREG | 0644; sb.st_size = total_size; if (write_header(fp, &sb, name, NULL, TAR_TYPE_PAX)) return -1; for (it = xattr; it != NULL; it = it->next) { len = strlen(prefix) + strlen(it->key) + it->value_len + 2; len += num_digits(len) + 1; fprintf(fp, PRI_SZ " %s%s=", len, prefix, it->key); fwrite(it->value, 1, it->value_len, fp); fputc('\n', fp); } return padd_file(fp, total_size); } int write_tar_header(FILE *fp, const struct stat *sb, const char *name, const char *slink_target, const tar_xattr_t *xattr, unsigned int counter) { const char *reason; char buffer[64]; int type; if (xattr != NULL) { sprintf(buffer, "pax/xattr%u", counter); if (write_schily_xattr(fp, sb, buffer, xattr)) return -1; } if (!S_ISLNK(sb->st_mode)) slink_target = NULL; if (S_ISLNK(sb->st_mode) && sb->st_size >= 100) { sprintf(buffer, "gnu/target%u", counter); if (write_gnu_header(fp, sb, slink_target, sb->st_size, TAR_TYPE_GNU_SLINK, buffer)) return -1; slink_target = NULL; } if (strlen(name) >= 100) { sprintf(buffer, "gnu/name%u", counter); if (write_gnu_header(fp, sb, name, strlen(name), TAR_TYPE_GNU_PATH, buffer)) { return -1; } sprintf(buffer, "gnu/data%u", counter); name = buffer; } switch (sb->st_mode & S_IFMT) { case S_IFCHR: type = TAR_TYPE_CHARDEV; break; case S_IFBLK: type = TAR_TYPE_BLOCKDEV; break; case S_IFLNK: type = TAR_TYPE_SLINK; break; case S_IFREG: type = TAR_TYPE_FILE; break; case S_IFDIR: type = TAR_TYPE_DIR; break; case S_IFIFO: type = TAR_TYPE_FIFO; break; case S_IFSOCK: reason = "cannot pack socket"; goto out_skip; default: reason = "unknown type"; goto out_skip; } return write_header(fp, sb, name, slink_target, type); out_skip: fprintf(stderr, "WARNING: %s: %s\n", name, reason); return 1; } int write_hard_link(FILE *fp, const struct stat *sb, const char *name, const char *target, unsigned int counter) { tar_header_t hdr; char buffer[64]; size_t len; memset(&hdr, 0, sizeof(hdr)); len = strlen(target); if (len >= 100) { sprintf(buffer, "gnu/target%u", counter); if (write_gnu_header(fp, sb, target, len, TAR_TYPE_GNU_SLINK, buffer)) return -1; sprintf(hdr.linkname, "hardlink_%u", counter); } else { memcpy(hdr.linkname, target, len); } len = strlen(name); if (len >= 100) { sprintf(buffer, "gnu/name%u", counter); if (write_gnu_header(fp, sb, name, len, TAR_TYPE_GNU_PATH, buffer)) { return -1; } sprintf(hdr.name, "gnu/data%u", counter); } else { memcpy(hdr.name, name, len); } write_number(hdr.mode, sb->st_mode & ~S_IFMT, sizeof(hdr.mode)); write_number(hdr.uid, sb->st_uid, sizeof(hdr.uid)); write_number(hdr.gid, sb->st_gid, sizeof(hdr.gid)); write_number(hdr.size, 0, sizeof(hdr.size)); write_number_signed(hdr.mtime, sb->st_mtime, sizeof(hdr.mtime)); hdr.typeflag = TAR_TYPE_LINK; memcpy(hdr.magic, TAR_MAGIC_OLD, sizeof(hdr.magic)); memcpy(hdr.version, TAR_VERSION_OLD, sizeof(hdr.version)); sprintf(hdr.uname, "%u", sb->st_uid); sprintf(hdr.gname, "%u", sb->st_gid); write_number(hdr.devmajor, 0, sizeof(hdr.devmajor)); write_number(hdr.devminor, 0, sizeof(hdr.devminor)); update_checksum(&hdr); return write_retry("writing tar hard link record", fp, &hdr, sizeof(hdr)); } squashfs-tools-ng-0.8/lib/tar/write_retry.c000066400000000000000000000011561360235375500210510ustar00rootroot00000000000000/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * write_retry.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include #include #include "tar.h" int write_retry(const char *errstr, FILE *fp, const void *data, size_t size) { size_t ret; while (size > 0) { if (feof(fp)) { fprintf(stderr, "%s: write truncated\n", errstr); return -1; } if (ferror(fp)) { fprintf(stderr, "%s: error writing to file\n", errstr); return -1; } ret = fwrite(data, 1, size, fp); data = (const char *)data + ret; size -= ret; } return 0; } squashfs-tools-ng-0.8/licenses/000077500000000000000000000000001360235375500165745ustar00rootroot00000000000000squashfs-tools-ng-0.8/licenses/GPLv2.txt000066400000000000000000000432541360235375500202370ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 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. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. squashfs-tools-ng-0.8/licenses/GPLv3.txt000066400000000000000000001045151360235375500202360ustar00rootroot00000000000000 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. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 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: Copyright (C) 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 . squashfs-tools-ng-0.8/licenses/LGPLv3.txt000066400000000000000000000167441360235375500203600ustar00rootroot00000000000000 GNU LESSER 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. 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. squashfs-tools-ng-0.8/licenses/LZ4.txt000066400000000000000000000024371360235375500177540ustar00rootroot00000000000000LZ4 Library Copyright (c) 2011-2016, Yann Collet All rights reserved. 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 HOLDER 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. squashfs-tools-ng-0.8/licenses/xz.txt000066400000000000000000000014001360235375500177710ustar00rootroot00000000000000liblzma is in the public domain. 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 . squashfs-tools-ng-0.8/licenses/zlib.txt000066400000000000000000000017271360235375500203040ustar00rootroot00000000000000 (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 squashfs-tools-ng-0.8/licenses/zstd.txt000066400000000000000000000027251360235375500203270ustar00rootroot00000000000000Copyright (c) 2016-present, Facebook, Inc. All rights reserved. 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. * Neither the name Facebook 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 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 HOLDER 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. squashfs-tools-ng-0.8/m4/000077500000000000000000000000001360235375500153075ustar00rootroot00000000000000squashfs-tools-ng-0.8/m4/ax_compile_check_sizeof.m4000066400000000000000000000103421360235375500224050ustar00rootroot00000000000000# ============================================================================ # https://www.gnu.org/software/autoconf-archive/ax_compile_check_sizeof.html # ============================================================================ # # SYNOPSIS # # AX_COMPILE_CHECK_SIZEOF(TYPE [, HEADERS [, EXTRA_SIZES...]]) # # DESCRIPTION # # This macro checks for the size of TYPE using compile checks, not run # checks. You can supply extra HEADERS to look into. the check will cycle # through 1 2 4 8 16 and any EXTRA_SIZES the user supplies. If a match is # found, it will #define SIZEOF_`TYPE' to that value. Otherwise it will # emit a configure time error indicating the size of the type could not be # determined. # # The trick is that C will not allow duplicate case labels. While this is # valid C code: # # switch (0) case 0: case 1:; # # The following is not: # # switch (0) case 0: case 0:; # # Thus, the AC_COMPILE_IFELSE will fail if the currently tried size does # not match. # # Here is an example skeleton configure.in script, demonstrating the # macro's usage: # # AC_PROG_CC # AC_CHECK_HEADERS(stddef.h unistd.h) # AC_TYPE_SIZE_T # AC_CHECK_TYPE(ssize_t, int) # # headers='#ifdef HAVE_STDDEF_H # #include # #endif # #ifdef HAVE_UNISTD_H # #include # #endif # ' # # AX_COMPILE_CHECK_SIZEOF(char) # AX_COMPILE_CHECK_SIZEOF(short) # AX_COMPILE_CHECK_SIZEOF(int) # AX_COMPILE_CHECK_SIZEOF(long) # AX_COMPILE_CHECK_SIZEOF(unsigned char *) # AX_COMPILE_CHECK_SIZEOF(void *) # AX_COMPILE_CHECK_SIZEOF(size_t, $headers) # AX_COMPILE_CHECK_SIZEOF(ssize_t, $headers) # AX_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers) # AX_COMPILE_CHECK_SIZEOF(off_t, $headers) # # LICENSE # # Copyright (c) 2008 Kaveh Ghazi # Copyright (c) 2017 Reini Urban # # This program is free software: you can 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 8 AU_ALIAS([AC_COMPILE_CHECK_SIZEOF], [AX_COMPILE_CHECK_SIZEOF]) AC_DEFUN([AX_COMPILE_CHECK_SIZEOF], [changequote(<<, >>)dnl dnl The name to #define. define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl dnl The cache variable name. define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl changequote([, ])dnl AC_MSG_CHECKING(size of $1) AC_CACHE_VAL(AC_CV_NAME, [for ac_size in 4 8 1 2 16 $3 ; do # List sizes in rough order of prevalence. AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include $2 ]], [[switch (0) case 0: case (sizeof ($1) == $ac_size):;]])], [AC_CV_NAME=$ac_size]) if test x$AC_CV_NAME != x ; then break; fi done ]) if test x$AC_CV_NAME = x ; then AC_MSG_ERROR([cannot determine a size for $1]) fi AC_MSG_RESULT($AC_CV_NAME) AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) undefine([AC_TYPE_NAME])dnl undefine([AC_CV_NAME])dnl ]) squashfs-tools-ng-0.8/m4/ax_prog_doxygen.m4000066400000000000000000000500221360235375500207440ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html # =========================================================================== # # SYNOPSIS # # DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...) # DX_DOXYGEN_FEATURE(ON|OFF) # DX_DOT_FEATURE(ON|OFF) # DX_HTML_FEATURE(ON|OFF) # DX_CHM_FEATURE(ON|OFF) # DX_CHI_FEATURE(ON|OFF) # DX_MAN_FEATURE(ON|OFF) # DX_RTF_FEATURE(ON|OFF) # DX_XML_FEATURE(ON|OFF) # DX_PDF_FEATURE(ON|OFF) # DX_PS_FEATURE(ON|OFF) # # DESCRIPTION # # The DX_*_FEATURE macros control the default setting for the given # Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for # generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML # help (for MS users), 'CHI' for generating a separate .chi file by the # .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate # output formats. The environment variable DOXYGEN_PAPER_SIZE may be # specified to override the default 'a4wide' paper size. # # By default, HTML, PDF and PS documentation is generated as this seems to # be the most popular and portable combination. MAN pages created by # Doxygen are usually problematic, though by picking an appropriate subset # and doing some massaging they might be better than nothing. CHM and RTF # are specific for MS (note that you can't generate both HTML and CHM at # the same time). The XML is rather useless unless you apply specialized # post-processing to it. # # The macros mainly control the default state of the feature. The use can # override the default by specifying --enable or --disable. The macros # ensure that contradictory flags are not given (e.g., # --enable-doxygen-html and --enable-doxygen-chm, # --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each # feature will be automatically disabled (with a warning) if the required # programs are missing. # # Once all the feature defaults have been specified, call DX_INIT_DOXYGEN # with the following parameters: a one-word name for the project for use # as a filename base etc., an optional configuration file name (the # default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an # optional output directory name (the default is 'doxygen-doc'). To run # doxygen multiple times for different configuration files and output # directories provide more parameters: the second, forth, sixth, etc # parameter are configuration file names and the third, fifth, seventh, # etc parameter are output directories. No checking is done to catch # duplicates. # # Automake Support # # The DX_RULES substitution can be used to add all needed rules to the # Makefile. Note that this is a substitution without being a variable: # only the @DX_RULES@ syntax will work. # # The provided targets are: # # doxygen-doc: Generate all doxygen documentation. # # doxygen-run: Run doxygen, which will generate some of the # documentation (HTML, CHM, CHI, MAN, RTF, XML) # but will not do the post processing required # for the rest of it (PS, PDF). # # doxygen-ps: Generate doxygen PostScript documentation. # # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake targets. # If doxygen is used to generate man pages, you can achieve this # integration by setting man3_MANS to the list of man pages generated and # then adding the dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # Then add this variable to MOSTLYCLEANFILES. # # LICENSE # # Copyright (c) 2009 Oren Ben-Kiki # Copyright (c) 2015 Olaf Mandel # # 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 24 ## ----------## ## Defaults. ## ## ----------## DX_ENV="" AC_DEFUN([DX_FEATURE_doc], ON) AC_DEFUN([DX_FEATURE_dot], OFF) AC_DEFUN([DX_FEATURE_man], OFF) AC_DEFUN([DX_FEATURE_html], ON) AC_DEFUN([DX_FEATURE_chm], OFF) AC_DEFUN([DX_FEATURE_chi], OFF) AC_DEFUN([DX_FEATURE_rtf], OFF) AC_DEFUN([DX_FEATURE_xml], OFF) AC_DEFUN([DX_FEATURE_pdf], ON) AC_DEFUN([DX_FEATURE_ps], ON) ## --------------- ## ## Private macros. ## ## --------------- ## # DX_ENV_APPEND(VARIABLE, VALUE) # ------------------------------ # Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it # as a substitution (but not a Makefile variable). The substitution # is skipped if the variable name is VERSION. AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl AM_SUBST_NOTMAKE([$1])])dnl ]) # DX_DIRNAME_EXPR # --------------- # Expand into a shell expression prints the directory part of a path. AC_DEFUN([DX_DIRNAME_EXPR], [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) # DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) # ------------------------------------- # Expands according to the M4 (static) status of the feature. AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) # DX_REQUIRE_PROG(VARIABLE, PROGRAM) # ---------------------------------- # Require the specified program to be found for the DX_CURRENT_FEATURE to work. AC_DEFUN([DX_REQUIRE_PROG], [ AC_PATH_TOOL([$1], [$2]) if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) fi ]) # DX_TEST_FEATURE(FEATURE) # ------------------------ # Expand to a shell expression testing whether the feature is active. AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) # DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) # ------------------------------------------------- # Verify that a required features has the right state before trying to turn on # the DX_CURRENT_FEATURE. AC_DEFUN([DX_CHECK_DEPEND], [ test "$DX_FLAG_$1" = "$2" \ || AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, requires, contradicts) doxygen-$1]) ]) # DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) # ---------------------------------------------------------- # Turn off the DX_CURRENT_FEATURE if the required feature is off. AC_DEFUN([DX_CLEAR_DEPEND], [ test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0) ]) # DX_FEATURE_ARG(FEATURE, DESCRIPTION, # CHECK_DEPEND, CLEAR_DEPEND, # REQUIRE, DO-IF-ON, DO-IF-OFF) # -------------------------------------------- # Parse the command-line option controlling a feature. CHECK_DEPEND is called # if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), # otherwise CLEAR_DEPEND is called to turn off the default state if a required # feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional # requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and # DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. AC_DEFUN([DX_ARG_ABLE], [ AC_DEFUN([DX_CURRENT_FEATURE], [$1]) AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) AC_ARG_ENABLE(doxygen-$1, [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], [--enable-doxygen-$1]), DX_IF_FEATURE([$1], [don't $2], [$2]))], [ case "$enableval" in #( y|Y|yes|Yes|YES) AC_SUBST([DX_FLAG_$1], 1) $3 ;; #( n|N|no|No|NO) AC_SUBST([DX_FLAG_$1], 0) ;; #( *) AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) ;; esac ], [ AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) $4 ]) if DX_TEST_FEATURE([$1]); then $5 : fi if DX_TEST_FEATURE([$1]); then $6 : else $7 : fi ]) ## -------------- ## ## Public macros. ## ## -------------- ## # DX_XXX_FEATURE(DEFAULT_STATE) # ----------------------------- AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])]) AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) # DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...) # -------------------------------------------------------------- # PROJECT also serves as the base name for the documentation files. # The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is # "doxygen-doc". # More arguments are interpreted as interleaved CONFIG-FILE and # OUTPUT-DOC-DIR values. AC_DEFUN([DX_INIT_DOXYGEN], [ # Files: AC_SUBST([DX_PROJECT], [$1]) AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])']) AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])']) m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2, [AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]), 'm4_default_nblank_quoted(m4_argn(DX_i, $@), [$(srcdir)/Doxyfile])')])])dnl m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2, [AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]), 'm4_default_nblank_quoted(m4_argn(DX_i, $@), [doxygen-doc])')])])dnl m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])], [])))dnl # Environment variables used inside doxygen.cfg: DX_ENV_APPEND(SRCDIR, $srcdir) DX_ENV_APPEND(PROJECT, $DX_PROJECT) DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) # Doxygen itself: DX_ARG_ABLE(doc, [generate any doxygen documentation], [], [], [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) DX_REQUIRE_PROG([DX_PERL], perl)], [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) # Dot for graphics: DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_DOT], dot)], [DX_ENV_APPEND(HAVE_DOT, YES) DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], [DX_ENV_APPEND(HAVE_DOT, NO)]) # Man pages generation: DX_ARG_ABLE(man, [generate doxygen manual pages], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_MAN, YES)], [DX_ENV_APPEND(GENERATE_MAN, NO)]) # RTF file generation: DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_RTF, YES)], [DX_ENV_APPEND(GENERATE_RTF, NO)]) # XML file generation: DX_ARG_ABLE(xml, [generate doxygen XML documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_XML, YES)], [DX_ENV_APPEND(GENERATE_XML, NO)]) # (Compressed) HTML help generation: DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_HHC], hhc)], [DX_ENV_APPEND(HHC_PATH, $DX_HHC) DX_ENV_APPEND(GENERATE_HTML, YES) DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) # Separate CHI file generation. DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file], [DX_CHECK_DEPEND(chm, 1)], [DX_CLEAR_DEPEND(chm, 1)], [], [DX_ENV_APPEND(GENERATE_CHI, YES)], [DX_ENV_APPEND(GENERATE_CHI, NO)]) # Plain HTML pages generation: DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], [], [DX_ENV_APPEND(GENERATE_HTML, YES)], [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) # PostScript file generation: DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_LATEX], latex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_DVIPS], dvips) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # PDF file generation: DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # LaTeX generation for PS and/or PDF: if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then DX_ENV_APPEND(GENERATE_LATEX, YES) else DX_ENV_APPEND(GENERATE_LATEX, NO) fi # Paper size for PS and/or PDF: AC_ARG_VAR(DOXYGEN_PAPER_SIZE, [a4wide (default), a4, letter, legal or executive]) case "$DOXYGEN_PAPER_SIZE" in #( "") AC_SUBST(DOXYGEN_PAPER_SIZE, "") ;; #( a4wide|a4|letter|legal|executive) DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) ;; #( *) AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) ;; esac # Rules: AS_IF([[test $DX_FLAG_html -eq 1]], [[DX_SNIPPET_html="## ------------------------------- ## ## Rules specific for HTML output. ## ## ------------------------------- ## DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/html]])[ "]], [[DX_SNIPPET_html=""]]) AS_IF([[test $DX_FLAG_chi -eq 1]], [[DX_SNIPPET_chi=" DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]], [[DX_SNIPPET_chi=""]]) AS_IF([[test $DX_FLAG_chm -eq 1]], [[DX_SNIPPET_chm="## ------------------------------ ## ## Rules specific for CHM output. ## ## ------------------------------ ## DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/chm]])[\ ${DX_SNIPPET_chi} "]], [[DX_SNIPPET_chm=""]]) AS_IF([[test $DX_FLAG_man -eq 1]], [[DX_SNIPPET_man="## ------------------------------ ## ## Rules specific for MAN output. ## ## ------------------------------ ## DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/man]])[ "]], [[DX_SNIPPET_man=""]]) AS_IF([[test $DX_FLAG_rtf -eq 1]], [[DX_SNIPPET_rtf="## ------------------------------ ## ## Rules specific for RTF output. ## ## ------------------------------ ## DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/rtf]])[ "]], [[DX_SNIPPET_rtf=""]]) AS_IF([[test $DX_FLAG_xml -eq 1]], [[DX_SNIPPET_xml="## ------------------------------ ## ## Rules specific for XML output. ## ## ------------------------------ ## DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/xml]])[ "]], [[DX_SNIPPET_xml=""]]) AS_IF([[test $DX_FLAG_ps -eq 1]], [[DX_SNIPPET_ps="## ----------------------------- ## ## Rules specific for PS output. ## ## ----------------------------- ## DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[ DX_PS_GOAL = doxygen-ps doxygen-ps: \$(DX_CLEAN_PS) ]m4_foreach([DX_i], [DX_loop], [[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\ \$(DX_LATEX) refman.tex; \\ \$(DX_MAKEINDEX) refman.idx; \\ \$(DX_LATEX) refman.tex; \\ countdown=5; \\ while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\ refman.log > /dev/null 2>&1 \\ && test \$\$countdown -gt 0; do \\ \$(DX_LATEX) refman.tex; \\ countdown=\`expr \$\$countdown - 1\`; \\ done; \\ \$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi ]])["]], [[DX_SNIPPET_ps=""]]) AS_IF([[test $DX_FLAG_pdf -eq 1]], [[DX_SNIPPET_pdf="## ------------------------------ ## ## Rules specific for PDF output. ## ## ------------------------------ ## DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[ DX_PDF_GOAL = doxygen-pdf doxygen-pdf: \$(DX_CLEAN_PDF) ]m4_foreach([DX_i], [DX_loop], [[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\ \$(DX_PDFLATEX) refman.tex; \\ \$(DX_MAKEINDEX) refman.idx; \\ \$(DX_PDFLATEX) refman.tex; \\ countdown=5; \\ while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\ refman.log > /dev/null 2>&1 \\ && test \$\$countdown -gt 0; do \\ \$(DX_PDFLATEX) refman.tex; \\ countdown=\`expr \$\$countdown - 1\`; \\ done; \\ mv refman.pdf ../\$(PACKAGE).pdf ]])["]], [[DX_SNIPPET_pdf=""]]) AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]], [[DX_SNIPPET_latex="## ------------------------------------------------- ## ## Rules specific for LaTeX (shared for PS and PDF). ## ## ------------------------------------------------- ## DX_V_LATEX = \$(_DX_v_LATEX_\$(V)) _DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY)) _DX_v_LATEX_0 = @echo \" LATEX \" \$][@; DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\ \$(DX_DOCDIR]DX_i[)/latex]])[ "]], [[DX_SNIPPET_latex=""]]) AS_IF([[test $DX_FLAG_doc -eq 1]], [[DX_SNIPPET_doc="## --------------------------------- ## ## Format-independent Doxygen rules. ## ## --------------------------------- ## ${DX_SNIPPET_html}\ ${DX_SNIPPET_chm}\ ${DX_SNIPPET_man}\ ${DX_SNIPPET_rtf}\ ${DX_SNIPPET_xml}\ ${DX_SNIPPET_ps}\ ${DX_SNIPPET_pdf}\ ${DX_SNIPPET_latex}\ DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V)) _DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY)) _DX_v_DXGEN_0 = @echo \" DXGEN \" \$<; .PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL) .INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL) doxygen-run:]m4_foreach([DX_i], [DX_loop], [[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[ doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL) ]m4_foreach([DX_i], [DX_loop], [[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS) \$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[) \$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[) \$(A""M_V_at)echo Timestamp >\$][@ ]])dnl [DX_CLEANFILES = \\] m4_foreach([DX_i], [DX_loop], [[ \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\ ]])dnl [ -r \\ \$(DX_CLEAN_HTML) \\ \$(DX_CLEAN_CHM) \\ \$(DX_CLEAN_CHI) \\ \$(DX_CLEAN_MAN) \\ \$(DX_CLEAN_RTF) \\ \$(DX_CLEAN_XML) \\ \$(DX_CLEAN_PS) \\ \$(DX_CLEAN_PDF) \\ \$(DX_CLEAN_LATEX)"]], [[DX_SNIPPET_doc=""]]) AC_SUBST([DX_RULES], ["${DX_SNIPPET_doc}"])dnl AM_SUBST_NOTMAKE([DX_RULES]) #For debugging: #echo DX_FLAG_doc=$DX_FLAG_doc #echo DX_FLAG_dot=$DX_FLAG_dot #echo DX_FLAG_man=$DX_FLAG_man #echo DX_FLAG_html=$DX_FLAG_html #echo DX_FLAG_chm=$DX_FLAG_chm #echo DX_FLAG_chi=$DX_FLAG_chi #echo DX_FLAG_rtf=$DX_FLAG_rtf #echo DX_FLAG_xml=$DX_FLAG_xml #echo DX_FLAG_pdf=$DX_FLAG_pdf #echo DX_FLAG_ps=$DX_FLAG_ps #echo DX_ENV=$DX_ENV ]) squashfs-tools-ng-0.8/m4/ax_pthread.m4000066400000000000000000000506131360235375500176750ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can 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 25 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], [ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif ], [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) AS_IF([test "x$GCC" = "xyes"], [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif ], [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" ax_pthread_clang_warning=no # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) PTHREAD_CFLAGS="-pthread" PTHREAD_LIBS= ax_pthread_ok=yes # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [ac_link="$ax_pthread_2step_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [break]) ]) done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ]) case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -mt,pthread) AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) PTHREAD_CFLAGS="-mt" PTHREAD_LIBS="-lpthread" ;; -*) AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_CACHE_CHECK([for joinable pthread attribute], [ax_cv_PTHREAD_JOINABLE_ATTR], [ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $ax_pthread_attr; return attr /* ; */])], [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], []) done ]) AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes"], [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$ax_cv_PTHREAD_JOINABLE_ATTR], [Define to necessary symbol if this constant uses a non-standard name on your system.]) ax_pthread_joinable_attr_defined=yes ]) AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ]) AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes"], [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT; return i;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ax_pthread_prio_inherit_defined=yes ]) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD squashfs-tools-ng-0.8/m4/compiler.m4000066400000000000000000000030331360235375500173620ustar00rootroot00000000000000dnl Copyright (C) 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 Simon Josefsson dnl -- derivated from coreutils m4/warnings.m4 # UL_AS_VAR_APPEND(VAR, VALUE) # ---------------------------- # Provide the functionality of AS_VAR_APPEND if Autoconf does not have it. m4_ifdef([AS_VAR_APPEND], [m4_copy([AS_VAR_APPEND], [UL_AS_VAR_APPEND])], [m4_define([UL_AS_VAR_APPEND], [AS_VAR_SET([$1], [AS_VAR_GET([$1])$2])])]) # UL_ADD_WARN(COMPILER_OPTION [, VARNAME]) # ------------------------ # Adds parameter to WARN_CFLAGS (or to $VARNAME) if the compiler supports it. AC_DEFUN([UL_WARN_ADD], [ m4_define([warnvarname], m4_default([$2],WARN_CFLAGS)) AS_VAR_PUSHDEF([ul_Warn], [ul_cv_warn_$1])dnl AC_CACHE_CHECK([whether compiler handles $1], m4_defn([ul_Warn]), [ # store AC_LANG_WERROR status, then turn it on save_ac_[]_AC_LANG_ABBREV[]_werror_flag="${ac_[]_AC_LANG_ABBREV[]_werror_flag}" AC_LANG_WERROR ul_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="-Werror ${CPPFLAGS} $1" AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])], [AS_VAR_SET(ul_Warn, [yes])], [AS_VAR_SET(ul_Warn, [no])]) # restore AC_LANG_WERROR ac_[]_AC_LANG_ABBREV[]_werror_flag="${save_ac_[]_AC_LANG_ABBREV[]_werror_flag}" CPPFLAGS="$ul_save_CPPFLAGS" ]) AS_VAR_IF(ul_Warn, [yes], [UL_AS_VAR_APPEND(warnvarname, [" $1"])]) ]) squashfs-tools-ng-0.8/mkfs/000077500000000000000000000000001360235375500157275ustar00rootroot00000000000000squashfs-tools-ng-0.8/mkfs/Makemodule.am000066400000000000000000000007341360235375500203350ustar00rootroot00000000000000gensquashfs_SOURCES = mkfs/mkfs.c mkfs/mkfs.h mkfs/options.c gensquashfs_SOURCES += mkfs/dirscan.c mkfs/selinux.c gensquashfs_LDADD = libcommon.a libsquashfs.la libfstree.a gensquashfs_LDADD += libcompat.a $(LIBSELINUX_LIBS) $(LZO_LIBS) gensquashfs_LDADD += $(PTHREAD_LIBS) gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) gensquashfs_CFLAGS = $(AM_CFLAGS) $(LIBSELINUX_CFLAGS) $(PTHREAD_CFLAGS) if WITH_SELINUX gensquashfs_CPPFLAGS += -DWITH_SELINUX endif bin_PROGRAMS += gensquashfs squashfs-tools-ng-0.8/mkfs/dirscan.c000066400000000000000000000137641360235375500175310ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_from_dir.c * * Copyright (C) 2019 David Oberhollenzer */ #include "mkfs.h" #ifdef HAVE_SYS_XATTR_H static char *get_full_path(const char *prefix, tree_node_t *node) { char *path = NULL, *new = NULL; size_t path_len, prefix_len; int ret; path = fstree_get_path(node); if (path == NULL) goto fail; ret = canonicalize_name(path); assert(ret == 0); path_len = strlen(path); prefix_len = strlen(prefix); while (prefix_len > 0 && prefix[prefix_len - 1] == '/') --prefix_len; if (prefix_len > 0) { new = realloc(path, path_len + prefix_len + 2); if (new == NULL) goto fail; path = new; memmove(path + prefix_len + 1, path, path_len + 1); memcpy(path, prefix, prefix_len); path[prefix_len] = '/'; } return path; fail: perror("getting full path for xattr scan"); free(path); return NULL; } static int xattr_from_path(sqfs_xattr_writer_t *xwr, const char *path) { char *key, *value = NULL, *buffer = NULL; ssize_t buflen, vallen, keylen; int ret; buflen = llistxattr(path, NULL, 0); if (buflen < 0) { fprintf(stderr, "llistxattr %s: %s", path, strerror(errno)); return -1; } if (buflen == 0) return 0; buffer = malloc(buflen); if (buffer == NULL) { perror("xattr name buffer"); return -1; } buflen = llistxattr(path, buffer, buflen); if (buflen == -1) { fprintf(stderr, "llistxattr %s: %s", path, strerror(errno)); goto fail; } key = buffer; while (buflen > 0) { vallen = lgetxattr(path, key, NULL, 0); if (vallen == -1) { fprintf(stderr, "lgetxattr %s: %s", path, strerror(errno)); goto fail; } if (vallen > 0) { value = calloc(1, vallen); if (value == NULL) { perror("allocating xattr value buffer"); goto fail; } vallen = lgetxattr(path, key, value, vallen); if (vallen == -1) { fprintf(stderr, "lgetxattr %s: %s\n", path, strerror(errno)); goto fail; } ret = sqfs_xattr_writer_add(xwr, key, value, vallen); if (ret) { sqfs_perror(path, "storing xattr key-value pairs", ret); goto fail; } free(value); value = NULL; } keylen = strlen(key) + 1; buflen -= keylen; key += keylen; } free(buffer); return 0; fail: free(value); free(buffer); return -1; } #endif #ifdef _WIN32 int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle, sqfs_xattr_writer_t *xwr, unsigned int flags) { (void)fs; (void)path; (void)selinux_handle; (void)xwr; (void)flags; fputs("Packing a directory is not supported on Windows.\n", stderr); return -1; } #else static int xattr_xcan_dfs(const char *path_prefix, void *selinux_handle, sqfs_xattr_writer_t *xwr, unsigned int flags, tree_node_t *node) { char *path; int ret; ret = sqfs_xattr_writer_begin(xwr); if (ret) { sqfs_perror(node->name, "recoding xattr key-value pairs\n", ret); return -1; } #ifdef HAVE_SYS_XATTR_H if (flags & DIR_SCAN_READ_XATTR) { path = get_full_path(path_prefix, node); if (path == NULL) return -1; ret = xattr_from_path(xwr, path); free(path); if (ret) return -1; } #else (void)path_prefix; #endif if (selinux_handle != NULL) { path = fstree_get_path(node); if (path == NULL) { perror("reconstructing absolute path"); return -1; } ret = selinux_relable_node(selinux_handle, xwr, node, path); free(path); if (ret) return -1; } if (sqfs_xattr_writer_end(xwr, &node->xattr_idx)) { sqfs_perror(node->name, "completing xattr key-value pairs", ret); return -1; } if (S_ISDIR(node->mode)) { node = node->data.dir.children; while (node != NULL) { if (xattr_xcan_dfs(path_prefix, selinux_handle, xwr, flags, node)) { return -1; } node = node->next; } } return 0; } static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, dev_t devstart, unsigned int flags) { char *extra = NULL; struct dirent *ent; struct stat sb; tree_node_t *n; int childfd; DIR *dir; dir = fdopendir(dir_fd); if (dir == NULL) { perror("fdopendir"); close(dir_fd); return -1; } /* XXX: fdopendir can dup and close dir_fd internally and still be compliant with the spec. */ dir_fd = dirfd(dir); for (;;) { errno = 0; ent = readdir(dir); if (ent == NULL) { if (errno) { perror("readdir"); goto fail; } break; } if (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, ".")) continue; if (fstatat(dir_fd, ent->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { perror(ent->d_name); goto fail; } if ((flags & DIR_SCAN_ONE_FILESYSTEM) && sb.st_dev != devstart) continue; if (S_ISLNK(sb.st_mode)) { extra = calloc(1, sb.st_size + 1); if (extra == NULL) goto fail_rdlink; if (readlinkat(dir_fd, ent->d_name, extra, sb.st_size) < 0) { goto fail_rdlink; } extra[sb.st_size] = '\0'; } if (!(flags & DIR_SCAN_KEEP_TIME)) sb.st_mtim = fs->defaults.st_mtim; n = fstree_mknode(root, ent->d_name, strlen(ent->d_name), extra, &sb); if (n == NULL) { perror("creating tree node"); goto fail; } free(extra); extra = NULL; if (S_ISDIR(n->mode)) { childfd = openat(dir_fd, n->name, O_DIRECTORY | O_RDONLY | O_CLOEXEC); if (childfd < 0) { perror(n->name); goto fail; } if (populate_dir(childfd, fs, n, devstart, flags)) goto fail; } } closedir(dir); return 0; fail_rdlink: perror("readlink"); fail: closedir(dir); free(extra); return -1; } int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle, sqfs_xattr_writer_t *xwr, unsigned int flags) { struct stat sb; int fd; fd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC); if (fd < 0) { perror(path); return -1; } if (fstat(fd, &sb)) { perror(path); close(fd); return -1; } if (populate_dir(fd, fs, fs->root, sb.st_dev, flags)) return -1; if (xwr != NULL && (selinux_handle != NULL || (flags & DIR_SCAN_READ_XATTR))) { if (xattr_xcan_dfs(path, selinux_handle, xwr, flags, fs->root)) return -1; } return 0; } #endif squashfs-tools-ng-0.8/mkfs/mkfs.c000066400000000000000000000114061360235375500170350ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mkfs.c * * Copyright (C) 2019 David Oberhollenzer */ #include "mkfs.h" static int set_working_dir(options_t *opt) { const char *ptr; char *path; if (opt->packdir != NULL) { if (chdir(opt->packdir)) { perror(opt->packdir); return -1; } return 0; } ptr = strrchr(opt->infile, '/'); if (ptr == NULL) return 0; path = strndup(opt->infile, ptr - opt->infile); if (path == NULL) { perror("constructing input directory path"); return -1; } if (chdir(path)) { perror(path); free(path); return -1; } free(path); return 0; } static int pack_files(sqfs_data_writer_t *data, fstree_t *fs, data_writer_stats_t *stats, options_t *opt) { sqfs_inode_generic_t *inode; size_t max_blk_count; sqfs_u64 filesize; sqfs_file_t *file; tree_node_t *node; const char *path; char *node_path; file_info_t *fi; size_t size; int flags; int ret; if (set_working_dir(opt)) return -1; for (fi = fs->files; fi != NULL; fi = fi->next) { if (fi->input_file == NULL) { node = container_of(fi, tree_node_t, data.file); node_path = fstree_get_path(node); if (node_path == NULL) { perror("reconstructing file path"); return -1; } ret = canonicalize_name(node_path); assert(ret == 0); path = node_path; } else { node_path = NULL; path = fi->input_file; } if (!opt->cfg.quiet) printf("packing %s\n", path); file = sqfs_open_file(path, SQFS_FILE_OPEN_READ_ONLY); if (file == NULL) { perror(path); free(node_path); return -1; } filesize = file->get_size(file); max_blk_count = filesize / opt->cfg.block_size; if (filesize % opt->cfg.block_size) ++max_blk_count; if (SZ_MUL_OV(sizeof(sqfs_u32), max_blk_count, &size) || SZ_ADD_OV(sizeof(*inode), size, &size)) { fputs("creating file inode: too many blocks\n", stderr); file->destroy(file); free(node_path); return -1; } inode = calloc(1, size); if (inode == NULL) { perror("creating file inode"); file->destroy(file); free(node_path); return -1; } inode->block_sizes = (sqfs_u32 *)inode->extra; inode->base.type = SQFS_INODE_FILE; sqfs_inode_set_file_size(inode, filesize); sqfs_inode_set_frag_location(inode, 0xFFFFFFFF, 0xFFFFFFFF); fi->user_ptr = inode; flags = 0; if (opt->no_tail_packing && filesize > opt->cfg.block_size) flags |= SQFS_BLK_DONT_FRAGMENT; ret = write_data_from_file(path, data, inode, file, flags); file->destroy(file); free(node_path); if (ret) return -1; stats->file_count += 1; stats->bytes_read += filesize; } return 0; } static int relabel_tree_dfs(const char *filename, sqfs_xattr_writer_t *xwr, tree_node_t *n, void *selinux_handle) { char *path = fstree_get_path(n); int ret; if (path == NULL) { perror("getting absolute node path for SELinux relabeling"); return -1; } ret = sqfs_xattr_writer_begin(xwr); if (ret) { sqfs_perror(filename, "recording xattr key-value pairs", ret); return -1; } if (selinux_relable_node(selinux_handle, xwr, n, path)) { free(path); return -1; } ret = sqfs_xattr_writer_end(xwr, &n->xattr_idx); if (ret) { sqfs_perror(filename, "flushing completed key-value pairs", ret); return -1; } free(path); if (S_ISDIR(n->mode)) { for (n = n->data.dir.children; n != NULL; n = n->next) { if (relabel_tree_dfs(filename, xwr, n, selinux_handle)) return -1; } } return 0; } static int read_fstree(fstree_t *fs, options_t *opt, sqfs_xattr_writer_t *xwr, void *selinux_handle) { FILE *fp; int ret; if (opt->infile == NULL) { return fstree_from_dir(fs, opt->packdir, selinux_handle, xwr, opt->dirscan_flags); } fp = fopen(opt->infile, "rb"); if (fp == NULL) { perror(opt->infile); return -1; } ret = fstree_from_file(fs, opt->infile, fp); fclose(fp); if (ret == 0 && selinux_handle != NULL) ret = relabel_tree_dfs(opt->cfg.filename, xwr, fs->root, selinux_handle); return ret; } int main(int argc, char **argv) { int status = EXIT_FAILURE; void *sehnd = NULL; sqfs_writer_t sqfs; options_t opt; process_command_line(&opt, argc, argv); if (sqfs_writer_init(&sqfs, &opt.cfg)) return EXIT_FAILURE; if (opt.selinux != NULL) { sehnd = selinux_open_context_file(opt.selinux); if (sehnd == NULL) goto out; } if (read_fstree(&sqfs.fs, &opt, sqfs.xwr, sehnd)) { if (sehnd != NULL) selinux_close_context_file(sehnd); goto out; } if (sehnd != NULL) { selinux_close_context_file(sehnd); sehnd = NULL; } if (fstree_post_process(&sqfs.fs)) goto out; if (pack_files(sqfs.data, &sqfs.fs, &sqfs.stats, &opt)) goto out; if (sqfs_writer_finish(&sqfs, &opt.cfg)) goto out; status = EXIT_SUCCESS; out: sqfs_writer_cleanup(&sqfs); return status; } squashfs-tools-ng-0.8/mkfs/mkfs.h000066400000000000000000000023341360235375500170420ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mkfs.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef MKFS_H #define MKFS_H #include "config.h" #include "common.h" #include "fstree.h" #ifdef HAVE_SYS_XATTR_H #include #endif #ifdef WITH_SELINUX #include #include #endif #include #include #include #include #include #include #include #include #include typedef struct { sqfs_writer_cfg_t cfg; unsigned int dirscan_flags; const char *infile; const char *packdir; const char *selinux; bool no_tail_packing; } options_t; enum { DIR_SCAN_KEEP_TIME = 0x01, DIR_SCAN_ONE_FILESYSTEM = 0x02, DIR_SCAN_READ_XATTR = 0x04, }; void process_command_line(options_t *opt, int argc, char **argv); int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle, sqfs_xattr_writer_t *xwr, unsigned int flags); void *selinux_open_context_file(const char *filename); int selinux_relable_node(void *sehnd, sqfs_xattr_writer_t *xwr, tree_node_t *node, const char *path); void selinux_close_context_file(void *sehnd); #endif /* MKFS_H */ squashfs-tools-ng-0.8/mkfs/options.c000066400000000000000000000223541360235375500175740ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * options.c * * Copyright (C) 2019 David Oberhollenzer */ #include "mkfs.h" static struct option long_opts[] = { { "compressor", required_argument, NULL, 'c' }, { "block-size", required_argument, NULL, 'b' }, { "dev-block-size", required_argument, NULL, 'B' }, { "defaults", required_argument, NULL, 'd' }, { "comp-extra", required_argument, NULL, 'X' }, { "pack-file", required_argument, NULL, 'F' }, { "pack-dir", required_argument, NULL, 'D' }, { "num-jobs", required_argument, NULL, 'j' }, { "queue-backlog", required_argument, NULL, 'Q' }, { "keep-time", no_argument, NULL, 'k' }, #ifdef HAVE_SYS_XATTR_H { "keep-xattr", no_argument, NULL, 'x' }, #endif { "one-file-system", no_argument, NULL, 'o' }, { "exportable", no_argument, NULL, 'e' }, { "no-tail-packing", no_argument, NULL, 'T' }, { "force", no_argument, NULL, 'f' }, { "quiet", no_argument, NULL, 'q' }, #ifdef WITH_SELINUX { "selinux", required_argument, NULL, 's' }, #endif { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, }; static const char *short_opts = "F:D:X:c:b:B:d:j:Q:kxoefqThV" #ifdef WITH_SELINUX "s:" #endif #ifdef HAVE_SYS_XATTR_H "x" #endif ; static const char *help_string = "Usage: gensquashfs [OPTIONS...] \n" "\n" "Possible options:\n" "\n" " --pack-file, -F Use a `gen_init_cpio` style description file.\n" " The file format is specified below.\n" " If --pack-dir is used, input file paths are\n" " relative to the pack directory, otherwise\n" " they are relative to the directory the pack\n" " file is in.\n" " --pack-dir, -D If --pack-file is used, this is the root path\n" " relative to which to read files. If no pack\n" " file is specified, pack the contents of the\n" " given directory into a SquashFS image. The\n" " directory becomes the root of the file\n" " system.\n" "\n" " --compressor, -c Select the compressor to use.\n" " A list of available compressors is below.\n" " --comp-extra, -X A comma separated list of extra options for\n" " the selected compressor. Specify 'help' to\n" " get a list of available options.\n" " --num-jobs, -j Number of compressor jobs to create.\n" " --queue-backlog, -Q Maximum number of data blocks in the thread\n" " worker queue before the packer starts waiting\n" " for the block processors to catch up.\n" " Defaults to 10 times the number of jobs.\n" " --block-size, -b Block size to use for Squashfs image.\n" " Defaults to %u.\n" " --dev-block-size, -B Device block size to padd the image to.\n" " Defaults to %u.\n" " --defaults, -d A comma separated list of default values for\n" " implicitly created directories.\n" "\n" " Possible options:\n" " uid= 0 if not set.\n" " gid= 0 if not set.\n" " mode= 0755 if not set.\n" " mtime= 0 if not set.\n" "\n" #ifdef WITH_SELINUX " --selinux, -s Specify an SELinux label file to get context\n" " attributes from.\n" #endif " --keep-time, -k When using --pack-dir only, use the timestamps\n" " from the input files instead of setting\n" " defaults on all input paths.\n" " --keep-xattr, -x When using --pack-dir only, read and pack the\n" " extended attributes from the input files.\n" " --one-file-system, -o When using --pack-dir only, stay in local file\n" " system and do not cross mount points.\n" " --exportable, -e Generate an export table for NFS support.\n" " --no-tail-packing, -T Do not perform tail end packing on files that\n" " are larger than block size.\n" " --force, -f Overwrite the output file if it exists.\n" " --quiet, -q Do not print out progress reports.\n" " --help, -h Print help text and exit.\n" " --version, -V Print version information and exit.\n" "\n"; const char *help_details = "When using the pack file option, the given file is expected to contain\n" "newline separated entries that describe the files to be included in the\n" "SquashFS image. The following entry types can be specified:\n" "\n" "# a comment\n" "file []\n" "dir \n" "nod \n" "slink \n" "link \n" "pipe \n" "sock \n" "\n" " Absolute path of the entry in the image. Can be put in quotes\n" " if some components contain spaces.\n" " If given, location of the input file. Either absolute or relative\n" " to the description file. If omitted, the image path is used,\n" " relative to the description file.\n" " Symlink or hardlink target.\n" " Mode/permissions of the entry.\n" " Numeric user id.\n" " Numeric group id.\n" " Device type (b=block, c=character).\n" " Major number of a device special file.\n" " Minor number of a device special file.\n" "\n" "Example:\n" " # A simple squashfs image\n" " dir /dev 0755 0 0\n" " nod /dev/console 0600 0 0 c 5 1\n" " dir /root 0700 0 0\n" " dir /sbin 0755 0 0\n" " \n" " # Add a file. Input is relative to listing or pack dir.\n" " file /sbin/init 0755 0 0 ../init/sbin/init\n" " \n" " # Read bin/bash, relative to listing or pack dir.\n" " # Implicitly create /bin.\n" " file /bin/bash 0755 0 0\n" " \n" " # file name with a space in it.\n" " file \"/opt/my app/\\\"special\\\"/data\" 0600 0 0\n" "\n\n"; void process_command_line(options_t *opt, int argc, char **argv) { bool have_compressor; int i, ret; memset(opt, 0, sizeof(*opt)); sqfs_writer_cfg_init(&opt->cfg); for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'T': opt->no_tail_packing = true; break; case 'c': have_compressor = true; ret = sqfs_compressor_id_from_name(optarg); if (ret < 0) { have_compressor = false; #ifdef WITH_LZO if (opt->cfg.comp_id == SQFS_COMP_LZO) have_compressor = true; #endif } if (!have_compressor) { fprintf(stderr, "Unsupported compressor '%s'\n", optarg); exit(EXIT_FAILURE); } opt->cfg.comp_id = ret; break; case 'b': opt->cfg.block_size = strtol(optarg, NULL, 0); break; case 'j': opt->cfg.num_jobs = strtol(optarg, NULL, 0); break; case 'Q': opt->cfg.max_backlog = strtol(optarg, NULL, 0); break; case 'B': opt->cfg.devblksize = strtol(optarg, NULL, 0); if (opt->cfg.devblksize < 1024) { fputs("Device block size must be at " "least 1024\n", stderr); exit(EXIT_FAILURE); } break; case 'd': opt->cfg.fs_defaults = optarg; break; case 'k': opt->dirscan_flags |= DIR_SCAN_KEEP_TIME; break; #ifdef HAVE_SYS_XATTR_H case 'x': opt->dirscan_flags |= DIR_SCAN_READ_XATTR; break; #endif case 'o': opt->dirscan_flags |= DIR_SCAN_ONE_FILESYSTEM; break; case 'e': opt->cfg.exportable = true; break; case 'f': opt->cfg.outmode |= SQFS_FILE_OPEN_OVERWRITE; break; case 'q': opt->cfg.quiet = true; break; case 'X': opt->cfg.comp_extra = optarg; break; case 'F': opt->infile = optarg; break; case 'D': opt->packdir = optarg; break; #ifdef WITH_SELINUX case 's': opt->selinux = optarg; break; #endif case 'h': printf(help_string, SQFS_DEFAULT_BLOCK_SIZE, SQFS_DEVBLK_SIZE); fputs(help_details, stdout); compressor_print_available(); exit(EXIT_SUCCESS); case 'V': print_version("gensquashfs"); exit(EXIT_SUCCESS); default: goto fail_arg; } } if (opt->cfg.num_jobs < 1) opt->cfg.num_jobs = 1; if (opt->cfg.max_backlog < 1) opt->cfg.max_backlog = 10 * opt->cfg.num_jobs; if (opt->cfg.comp_extra != NULL && strcmp(opt->cfg.comp_extra, "help") == 0) { compressor_print_help(opt->cfg.comp_id); exit(EXIT_SUCCESS); } if (opt->infile == NULL && opt->packdir == NULL) { fputs("No input file or directory specified.\n", stderr); goto fail_arg; } if (optind >= argc) { fputs("No output file specified.\n", stderr); goto fail_arg; } opt->cfg.filename = argv[optind++]; return; fail_arg: fputs("Try `gensquashfs --help' for more information.\n", stderr); exit(EXIT_FAILURE); } squashfs-tools-ng-0.8/mkfs/selinux.c000066400000000000000000000031701360235375500175630ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * selinux.c * * Copyright (C) 2019 David Oberhollenzer */ #include "mkfs.h" #define XATTR_NAME_SELINUX "security.selinux" #define XATTR_VALUE_SELINUX "system_u:object_r:unlabeled_t:s0" #ifdef WITH_SELINUX int selinux_relable_node(void *sehnd, sqfs_xattr_writer_t *xwr, tree_node_t *node, const char *path) { char *context = NULL; int ret; if (selabel_lookup(sehnd, &context, path, node->mode) < 0) { context = strdup(XATTR_VALUE_SELINUX); if (context == NULL) goto fail; } ret = sqfs_xattr_writer_add(xwr, XATTR_NAME_SELINUX, context, strlen(context)); free(context); if (ret) sqfs_perror(node->name, "storing SELinux xattr", ret); return ret; fail: perror("relabeling files"); return -1; } void *selinux_open_context_file(const char *filename) { struct selabel_handle *sehnd; struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, filename }, }; sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (sehnd == NULL) perror(filename); return sehnd; } void selinux_close_context_file(void *sehnd) { selabel_close(sehnd); } #else int selinux_relable_node(void *sehnd, sqfs_xattr_writer_t *xwr, tree_node_t *node, const char *path) { (void)sehnd; (void)xwr; (void)node; (void)path; fputs("Built without SELinux support, cannot add SELinux labels\n", stderr); return -1; } void *selinux_open_context_file(const char *filename) { (void)filename; fputs("Built without SELinux support, cannot open contexts file\n", stderr); return NULL; } void selinux_close_context_file(void *sehnd) { (void)sehnd; } #endif squashfs-tools-ng-0.8/mkwinbins.sh000077500000000000000000000121121360235375500173240ustar00rootroot00000000000000#!/bin/bash set -e W32_ZIP_NAME="squashfs-tools-ng-0.8-mingw32" W64_ZIP_NAME="squashfs-tools-ng-0.8-mingw64" W32_DIR="$(pwd)/$W32_ZIP_NAME" W32_PREFIX="i686-w64-mingw32" W64_DIR="$(pwd)/$W64_ZIP_NAME" W64_PREFIX="x86_64-w64-mingw32" PKG_URL="https://infraroot.at/pub/squashfs/windows" download() { echo "-- fetching $PKG_TAR -- " [ -f "$PKG_TAR" ] || { curl -s -L "$PKG_URL/$PKG_TAR" > "$PKG_TAR" echo "$PKG_HASH $PKG_TAR" | sha256sum -c --quiet "-" } [ -d "$PKG_DIR" ] || { case "$PKG_TAR" in *.zip) unzip "$PKG_TAR" -d "$PKG_DIR" ;; *) tar -xf "$PKG_TAR" ;; esac } } ################################### get xz ################################### PKG_DIR="xz-5.2.4" PKG_TAR="${PKG_DIR}.tar.xz" PKG_HASH="9717ae363760dedf573dad241420c5fea86256b65bc21d2cf71b2b12f0544f4b" download pushd "$PKG_DIR" ./configure CFLAGS="-O2" --prefix="$W32_DIR" --host="$W32_PREFIX" \ --disable-xz --disable-xzdec --disable-lzmadec \ --disable-lzmainfo --disable-links \ --disable-scripts --disable-doc make -j make install-strip make clean ./configure CFLAGS="-O2" --prefix="$W64_DIR" --host="$W64_PREFIX" \ --disable-xz --disable-xzdec --disable-lzmadec \ --disable-lzmainfo --disable-links \ --disable-scripts --disable-doc make -j make install-strip popd ################################## get lzo ################################### PKG_DIR="lzo-2.10" PKG_TAR="${PKG_DIR}.tar.gz" PKG_HASH="c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072" download pushd "$PKG_DIR" ./configure CFLAGS="-O2" --prefix="$W32_DIR" --host="$W32_PREFIX" \ --enable-shared --disable-static make -j make install-strip make clean ./configure CFLAGS="-O2" --prefix="$W64_DIR" --host="$W64_PREFIX" \ --enable-shared --disable-static make -j make install-strip popd ################################## get zstd ################################## PKG_DIR="zstd-v1.4.4-win32" PKG_TAR="${PKG_DIR}.zip" PKG_HASH="60d4cd6510e7253d33f47a68554a003b50dba05d1db89e16ef32bc26b126b92c" download mv "$PKG_DIR/dll/libzstd.dll" "$W32_DIR/bin" mv "$PKG_DIR/dll/libzstd.lib" "$W32_DIR/lib/libzstd.dll.a" mv "$PKG_DIR/include"/*.h "$W32_DIR/include" cat > "$W32_DIR/lib/pkgconfig/libzstd.pc" <<_EOF prefix=$W32_DIR libdir=$W32_DIR/lib includedir=$W32_DIR/include Name: zstd Description: fast lossless compression algorithm library URL: http://www.zstd.net/ Version: 1.4.4 Libs: -L$W32_DIR/lib -lzstd Cflags: -I$W32_DIR/include _EOF PKG_DIR="zstd-v1.4.4-win64" PKG_TAR="${PKG_DIR}.zip" PKG_HASH="bb1591db8376fb5360640088e0cc9920c6da9cd0f5fd4e9229316261808c1581" download mv "$PKG_DIR/dll/libzstd.dll" "$W64_DIR/bin" mv "$PKG_DIR/dll/libzstd.lib" "$W64_DIR/lib/libzstd.dll.a" mv "$PKG_DIR/include"/*.h "$W64_DIR/include" cat > "$W64_DIR/lib/pkgconfig/libzstd.pc" <<_EOF prefix=$W64_DIR libdir=$W64_DIR/lib includedir=$W64_DIR/include Name: zstd Description: fast lossless compression algorithm library URL: http://www.zstd.net/ Version: 1.4.4 Libs: -L$W64_DIR/lib -lzstd Cflags: -I$W64_DIR/include _EOF ################################ build 32 bit ################################ export PKG_CONFIG_PATH="$W32_DIR/lib/pkgconfig" ./autogen.sh ./configure CFLAGS="-O2" LZO_CFLAGS="-I$W32_DIR/include" \ LZO_LIBS="-L$W32_DIR/lib -llzo2" \ --prefix="$W32_DIR" --host="$W32_PREFIX" --with-builtin-lz4 \ --with-builtin-zlib cp "$W32_DIR/bin/"*.dll . make -j check rm *.dll ./configure CFLAGS="-O2 -DNDEBUG" LZO_CFLAGS="-I$W32_DIR/include" \ LZO_LIBS="-L$W32_DIR/lib -llzo2" \ --prefix="$W32_DIR" --host="$W32_PREFIX" --with-builtin-lz4 \ --with-builtin-zlib make clean make -j make install-strip ################################ build 64 bit ################################ export PKG_CONFIG_PATH="$W64_DIR/lib/pkgconfig" ./configure CFLAGS="-O2" LZO_CFLAGS="-I$W64_DIR/include" \ LZO_LIBS="-L$W64_DIR/lib -llzo2" \ --prefix="$W64_DIR" --host="$W64_PREFIX" --with-builtin-lz4 \ --with-builtin-zlib make clean cp "$W64_DIR/bin/"*.dll . make -j check rm *.dll ./configure CFLAGS="-O2 -DNDEBUG" LZO_CFLAGS="-I$W64_DIR/include" \ LZO_LIBS="-L$W64_DIR/lib -llzo2" \ --prefix="$W64_DIR" --host="$W64_PREFIX" --with-builtin-lz4 \ --with-builtin-zlib make clean make -j make install-strip ############################# package everything ############################# cp -r licenses "$W64_DIR" cp README.md COPYING.md CHANGELOG.md "$W64_DIR" cp -r licenses "$W32_DIR" cp README.md COPYING.md CHANGELOG.md "$W32_DIR" rm -r "$W32_DIR/lib/pkgconfig" "$W64_DIR/lib/pkgconfig" rm "$W32_DIR/lib"/*.la "$W64_DIR/lib"/*.la ${W32_PREFIX}-strip --discard-all "$W32_DIR/bin"/*.dll "$W32_DIR/bin"/*.exe ${W64_PREFIX}-strip --discard-all "$W64_DIR/bin"/*.dll "$W64_DIR/bin"/*.exe zip -r "${W32_ZIP_NAME}.zip" "$W32_ZIP_NAME/bin" "$W32_ZIP_NAME/lib" zip -g -r -l "${W32_ZIP_NAME}.zip" "$W32_ZIP_NAME/include" zip -g -r -l "${W32_ZIP_NAME}.zip" "$W32_ZIP_NAME/licenses" $W32_ZIP_NAME/*.md zip -r "${W64_ZIP_NAME}.zip" "$W64_ZIP_NAME/bin" "$W64_ZIP_NAME/lib" zip -g -r -l "${W64_ZIP_NAME}.zip" "$W64_ZIP_NAME/include" zip -g -r -l "${W64_ZIP_NAME}.zip" "$W64_ZIP_NAME/licenses" $W64_ZIP_NAME/*.md squashfs-tools-ng-0.8/tar/000077500000000000000000000000001360235375500155555ustar00rootroot00000000000000squashfs-tools-ng-0.8/tar/Makemodule.am000066400000000000000000000007361360235375500201650ustar00rootroot00000000000000sqfs2tar_SOURCES = tar/sqfs2tar.c sqfs2tar_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) sqfs2tar_LDADD = libcommon.a libsquashfs.la libtar.a libcompat.a sqfs2tar_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) tar2sqfs_SOURCES = tar/tar2sqfs.c tar2sqfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) tar2sqfs_LDADD = libcommon.a libsquashfs.la libtar.a tar2sqfs_LDADD += libfstree.a libcompat.a libfstree.a $(LZO_LIBS) tar2sqfs_LDADD += $(PTHREAD_LIBS) bin_PROGRAMS += sqfs2tar tar2sqfs squashfs-tools-ng-0.8/tar/sqfs2tar.c000066400000000000000000000352501360235375500174730ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * sqfs2tar.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "common.h" #include "tar.h" #include #include #include #include #include #include #include static struct option long_opts[] = { { "subdir", required_argument, NULL, 'd' }, { "keep-as-dir", no_argument, NULL, 'k' }, { "root-becomes", required_argument, NULL, 'r' }, { "no-skip", no_argument, NULL, 's' }, { "no-xattr", no_argument, NULL, 'X' }, { "no-hard-links", no_argument, NULL, 'L' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, }; static const char *short_opts = "d:kr:sXLhV"; static const char *usagestr = "Usage: sqfs2tar [OPTIONS...] \n" "\n" "Read an input squashfs archive and turn it into a tar archive, written\n" "to stdout.\n" "\n" "Possible options:\n" "\n" " --subdir, -d Unpack the given sub directory instead of the\n" " filesystem root. Can be specified more than\n" " once to select multiple directories. If only\n" " one is specified, it becomes the new root of\n" " node of the archive file system tree.\n" "\n" " --root-becomes, -r Turn the root inode into a directory with the\n" " specified name. Everything else will be stored\n" " inside this directory. The special value '.' is\n" " allowed to prefix all tar paths with './' and\n" " add an entry named '.' for the root inode.\n" " If this option isn't used, all meta data stored\n" " in the root inode IS LOST!\n" "\n" " --keep-as-dir, -k If --subdir is used only once, don't make the\n" " subdir the archive root, instead keep it as\n" " prefix for all unpacked files.\n" " Using --subdir more than once implies\n" " --keep-as-dir.\n" " --no-xattr, -X Do not copy extended attributes.\n" " --no-hard-links, -L Do not generate hard links. Produce duplicate\n" " entries instead.\n" "\n" " --no-skip, -s Abort if a file cannot be stored in a tar\n" " archive. By default, it is simply skipped\n" " and a warning is written to stderr.\n" "\n" " --help, -h Print help text and exit.\n" " --version, -V Print version information and exit.\n" "\n" "Examples:\n" "\n" "\tsqfs2tar rootfs.sqfs > rootfs.tar\n" "\tsqfs2tar rootfs.sqfs | gzip > rootfs.tar.gz\n" "\tsqfs2tar rootfs.sqfs | xz > rootfs.tar.xz\n" "\n"; static const char *filename; static unsigned int record_counter; static bool dont_skip = false; static bool keep_as_dir = false; static bool no_xattr = false; static bool no_links = false; static char *root_becomes = NULL; static char **subdirs = NULL; static size_t num_subdirs = 0; static size_t max_subdirs = 0; static sqfs_xattr_reader_t *xr; static sqfs_data_reader_t *data; static sqfs_file_t *file; static sqfs_super_t super; static sqfs_hard_link_t *links = NULL; static FILE *out_file = NULL; static void process_args(int argc, char **argv) { size_t idx, new_count; int i, ret; void *new; for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'd': if (num_subdirs == max_subdirs) { new_count = max_subdirs ? max_subdirs * 2 : 16; new = realloc(subdirs, new_count * sizeof(subdirs[0])); if (new == NULL) goto fail_errno; max_subdirs = new_count; subdirs = new; } subdirs[num_subdirs] = strdup(optarg); if (subdirs[num_subdirs] == NULL) goto fail_errno; if (canonicalize_name(subdirs[num_subdirs])) { perror(optarg); goto fail; } ++num_subdirs; break; case 'r': free(root_becomes); root_becomes = strdup(optarg); if (root_becomes == NULL) goto fail_errno; if (strcmp(root_becomes, "./") == 0) root_becomes[1] = '\0'; if (strcmp(root_becomes, ".") == 0) break; if (canonicalize_name(root_becomes) != 0 || strlen(root_becomes) == 0) { fprintf(stderr, "Invalid root directory '%s'.\n", optarg); goto fail_arg; } break; case 'k': keep_as_dir = true; break; case 's': dont_skip = true; break; case 'X': no_xattr = true; break; case 'L': no_links = true; break; case 'h': fputs(usagestr, stdout); goto out_success; case 'V': print_version("sqfs2tar"); goto out_success; default: goto fail_arg; } } if (optind >= argc) { fputs("Missing argument: squashfs image\n", stderr); goto fail_arg; } filename = argv[optind++]; if (optind < argc) { fputs("Unknown extra arguments\n", stderr); goto fail_arg; } if (num_subdirs > 1) keep_as_dir = true; return; fail_errno: perror("parsing options"); goto fail; fail_arg: fputs("Try `sqfs2tar --help' for more information.\n", stderr); goto fail; fail: ret = EXIT_FAILURE; goto out_exit; out_success: ret = EXIT_SUCCESS; goto out_exit; out_exit: for (idx = 0; idx < num_subdirs; ++idx) free(subdirs[idx]); free(root_becomes); free(subdirs); exit(ret); } static int terminate_archive(void) { char buffer[1024]; memset(buffer, '\0', sizeof(buffer)); return write_retry("adding archive terminator", out_file, buffer, sizeof(buffer)); } static int get_xattrs(const char *name, const sqfs_inode_generic_t *inode, tar_xattr_t **out) { tar_xattr_t *list = NULL, *ent; sqfs_xattr_value_t *value; sqfs_xattr_entry_t *key; sqfs_xattr_id_t desc; sqfs_u32 index; size_t i; int ret; if (xr == NULL) return 0; sqfs_inode_get_xattr_index(inode, &index); if (index == 0xFFFFFFFF) return 0; ret = sqfs_xattr_reader_get_desc(xr, index, &desc); if (ret) { sqfs_perror(name, "resolving xattr index", ret); return -1; } ret = sqfs_xattr_reader_seek_kv(xr, &desc); if (ret) { sqfs_perror(name, "locating xattr key-value pairs", ret); return -1; } for (i = 0; i < desc.count; ++i) { ret = sqfs_xattr_reader_read_key(xr, &key); if (ret) { sqfs_perror(name, "reading xattr key", ret); goto fail; } ret = sqfs_xattr_reader_read_value(xr, key, &value); if (ret) { sqfs_perror(name, "reading xattr value", ret); free(key); goto fail; } ent = calloc(1, sizeof(*ent) + strlen((const char *)key->key) + value->size + 2); if (ent == NULL) { perror("creating xattr entry"); free(key); free(value); goto fail; } ent->key = ent->data; strcpy(ent->key, (const char *)key->key); ent->value = (sqfs_u8 *)ent->key + strlen(ent->key) + 1; memcpy(ent->value, value->value, value->size + 1); ent->value_len = value->size; ent->next = list; list = ent; free(key); free(value); } *out = list; return 0; fail: while (list != NULL) { ent = list; list = list->next; free(ent); } return -1; } static char *prepend_prefix(char *name) { size_t len = strlen(root_becomes); char *temp = realloc(name, strlen(name) + len + 2); if (temp == NULL) { perror("assembling tar entry filename"); return NULL; } name = temp; memmove(name + len + 1, name, strlen(name) + 1); memcpy(name, root_becomes, len); name[len] = '/'; return name; } static int write_tree_dfs(const sqfs_tree_node_t *n) { tar_xattr_t *xattr = NULL, *xit; sqfs_hard_link_t *lnk = NULL; char *name, *target; struct stat sb; size_t len; int ret; if (n->parent == NULL) { if (root_becomes == NULL) goto skip_hdr; len = strlen(root_becomes); name = malloc(len + 2); if (name == NULL) { perror("creating root directory"); return -1; } memcpy(name, root_becomes, len); name[len] = '/'; name[len + 1] = '\0'; } else { if (!is_filename_sane((const char *)n->name, false)) { fprintf(stderr, "Found a file named '%s', skipping.\n", n->name); if (dont_skip) { fputs("Not allowed to skip files, aborting!\n", stderr); return -1; } return 0; } name = sqfs_tree_node_get_path(n); if (name == NULL) { perror("resolving tree node path"); return -1; } if (canonicalize_name(name)) goto out_skip; for (lnk = links; lnk != NULL; lnk = lnk->next) { if (lnk->inode_number == n->inode->base.inode_number) { if (strcmp(name, lnk->target) == 0) lnk = NULL; break; } } if (root_becomes != NULL) { name = prepend_prefix(name); if (name == NULL) return -1; } } inode_stat(n, &sb); if (lnk != NULL) { ret = write_hard_link(out_file, &sb, name, lnk->target, record_counter++); free(name); return ret; } if (!no_xattr) { if (get_xattrs(name, n->inode, &xattr)) { free(name); return -1; } } target = S_ISLNK(sb.st_mode) ? n->inode->slink_target : NULL; ret = write_tar_header(out_file, &sb, name, target, xattr, record_counter++); while (xattr != NULL) { xit = xattr; xattr = xattr->next; free(xit); } if (ret > 0) goto out_skip; if (ret < 0) { free(name); return -1; } if (S_ISREG(sb.st_mode)) { if (sqfs_data_reader_dump(name, data, n->inode, out_file, super.block_size, false)) { free(name); return -1; } if (padd_file(out_file, sb.st_size)) { free(name); return -1; } } free(name); skip_hdr: for (n = n->children; n != NULL; n = n->next) { if (write_tree_dfs(n)) return -1; } return 0; out_skip: if (dont_skip) { fputs("Not allowed to skip files, aborting!\n", stderr); ret = -1; } else { fprintf(stderr, "Skipping %s\n", name); ret = 0; } free(name); return ret; } static sqfs_tree_node_t *tree_merge(sqfs_tree_node_t *lhs, sqfs_tree_node_t *rhs) { sqfs_tree_node_t *head = NULL, **next_ptr = &head; sqfs_tree_node_t *it, *l, *r; int diff; while (lhs->children != NULL && rhs->children != NULL) { diff = strcmp((const char *)lhs->children->name, (const char *)rhs->children->name); if (diff < 0) { it = lhs->children; lhs->children = lhs->children->next; } else if (diff > 0) { it = rhs->children; rhs->children = rhs->children->next; } else { l = lhs->children; lhs->children = lhs->children->next; r = rhs->children; rhs->children = rhs->children->next; it = tree_merge(l, r); } *next_ptr = it; next_ptr = &it->next; } it = (lhs->children != NULL ? lhs->children : rhs->children); *next_ptr = it; sqfs_dir_tree_destroy(rhs); lhs->children = head; return lhs; } int main(int argc, char **argv) { sqfs_tree_node_t *root = NULL, *subtree; int flags, ret, status = EXIT_FAILURE; sqfs_compressor_config_t cfg; sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; sqfs_dir_reader_t *dr; sqfs_hard_link_t *lnk; size_t i; process_args(argc, argv); #ifdef _WIN32 _setmode(_fileno(stdout), _O_BINARY); out_file = stdout; #else out_file = freopen(NULL, "wb", stdout); #endif if (out_file == NULL) { perror("changing stdout to binary mode"); goto out_dirs; } file = sqfs_open_file(filename, SQFS_FILE_OPEN_READ_ONLY); if (file == NULL) { perror(filename); goto out_dirs; } ret = sqfs_super_read(&super, file); if (ret) { sqfs_perror(filename, "reading super block", ret); goto out_fd; } ret = sqfs_compressor_exists(super.compression_id); #ifdef WITH_LZO if (super.compression_id == SQFS_COMP_LZO) ret = true; #endif if (!ret) { fprintf(stderr, "%s: unknown compressor used.\n", filename); goto out_fd; } sqfs_compressor_config_init(&cfg, super.compression_id, super.block_size, SQFS_COMP_FLAG_UNCOMPRESS); cmp = sqfs_compressor_create(&cfg); #ifdef WITH_LZO if (super.compression_id == SQFS_COMP_LZO && cmp == NULL) cmp = lzo_compressor_create(&cfg); #endif if (cmp == NULL) { fputs("Error creating compressor.\n", stderr); goto out_fd; } if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { ret = cmp->read_options(cmp, file); if (ret) { sqfs_perror(filename, "reading compressor options", ret); goto out_cmp; } } idtbl = sqfs_id_table_create(); if (idtbl == NULL) { perror("creating ID table"); goto out_cmp; } ret = sqfs_id_table_read(idtbl, file, &super, cmp); if (ret) { sqfs_perror(filename, "loading ID table", ret); goto out_id; } data = sqfs_data_reader_create(file, super.block_size, cmp); if (data == NULL) { sqfs_perror(filename, "creating data reader", SQFS_ERROR_ALLOC); goto out_id; } ret = sqfs_data_reader_load_fragment_table(data, &super); if (ret) { sqfs_perror(filename, "loading fragment table", ret); goto out_data; } dr = sqfs_dir_reader_create(&super, cmp, file); if (dr == NULL) { sqfs_perror(filename, "creating dir reader", SQFS_ERROR_ALLOC); goto out_data; } if (!no_xattr && !(super.flags & SQFS_FLAG_NO_XATTRS)) { xr = sqfs_xattr_reader_create(file, &super, cmp); if (xr == NULL) { sqfs_perror(filename, "creating xattr reader", SQFS_ERROR_ALLOC); goto out_dr; } ret = sqfs_xattr_reader_load_locations(xr); if (ret) { sqfs_perror(filename, "loading xattr table", ret); goto out_xr; } } if (num_subdirs == 0) { ret = sqfs_dir_reader_get_full_hierarchy(dr, idtbl, NULL, 0, &root); if (ret) { sqfs_perror(filename, "loading filesystem tree", ret); goto out; } } else { flags = 0; if (keep_as_dir || num_subdirs > 1) flags = SQFS_TREE_STORE_PARENTS; for (i = 0; i < num_subdirs; ++i) { ret = sqfs_dir_reader_get_full_hierarchy(dr, idtbl, subdirs[i], flags, &subtree); if (ret) { sqfs_perror(subdirs[i], "loading filesystem " "tree", ret); goto out; } if (root == NULL) { root = subtree; } else { root = tree_merge(root, subtree); } } } if (!no_links) { if (sqfs_tree_find_hard_links(root, &links)) goto out_tree; if (root_becomes != NULL) { for (lnk = links; lnk != NULL; lnk = lnk->next) { lnk->target = prepend_prefix(lnk->target); if (lnk->target == NULL) goto out; } } } if (write_tree_dfs(root)) goto out; if (terminate_archive()) goto out; status = EXIT_SUCCESS; fflush(out_file); out: while (links != NULL) { lnk = links; links = links->next; free(lnk->target); free(lnk); } out_tree: if (root != NULL) sqfs_dir_tree_destroy(root); out_xr: if (xr != NULL) sqfs_xattr_reader_destroy(xr); out_dr: sqfs_dir_reader_destroy(dr); out_data: sqfs_data_reader_destroy(data); out_id: sqfs_id_table_destroy(idtbl); out_cmp: cmp->destroy(cmp); out_fd: file->destroy(file); out_dirs: for (i = 0; i < num_subdirs; ++i) free(subdirs[i]); free(subdirs); free(root_becomes); return status; } squashfs-tools-ng-0.8/tar/tar2sqfs.c000066400000000000000000000330361360235375500174730ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar2sqfs.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "common.h" #include "compat.h" #include "tar.h" #include #include #include #include #include #ifdef _WIN32 #include #endif static struct option long_opts[] = { { "root-becomes", required_argument, NULL, 'r' }, { "compressor", required_argument, NULL, 'c' }, { "block-size", required_argument, NULL, 'b' }, { "dev-block-size", required_argument, NULL, 'B' }, { "defaults", required_argument, NULL, 'd' }, { "num-jobs", required_argument, NULL, 'j' }, { "queue-backlog", required_argument, NULL, 'Q' }, { "comp-extra", required_argument, NULL, 'X' }, { "no-skip", no_argument, NULL, 's' }, { "no-xattr", no_argument, NULL, 'x' }, { "no-keep-time", no_argument, NULL, 'k' }, { "exportable", no_argument, NULL, 'e' }, { "no-tail-packing", no_argument, NULL, 'T' }, { "force", no_argument, NULL, 'f' }, { "quiet", no_argument, NULL, 'q' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, }; static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqThV"; static const char *usagestr = "Usage: tar2sqfs [OPTIONS...] \n" "\n" "Read an uncompressed tar archive from stdin and turn it into a squashfs\n" "filesystem image.\n" "\n" "Possible options:\n" "\n" " --root-becomes, -r The specified directory becomes the root.\n" " Only its children are packed into the image\n" " and its attributes (ownership, permissions,\n" " xattrs, ...) are stored in the root inode.\n" " If not set and a tarbal has an entry for './'\n" " or '/', it becomes the root instead.\n" "\n" " --compressor, -c Select the compressor to use.\n" " A list of available compressors is below.\n" " --comp-extra, -X A comma separated list of extra options for\n" " the selected compressor. Specify 'help' to\n" " get a list of available options.\n" " --num-jobs, -j Number of compressor jobs to create.\n" " --queue-backlog, -Q Maximum number of data blocks in the thread\n" " worker queue before the packer starts waiting\n" " for the block processors to catch up.\n" " Defaults to 10 times the number of jobs.\n" " --block-size, -b Block size to use for Squashfs image.\n" " Defaults to %u.\n" " --dev-block-size, -B Device block size to padd the image to.\n" " Defaults to %u.\n" " --defaults, -d A comma separated list of default values for\n" " implicitly created directories.\n" "\n" " Possible options:\n" " uid= 0 if not set.\n" " gid= 0 if not set.\n" " mode= 0755 if not set.\n" " mtime= 0 if not set.\n" "\n" " --no-skip, -s Abort if a tar record cannot be read instead\n" " of skipping it.\n" " --no-xattr, -x Do not copy extended attributes from archive.\n" " --no-keep-time, -k Do not keep the time stamps stored in the\n" " archive. Instead, set defaults on all files.\n" " --exportable, -e Generate an export table for NFS support.\n" " --no-tail-packing, -T Do not perform tail end packing on files that\n" " are larger than block size.\n" " --force, -f Overwrite the output file if it exists.\n" " --quiet, -q Do not print out progress reports.\n" " --help, -h Print help text and exit.\n" " --version, -V Print version information and exit.\n" "\n" "Examples:\n" "\n" "\ttar2sqfs rootfs.sqfs < rootfs.tar\n" "\tzcat rootfs.tar.gz | tar2sqfs rootfs.sqfs\n" "\txzcat rootfs.tar.xz | tar2sqfs rootfs.sqfs\n" "\n"; static bool dont_skip = false; static bool keep_time = true; static bool no_tail_pack = false; static sqfs_writer_cfg_t cfg; static sqfs_writer_t sqfs; static FILE *input_file = NULL; static char *root_becomes = NULL; static void process_args(int argc, char **argv) { bool have_compressor; int i, ret; sqfs_writer_cfg_init(&cfg); for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'T': no_tail_pack = true; break; case 'b': cfg.block_size = strtol(optarg, NULL, 0); break; case 'B': cfg.devblksize = strtol(optarg, NULL, 0); if (cfg.devblksize < 1024) { fputs("Device block size must be at " "least 1024\n", stderr); exit(EXIT_FAILURE); } break; case 'c': have_compressor = true; ret = sqfs_compressor_id_from_name(optarg); if (ret < 0) { have_compressor = false; #ifdef WITH_LZO if (cfg.comp_id == SQFS_COMP_LZO) have_compressor = true; #endif } if (!have_compressor) { fprintf(stderr, "Unsupported compressor '%s'\n", optarg); exit(EXIT_FAILURE); } cfg.comp_id = ret; break; case 'j': cfg.num_jobs = strtol(optarg, NULL, 0); break; case 'Q': cfg.max_backlog = strtol(optarg, NULL, 0); break; case 'X': cfg.comp_extra = optarg; break; case 'd': cfg.fs_defaults = optarg; break; case 'x': cfg.no_xattr = true; break; case 'k': keep_time = false; break; case 'r': free(root_becomes); root_becomes = strdup(optarg); if (root_becomes == NULL) { perror("copying root directory name"); exit(EXIT_FAILURE); } if (canonicalize_name(root_becomes) != 0 || strlen(root_becomes) == 0) { fprintf(stderr, "Invalid root directory '%s'.\n", optarg); goto fail_arg; } break; case 's': dont_skip = true; break; case 'e': cfg.exportable = true; break; case 'f': cfg.outmode |= SQFS_FILE_OPEN_OVERWRITE; break; case 'q': cfg.quiet = true; break; case 'h': printf(usagestr, SQFS_DEFAULT_BLOCK_SIZE, SQFS_DEVBLK_SIZE); compressor_print_available(); exit(EXIT_SUCCESS); case 'V': print_version("tar2sqfs"); exit(EXIT_SUCCESS); default: goto fail_arg; } } if (cfg.num_jobs < 1) cfg.num_jobs = 1; if (cfg.max_backlog < 1) cfg.max_backlog = 10 * cfg.num_jobs; if (cfg.comp_extra != NULL && strcmp(cfg.comp_extra, "help") == 0) { compressor_print_help(cfg.comp_id); exit(EXIT_SUCCESS); } if (optind >= argc) { fputs("Missing argument: squashfs image\n", stderr); goto fail_arg; } cfg.filename = argv[optind++]; if (optind < argc) { fputs("Unknown extra arguments\n", stderr); goto fail_arg; } return; fail_arg: fputs("Try `tar2sqfs --help' for more information.\n", stderr); exit(EXIT_FAILURE); } static int write_file(tar_header_decoded_t *hdr, file_info_t *fi, sqfs_u64 filesize) { const sparse_map_t *it; sqfs_inode_generic_t *inode; size_t size, max_blk_count; sqfs_file_t *file; sqfs_u64 sum; int flags; int ret; max_blk_count = filesize / cfg.block_size; if (filesize % cfg.block_size) ++max_blk_count; if (SZ_MUL_OV(sizeof(sqfs_u32), max_blk_count, &size) || SZ_ADD_OV(sizeof(*inode), size, &size)) { fputs("creating file inode: too many blocks\n", stderr); return -1; } inode = calloc(1, size); if (inode == NULL) { perror("creating file inode"); return -1; } inode->block_sizes = (sqfs_u32 *)inode->extra; inode->base.type = SQFS_INODE_FILE; sqfs_inode_set_file_size(inode, filesize); sqfs_inode_set_frag_location(inode, 0xFFFFFFFF, 0xFFFFFFFF); fi->user_ptr = inode; if (hdr->sparse != NULL) { for (sum = 0, it = hdr->sparse; it != NULL; it = it->next) sum += it->count; file = sqfs_get_stdin_file(input_file, hdr->sparse, sum); if (file == NULL) { perror("packing files"); return -1; } } else { file = sqfs_get_stdin_file(input_file, NULL, filesize); if (file == NULL) { perror("packing files"); return -1; } } flags = 0; if (no_tail_pack && filesize > cfg.block_size) flags |= SQFS_BLK_DONT_FRAGMENT; ret = write_data_from_file(hdr->name, sqfs.data, inode, file, 0); file->destroy(file); sqfs.stats.bytes_read += filesize; sqfs.stats.file_count += 1; if (ret) return -1; return skip_padding(input_file, hdr->sparse == NULL ? filesize : hdr->record_size); } static int copy_xattr(tree_node_t *node, const tar_header_decoded_t *hdr) { tar_xattr_t *xattr; int ret; ret = sqfs_xattr_writer_begin(sqfs.xwr); if (ret) { sqfs_perror(hdr->name, "beginning xattr block", ret); return -1; } for (xattr = hdr->xattr; xattr != NULL; xattr = xattr->next) { if (sqfs_get_xattr_prefix_id(xattr->key) < 0) { fprintf(stderr, "%s: squashfs does not " "support xattr prefix of %s\n", dont_skip ? "ERROR" : "WARNING", xattr->key); if (dont_skip) return -1; continue; } ret = sqfs_xattr_writer_add(sqfs.xwr, xattr->key, xattr->value, xattr->value_len); if (ret) { sqfs_perror(hdr->name, "storing xattr key-value pair", ret); return -1; } } ret = sqfs_xattr_writer_end(sqfs.xwr, &node->xattr_idx); if (ret) { sqfs_perror(hdr->name, "completing xattr block", ret); return -1; } return 0; } static int create_node_and_repack_data(tar_header_decoded_t *hdr) { tree_node_t *node; if (hdr->is_hard_link) { node = fstree_add_hard_link(&sqfs.fs, hdr->name, hdr->link_target); if (node == NULL) goto fail_errno; if (!cfg.quiet) { printf("Hard link %s -> %s\n", hdr->name, hdr->link_target); } return 0; } if (!keep_time) { hdr->sb.st_mtime = sqfs.fs.defaults.st_mtime; } node = fstree_add_generic(&sqfs.fs, hdr->name, &hdr->sb, hdr->link_target); if (node == NULL) goto fail_errno; if (!cfg.quiet) printf("Packing %s\n", hdr->name); if (!cfg.no_xattr) { if (copy_xattr(node, hdr)) return -1; } if (S_ISREG(hdr->sb.st_mode)) { if (write_file(hdr, &node->data.file, hdr->sb.st_size)) return -1; } return 0; fail_errno: perror(hdr->name); return -1; } static int set_root_attribs(const tar_header_decoded_t *hdr) { if (hdr->is_hard_link || !S_ISDIR(hdr->sb.st_mode)) { fprintf(stderr, "'%s' is not a directory!\n", hdr->name); return -1; } sqfs.fs.root->uid = hdr->sb.st_uid; sqfs.fs.root->gid = hdr->sb.st_gid; sqfs.fs.root->mode = hdr->sb.st_mode; if (keep_time) sqfs.fs.root->mod_time = hdr->sb.st_mtime; if (!cfg.no_xattr) { if (copy_xattr(sqfs.fs.root, hdr)) return -1; } return 0; } static int process_tar_ball(void) { bool skip, is_root, is_prefixed; tar_header_decoded_t hdr; sqfs_u64 offset, count; sparse_map_t *m; size_t rootlen; int ret; rootlen = root_becomes == NULL ? 0 : strlen(root_becomes); for (;;) { ret = read_header(input_file, &hdr); if (ret > 0) break; if (ret < 0) return -1; if (hdr.mtime < 0) hdr.mtime = 0; if ((sqfs_u64)hdr.mtime > 0x0FFFFFFFFUL) hdr.mtime = 0x0FFFFFFFFUL; hdr.sb.st_mtime = hdr.mtime; skip = false; is_root = false; is_prefixed = true; if (hdr.name == NULL || canonicalize_name(hdr.name) != 0) { fprintf(stderr, "skipping '%s' (invalid name)\n", hdr.name); skip = true; } if (root_becomes != NULL) { if (strncmp(hdr.name, root_becomes, rootlen) == 0) { if (hdr.name[rootlen] == '\0') { is_root = true; } else if (hdr.name[rootlen] != '/') { is_prefixed = false; } } else { is_prefixed = false; } if (is_prefixed && !is_root) { memmove(hdr.name, hdr.name + rootlen + 1, strlen(hdr.name + rootlen + 1) + 1); } if (is_prefixed && hdr.name[0] == '\0') { fputs("skipping entry with empty name\n", stderr); skip = true; } } else if (hdr.name[0] == '\0') { is_root = true; } if (!is_prefixed) { clear_header(&hdr); continue; } if (is_root) { if (set_root_attribs(&hdr)) goto fail; clear_header(&hdr); continue; } if (!skip && hdr.unknown_record) { fprintf(stderr, "%s: unknown entry type\n", hdr.name); skip = true; } if (!skip && hdr.sparse != NULL) { offset = hdr.sparse->offset; count = 0; for (m = hdr.sparse; m != NULL; m = m->next) { if (m->offset < offset) { skip = true; break; } offset = m->offset + m->count; count += m->count; } if (count != hdr.record_size) skip = true; if (skip) { fprintf(stderr, "%s: broken sparse " "file layout\n", hdr.name); } } if (skip) { if (dont_skip) goto fail; if (skip_entry(input_file, hdr.sb.st_size)) goto fail; clear_header(&hdr); continue; } if (create_node_and_repack_data(&hdr)) goto fail; clear_header(&hdr); } return 0; fail: clear_header(&hdr); return -1; } int main(int argc, char **argv) { int status = EXIT_FAILURE; process_args(argc, argv); #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); input_file = stdin; #else input_file = freopen(NULL, "rb", stdin); #endif if (input_file == NULL) { perror("changing stdin to binary mode"); return EXIT_FAILURE; } if (sqfs_writer_init(&sqfs, &cfg)) return EXIT_FAILURE; if (process_tar_ball()) goto out; if (fstree_post_process(&sqfs.fs)) goto out; if (sqfs_writer_finish(&sqfs, &cfg)) goto out; status = EXIT_SUCCESS; out: sqfs_writer_cleanup(&sqfs); return status; } squashfs-tools-ng-0.8/tests/000077500000000000000000000000001360235375500161315ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/Makemodule.am000066400000000000000000000125051360235375500205360ustar00rootroot00000000000000test_canonicalize_name_SOURCES = tests/canonicalize_name.c test_canonicalize_name_LDADD = libfstree.a test_str_table_SOURCES = tests/str_table.c lib/sqfs/str_table.c test_str_table_SOURCES += lib/sqfs/alloc.c lib/sqfs/util.h test_str_table_SOURCES += lib/sqfs/str_table.h test_str_table_LDADD = libcompat.a test_str_table_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests test_str_table_CPPFLAGS += -I$(top_srcdir)/lib/sqfs test_abi_SOURCES = tests/abi.c test_abi_LDADD = libsquashfs.la check_PROGRAMS += test_canonicalize_name test_str_table test_abi TESTS += test_canonicalize_name test_str_table test_abi if BUILD_TOOLS test_mknode_simple_SOURCES = tests/mknode_simple.c test_mknode_simple_LDADD = libfstree.a libcompat.a test_mknode_slink_SOURCES = tests/mknode_slink.c test_mknode_slink_LDADD = libfstree.a libcompat.a test_mknode_reg_SOURCES = tests/mknode_reg.c test_mknode_reg_LDADD = libfstree.a libcompat.a test_mknode_dir_SOURCES = tests/mknode_dir.c test_mknode_dir_LDADD = libfstree.a libcompat.a test_gen_inode_numbers_SOURCES = tests/gen_inode_numbers.c test_gen_inode_numbers_LDADD = libfstree.a libcompat.a test_add_by_path_SOURCES = tests/add_by_path.c test_add_by_path_LDADD = libfstree.a libcompat.a test_get_path_SOURCES = tests/get_path.c test_get_path_LDADD = libfstree.a libcompat.a test_fstree_sort_SOURCES = tests/fstree_sort.c test_fstree_sort_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib/fstree test_fstree_sort_LDADD = libfstree.a libcompat.a test_fstree_from_file_SOURCES = tests/fstree_from_file.c test_fstree_from_file_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/fstree1.txt test_fstree_from_file_LDADD = libfstree.a libcompat.a test_fstree_init_SOURCES = tests/fstree_init.c test_fstree_init_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib/fstree test_fstree_init_LDADD = libfstree.a libcompat.a test_filename_sane_SOURCES = tests/filename_sane.c lib/fstree/filename_sane.c test_filename_sane_w32_SOURCES = tests/filename_sane.c test_filename_sane_w32_SOURCES += lib/fstree/filename_sane.c test_filename_sane_w32_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_WIN32=1 test_tar_gnu_SOURCES = tests/tar_gnu.c test_tar_gnu_LDADD = libtar.a libcompat.a test_tar_gnu_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/tar test_tar_pax_SOURCES = tests/tar_pax.c test_tar_pax_LDADD = libtar.a libcompat.a test_tar_pax_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/tar test_tar_ustar_SOURCES = tests/tar_ustar.c test_tar_ustar_LDADD = libtar.a libcompat.a test_tar_ustar_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/tar test_tar_sparse_gnu_SOURCES = tests/tar_sparse_gnu.c test_tar_sparse_gnu_LDADD = libtar.a libcompat.a test_tar_sparse_gnu_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/tar test_tar_sparse_gnu1_SOURCES = tests/tar_sparse_gnu1.c test_tar_sparse_gnu1_LDADD = libtar.a libcompat.a test_tar_sparse_gnu1_CPPFLAGS = $(AM_CPPFLAGS) test_tar_sparse_gnu1_CPPFLAGS += -DTESTPATH=$(top_srcdir)/tests/tar test_tar_sparse_gnu2_SOURCES = tests/tar_sparse_gnu1.c test_tar_sparse_gnu2_LDADD = libtar.a libcompat.a test_tar_sparse_gnu2_CPPFLAGS = $(AM_CPPFLAGS) test_tar_sparse_gnu2_CPPFLAGS += -DTESTPATH=$(top_srcdir)/tests/tar test_tar_xattr_bsd_SOURCES = tests/tar_xattr_bsd.c test_tar_xattr_bsd_LDADD = libtar.a libcompat.a test_tar_xattr_bsd_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests/tar test_tar_xattr_schily_SOURCES = tests/tar_xattr_schily.c test_tar_xattr_schily_LDADD = libtar.a libcompat.a test_tar_xattr_schily_CPPFLAGS = $(AM_CPPFLAGS) test_tar_xattr_schily_CPPFLAGS += -DTESTPATH=$(top_srcdir)/tests/tar test_tar_xattr_schily_bin_SOURCES = tests/tar_xattr_schily_bin.c test_tar_xattr_schily_bin_LDADD = libtar.a libcompat.a test_tar_xattr_schily_bin_CPPFLAGS = $(AM_CPPFLAGS) test_tar_xattr_schily_bin_CPPFLAGS += -DTESTPATH=$(top_srcdir)/tests/tar fstree_fuzz_SOURCES = tests/fstree_fuzz.c fstree_fuzz_LDADD = libfstree.a libcompat.a tar_fuzz_SOURCES = tests/tar_fuzz.c tar_fuzz_LDADD = libtar.a libcompat.a check_PROGRAMS += test_mknode_simple test_mknode_slink test_mknode_reg check_PROGRAMS += test_mknode_dir test_gen_inode_numbers test_add_by_path check_PROGRAMS += test_get_path test_fstree_sort test_fstree_from_file check_PROGRAMS += test_fstree_init test_filename_sane test_filename_sane_w32 check_PROGRAMS += test_tar_ustar test_tar_pax test_tar_gnu check_PROGRAMS += test_tar_sparse_gnu test_tar_sparse_gnu1 test_tar_sparse_gnu2 check_PROGRAMS += test_tar_xattr_bsd test_tar_xattr_schily check_PROGRAMS += test_tar_xattr_schily_bin noinst_PROGRAMS += fstree_fuzz tar_fuzz TESTS += test_mknode_simple test_mknode_slink TESTS += test_mknode_reg test_mknode_dir test_gen_inode_numbers TESTS += test_add_by_path test_get_path test_fstree_sort test_fstree_from_file TESTS += test_fstree_init test_filename_sane test_filename_sane_w32 TESTS += test_tar_ustar test_tar_pax TESTS += test_tar_gnu test_tar_sparse_gnu test_tar_sparse_gnu1 TESTS += test_tar_sparse_gnu2 test_tar_xattr_bsd test_tar_xattr_schily TESTS += test_tar_xattr_schily_bin if CORPORA_TESTS check_SCRIPTS += tests/cantrbry.sh tests/test_tar_sqfs.sh TESTS += tests/cantrbry.sh tests/test_tar_sqfs.sh endif endif EXTRA_DIST += $(top_srcdir)/tests/tar $(top_srcdir)/tests/words.txt EXTRA_DIST += $(top_srcdir)/tests/fstree1.txt EXTRA_DIST += $(top_srcdir)/tests/corpus/cantrbry.tar.xz EXTRA_DIST += $(top_srcdir)/tests/corpus/cantrbry.sha512 squashfs-tools-ng-0.8/tests/abi.c000066400000000000000000000010421360235375500170250ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * abi.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "sqfs/compressor.h" #include #include int main(void) { sqfs_compressor_config_t cfg; assert(sizeof(cfg.opt.gzip) == sizeof(cfg.opt)); assert(sizeof(cfg.opt.zstd) == sizeof(cfg.opt)); assert(sizeof(cfg.opt.lzo) == sizeof(cfg.opt)); assert(sizeof(cfg.opt.xz) == sizeof(cfg.opt)); assert(sizeof(cfg.opt.padd0) == sizeof(cfg.opt)); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/add_by_path.c000066400000000000000000000065501360235375500205410ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * add_by_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include #include int main(void) { tree_node_t *a, *b; struct stat sb; fstree_t fs; char *opts; opts = strdup("mode=0755,uid=21,gid=42"); assert(fstree_init(&fs, opts) == 0); free(opts); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0750; sb.st_uid = 1000; sb.st_gid = 100; assert(fs.root->link_count == 2); a = fstree_add_generic(&fs, "dir", &sb, NULL); assert(a != NULL); assert(strcmp(a->name, "dir") == 0); assert(a->mode == sb.st_mode); assert(a->uid == sb.st_uid); assert(a->gid == sb.st_gid); assert(a->parent == fs.root); assert(a->link_count == 2); assert(a->next == NULL); assert(fs.root->data.dir.children == a); assert(fs.root->link_count == 3); assert(!a->data.dir.created_implicitly); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFBLK | 0640; sb.st_rdev = 1234; b = fstree_add_generic(&fs, "blkdev", &sb, NULL); assert(b != NULL); assert(b != a); assert(strcmp(b->name, "blkdev") == 0); assert(b->mode == sb.st_mode); assert(b->uid == sb.st_uid); assert(b->gid == sb.st_gid); assert(b->parent == fs.root); assert(b->link_count == 1); assert(b->data.devno == sb.st_rdev); assert(b->next == a); assert(fs.root->link_count == 4); assert(fs.root->data.dir.children == b); assert(fstree_add_generic(&fs, "blkdev/foo", &sb, NULL) == NULL); assert(errno == ENOTDIR); assert(fstree_add_generic(&fs, "dir", &sb, NULL) == NULL); assert(errno == EEXIST); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0755; assert(fstree_add_generic(&fs, "dir", &sb, NULL) == NULL); assert(errno == EEXIST); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFCHR | 0444; b = fstree_add_generic(&fs, "dir/chrdev", &sb, NULL); assert(b != NULL); assert(b->mode == sb.st_mode); assert(b->uid == sb.st_uid); assert(b->gid == sb.st_gid); assert(b->link_count == 1); assert(b->parent == a); assert(b->data.devno == sb.st_rdev); assert(b->next == NULL); assert(a->data.dir.children == b); assert(a->link_count == 3); assert(fs.root->link_count == 4); b = fstree_add_generic(&fs, "dir/foo/chrdev", &sb, NULL); assert(b != NULL); assert(b->next == NULL); assert(b->mode == sb.st_mode); assert(b->uid == sb.st_uid); assert(b->gid == sb.st_gid); assert(b->link_count == 1); assert(b->parent != a); assert(b->parent->parent == a); assert(b->data.devno == sb.st_rdev); assert(b->next == NULL); assert(a->link_count == 4); assert(fs.root->link_count == 4); assert(a->data.dir.children != b); b = b->parent; assert(b->data.dir.created_implicitly); assert(b->mode == (S_IFDIR | 0755)); assert(b->uid == 21); assert(b->gid == 42); assert(b->link_count == 3); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0750; sb.st_uid = 1000; sb.st_gid = 100; a = fstree_add_generic(&fs, "dir/foo", &sb, NULL); assert(a != NULL); assert(a == b); assert(!a->data.dir.created_implicitly); assert(a->mode == sb.st_mode); assert(a->uid == sb.st_uid); assert(a->gid == sb.st_gid); assert(a->link_count == 3); assert(a->parent->link_count == 4); assert(fs.root->link_count == 4); assert(fstree_add_generic(&fs, "dir/foo", &sb, NULL) == NULL); assert(errno == EEXIST); fstree_cleanup(&fs); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/canonicalize_name.c000066400000000000000000000033251360235375500217370ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * canonicalize_name.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include static const struct { const char *in; const char *out; } must_work[] = { { "", "" }, { "/", "" }, { "\\", "" }, { "///", "" }, { "\\\\\\", "" }, { "/\\//\\\\/", "" }, { "foo/bar/test", "foo/bar/test" }, { "foo\\bar\\test", "foo/bar/test" }, { "/foo/bar/test/", "foo/bar/test" }, { "\\foo\\bar\\test\\", "foo/bar/test" }, { "///foo//bar//test///", "foo/bar/test" }, { "./foo/././bar/test/./.", "foo/bar/test" }, { "./foo/././", "foo" }, { ".", "" }, { "./", "" }, { "./.", "" }, { "foo/.../bar", "foo/.../bar" }, { "foo/.test/bar", "foo/.test/bar" }, }; static const char *must_not_work[] = { "..", "foo/../bar", "../foo/bar", "foo/bar/..", "foo/bar/../", }; int main(void) { char buffer[512]; size_t i; for (i = 0; i < sizeof(must_work) / sizeof(must_work[0]); ++i) { strcpy(buffer, must_work[i].in); if (canonicalize_name(buffer)) { fprintf(stderr, "Test case rejected: '%s'\n", must_work[i].in); return EXIT_FAILURE; } if (strcmp(buffer, must_work[i].out) != 0) { fprintf(stderr, "Expected result: %s\n", must_work[i].out); fprintf(stderr, "Actual result: %s\n", buffer); return EXIT_FAILURE; } } for (i = 0; i < sizeof(must_not_work) / sizeof(must_not_work[0]); ++i) { strcpy(buffer, must_not_work[i]); if (canonicalize_name(buffer) == 0) { fprintf(stderr, "Test case accepted: '%s'\n", must_not_work[i]); fprintf(stderr, "Transformed into: '%s'\n", buffer); return EXIT_FAILURE; } } return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/cantrbry.sh.in000077500000000000000000000024411360235375500207220ustar00rootroot00000000000000#!/bin/sh set -e CORPUS="@abs_top_srcdir@/tests/corpus/cantrbry.tar.xz" SHA512FILE="@abs_top_srcdir@/tests/corpus/cantrbry.sha512" TAR2SQFS="@abs_top_builddir@/tar2sqfs" if [ ! -f "$TAR2SQFS" -a -f "${TAR2SQFS}.exe" ]; then TAR2SQFS="${TAR2SQFS}.exe" fi COMPRESSORS=$("$TAR2SQFS" --help | tr -d '\015' |\ awk '/Available compressors:/,EOF' | sed -n '/\t/p') for size in 4096 8192 16384 32768 65536 131072 262144 524288 1048576; do for cmp in $COMPRESSORS; do for threads in 1 2 3 4; do name="cantrbry_${cmp}_${size}_${threads}.sqfs" xzcat "$CORPUS" | \ "$TAR2SQFS" -q -c "$cmp" -b "$size" \ -j "$threads" --defaults mtime=0 \ "$name" name="cantrbry_${cmp}_${size}_${threads}_T.sqfs" xzcat "$CORPUS" | \ "$TAR2SQFS" -qT -c "$cmp" -b "$size" \ -j "$threads" --defaults mtime=0 \ "$name" done # check that the ones with > 1 thread are identical, # then remove them. for threads in 2 3 4; do name="cantrbry_${cmp}_${size}_${threads}.sqfs" ref="cantrbry_${cmp}_${size}_1.sqfs" diff "$name" "$ref" rm "$name" name="cantrbry_${cmp}_${size}_${threads}_T.sqfs" ref="cantrbry_${cmp}_${size}_1_T.sqfs" diff "$name" "$ref" rm "$name" done done done sha512sum --ignore-missing -c "$SHA512FILE" rm cantrbry_*.sqfs squashfs-tools-ng-0.8/tests/corpus/000077500000000000000000000000001360235375500174445ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/corpus/cantrbry.sha512000066400000000000000000000412041360235375500222160ustar00rootroot000000000000008ca4426181c8d1ffc3272e9d5726dad9aa5515c16897b05d2aa984a71f18df85bf99234e62b1edd297cc570f8b93deeba4654493d68818ce6ee0c0b246a6ab5b cantrbry_gzip_1048576_1.sqfs 8ca4426181c8d1ffc3272e9d5726dad9aa5515c16897b05d2aa984a71f18df85bf99234e62b1edd297cc570f8b93deeba4654493d68818ce6ee0c0b246a6ab5b cantrbry_gzip_1048576_1_T.sqfs 585f5214eca73a1c13dae4cdb92855d4f341cf823807de5e546a19f74a81d80ba9fad916b864bc34bebc04e651d91450345eb8f4f2b2f9af3dfed0ce2449b778 cantrbry_gzip_131072_1.sqfs 585f5214eca73a1c13dae4cdb92855d4f341cf823807de5e546a19f74a81d80ba9fad916b864bc34bebc04e651d91450345eb8f4f2b2f9af3dfed0ce2449b778 cantrbry_gzip_131072_1_T.sqfs 6917aa213bb0ecb2caa1a60e5ea7eecb9463662e8da2d3fa61b70f5f64607b7f9b3a491bb86868d3310fd5fa90b7c4f49a88daa1d40f51923f0cda7632c85796 cantrbry_gzip_16384_1.sqfs 6917aa213bb0ecb2caa1a60e5ea7eecb9463662e8da2d3fa61b70f5f64607b7f9b3a491bb86868d3310fd5fa90b7c4f49a88daa1d40f51923f0cda7632c85796 cantrbry_gzip_16384_1_T.sqfs 0fca5cda692115d1bc5678a24adba44af29faa8f0700857744ba6d51becc26220f838c46769713f84f987af1075cd6da71d914ae5b67f9ec09d911cf3cff2ee6 cantrbry_gzip_262144_1.sqfs 0fca5cda692115d1bc5678a24adba44af29faa8f0700857744ba6d51becc26220f838c46769713f84f987af1075cd6da71d914ae5b67f9ec09d911cf3cff2ee6 cantrbry_gzip_262144_1_T.sqfs 294fc5b6f0612d4f90de69f734a7cbb4e639e0772da589a85d871ebae380c809be1b582c200c6340192a5f41d3067e977ccd3659640a6618c308977dbb12ba01 cantrbry_gzip_32768_1.sqfs 294fc5b6f0612d4f90de69f734a7cbb4e639e0772da589a85d871ebae380c809be1b582c200c6340192a5f41d3067e977ccd3659640a6618c308977dbb12ba01 cantrbry_gzip_32768_1_T.sqfs 5babc9729e66ae5c92e3864dea6fb35f23aa3317d5f0807959b10228cd3240cc49365dab3667bd883b3d5449263eef6bc8dd8c31a215912724ea470404b994fb cantrbry_gzip_4096_1.sqfs 5babc9729e66ae5c92e3864dea6fb35f23aa3317d5f0807959b10228cd3240cc49365dab3667bd883b3d5449263eef6bc8dd8c31a215912724ea470404b994fb cantrbry_gzip_4096_1_T.sqfs 87c79b5e4199e64fb11a48ca6b80fe10cd0377077bb0a0feef33db73f800cd73fde6dc921f78003b8c7be0892d00d373e2580d4c2afcdabb64ba152ad60c375a cantrbry_gzip_524288_1.sqfs 87c79b5e4199e64fb11a48ca6b80fe10cd0377077bb0a0feef33db73f800cd73fde6dc921f78003b8c7be0892d00d373e2580d4c2afcdabb64ba152ad60c375a cantrbry_gzip_524288_1_T.sqfs 6e1d0290dc45a5f7e927f9fa859c7c416a73ad2cf57b017404f40dce03305a90682fe615e5cd247d1bc757188962169e679c8de9d4b97632bef94c020e0fe842 cantrbry_gzip_65536_1.sqfs 6e1d0290dc45a5f7e927f9fa859c7c416a73ad2cf57b017404f40dce03305a90682fe615e5cd247d1bc757188962169e679c8de9d4b97632bef94c020e0fe842 cantrbry_gzip_65536_1_T.sqfs 74a9ea2b90721e366f2d68c0727e9f4837f906fb6c954ba8a5ff8f1a204fe12251cf0927c05776f6382a961f7502ebb13ba15a07515c2bab51c00ca9ad20dbc3 cantrbry_gzip_8192_1.sqfs 74a9ea2b90721e366f2d68c0727e9f4837f906fb6c954ba8a5ff8f1a204fe12251cf0927c05776f6382a961f7502ebb13ba15a07515c2bab51c00ca9ad20dbc3 cantrbry_gzip_8192_1_T.sqfs a8ab50996335f68851a69666398cf39ee3d5d5aba064f08b03cd5d5efee15ddc41628bef72a84798ec17849619eec67ae4bf4b03c16b3fe4736126890526602f cantrbry_lz4_1048576_1.sqfs a8ab50996335f68851a69666398cf39ee3d5d5aba064f08b03cd5d5efee15ddc41628bef72a84798ec17849619eec67ae4bf4b03c16b3fe4736126890526602f cantrbry_lz4_1048576_1_T.sqfs 21c9fdae669250203289bc32048b5238a94ad1b685b45aa6c01f615bd21a1a2dc7a980be28538070b586ae9f28d063c2014d60950d4f6b25cfc92cc98a3735e1 cantrbry_lz4_131072_1.sqfs 21c9fdae669250203289bc32048b5238a94ad1b685b45aa6c01f615bd21a1a2dc7a980be28538070b586ae9f28d063c2014d60950d4f6b25cfc92cc98a3735e1 cantrbry_lz4_131072_1_T.sqfs 1f7846a6cd809a933f6fd41ee6538aeea7591ec2d91a95e01e1dfc3da5fab673d0a59a430443c4089228c7529323e994d24b2cf898585f67e2193f1edd5e605f cantrbry_lz4_16384_1.sqfs 1f7846a6cd809a933f6fd41ee6538aeea7591ec2d91a95e01e1dfc3da5fab673d0a59a430443c4089228c7529323e994d24b2cf898585f67e2193f1edd5e605f cantrbry_lz4_16384_1_T.sqfs 5e5ac30b64157626b8a3a168ab71f61839239de9c6c0fee129398e2dd88bcd66a1112ea5c13ab5b4b25fa419e2ad767e438c58871d8297a0e5590e0572080eb4 cantrbry_lz4_262144_1.sqfs 5e5ac30b64157626b8a3a168ab71f61839239de9c6c0fee129398e2dd88bcd66a1112ea5c13ab5b4b25fa419e2ad767e438c58871d8297a0e5590e0572080eb4 cantrbry_lz4_262144_1_T.sqfs 8ffe892e9d67d01e68e6ae77962a28f48f0cc7013ed56bfca9232f9db7db3caffad15180e02f924317f172946fde4e973a928849a7834f49606dc05502158068 cantrbry_lz4_32768_1.sqfs 8ffe892e9d67d01e68e6ae77962a28f48f0cc7013ed56bfca9232f9db7db3caffad15180e02f924317f172946fde4e973a928849a7834f49606dc05502158068 cantrbry_lz4_32768_1_T.sqfs ee494abb8bb0701a846b3aad499734dd10470496e5e876c42c0b01cd804b6f0fd11950c00f80e38c21bb25a7b08d32fdb83045e623c0f7843fb7cdb99bccf501 cantrbry_lz4_4096_1.sqfs ee494abb8bb0701a846b3aad499734dd10470496e5e876c42c0b01cd804b6f0fd11950c00f80e38c21bb25a7b08d32fdb83045e623c0f7843fb7cdb99bccf501 cantrbry_lz4_4096_1_T.sqfs d1f1799810758ad01c26e4929a52d333848b67ca44f457e8e2564376c1c70a2b21103ed79b54e25f38db7ca415effacb24c9e0af0bddf186c3c0718f05185aae cantrbry_lz4_524288_1.sqfs d1f1799810758ad01c26e4929a52d333848b67ca44f457e8e2564376c1c70a2b21103ed79b54e25f38db7ca415effacb24c9e0af0bddf186c3c0718f05185aae cantrbry_lz4_524288_1_T.sqfs da0fc626bd29452ddabff31d6364b9c9585e0bc7f3d998379b14abf51eb14dc4d66e8962a0e8a13015386072d13ef88b1eeb028388f68ab172ddb6a7d30ef1fb cantrbry_lz4_65536_1.sqfs da0fc626bd29452ddabff31d6364b9c9585e0bc7f3d998379b14abf51eb14dc4d66e8962a0e8a13015386072d13ef88b1eeb028388f68ab172ddb6a7d30ef1fb cantrbry_lz4_65536_1_T.sqfs 96e4a59630e402e267d7ade6aa5b483c2d08d279ba1a47ce3af7891bd48d01bb6ecbc816067e113bd88bee9ef76ff8b3078166c3bcf46c95e4072db385e446a4 cantrbry_lz4_8192_1.sqfs 96e4a59630e402e267d7ade6aa5b483c2d08d279ba1a47ce3af7891bd48d01bb6ecbc816067e113bd88bee9ef76ff8b3078166c3bcf46c95e4072db385e446a4 cantrbry_lz4_8192_1_T.sqfs 98e02cb00e61f807010fac696496d55ffdbef04c35bac3817daa425b18abe08cba0150798dc5e3e5b6ca29cad339aa555e37952e3e1172c03a2af2c49f1019b3 cantrbry_lzma_1048576_1.sqfs 98e02cb00e61f807010fac696496d55ffdbef04c35bac3817daa425b18abe08cba0150798dc5e3e5b6ca29cad339aa555e37952e3e1172c03a2af2c49f1019b3 cantrbry_lzma_1048576_1_T.sqfs 5e2a2d44e10f4a5544a8dc39741f5637978184c71b7a68b3104e94962305da0d5610c7c9232b121495cf69a5d064509b9c0909128c97affd169ef811d8274671 cantrbry_lzma_131072_1.sqfs 5e2a2d44e10f4a5544a8dc39741f5637978184c71b7a68b3104e94962305da0d5610c7c9232b121495cf69a5d064509b9c0909128c97affd169ef811d8274671 cantrbry_lzma_131072_1_T.sqfs 8af56c478418d3c29bea9688a6248d8a3fb203891f387cdb1a0be1e3b3697942372780f606913ee5e75b5b222001123b9027fea96b560e3a3ac47279c77273f1 cantrbry_lzma_16384_1.sqfs 8af56c478418d3c29bea9688a6248d8a3fb203891f387cdb1a0be1e3b3697942372780f606913ee5e75b5b222001123b9027fea96b560e3a3ac47279c77273f1 cantrbry_lzma_16384_1_T.sqfs 06e3f084a4b3915bab11b2d7eea709b6d630bcc62754a5c8eae7f7d37ddbec522f07df7aa449b55cbb40986398911be907e0be336ce2f2a1505e97c84933766a cantrbry_lzma_262144_1.sqfs 06e3f084a4b3915bab11b2d7eea709b6d630bcc62754a5c8eae7f7d37ddbec522f07df7aa449b55cbb40986398911be907e0be336ce2f2a1505e97c84933766a cantrbry_lzma_262144_1_T.sqfs b8b66bbd0257ada9a6731d3f67cdc134b3b080be7aea078c8c1b68e1d201d8bdd7885d618e6549989d4a01f133b4903ecc1e314e57f45d34326eba4a6a5cb60d cantrbry_lzma_32768_1.sqfs b8b66bbd0257ada9a6731d3f67cdc134b3b080be7aea078c8c1b68e1d201d8bdd7885d618e6549989d4a01f133b4903ecc1e314e57f45d34326eba4a6a5cb60d cantrbry_lzma_32768_1_T.sqfs 679f53f2dbf10339427c0fc695917a956f287840ceb43e874c36d118c1c9e4aff8c276fa0dffa05dd29515bb48f5aec92632a3df55cdcf626e9ffa8d6d607012 cantrbry_lzma_4096_1.sqfs 679f53f2dbf10339427c0fc695917a956f287840ceb43e874c36d118c1c9e4aff8c276fa0dffa05dd29515bb48f5aec92632a3df55cdcf626e9ffa8d6d607012 cantrbry_lzma_4096_1_T.sqfs e9f4be0861eb0637ccab409c40dc0c6d29b6c56b98ff65297d8cdf80b98307e5c5ca2d0140b80b95e8c03a7a895134c2d6474e1583ad0d2860d6a9be92ee7758 cantrbry_lzma_524288_1.sqfs e9f4be0861eb0637ccab409c40dc0c6d29b6c56b98ff65297d8cdf80b98307e5c5ca2d0140b80b95e8c03a7a895134c2d6474e1583ad0d2860d6a9be92ee7758 cantrbry_lzma_524288_1_T.sqfs b0864d098a372dc7c8ef748250a88845a7215e52c10ab12335b689deb5848174ba81d1b5d22b25c32786f590a28432a2a64ebab99151753b06eaef0f2a7e460c cantrbry_lzma_65536_1.sqfs b0864d098a372dc7c8ef748250a88845a7215e52c10ab12335b689deb5848174ba81d1b5d22b25c32786f590a28432a2a64ebab99151753b06eaef0f2a7e460c cantrbry_lzma_65536_1_T.sqfs 8e119a2c3243cd4de255087ba8ba96d635fa6423af598679862b647b832a8d2e856d59a0230d9419e01a73ce7a5ef003ed119e01dbe0abf523c24da99758083c cantrbry_lzma_8192_1.sqfs 8e119a2c3243cd4de255087ba8ba96d635fa6423af598679862b647b832a8d2e856d59a0230d9419e01a73ce7a5ef003ed119e01dbe0abf523c24da99758083c cantrbry_lzma_8192_1_T.sqfs 8e7ec2f3a2cb5bd30cbcdac2cb4e8633a2f714aecd4d43ee826ed4982ac0c3c2d54f587d68f36f4985af905de26d11590bb24ee44dbe806b15e8e6e4796ff97f cantrbry_lzo_1048576_1.sqfs 8e7ec2f3a2cb5bd30cbcdac2cb4e8633a2f714aecd4d43ee826ed4982ac0c3c2d54f587d68f36f4985af905de26d11590bb24ee44dbe806b15e8e6e4796ff97f cantrbry_lzo_1048576_1_T.sqfs c5549a283754973ce932fd365c2545b2a1847264dc9e9a0311d0a1573c42445488f820e12d0eb3c79376f2aa953cb7aa3e126fca5910b0418e569354a5bfbb58 cantrbry_lzo_131072_1.sqfs c5549a283754973ce932fd365c2545b2a1847264dc9e9a0311d0a1573c42445488f820e12d0eb3c79376f2aa953cb7aa3e126fca5910b0418e569354a5bfbb58 cantrbry_lzo_131072_1_T.sqfs 2db6fa07b782251b012baa7aea7a10b9ad93264fe89f4438f0d787b291791213706dcb67b33209e8922e02facde1e3783fb9579e1706bcc5015ae4677f25614d cantrbry_lzo_16384_1.sqfs 2db6fa07b782251b012baa7aea7a10b9ad93264fe89f4438f0d787b291791213706dcb67b33209e8922e02facde1e3783fb9579e1706bcc5015ae4677f25614d cantrbry_lzo_16384_1_T.sqfs 3086144d24c44435153496ca9ba0e5963f4da9423f6010dfacfafe590fea74df112cf8abf2fffd5d9e66512f86ab0ec571486ee036f2f999ce84a50db9c0b514 cantrbry_lzo_262144_1.sqfs 3086144d24c44435153496ca9ba0e5963f4da9423f6010dfacfafe590fea74df112cf8abf2fffd5d9e66512f86ab0ec571486ee036f2f999ce84a50db9c0b514 cantrbry_lzo_262144_1_T.sqfs 4c79c05219dbff416f7dc79404a6d685c1f581fe835cede5320cc55582e7d9bf78d4367abbbac845bcc0b6896a7184b5076d6b8ef1ffbb09bec67a91dabe716b cantrbry_lzo_32768_1.sqfs 4c79c05219dbff416f7dc79404a6d685c1f581fe835cede5320cc55582e7d9bf78d4367abbbac845bcc0b6896a7184b5076d6b8ef1ffbb09bec67a91dabe716b cantrbry_lzo_32768_1_T.sqfs f033e4bfdd4fd2121d1db622e18d3d36099d85a80e43e38392e624f131e74b66c5895bb3e868d01db4fe01dfad3a2116645eceac91c3dfd6301cd39f49171597 cantrbry_lzo_4096_1.sqfs f033e4bfdd4fd2121d1db622e18d3d36099d85a80e43e38392e624f131e74b66c5895bb3e868d01db4fe01dfad3a2116645eceac91c3dfd6301cd39f49171597 cantrbry_lzo_4096_1_T.sqfs 82ee7f3d980f01322616cd73ffbab269bdca5e1777d5500116b93c28a1336618d3bce2026c3e245c2f3c65ad035bc075557201a0efc08316025226362f9c3804 cantrbry_lzo_524288_1.sqfs 82ee7f3d980f01322616cd73ffbab269bdca5e1777d5500116b93c28a1336618d3bce2026c3e245c2f3c65ad035bc075557201a0efc08316025226362f9c3804 cantrbry_lzo_524288_1_T.sqfs 7815fd53cae896cd1517d52ca594fac35f9aa2fd8bcf815f04264824989668e9a6a8d68e2d818b08a72909a3840ead62d7c3f5bc4cfcf32218ee2143c4bdf422 cantrbry_lzo_65536_1.sqfs 7815fd53cae896cd1517d52ca594fac35f9aa2fd8bcf815f04264824989668e9a6a8d68e2d818b08a72909a3840ead62d7c3f5bc4cfcf32218ee2143c4bdf422 cantrbry_lzo_65536_1_T.sqfs 8741c626db80aab5bbe8d457a1f95bf2d070a2950590e55d7b06689689237c6f9de049ad55224fdf34ab3997b142cf67a16ebf2d2aa3aa355733ee900380c442 cantrbry_lzo_8192_1.sqfs 8741c626db80aab5bbe8d457a1f95bf2d070a2950590e55d7b06689689237c6f9de049ad55224fdf34ab3997b142cf67a16ebf2d2aa3aa355733ee900380c442 cantrbry_lzo_8192_1_T.sqfs b62816efd2b63729b42331f9119c3f0ab632bb134d2dbba0f05b3b3d161c0fe01aa5b03f5726faa5a9f31c45c3cbb3626d16eb02a6db8fd434e5b1ae8a95723f cantrbry_xz_1048576_1.sqfs b62816efd2b63729b42331f9119c3f0ab632bb134d2dbba0f05b3b3d161c0fe01aa5b03f5726faa5a9f31c45c3cbb3626d16eb02a6db8fd434e5b1ae8a95723f cantrbry_xz_1048576_1_T.sqfs 9f1b45d999da3c785c1c2f6be36a77b1cfa472f72d66698be489547ebeea0aef888839490d9fb310c105bd7443b6723ffde0537d51c473974b72ade2314f17b5 cantrbry_xz_131072_1.sqfs 9f1b45d999da3c785c1c2f6be36a77b1cfa472f72d66698be489547ebeea0aef888839490d9fb310c105bd7443b6723ffde0537d51c473974b72ade2314f17b5 cantrbry_xz_131072_1_T.sqfs 2823fabe23da40d25819e377e96b7a44b7ab1adda6756d705280d6dec75e7a6079ed9b3ebcea2f2880b8b882f95e1f954faff912d4dee15bbd574ada9b281eba cantrbry_xz_16384_1.sqfs 2823fabe23da40d25819e377e96b7a44b7ab1adda6756d705280d6dec75e7a6079ed9b3ebcea2f2880b8b882f95e1f954faff912d4dee15bbd574ada9b281eba cantrbry_xz_16384_1_T.sqfs 547717e0045167cf25efa4515c7434981424c6ad2ce9b5a694b31ff08f350005ca63e4f93e77919fa37e4db328b1129e4522e9faa164af1e7fe8344e40583b72 cantrbry_xz_262144_1.sqfs 547717e0045167cf25efa4515c7434981424c6ad2ce9b5a694b31ff08f350005ca63e4f93e77919fa37e4db328b1129e4522e9faa164af1e7fe8344e40583b72 cantrbry_xz_262144_1_T.sqfs 7eae41f2ef0643ce658a7ad9250dcd93715802b7b279f752274c90179176cafd6bcdb55932beb68ec160c3e0002454a3da35b9cdbcad9b96f1e19390e0413dde cantrbry_xz_32768_1.sqfs 7eae41f2ef0643ce658a7ad9250dcd93715802b7b279f752274c90179176cafd6bcdb55932beb68ec160c3e0002454a3da35b9cdbcad9b96f1e19390e0413dde cantrbry_xz_32768_1_T.sqfs 64a13166aed798d53c9f0200d2d2cb8e0826123655a96d8f3b384c2282005185ba3c80ebd88f167b43e5daf007fded80614447f31f9d89be09034da29c9903f4 cantrbry_xz_4096_1.sqfs 64a13166aed798d53c9f0200d2d2cb8e0826123655a96d8f3b384c2282005185ba3c80ebd88f167b43e5daf007fded80614447f31f9d89be09034da29c9903f4 cantrbry_xz_4096_1_T.sqfs 02bc503e6e762ff75584fac9ec64391ff4308fb2c13f00c0bcf80862dd5fd80df63a4a8819b9bd27ec33e4eeceadf6923a03b2dd5c98af9a4a9404c91dd45250 cantrbry_xz_524288_1.sqfs 02bc503e6e762ff75584fac9ec64391ff4308fb2c13f00c0bcf80862dd5fd80df63a4a8819b9bd27ec33e4eeceadf6923a03b2dd5c98af9a4a9404c91dd45250 cantrbry_xz_524288_1_T.sqfs 906a1968ab1add048b9a7c0b56f1bcd1fbffdccb12ec77c1f35fba7be40cd2eeb5ea08edda67d4a6f00ba5fcd2ca6505b58998bd8f430ada8d4f170bf193dc0d cantrbry_xz_65536_1.sqfs 906a1968ab1add048b9a7c0b56f1bcd1fbffdccb12ec77c1f35fba7be40cd2eeb5ea08edda67d4a6f00ba5fcd2ca6505b58998bd8f430ada8d4f170bf193dc0d cantrbry_xz_65536_1_T.sqfs 79f38b253a18d752772a3acdb4cd5ca05007e78c9b5a86bef73e670763b6cc3d100a9c44bcaeeaf9bd0adbaba9bbaec6d8d4272d4f8a4c806513163ba6bdbbd9 cantrbry_xz_8192_1.sqfs 79f38b253a18d752772a3acdb4cd5ca05007e78c9b5a86bef73e670763b6cc3d100a9c44bcaeeaf9bd0adbaba9bbaec6d8d4272d4f8a4c806513163ba6bdbbd9 cantrbry_xz_8192_1_T.sqfs 0a335c95af7b907bdc99d066cad3d43d6bdf0abb59012c5035f92b8fe14d1d6ae6fe81e5bb3a8862a99b2c852769a7af09389429982cd09c7170f55e850ee081 cantrbry_zstd_1048576_1.sqfs 0a335c95af7b907bdc99d066cad3d43d6bdf0abb59012c5035f92b8fe14d1d6ae6fe81e5bb3a8862a99b2c852769a7af09389429982cd09c7170f55e850ee081 cantrbry_zstd_1048576_1_T.sqfs e6750bf8ab7cabc61214914a2232429ea369a6256780bf5e5f5336cf09e70bbf4a0a8ac7e570ee17a95122b394ba752e61887450bc207fe7417da6843e46df90 cantrbry_zstd_131072_1.sqfs e6750bf8ab7cabc61214914a2232429ea369a6256780bf5e5f5336cf09e70bbf4a0a8ac7e570ee17a95122b394ba752e61887450bc207fe7417da6843e46df90 cantrbry_zstd_131072_1_T.sqfs 213aca714595a6d70d0aa6d100d3a43b95cd240ddbd4b54172172fb795fde25129ba5e1a0c5aa396255c29c28267d794f779822f20dd31a9dabc68865cf5389d cantrbry_zstd_16384_1.sqfs 213aca714595a6d70d0aa6d100d3a43b95cd240ddbd4b54172172fb795fde25129ba5e1a0c5aa396255c29c28267d794f779822f20dd31a9dabc68865cf5389d cantrbry_zstd_16384_1_T.sqfs c7c1fe941253766812ac065788574844c87fac1f1612988ebadfe127252ba9a79131728fd6695145bf5aa4d9002a2a8f664f35c1b50e33d80bd405c64a56f2c6 cantrbry_zstd_262144_1.sqfs c7c1fe941253766812ac065788574844c87fac1f1612988ebadfe127252ba9a79131728fd6695145bf5aa4d9002a2a8f664f35c1b50e33d80bd405c64a56f2c6 cantrbry_zstd_262144_1_T.sqfs f38b06d0a20b07f7a70be94e0b881ce49c1ba13081646e5b2e2414ee1726a25141c0ea1dad7833a84a0974d0fe022df3d48f4a5dc2b1fa8d4119510b5d85aa92 cantrbry_zstd_32768_1.sqfs f38b06d0a20b07f7a70be94e0b881ce49c1ba13081646e5b2e2414ee1726a25141c0ea1dad7833a84a0974d0fe022df3d48f4a5dc2b1fa8d4119510b5d85aa92 cantrbry_zstd_32768_1_T.sqfs 9d2b0c5a6ccbb856bec91f54fa62ffda0025bb5ebeb86943196b8a38d8b47793d5048d4b5b9d3bdeb5b488d6c1bd41578bdaf1c59cdfa5c2a3f05a9a0ecee8f7 cantrbry_zstd_4096_1.sqfs 9d2b0c5a6ccbb856bec91f54fa62ffda0025bb5ebeb86943196b8a38d8b47793d5048d4b5b9d3bdeb5b488d6c1bd41578bdaf1c59cdfa5c2a3f05a9a0ecee8f7 cantrbry_zstd_4096_1_T.sqfs 9c9084f09bcbe3a68a483dbc70a3a7f6c279af153e7652b8f7aefad6980d866298ab100ff12a11cd0fe077676e63b764db6145facf3d8662f6bba9468410232a cantrbry_zstd_524288_1.sqfs 9c9084f09bcbe3a68a483dbc70a3a7f6c279af153e7652b8f7aefad6980d866298ab100ff12a11cd0fe077676e63b764db6145facf3d8662f6bba9468410232a cantrbry_zstd_524288_1_T.sqfs 261b6a13764710eac571e1aa6ba1907a8ef4ab8f79a0feb748c4ad5523f3260367f62ca3b98068fa76062ecbc07139c3211a68001a3bb912a2f29974e185d5ff cantrbry_zstd_65536_1.sqfs 261b6a13764710eac571e1aa6ba1907a8ef4ab8f79a0feb748c4ad5523f3260367f62ca3b98068fa76062ecbc07139c3211a68001a3bb912a2f29974e185d5ff cantrbry_zstd_65536_1_T.sqfs 22b6dd728b5d8fcba83214a426864aff47811b22e213237fc87ab77b7d08d9f1a38a04186e9f2df75f71561d4f03d52dad839287c5def35b417d2550b5752d87 cantrbry_zstd_8192_1.sqfs 22b6dd728b5d8fcba83214a426864aff47811b22e213237fc87ab77b7d08d9f1a38a04186e9f2df75f71561d4f03d52dad839287c5def35b417d2550b5752d87 cantrbry_zstd_8192_1_T.sqfs squashfs-tools-ng-0.8/tests/corpus/cantrbry.tar.xz000066400000000000000000016652341360235375500224610ustar00rootroot00000000000000ý7zXZæÖ´F!t/å£âáÜïþ]0› `Ä£cèóCÅ-trQ{„F‹œ+z¯õ¦Ñ~1âäw÷nwj·ÇH„V\t^ú‡ àkjP)šè%$Œðe‰ÓNJÚi¶c9*lÆ,&9Ú!ªúWZëGäSHÜb€ é"ÝiYÅk²I1Ü íB’í0H ËïCV¦,Ý ÷ë : ²-ƒ\ú,‡5·R°Î¸‹müÝʀƊž¤e¬‹f.à§h$#Y=¸¿Ã5-^`ËÍY.]C–ôŒ­,Â^qÄñæƒy5ÂFÊ}‚wøYºV]üߢ % iÿã÷©ä+SškRT}8ˆ{9‘§Ù Ù°>ð׉.²K˜‹³’ÌŽ 70³àaŒî1©^wü,ããÙžWYa ]{J)RÆ ÿJ¦q¥á‡Lølcy‹âݸû½dFZö F&íÇ çH²bš(·Ô#Òê—j\õHkTAÍõC|iîÄ# A;…;föl2}B–˜¬¹Skûë_üüÒ™Lôÿ!-41´/•MÛã;»ø^¥º·/-y/ÃòÔ¦´èOð‰ì&Z´Äª(Í÷×HU™ùöì)cÂãš\Ǽ†¬NÏiuv} ~¤ŽšßêÎñ oR)ÚOü´*›&¬XÚ 1T@x&,’áü±Õ&vÅ€ Å:%`%ø\‚âi7xîÁâUMçr^ï¶S¨Éц©RÀ¢, }7J~oÀº òѪ·l}YϽßl~ãä.8’´¥-7[öcøÿqƒ âr[¯ ðfx¹`} ÚÖ)ÅÜõÊ[UifÁÆl®! TIº@}7,ÃE–ü£Ýj˜X”ÏÌñW>ZÝ”ÒKÐj`§4I‡ ¦ŒÇPa ‘pL ²DE ÑÝ8¢«¥×>põöö“‹±êÿÒ*“¹Ûâó±òÑÈä‰Î©ßñC§ö±#ÅürX$‹õì=°ô­3›”ÞWßcúñÅY碶±Ð+»¼Î`çĘð±„È{ØÄ²Ca"ÏòöP¦&V{ªï°ø;rYòzÎŽš¿ÊpÆD¶^Œ¨è…Rú;(pèÎ_lË~H±RȱáÊwôÖî÷e$¯ë„GèFÔð"¡Íæ>þ«¶ (zB;É÷ÒÒ]¡2T¿tãÖ“•/"à` ”—oÛ$•ÙÂcëcXέv=2Åß;‘4ÐVر 7û6¾Tc@Ò—h„D5NZÛf4¥b!;o2*í0œ6¶¤6lhíC8àjõäâW«²h…h¾à­¯ C7FîÎ×ÃcC’.Ác´¤˜H¼]o•WqòððîŒ~nÿ ÚJŸØ‹3›[³²%²L[ð :¶µ{$RþwŠ"Žp óTªÅWu¯§”tÆbì,t‡’CÐkS*PZ,§Ùxyy°ÇoËaí«X® òÛCÁæ¯@î¤É‹Ôjh j…œ®KE RuÔÜD %€—ÆÀ÷‰ooú] !ùeZîÄz_´Õ FïCÚîKéÒPv°Æ×£õ(‹Ù4·óüó§à£J:'uZÎdw§/·ÄÛáÔ¶À\‘{M›ýŠWcbꥡ;úJòøÎHC”UT‘+\U†Ìî.Á"£‡DÕÄpï*ÆW¨ŽDJa·ÑÜ­ïz]¾Æ ÛÃä¡ÛÞ¬<ñpÊ5{Ù€§à›ºÇs®ñ¾×mlS‹ç'´õ[}ž±‘Rä4W†’ „—çmÆÜô¼‘HG¡±E©®ö.h³5¼‚Î=$iéqðví ¤™Ðj§ÿè ÇÉ[)÷Z·|ø ßóAèèάިë'o9ÌŽí§«¨E»#7tõÕ5¤È:@7r’YÕl¢±ðZ㻓póèE¢”¤Ù{:*;0U‰ZîžPÄÓgHµ]ˆÿôŽt ?JÇÖ•Ûò5ªO`s36¹£òÙͯywB¡EÃõøK¤P×=‹¤‹'õ@ޤ‘†ãSý`Cc¸ñ5LñàY>Y0¿Õ3+H@**þEuùNð‹;ºâû((tåo7ƒµõn>¦ Üd‹²Lî²îè™wBNB{®Hù²g5u ²Løqb³o½x&Wà‘f¼³Üß„'{½ñÃÐÔfîƒO8êà .,™Y‰}„¿¢&á’®ØÖ{r¹›¯éI@AíXÚF ÷Íó¶c¯¯lU\uŒ|ˆdÒR)¿d>wñö­Î†‘âÏŒ»õ ݦ†L¹Àåó¼e¥§Á¥íÔÈæÝÓÁëH/Ä?†~Ù/58#øÁýoâäqˆP "µ¹–OiV ý»~§Å]]m^?R<‘F}¢Érá‹mÊ¢Kà­B%)c`»öˆå®TÅðî}^¥£r,˜øëI¸`¯ëóƒÍàE?uï¯ZÞ{2zrcXΈê;y Õ×¥À*ñG­˜Gâ.‡æ–*¥˜•\7Ts‹ v*l@ŒÐÂ/‚}}šå0#÷ZæÓ*Ð@&k­ gG]&ßFÕþòJé÷Š«xpuWóým®¨ôŸd•Œ#l ÒÉ^‰9ÚVV¿æSÅ$Çâ)isgBNÖÊίxF¬unš? ìS|T*¨Äø²4žQxÇ_Œ™½mmœºxoÞðÃÍCÈô@Úd¾3¹Æ-}R7ƒý’!M)-E^¢«¬+óíJ ®Fó8€¬utúÅßÝÖÖ«ÚI'CÙÐÀ×·C­Ø“[ا[Ýœ†Nuùö²¢—éE5£Á£À­søRlÒyh( 3úJ÷˜ÿfl8µ¥µú:9"Î=Ÿ,jÜýK(¬’ëÏÑ ,¯S$Z¶|5²Ì½e@S‘ÞFb ¸œ›ª+f]¹ ÝrÀ8Dö¦i…¡ 4·†T€³O”¯[¢È%ô“Ü·iŸ^ïCÜ¥ùâÌ7K2˜„³äþí2QLêž"*ÌQ !³`†ÈtÐ’q.fTüÝ?ÎDý¾û‹SsŒkTLŽ;yµb‡‹èí_A/k{¶Òá1)¦¹ŸVœ¢LÃ^ò«ù[K¦l(«QýÔN@e0­îZ½N¼Óù­ÇZêRØ/Fôù-ÿ¸•u8Xdª{@ŒÂT?>¸£8‹s&{ÏsIµ`¸‡š$1)=Èiücâ kêò‚ÜWXAƒñTx¬U‚ˆZ ïvgb½B×/‡ÀîTŠÛ¢ÊüÈ╽[?áqv÷ñÑ…ôLгT… Öý³³'ÏñIsˆãô[ŠJE–t˜VÑŸ]pÚO#ëvÇãM YûFÐí×0—ýH´†dP=–"à¨R@œHÇèøíßî¾p[*ÎpU§Å1¯ÏuÝy𕼋“ÁwF#ÿ¥XêkˆîƒšÎBŠ9+| ¢÷<¶;:XN¸³!rEÆë¼tä´)Qù¥¿uJOÔ@þA„×)jZE'.”îïÇcÀ“ð²m¬•†¡µ<51 ,°2j/!;§ùïR‚¶]A È £óP„®?k$CÑ«/×§VÒ@zÕ%-ÇŽ­ê~£|5ozH»µ† n¬ÁS ë=K|ºVÍ‚¢šWÙÚ˜æîƒ#ãlÞ_…’{3¤âŸeÙ–A»;Y–É+bZ»É¢Øøµÿ£_íµ9bäL=@"ÿ3‚«½=¿/Œhb³æNc“ÃæAqw„KгשjFÌ1½ï2€6?ôßg6üÖ‚ÍîLW9; À¦u&qªíiÇè;?ɵòv2¼nñª¼{’³ÏtÇXuñ–ȉ2ùÝþö;–Y[zöÀ¡3 `‹VzHGÂ^á#d9Áiq[‡ŽÜ½(ð£Íר|Æó²{–Ý9e¶HEe «™¼‹™ñ(ªmû€ßÒVV0¬.½K§½Ý#ÚašÙêOûv“'ÈûäNšö\°ü“ˬ$N¢šž”³5‚÷-Ô=#T~Ò¤Š7Î|dÛë2iwüÑʦäæ|à¨Qä¤a‡Ë>W94­’\oYua)Ó°¹‡ÕÕD!>߸o ×"“IäÆs®©3ÃÕ ¾ ȳ‹INÚ;V7 èM0!iŽ‘º™<ý‡€„40ðÙªŸ´±‰û§‘—Òù†;¸ËʦF¼ôÕk•ïØßJ¼þýf „Âí_n ½p° Ø«‰úÒâS½…·üÀµí¢ ‚¥Ç[ oÔðb íÑØPïhé]»lS:ý¬_ U|þl˜öwªd  «)Æ2­yuÀT[Ñ|Ýè^Oj¾t*As›~öš7kºS´²—rçUüUÈa\¸-ÌÁÌl…“S|¶‘bñ±Qi¦™°ñáW†g8 Zÿ²'@=„¦Ç¯F”ÁóõËôÕoõ§+€âSáÿ:[(7Ê[Þæ˜:­ë‹Óçßz^Ê"8GfíxƱ2×ÁSZMé^Ñ¿ÝV!<©a¼rúÙ>+'‚Á%nùLÊ“&O`«¾ÇP ñ®¸Vð×Bßb+ †–dŒÈÍDµ³âÂÓ°"…f.–"ËWÜ\Áo9½£Ë¼Ù¿XÉ\îR Õæ°y訟G˜±¾í£*”>ú ‹O}¦ÍXZAa{“W:¶ò§ôŠ`Ì<‘ä;T‡ÑJú )F"±\¤AJg½ }IqCoZå¼{•ËÖ¹”Fÿÿä¦9`>-$íVä?Þ$ÝÚj¦ñ/.LaÄñ#×§MÅ÷tä0k­üx`»'Aéu6/7d ‹3'3=ôIG¦m8é~¡c"\—•îlMJ nÉï‡Â&Æ!cº˜j±´¡„DÉ%Qņ]ÎߨC÷ÊÑ;ù©+û¥Œý¸Tî¦éDJ¶4w"ϨBÊSÆàãÓÌÎnfud k&_®[nè^¦xÄpB…K7*8ƒkòˆbõˆM0fÏ%änB¹ ÉcòBõšk{T©Ç©sН÷.$ç;CôKm aš0ûø0SR+í‡å-±KxÞ,þBÝ@èUG„ÏÐý²Ä6Ȥ6ßY‹ÔðOÓsÑQð°ÖqãÊ|E5A˜i2`„ÅkQW븬Ü6ÜÐC›ž÷êCë' Úµ©í'—‘1,ÝÖ~x*AÝ^ùÍ)ôÈ þ“%©5KH8u[…ͶP ¡J\3€mW¼)åž½ …•hDEéÐX±Ø¤„4¸g•ÉÔªÙâ©K¦Üƒ›OdÔ€t*é_7íøawÈ/ÈG€JæÄÔU=X¦ª¤’ü^Êêô1÷LTÄnæ‘þ‹…dˆÁf£lÂDçáÕJ•{Úg•§È£OŽqÿq±SôuÂû.(öÒ‰àïfQÖÏ ;éçÎ9— ¤Ÿq1¹ëÖMäïL¡Ã=u™ÑækÛqÃWnr»=§“Ä}‰ô1D ¤ÃYh"VÆ@ À}äNøaæ'I\ëå#Å ~Ó‘‚&* FS;ÈŽ6&Sýðæ\2†‰n_·™r}P…8²Áíëù³HQ ·¶ýmÚv¼‹ éjžÅëÊ’nÙ¥ù¢3—8í?'Â$ö¾û]–¦Ì™F“¥e€rÔI.Âϵ/å«ö&±ó'©G…c-Ý&ÀyoG´…·» |Oeî}ÿò>…Í8+l­i,(¼€º `ä/Ä.Ù<÷úœ)$ß'X„Ån’*À¢¹ºI]8þ¶Z·zŽB›à"ÑcÛº|Ÿ¤d2A¶² ®ƒð‡½Üã‚•d7ñCõ¯àiÄ5ÈÇÀ2[#“Kâ€~ó æ˜Îé¶À™¾mñFSÀÓ–X_j;Ê=ŸD!ZR·¸¨¿Á¹Ì­¥¥B’çZEäí+ÜÞ(ÖÄŽzñyÍ…dTUuÂ+_u¿Ã äà5 ½DëÛb_´å\ÚШ¥¬ýŠ»Á=UÞ´ïd<Âh¿­eËÐõé²›Æ|Iâ¶ö†·-=^Ãy_áóŠÛ{ÃIß 7:\µgʦ0õüi×*N“Pµê¾ÕNݽ­W×B÷ν÷1ìÆôÖaO"M1qgÁ²Ÿ•ªè§7En†ˆI·£d7íÙ;j+-³ÅMä¾ ‘PÕeeõÝ?ÛýÛ›D*4|}#9Ú æ¹a®Ps]Qö“fÈ©·ðÞhŠf¨¥¾Gy$9ꃲë¤é[ÔqoÕ”…‹±ÇÅáz¦!ÌÌ@é+ M`לAV“:áÛà§ ý]‹-Xå£ïÖaÓ«:nÂX·z µ Šå!Môè”Ó¦á&W"¡ÔÉé^‘Á^Qtòòï׌‰˜œ÷ 2oóhQƒ«ÓØÚŸtllŸBÚ»ÞÄn„ê—[¾Õ•µk©íË6¡ŒÖH·BË~œ¬‡OåÖ|3ÐÖr˜q¸ªŽ$ê‰Ùí-õTõ BÉÕKd~Æ<~uðóÀ5ß×ë¿õÑr«É’Žy¬(T±²Hw!I‹Œgàœq¦á䀆m‡7Ìñõ¾4P¸Þ"{_ÿÏeÞfê+k–éÁÅ=±9Õ²pá_YÂQ¾i@ƒÏžrZ3G© \ ʈ\˜Â¼é+;o"÷h~BÅž`RöR⧃SxÞRw,¦ R£ûQŒüU¿ˆI™Ãøë<èlMM)w±{©]UëI}ë³]Ih§f¾]ÅË~Òæ‘+:ÕÃÎzÙ¹ÆZn@À#Y^C=!_ÆAC„fÆê3`y:;4þ™ëÊ7ñtU½Üeq|ÏÞlHHß&m𠼩èÁܳ6%¼÷“/ÛÊgè_+0Ë nø+Û)žf?Æ"\ý˜·¶í?¢1¯è®1ŒÏ.vÝzá²B!¢·u XžqeP ƒçhîö¼tIZ“cÇÆïÅk µ³aŒºá pRp¬wâ…²«¯àõV‹¢ól³’äÂ]¦K«ñ¾Ú>àW¿aò5£ÇžJ`gÔÚ{iÏ¢K½]¬j|#«Kšm 1=…ä'—ÆP Þ_•Š[Ð6Püs« JNÜËãžÞ¿Æ¾¿ÄA"-I(6”Ö£¤½ ±qflþE_IÏu<®0—w—E¡bW¡cƒ«#‰«™ùTùy`Jõqÿ®äÏ{Õ³cÆDÝ]×/×"-ô²,DÔ°‘#ö…ÄC܇ˆ7’$=.e›²oƺêî&‚æöûÓ7ó5† # Å#mLë8•Ø´sªÓèzWFÇ?Ž\º& 'F0,™÷f ø 3ÓaNÓëÕZDpÆŸæ$ów`CÒIä #6Õ»Já#Š6eùÞ PQ¢ÁØz[Qül† -qŽ XU;ЋÙM‘r Œ¼!øgî[«?ðŸ’z§,ZÔKòv锵˒P|Ü7¥~–ˆTè&ùåëƒYŽz° +:TaÝ.‡…}äÃ/Ų﷮ç‘Þhâ׃âjÍ9×ßzùB+0…˜‚ÃôÖfèm&âÚÖÿc¬0ø-O:Iµ= {ÈdMQÖ_ôýÍkåñyⲻعg€/ZçÑ àxÍ.†$=KVXæHíÜG‚8Wz_.`ˆÞ,mÜ.¢ñ´#‚Èmþ=õ7ŽO¾éH˜ùHçÔ¨›AEÅ_ ÚKå ­û]4& Íÿmå¤À]Tž‡eQ†h4šë éõ¹À['¢ ô´³©8™¹ºx¼ãåÊìEˆ^ëÅ8q»ëðbø°/¥5XéÓi]‡0 |«©õǯ­-Nsµý^D±/Ø6¤uXnK,9BG;Ä›.dÍÍBÇ_Rg‡2p|=Sã:–Ÿäðç]ØX׬ݘ¬IÐ÷®ó0{Ä,[Æ@ej:Ü’€?Œ-e ˆ<±ûî{ø\Ÿ‹¥kª.—* "?ìÓŸ?€ÄP@êxéÖà3;aM6µ‡¼‚·X ˬtÈç°°Bc¡çƒÚ_a½ÏµM!’ºVå¢úŠ6£å ™]C­Ðzôþbª¹èi÷BÛÉÓïû#ÌQ`}]ƒw·HÎóp-:\ðÌþßq6Þë¬?XiÈê¨r/ ñ¢ÖŽ\xÚgH“û©+êçB‚Já@ä4§Ý@ɨ©³\šðVª”Ô`Ö? þ¹¸e_Û‚ò5ºwFrA:ÚîHº¦ D‰bP{~_»þÝÛÔK7)^_GΦ ³gh.‘Y›õgÜv  WfÎð°uel€è¢yÍ3/؉œhÍ•@Ñ•ä®ýf ØÏ¡õŸ­´âÊÂ&¯ÝLâU¢7aðªêò`c‹¤ô×­õ™eÄ?P¨ TY2,¯Á$G%6ï æ˜Ã ÷‚Ø-ôª‘e?:>ß‹A’^ÖÀÊ|ò±ïdôê‰ÂâbÂöÖjRd_#»Ìò ù­ù‘æîzß“nO8ù.vd!ps‡tAW©±r €9î}†ºñß„³šþ4XpýwKGþ¢ÏÜ€–‡³á.ŽšJƒî =š5ør§·æz…§D®„;ÝÞJQ<ÊF“S¨yÝÙÆRz;=³«ÔúÓÃý7Ç…QÄèLýäÏö»rÛ|ÀË, E:áý­óüÞÈõÙ¨IÃà4ü3|QY²ÃL!(YæÿëjzáŒEC¢ÉÖ_ Âj ¬ß˜¦Æ¿?vEj$ç¡ÂôßÍÔDÝ€fá<›¢ª4ÓÉ0Z³xµå 3==+C$œûXÍz÷”Ôç½…úÆ‘©tè×s”û¼éQ‚ÕÌPKÂ]ë3’‹SÿJ:e“—{À¤ßïAÏî”ë†U³¤v³X7ÞjC§CfôB•¥F±é+Wâ}FDÆé:þ˜©*ça”^n¨Ëa(Dºy?CEB®]?†f<Ó,ëžœAÕøÌ –of•v(¸ÎfËåpOÍ™ƒ–ÙŽªsdN¼¬û&»oØ” Uz~8’ОRÜÒÃßnà6Øxȱ‹ÎëIá[…+’(OŠL¶ËÛ X šL*G]ü)(©µ™5T8§aI–}süÍû£Tók À»q Öù‘Þ qb›‡êcµ×yˆŒ!Ñ£(q®¥õ—$ˆöSÿVùÕï‰E®qqs–Š4x*b.Â[ý%RJÄHp ¸ -é²õñQm„ä§õ'Œ1\o2ÍÞÕ9¦X®8pŒƒz]ÐGÛ ²[ASÓÌ÷ óBÈW4Ý=„é m»…Ä›´dsí(¨&Ô‚m€ÚÛ¤—ÄuØä3ix.ÑXf­k!á7DDë’™'€Áý¸d[ùÞȪ{íuu¬Mw§ƒ‘ÝTØ-èß:ÀFý_ ’@fÖé:&ðZËà¿iÉ“¥!«·ðâãÓ‚gp’CL_ôu„ 1ÄÃ(aÖ>v¹œ–l6=q¦}¶d“ÑõÆBoÔ@œñz_õ}‚¢8äqØœðqdDzò7òI£¼Z¨>_Ù+ísF„9l0ýÁ0Yï·˜!ì ENýÀ¯Dɼù—Wä9e¦?­ÜÃÁ hQ¶dÚ$¡x’2¤`IÂÿ^déŠHm¡ |n(/(¡¯FrD#iT"ó•B4ÐÈÚé—·Ž9~¬S¹d)%™§òùlŽ*w¿!Èò/ _Á¯=Ž<¡p ƒ±«™þçqÀ0ÐrYšj¡¿ß”…$ šÔd•¦æï-þÇÕn¸¹gÐkÑ©VÍ,‰sÜ,i+¤3©ÝrZOXA˜ò!«æ‡¹n•Ô»l€?úHÄhÂ5‹–a®@\àÌ«³~~ÏköPLÝ&·*‰ úJ¿1s¡ÔÉ»àKEeJ‡"ÂÁ§âáˆÙßz&fo­(ä{‰KS)9¦KBèÀ=N+3® ýÍߨ¤(zFU?üÐ(WYüRQbÇDV8`æwZˆWÊnZµŸLŒ‘0©và) UT§‡…6­—Ò¯­:€«ôBÙÚ˼”=^|XNBOºHjÐÑMßY\<ÞW€,âI—Ê™¥!g7iÉÂb”óæ7u€õqŽéÔ«iB zâÔÚC‡¨UŽ$·êC©æ•{Z.AºÑ8ÿ’É3‹’:¤­mÛõþ›B—b‚HvVW0 ¾D# „soÔl/DžÂÀd÷ƒÊY2€“ ‘Ž?X×v+°wšsKùê…OV+ aƒôÔZð:ûx +¤•ól²÷†©ä¨Ê¿²CJ¨’½¹Eƒ¨ƒÀ¹W mâñö޹x“åî-,à¿2¢…B K» ý륲eì[¦îI2[šÌñ–Ä]*r±d ©þŸœ¶à11‹ý¯•žåí WIÎn¦"ÔÿœR!HmTw$É =Š£$)¸›†ÕwâË•–máür¤êjó+wõòÎÑ´éô¾˜ƒdÇää[Ÿª§*8U ƒ‹C"–Tác¿Ÿ6-|o»@ä´¸´¼+\7Oqø”a7Ö\sªÎ>Pè\:ŸYW?‡ Fcçö<÷¡Â«i!ª[Éü¦Ž÷ p|0…jöÝXz•‚˜Ç7…®¨~Dkf-ùýÄi4ÌÉ9A¼]UâjfÊÔ˜.‹6lr`6>H͵:Ï|Ó)PÆMÂÞãökFÏØÛ2‹%\ŸÃ>2r¾K„_²)Zžd8Ñ—ø±±ðïH„šß ø––“¦¾¤N(·²K´²ÃbŒðÖ‰ 2À -¿ <•½Ð+\]°pØp©LFŸ`¯`•úš“(ÿP­ºÿ(ã‚`°y¨…C•¯£Ü™‚þ…zæ'XÇ«]É÷''Ä+bcŽ´¼]«„x”†L‹–ýòå+|Íó½²v»zø:Ï!Ÿï–ȧ). Iæs€¬îŠ4h~£FdéìšOÚ°Îc¾U0^¹söþÄ›üŠI¤xpª|% zÆ%@ÅysrŒ¨ñ½&¸šª›Baq´%‹¿¦U hÏõ¯¤ se[­C—yŠV: šœÄõ9)ÛÜ“‹¸ ©Þò×”6ŠÐÑðHªŒöŠÇ^ﯤú(ËhÂÍ+S=\p8j`ýfß2h [¯Ÿ’¦<‹wæfÞ ¿ýÚ¼ò!þñ¡Ã*üÛ=ÎQå¡(¾b[»Š«á6øÍZÏÜǃ¹”ZáôàsÓ[Ÿ¶ÛÂMðg‰q<-çÜqÇSM6·Ìòv˜a>)·HB‰m –‘u€VßäŽP¼:²µ£Áæ ä¯=b´Á Ý:r ^ÿ¾éä“' —^øb]u·_ÎäÇK©´“™@ûš?¢¥Â„ÆÍ'EϪm“ljÇñußÚ+™«‹ï i°šû$ÍìÚC1^“hê£K¯ÀN9!—.é˜e9Y͸ð^1oß_y98\ॠ+wav——ݬQç–œO¯cÑ&æÄfa ¡ÊM߯5RÅ÷ÜE¨OÈË¿-f˜¼—FÙé©]ûÏÓš4ðC¼AmàÀîÜg'qEÁS¾ð÷o8Â}'1-¼JÆß2JÚíF™Z¤ú&±ð`i«3Ñ·ôtx¥ùµ/yÛö®’+rn[:Õ‚)iì/—$™íÉé0ó;5E{1gÝP—ÚI¹1)”íÊqV:Æ+°H1.ZG ê?b“,Ôó¤1¾¶ÊL™rOP@ù;†‚Xĸ‡X“)·tÄÅ8O‘¢ìb¨G…‚ü›¨Žb¬K?piôÚ\ó žI>k´'ÕTvèÉž‚^‹ÞyO4zÐú €Qbn,Õ¼º@ýD‘˜-v.Ó\Æ´ÿ³±h®gˆþzúÃUù¿‡…p1ðíÊÔ{"]/ä†NèkKš¹"w8 Õ5HÊîáé†@ç6:³ã𹦦)ëqè…¼§ô?Aù¿À€Þ˜WÍ‘}艆ÚIGºlÒ_¾Ú®µä°ü¼kÓ\ÂRÝ~c"è¬brFX¶uBûUt‡3±^eÉ\RÅس1BÁ—Ò°ûܧœˆ')cÎéÇ»‡œö²{«°8sŠæŠk÷EÙ…!Jï ˜¸ÔpøyÿX7LO1€ -ØÉÂíGŽßYaELÉ­ìWá©08 „sÎü¨>MnËÝk7E&]!Á|ø<\=Nëtx!¢ ôUPvË8Âw! `¹4}AŽæß*×V ÆÆ[U©°jygáêö*'9H\ÌPÊIqë*–±Ø˜ Àf—’TY¿—ÙØ;&jyˆ/47E#ŒÑ(</1OãBÚuš`oÎB ´9+ÒgáÂYÊd¶rDñ%5ØÎfÄŠ8çrº“ø™{Û=ˆulòýžaÆ Uª|›[Ï«ôûpkr[_ÚŸ!JGŠ3 >d»M#»Ÿ!’;ôå¾³Ó ´7ÆóE`îLEG[é’ÿ˜Ÿd%×ÍÂg`Al}€šk,‘ÞÝ…=½¾5–ök`÷ÏcU³­§Í›²Ù˜´ £:L¸5ˆðKÂ.AÅÞ¥fÀcK¢Tü¦néSÙU±¶6ãâÂÏ1áæµûÉT“¤ššl‰^¿{*gˆŠEHù¾Ú¿Æá¹ ÔFrS.áù•ñyoªw \#ÂW¶Ænçæ»/ ¿.³òƒuuÎém'AÞM¡íä1bï§rº— K™Ò5^…AÄcöD^Y*ì~….*fFlýSnõ…Ù_‹¯¿²©¥2×çF”ˆ¾f‰U¾•!ºêãÎa}0Gó²«Ð`¶#xò~Ê ¯­+ ›3Ÿ„ÙL«cFòþk1îƊ…e¬Eå¶ŸåÔ÷ ˜Rf÷5£èL…ðKºÝ›¯Y%•%bß$Íñ…Ô\9çZbGH_ܨ\û»ÌqÓÊ…Lù7ùª‘ÁÎói¾¾ø³"}ø±Œ'b§£~ˆ]†Þ²ôôë¸çMy?¹@.«`/δIœ‚Í iZËB®œ11Q ñ€£ýœSʧÈRû‘´åz¬ceUHþ@¼´&Oqê 2Å\˜2Seä7k+þ~‘`5£¶Dt›ö†M¼$8­±ÁøkNA¢„t¦žf´äN¤øŒŠ!Eâ=Ø HBŸò>­ZÅöð™ówÑl^;9éqgöóåg{›|À¢“@7¸‘lÜ˽ÍeÆãæR™ô¢§£¾¦Ï®VãZ÷b¥¨Jªèe1æÊ¦”«­ÕÅ%°þMä$¼or5Jõ Ù0äD‡ËvŠÓ¸÷ýTº÷ÝÓQ×ír%SÔ3%ic5z\R4Þߢķ>Î^F2º±î£Ð|@ãE²”³»åxnZÑ¡Im«Ö`_[÷{oÏEÛk¯Ï¦xå¿¶¹žwd·Ed-€SQÿr æÜYg,Òœ©cR½ó×·Ðë³tKR] g?cÞø–´ #b†¸ ³’M‹…àä0o< X6_CòÎ7‹xšº2•&PYZóÖQ:Õ=¦’Ï´°•.Sš¼ Í,°Ð³ßNoÙšï ìúö9—èiâ¨Ê “Dç®J~·ö°¿ŸYåñó,&º%³;­·˜‹}/| ®¸ãl™ãa\: ÿË¥¹®KkOi&S*[Ïi·90Þ¦ÚÀ×íd/»In  ÂÞø·DW¿2má½9 ïc™.´`9®úâ!«ÄÇ#ƒZaJsZ´‘Í]eŽÙõøœ~ìÊæˆ;þµÁS¿ÙûªAEäîL—@¢3c€™`–ç /hÂÑ5fo^/V ÚEêwÚŸÁQX°(Á¯ã²Q·‘]—xJ>kítj”þ Þ çg×BmJ‘uÐläè\cðÎñ(Y÷à ‡çN[üõÊ}®PÌ2 ¬àÿÆ­RÊ¢Íõr&±®JVž6àFáõAa‡þT2*’d¨¨wf'áò¶¸…TT@*·²@Á*7æ{WMšA»9µ1û³Ô2J ÿÕ6D›Î L_ ´ *ðó™n]Mº¢QaÌ=3.U‚yÁGXS âN ‰“– {ž¬"¢%"©¹ŒQÌ¢Øúx|¸”ñÃy /NÈ™ÇΨsKN¿KÿòqeñÉÁø¾RS!´¢ófÅCíˉSžÝ«eÃ5~ÍÕ¿1;x‡XÏ–©iù‹¹ Et;ií¸±õO¬Þõê´1yþÊ™ÒûþtÆvMo?÷N#ŸôƒÈß2¾ B7B+ªšÓnù‰µ_Í™¶Áñ›©ÝjÕÜOMË7l‘{@¶jÐjjAÅp*Q¦½Û­¤â',Šä@C^÷×1ú°u¦"ö8ä‹P^€—W2Wž}ÐÙè©@7‚%‘¾ž0dŽäa©"—¥¡OBÈyÔ·Ô‘d÷PeÓTÑו«Ï¬§ñdH›Þƒ@ñè¾1žbÏúA·ÆÙåNŸNmfÜ8ɬd¼xÀCà ¹âÑãaðóDu˜ËüeÐX¢j²MõcÊŠ8­Ýꕌ×þ[óP( 0LŒ@ŒË5Éô‰ :€ä3˜gr'¡ü×½‰Ü }äPïÞJ¾c²ÇTÁ_—º2MQUÈ'$üe)yô×>ÓR÷©»Âëï.gÞ Ü’§mê|‰„Î8¯ëi±4š¨^8àð{Æ  ® `\µšÇm.Ó>b—µ I’‚¼˜Â¬tXßïÞrôC#Œs¥DŸl°‡S(-_™Q5X*žÆsâ¹`êܲÁQ\‹ÑØ„mÑÔdK25ºßêîŒ5…qÑÖ>Ã~a”_«?Æ\’¨ôç$!ÉG°â>¯ü‘y8@ù!L,È(oIxÑéÿåÝ:ÐÓŸõðTš§_ÙX¥i/ðÑLÕ¡–Æwht!äþ€$ µAÍq$Œ/% ºsÕ4%¸E©ÿ`ÝÒVÔPG\ܧ\õ'g :nB Ì÷P˜j6Êaõz Œ¯ &u;¹uo'**¨Sàlsç}eî©'ívFõá/ænîjºMG™ÙTdúÖ¿À¬ŸNþ^¥Ÿùü)Ê©#Œ«ýº¦›Ÿ¥ö¾hÐ\úsÒÆšåm+ï<2ÒG¿È¥‡¿]ªk0«ZçGWK•åh¬\:3‚Íé˜'2rèÄ ^|tØ£¨·†f—æœ%ðê ¤ï ÞYØ];?ó̆…ŽoWÕUG‹Úd§’K§àß6~.a­Tÿï§?éˆK­<ó¬ÀŒÄEÀ­‡òÝáŽFÊ §ð¢:R?âÛ2 àMÿ/˜¥€|ÂsÀ×Q$,«_]?’Z‚²"¦ gÑâ1)»¨*j}à`*bØ=°Æô&~Ú‡ñ樕ô¬†M §dNÀéYv5\<4¥à"È@ŸìŒìGÖ—`uÁ Ý¿Ê XÎvφûH"Ù'ÂYÀóŽÊ(ùiXçC²0Ø;ØV,Ÿ–¤#–˜¹…2²Ø#Ç9NÓó_ éãuHˆUîm„ua0ê²Ñç^SþŠq¯á '_šA-lïí‚áx˜š”›ˆ² pÎs\ç®WüÜ=üæšÉ¼W8}ÿ&áÚgþBï µhYŸ@×}ɺ‹=f ë(ß»`®-(Äó”g%™¬¬eU2z,gcù®<óÓboÔ~³À›pòÞ"­4u¹«ÿ¥wÊ(rêOcý{)/q›´)¬×ÐÀ\EåRÖWs%QsüÖß“[Cäu eyX„TQ¯w)"ðÀ‘œÞÕýJõÎ÷Ýb×£X¯>3”`Û <̲VùwWÌé 5çÑÝÑØÃ¸Õà fÌIð5ú:^­…{Þe»ü÷Æã\)Ú²Ì>?Mð@Y³xÐÔé@çÚj6]zÒn¸'/˜ 3Á¼­A=ÉTt,[5)šE¿ÁŸ *cgÎÍÝxô(qìŸnĵUNJá‰>Þ*r!(ÝH!g @·JÊMQ—=Ñ@YŽVÄü-Jîâ`­½.$ôz„Z'éÓÎì³üsÒµ~å¯Û}= 5‘–¨Yêáî-¤†U##qÆBö@m¢Èö ôº!¾‰ŽÞAŠ‘¡BKÎæMk6¤Q°Ü6pº¥#o:tt÷!Àv‚ ]“ˆeÔËyÔ:ÑÈÞ^F]yÛ>ûó[YË"‚”‰>ÉËZ§ #2s‚\˜üÁ|úcˆ|ú_LóÜšÑ( ˜^–êhØ ¡–~@ ].Æ¥Ú~IÔ:"EГ¶2ã  ~‘Ä•.8›&ö¸÷ìè׋¤Þ승”âfò&·4,¢ÀÃÀK¶rªZ_mv5ÌpdÎOh—gŒâc¦èY“W–¤Ç<Å*<¤:3ކøþKX`AÃþ·Òw­´ÖÙ0ûÎÕV·W襀DM7ÓŸÊ{hû]o½°Z¨ô=HBk=Ùv1¨îzÃú®ݾ#Ìz!®=µ úÐĬñ'؈p^uY3dèÏC‡Š—^M[åKq#wy]‘œÞÁÃ@æeí:®gôßIG,òøíQqxfœí\ÙœFgþ¬êÕ«:œ^|+`¼ »µ^9Æq‰ÐÄ2K­§‡Üç[øsÛzͽë˜ÂÈs&°,ÎóO ClWå¸T.®÷9žM”ÕXéaÝ+³GmË~[w??šóî!þž6ÚÌ£'ß ÄWF<å(¤ãïÕ¸i× Ð Â9ó|}*?™H[Ü­ƒ …5ßX@¡8Õ÷À^Ø¿´ð®´†Ÿž½N7fïÔ™úZÒü7™¨Ðd¾  Ž·ˆÿû7úL1åW}Íőƴ(5;Í¢bÏijÿ€  }bjlÚ•cµÄÛ|¢F#Rn“\L[“¶»z/13÷‡kˆ=¢Mœ! ƒÑ²-RÝ…IÜ%ðÊ]^˽>ÆEûÞhbÀšÈЬ;’^KÓŒ®§=9e{[A€¨¹cS½Ä‡jл‹T˜VÓKÆ­yì.ÁN…z¹”WQiÆ,©Ñ­¼XRñ»Ž0µî‘ýP­ÁºI!Y¶D·š z?õtÛŸ%tµ.¡SÙĆ%Ë0€Ž —H+™´ÖQD{îeÃ+„O¶)ÊpÐoìÿ-f‚afÀ¨´Ð1¶¡xÁî¡B¦§JX±ÀŽ#ÏÜ=Œd9ù†’ "V,ßÂÁd©Jl1Vx<â HØ+|¨5þþÀøß™2iåBµ&¡†ÖàË =qd± xÝlmã`¤“ý›Ñ×õ "pX½oÖQ“¾‹àýÚô%‘H ž¼U%…G‚) ñךû g²ò#`ó¾ˆ0bÚj…ÿ((îf±À˦¨[Œ 3x/oª³§”ª$•¼ç.*¦ì“ž:2Šlôª Õ@âH&e¹"r«˜_acO¸ìÅbiKOýŽ.> 7x à`_M¾¨`‘N·êç½&òBŸ?3õP‘ÃyéûÕf'mcmÛ´}5|Lñà†¡cƒ¢äjõ<|ø»¸½&þNÏ~"›³}ÀO?iª@ù‘ {ãîDr’-‡]¼L½¼ìàpïŸX¤l\³Ä¢2i°ÃRÖ õRiÇMÒ•Ehoë8sÄF±]ž´ÞP33ªÄÕ¡Éáþxp]™Þ]JmŽï. Ro=tšò‘Žë—åM4ŸE*jx y'²†i¥þýÑ$É¿†{„©¿­7Qnt¹Íö¨h©Ç¨¸‘4ÿ½¨˜e*®¬|l™Þ˜÷KƒßÝÐÚ¤…ÇÛtÓ±¹OÎÎE S÷UìÎp2§xª8ó[¬ä©ŸcCàs\›!.³Ñû;ac(N–ô-<7>yIá^²Ô$ãί°ÈSü$!ÙT…£e(hx×ɬ#iE“Ìs•8ÞzÝ<ªÈM 9lcnüúÆÃHœôrÔ°†àËÉ[~Tr6¼--ÕÚAþ”•5ƒb Ïv4IƒÓ¸ö©Ä,·pyr€çTë#›ÈUiÍîÐ÷ ¯v<2L©â6˜d$ò²®d ^‘iÎÄ㩳Ì3â“û×üé. Æø «nåçóÖ-Eðq§KeùÊЉ‚(|ÿzÐÉ&j"ù öË2^ÚnΫ÷:Øâjö /¤AsçÆ´1Q¿<Ò¼6¶å”0b'wv ¤Tº” ª…Ó·¼/Äx÷ÎbyÿqGû‡kªYìË—"%àëú¶ÆÎPú@vL'n‡xvJü”Z÷ôÝŵÁÙÀ³çÊcÛýº¾Áo/ß×z‘¨ºS±Ñ—%ÿÁ¨úº{–!FIâ ½¨å>{óè„9 ÞoŸŒŽ6vRtKðbHÃ1Îz¿<¡ÓÍ*$ÇÓ¬Ç d8g«Ñ9ªç±¨ízÎ}ÊImóE¹Ên ]gD;¹#£7bl#,£CEÄ踨=R Z=“ÖÁAž©õè‡ÜIÄ\Ù_Å.Q’ÿð7Ôè7ï ÚD * '‡¥‡ü#ÅA‹•Kíà}àÞÞYõwo]PRdövEd«ùõǃÉRãk•ð|ñm„d/%¯`i÷ô^]XØ Õíå­¨¢•»Z'ŸŽ»IC:Õš·\Šì‡uB’¹üG{¹-ÔNùÞúç„Q¾•=¿Ÿ‘h ü«Œ´b ãø×.,(-ž—œrež%¹0Ø'†VÇ)þqÕ&ª¨+íuŽ> u7n½C8’GW:dC¹VäI' ¹g|èà®%Kjâ£óƒf3°ŸÓÁ«dqŒrÁœ:ŒÈ Ç©5NØñ<4™\è)ÃÍtëƒâVCÕ|©¾eçØÈ§UäS¤¦¯\Ï9^”©)œ3à)I§¤áÚ† RýÁ%ŸY¢:Ü’ûìø¶‡áìùP|% ~\Âñä½2ÙË‹É9^Tpÿ³ž3ϯÓY®™â«²ñ…¡%íÎÇ'™¼ê¯%M¦¯6‹ÎÔ[iNQ óG) ”ÈÓ‡ú ý‡ }ïn7[Ä…»ÅæEûŸ]%逫ô4­¶U²/$®¶¹8ãd ™þÉæL¥– —8&ÈcVþ˜Jq³wÉaªËÊï§Ä V¬;g‚¡¤#·"þ郭Šl7úÝHÕ\ßá y`®”&¯ö©›q§K+ Ô˜ðê.š‹ÆQOóæ“ê@+¢Ó#£©#€·#œD>­• 9E’í*€$iÁdªÍárgJt†œ@äÞ-îm¡…]IÃÌ{øž&2\!t?õÑgø ÁÏæ’š4êéµ @U «ˆnL‚ÑËò¦f‘#® Y!öÿ«`±BlÍ™†5Žúí'ÆéŠJÕ_pøé£Áúg1°KÝU–ˆ àŠÒŒÆ/iõÌ™âöжšj$¥8ÈÌñðsøq¬G–ÂÑço]’ÀGr~HáBrƒ9xnž9Rg÷]¤(Ñ¡÷¥ Ðúõ/q˲Hôû·JæŽ|¡Þ_óæ•§fÐÒ¯ôö&ÃÔàfÐó?Ÿ}AV=¯}»©W&l.ÅŠ&Öçf®Ñ7ÔïÎùpÃX(;çfø#‹¾¶,?G—jX§ jûnaeŒ;1>o'CÕUNÚ8W!ޤÃ^¿f‡Ó G¶BP0)ê‘ô@– Ý#„EÓ™Nc’q÷3‚ûÜ–·ôüƒ×¥SL¾Ï%ŸÝ×)Û÷Õ'ïâÃõÆPwq¸ëTIÏÍ%‘ƒç1;ÙÜ #ý1´z–SHr`q\¬ëá;;íÞE2IÎrÑ‘ºm§ì(£Ê4¼–ù°9¥,ä#µ kpß/}Ä`(WÚ#ò0#åêÁsœŸ½y•P)µâK›'ä1.Ÿ ïJµ€ äNCpwv`1•ˆ8͕ەé ý5Å‚â+|Áf]—jÇŸS4Ù(é9/ÕêCs|ñOŸY̧¿Q« ¡b«UbŠENÔ½ú}è‘ t°`UG@*e•yyì8Úfè%ùm®VªÎ$Ï“Bïh²rü¼#uÏP”Dá²Xáx#²E㎠£bv#ˆm2ó£)^ð6Ã,hˆÐ¼xta÷¾'ƒpÔêÕã·µŽΟ¹¿¼¯qõJÍÿßNÌp§]Á‹lŠN­ÀKMÈð…센O­;Gî’ÃU¥™Ì…wmM•~Ëé kqeA"Õ†JÑÓ- úKº%é6cªÚ)ŽÚƒt8Æž\ÉÅìy}A²yÃ$æ».Uõ¹~àŠÒPšCˆˆ ‹ 4¢Ö¬Œþž£Ø€uM‘(nx¸9x3Ûfš'¬ÑÚ×àódþNàm3Ì‘9„ï7žlVä®È¢§N°PßáÙÌȳ#žæh3MPà:^ÛCàš˜y"õú€ÂÖÒ¾¦¶ý4‚Bí5šm&s’à¦tÞ‚‚«´ÞhÔ>­l>Õ`AM¼\;„›ÏTE-boÅ2…@s+]ݧ6=2^ø‰ð|2»=̦冷úª™›¡™œÞ€>(¥Rþm8ÇÐ’;äöÞ нXáÔü.:6UTR$§_Î5·ÝêûQo2eaŠ„*™úJsÝ.ôç¡îzK“Ò„Äû·W_Q‘Ìh¦gYkt± B—¢Çþó‘Ö¬®¡Á› ¥'ìÚ(Ú%§#æDÏJŽÞÜ{õÍ4@ˆ-Fö+ATØ¢X˜äyÈÌEMjéç´* í¢0,Js[§Þ—µöÆœÝW ù¿ý7ó ~›Ë|í>aÖeqV¢9¡qæèw~ÙÈ£Çn‡pßçä”ܯ]K/aû=0Y‹ ê:”(1Àï§¹ß Ý¢¦hº_ˆtõo ¦5ü) FªÙm^ðf˜Ûü--j¢x3­°±ÚZß9ùÎg#¿bÈüØ2T̸¼PºD ¶«ÕÐvN†GÀÛæ] “E”XkÝãÆy˜„¨¨ƒ«úßâ_Qr;¯vhÐcÙm&…zå³&²H’ýS²¨]ÖÊ'Ãk³Ÿ!zÅ÷ÅÉ+M·TþbÑè˜n`5`ñ²C l{ÏœeÐÅœ=hôŽ÷¨e&K×MÀÚXÒRPg2è´SÇ|•ÿ½¾c½¹H±É¹¯q C\:v5>\Ñw×~hx:*¦ûpÅï…o ziÉSi±šÔF-䲿ÿÈϹç/^\rÌ-$™vWï$ÐC3JÒD'×|÷‹•ÚÜüåÈú ³‰øgd‡}ÛüÈËu ߢ T¨íúaÏå—ÈÃç9ŒÙþ ¾ù¤o¢ÑsÈ΢È\°wà·7AgäùhóP]•ÊÀb6aa®(i…ø„§©jNc€· =Hüèà¹üßjK Ü&Õ:Ï…åP­D5›\y5´îȵBìEH!0£÷¡]a¡%ÍßœBÓ¸ž «ç±4RÜÆD"h=‰ñÅ}¨Õ°tEhöÃí~3.ã¿ìF@¶*VoÀ­íź–)9 7¿½›é‡_á£Dó»u1†ÈáÉ ƒÙ#û Ù’ºÕ‚z¦¯¢žh¸¾°L± ±e4þ=´Ë%*žß·knQ²-Àó6tW¹¥ËõœäKþá´•¤PiÕ`Sjš*X\Ó8A€åžQç&áà7QE8µi4âKˆæÚø¾¡Dn£-Ó‰ŒÂát?À½sÐøzY~åsê˜röé/ nEî°³}5ô²ÚðElj‚™„{Åß]Ok(ù4¤µušåΰY.ÂŽÅ5•ªÎæU³Ô¶ú™ÏcÆ`ÄJ´ñßbm?X²·JÓ:úðyüÊ'ëœí:ð;ƒ~Þ¾˜¾2‚XÅ^‰´,G ®6Du*ŸÊF}ð6ùˆT…éU|XˆÅËô¸Vºn€žèï:Pòñ•Ë6«¢Î¡j‘¼îc¶ÁXùú :4-̼!Д2©¤©º°¹´®Cßwëò$ÅNköèÆ6‰þHNÁÑPf(ÙÝÎæðl·Õ¢Üd%2ÝV=ôG¯UÃÅ¢`E[ :àyjˆ+´ñÅoÐnëqÖ¥\T¾¨(ú.û4è*”eé CO:&oq¹¡€©Q ä¸ìêJ3™ô¹¶ìγþ[šD÷/bZ½¶Á…Ýt4qN°PÊÕÚÏ}î]rÎ_IíI»…¿Û¬kÐÝòsÀº+6½‹Aç̲;\WéׄOrá ? Xßêþ§˜­$‚×Už"ÄNx£Ä:’±˜¥¢é°KÔ¦6uº°|ë¤öìØk 'A&ä ‘UûnMzú2\ 𣆟hÄÑêIbÜ4• =¥‰¼p=©blçŒoRSW¾Ï4éPòGÙ÷øo‘®„* ZýÎòÌ~ ·€C<úøÓ½ªáÚÆ0<»Uây ª»Å~BâÎÚ켈Ãj%ÈØøÃJ.½Xh¬xWkÇÅ¢¼Oæü›Uó¦¹a“­­X|—Æ5Vƒ9¼t^EùëÞE®à)j†Ì"‚O(ÿLܽ—‚uêÛc~+ÑÏ—&«Ñ m7Þž½*>´Ï(v1d8 <®Ò£\VUz›èk˪ÌzYGî*nÛ…üÇ&¿ÅSP¼­A[UžLñß½1ÐŽD»®µGBò”ÂÅ©¬€¤6ž'‚ ¯d®DØm˜òÓܼ€ÛO­G"8iý¶A-.ãG““.T®]‹É%óŠïÒ€šÛôáJ÷©)›ÒsÅ"Ö¼ûÄõ#~ÜKò«”Tä°îU )Ãý&¹=PI[ËétÈ«EÆÍ!E#£6Ú3Ç]·}¯óe ‰ç€ùIê¿]¥Ùy%έ¹Mp^¶«GÇxµ|ì\ <†…ÇÊ%ð[–GÝŒÑí~Ôñ!÷x¨øc·:Ç6œ;°óHøÌ¯²^˜-ñ)®¬>TdƒS»‰¨Wl$`¦=(Ù\…¡ P•o¯úRÃ\ÿPßaoáÏä GÐÀ:úEÊ6ˆÒœ?äý ¹5;åÆSÛÿÒÛóWíP-,â©“¡ç Êè…X𲨗%‰m±+γ™q“}‰ºßÂTÑ à¢ðxîD {ÑÓå8~P"6ì˜èŠîÒÚ3—·›·­¢g‡™µC 7«¶íQ§·5ÒЈ4 ¡/FÝ[˜ Îù³¥§ 8nü¦Lgµ!Z_1ìÔw1\ËPR~Hð·í“‹?coaÈà€Š¿7¤^äEt`èœRPLÊàb2ï£ù> ]|h ªïK|yʥʞÆÿÙu”ê×rK¡fU¤@îwÛžÉOê=q!#’×À)Gšl "j×Ķ5MNÀ¾èÌ|+Cì§ûçÆSíæ¯„€@U#PzMû¹é Kˆ¸LÂ*bÄ•záËxîˆ$eÁÖ,?=Ý$?aíI)~:{JœT{ïÈ™§´8hZaúJ©¸ªDùQ¦ÈîÿI¦Q$H\IŽ›çb ÛRŒãH"Óxí >\BÝÛr 5š„·?p`17<Ûw¨wFÕáÝùÂW—9ŸXZïç.Õê3%¨]3feåF9~%Õ0öÏE.jpøRѵ~ƒ®é¤é=Rœï÷ÉÏ%PJ{ì³#—›. ò‰bƪÙB˜0¯@(]—ë¯)¨õþÉþ¢Þ³bÈ #Ò5ÑiEï•.÷XI¬LÏ W­>¾ª‰‚ôh&‰Sýzê[¼|¦„˜ÿwE *θ\XŸÐnÀ+¿—DjYr ˆCÀ'#³² ºÊPá]‡uïæ l¶E³1é•Muq2:ññ3#ƒ:Aß=KÎöµsÑ)”}®HþÐÖîÉ×ŠÖ v4'ºíc¥jAt“%éA­1 ¤\h'ǧª ¦dL¹Ÿ”Sê²ãéF¦ñJÑ¢-µgÒæÝgÄÐt­Ÿ³4y©iUÿ­yVÇ ­ÉxTˆ‹T«4˜À4d@MÌÍ9%ShÐi,A³‚ÚŒ³‹Ùò°Ùÿ =ƒ¦šèz…ïnÒ_e¨LÕeì@­=˜àloU Z®5ì×µÌíOŸýÇ­_&x‰ §?SÖ­0Þ:ð ‡]dÓþ‹R9–™™¨¦÷3qмÇhw7t¢V}F-[ãàÎC•ªæ·?ó#÷ Ÿah!ö³½Õü¡;]D³ïÑ=E½Ç¦‡Á/Ö^8®z(ɸ›¯i{§çôGøºDÏuØ¡Þ å'¿Bo¾ýHJgLhòXi÷“g†?"þDÑP—T )ÞÇ"ó«)>$Ò[ÝG“0zñ´ä¼Ö{[´®‡c}/ˆúÕôãR>I§p)c c3€¼ñ%èÀË_ W\¿Pϸ(ø ýŸ-æŠ-g’MýöËþ=øÚo-}˜ðšõ/QÔ…{—ÄnóDܡЃ$-§÷§¦´ ü@¿€º¶ºùHKS c™™š¨~¸áÌL)AàB/üV!2“Sáz >6oŠÁÚòÓä;ÐKŽLtïüÿĈV¸}“*67 X££Z[Y R÷ç‰EëËÚjèÇ‚x¥ ôæËr3=9" õ"Ž!è,|§úÊ…ÃæÐc›^ ‹€¸Ž\%Üý`–^Ës&"Æ;ÇÊóy;<¿)1BùšÙCeÓ1Í!-oØ?]˜f{šóßH !Éí¬'¶;ô™ý“ÇÎÞ‘ŠAöÕ¡ Uð½Â¦@¶( Ðs<Ìô_̹^Wsç¢I?% &оÂP»ŒqjÁ8ä~GÙ CUe¨Â8­LG ö,n°w%ól.Ì€.ܨ†æ3ö‰×g–|g¹-ïÞ;@Ìó¾qÝZ ëU•åµøÿ‰ÙªÚB, fË¢­iÕ37tníÞ‘'0]Úת5›Ê¾}H ¿üPÖ½uŸU½x#˜óó·I…D;Ð'ª[þ-]»6å— Ð'Bq{cQO\"#Çn Ǹÿ­ðÖ½8«IDzåÛÊo æí+Áx•äSÎ!"È9rõ÷©\êI…úC¾^߉M‚ßÒ´$UïùŽþe»æÿÕ†ô(Ù  O6¸/y‹©§§LKѵa>¦:³Ý§\ë+SmöÈaíCq.°ÖÄBP€ZóŸõèL oòŽu7Û~‹…CNÃòJ+[p¨ `Õæ0¡NG]%Bu-ªâ ÿmœ3ÌÜBÝðœ…my“a„XÐBg>4²“n{­þS¼j>R8öd¨gŠ ¼Ä÷Sñ2„qP_­ŠóX=Âï“C#ï_Wd­‚XìrQøF™?^ [Dw}Ëˉlª áЩÊÛ!¶Á”Âý9-ûDËW7cƒÁ!ÿ†c#Q7Y•jBùVôÝû$´ü«ÁÐ|Ôk/ö´•{a&õUO¿WªÄÎi¬“2ÜPæìdëßz¶X¦*îÈ*톢¶$¨vwwÇÊŠffÖ*:Ëð¹RÂU¶” wIß»þž‰tÙÍf½Ûíªík@›ÝkÎöÔÊ|´§Á¬ñbº¦­ÚìEôÞö S–c´Ü»a>Ë«ûYÙyÃaFud@ˆ1DåQÇ€BÄSËÏ_,â©æ†ŒÕåbKs>Ü•â§rͧBm\p^'tt ˆ•âw i-ÒŠbéZj¥y•ðvv"7üâ7dá¢ZJjÊ|ß³±“øFdwÑ7Vñß–M ŸQ¬òí,{7.®¢öŒŽJâwpÃǺ•½Ò5¢_)ZþÁ÷"Å g£ºÙjÏ@çy„:?O§üsLÅLª– ã…W¾m¥åDo4;¶ð(!ÇDkÊ«€§ˆdUÊ•:_”ÓcI ]½8ùŠpidBÕóm;¾?¶4Þ A‚І˜ïFñ1€ýòy¥,&´‹d¬ä¢£JÔuŠø+Ü=²O´ÂW”)¾Ôd5u79²„Í}m"¸N,(TŸyI˜ôûÔê„çí%åÝ?ísìaÖü1ȯšø·Фú+átÎk83}nP–P+$ê=›}³°m»+ÂH0b7$¾`èQztaަ­n¤Ð’Í5°.¼ávóø Û˜HqJ×vÈÄp¨ä[æ_õÆŠžžŸÌ—F¿ U|[ ‹°!;þnhø—RTö°¿@ ãLStAyYÌf;#+úV} Oƒç4 ‡žçžeáûÁðÑœ›O ÈñíßK'„‹= ÷cy¢ ÝãæPa{'úº‘ŸÝ½˜ê±t1 Ý¾_O:þ £|é|ã>B¬Òðt%}Â9Á9ŒPÑ‘1Kãeù×ãBL=e'Ÿ¶—ï˵°§þß¼ÛÖ­"ú ™{•¹º&ØÑQ+P–ýUÛâÿ7#ÆŒºlø£@.Xìî!Ý/œ€#°Âk}™zv—øÃã•zïtbù5„5Èpðªb¿d´åƒ§£»ÌØ€Çñ!¶ºü¿áB‡ò&W×,ÈüŸÝjiM¼’ §›d—Ór‚jNWààÈlLÇV¶±ÙrGž;(£hx˜/ƒ§ƒÂ2º }´7u½Û'K÷ ÷E½Ë~÷[N»§öìÃ|¶æ’eÎò£®ÈF¯„]dn Ò!jðÖKNË£»hãL„ÙÍCø›¤•ü¤/.ú´€ñU|qÕ %ÑRF6«p€ªP±à-CCùêÃè n‹8,œE[O祃ð -w¥x„ñ[!§¢ÎÆcxMSxQ“2ŽcGÐm@‹aD 2܈ý‡™t]ËU”.íh:rt@PÅVÏĺ¡0¶_Âè¡4DÌÉI[æö:Ý“ŸµðË1_U²¥Y<û/š]ŽüÌûf‚½®,1¢i%<¸Ù1¨§ç®s×fÿIdm[N®f}Íõ- 1_¸ËQçYæ-ì² {'èø••Ž[5ǽßDR€Ž’¢ãØ1¿·ÍƒgŸ®ÏïB´ñ”+–§¢´~ÄPN=àñ?LÝydáùÅ/ug ’®Û^îÐñâgz®ÉÇø 'DVaîß’cVžö´_s=¢EqßÌÍåc¸TÂ|D!b‹KŒYG7íh’?ÝÂEÍCÄœµÅ³Âûu‡… Ñõ›!ê;MÉI·|)Ë-ÛækÆÐl„&ø&‚Ü„;æ-± *ME”£9j¬>Ó#ûëjw”ššrÁ)5èù]zDD*îåœ,«ºEáŽT*Ü‹èáô@ö8ìRÓ‹‹á¯Û"71s&ÝÉzD(k˘' :ïòh¢GLØDÆüÚ3»,È˧€Š†{¶ùˆS;l‰`v<Ò$?­.î&|)Þ#›ÊŸm=XEg´ÑÕ´'цœBú¶”TaÓp—Y•sAú“^Ta…FfÅOÓ¬þê·<Ø›+R0­H=yU)a+úßš,õݹîοÄLM—áï¢ÊùÐ °WçJñ”c$K$±¿f%á#PÒF62•Ûõ“úMÿBãÛNgj‡XÇJ™¿ÐÑ”,ÞäSìÕÆȎïkþÓr“Ü8‚¦™‹s©¤:ÓU^sÀ6 jÙ°jؾ™5Jcœz60›±%¬ÖÐý¦©â=™0í QÌòµñIDíGœ”¬ÇÔæ’¸&9–µeåHN´K5aZ9FZŽ£Œmkä[bØcɬiyF3b͇¢ÁtŠá_+—a.>"Z¤t:6Èiú“5Ðо\5)ÇpXÌKÄK÷PP"WnN½ñ¶Ô”šzs‘d3E¤eH‡µÌ ÿÇàì5°KÜHÙ U€™Šã†+÷]§ò®™Ü¡¢-¡>åi«±ë–ö•Zå-ohh|o;è£Á—ˆ¥E¼úͲ|G2èµ ¬çQ¬Ì ¨sLçþë}. ª¨È+=âýO¹³¨’Bu3M‰JõFƒfGµåß2õQÿ¨àl6Pâ—uª7ùÃïý“PN8#ílmGÖÀÕlÑûj{]혾ÿÿ¹×݉òtYÐOx¼f» ѯ|XyÁtvÿ4 ¹×ô+‰BU¿8œ“D&+{ðžº.7ït⦰KäÓ1 ¯V’Yå7}€¦5ççd –ÓÊGÒËú´BÔ’é8¬8ÅPR•f©Áíî™ /9ßvâÁtÎܘU ÊÐ #y‡ŒbÛc&Ãú\<Êžr…ǽ¢®üXà߯ž˜g”9p»¡‡‡P ùD¤œ[„_®ö=ð?ó#ÀÙ  Lp”é€RÆŒ5Ò¹YS+u?"ºRŽ· ol¥ôèàÆRZ®(ˆÁQ1}œ¼³ S sf#ƒk6-"Ä9¬„-МpGU”^í“WÙ¼!ãŸz´—Þ“³O·ý²ûí&°&ÊJ,$ö~N-¡ésŸR*MZñ^¸o‡”$‹ ·£dJÃ8ÔV^±“J¾˜À&sŽÓï,¡ñøLœ±Q’iRð°¡ã¾ôºÜ » žQûÑ,¨’îù“õšF˜Õߘ£¹m?–ÐI_ÙÕ‹0EÕLêž!S TEÜÔd™WbôPÁ3¯ÎbAþŠÕŒëý¼Xϰ)¸õr¥\Ƨ÷÷»_ÀœŠ!ž‹‘úÕnU&¥›ÂQ‰!ºW„¯ŒÆ-$p8Òbü:‚ã¹f-4®*&YRn­]dl&‰É [V&)’§/^Œ"–3…¿}°¢ ⦡XæùþÏaIn0žøÔ.M­Bÿ­´£mù-;˜ýE ‡­*…2Ùl“‡þ—­ºÍ2Èè_d$®W+½Sól“J„Ú%[åLæÀ9 êÅíÆÙç«Î#dxW°/eá:Åù™wn‹óèS6šSyË!ç!A&ÿ²½ÜŠ16Yÿfl¢œwÁáø}Lªp{8cÏõ»Ó°}7)¯üˆÁ¦ÌMÙåíÂê“•qš,øóÉ{÷„*SOIAìЛpíí;ÑhƒÙ·sR3C~7Þî#¼ssÚW+ŽºqDú¾µ…ØO¼÷(†çK,ضÔçÖ¤Q† Î8ÎOÞŸ Ÿ{ù*â@t¹“wúòÙ4aý/ç@Å28] %?_—9yÞ Á.7ŸþœIì1U t÷Þw·à-n¹²9ï&=Sc÷Ô¿ äüÚî«Ï¿5hCâ0fÞ‰z´9Pä­¡Ó>Áž’æ{Åc¨¢q'Sq¸ „¹˜¿ LlÑi%S¢NŒ“޽§-!TEH¡w¹axG¹Íj~,Ó¯rê\ó¶\¦Ä¨Œ”õ«— zPKߨÿà…^C´OéåFTó¤èCbzã~ßåeaöLj÷•þ¢ó{S!ý5õ; <ämøØä@«¬=û¼Az¯Néd™P9A‚*áz!(¯e™Á-ìüâœÃ½$_˱ñ_f[Ì:&NbÆÃÈ^/z¬7×$"hÙéeÁÃÚ[‘Ý7wSos}|'M¬b¦£ýáÅi…`¿ï‰WÂpŽÌOåïÁÌ7I:¸’kÝ»e…2ö[»ŸMîþ¡±ºÔ¯%‰”™fò9(k¯?_–ÀŸ}Öó·£äfÈíM67Ÿ+Š>j_gô ýïâõ<­Ä‡î‘®ê^¶¤)—ÐG5Á*c§U½8é5­õ;„gKU» ¶EJŸFj–V;{Ù³'¿oÓ·ê¾…J9Ÿî<ØSU$nÒæÙ‚ÆÔŒax‹/lçþÛpýÈž¥I0ÒÊ)Ì“O%Õ·@YC‚y÷ô0Á 2P‹£‡:Á}ê+R£Ý` l€vRùŒ_¡r&VþÃ~™s‡ ¹’C ²óÓþ$ë-—²¾ÞžÍЬ_q§ŸœMzs°AV Üj@í "ʺÓô÷Jþæð"­ø 71ô»Æ/epÀâ<ˆ¥—ßGßßwT˜]£T¨€â€áˆÁž]3{\Ð$×µ5y-ÖnD˜Ž)–‚æ«á1l¡d¤›;}¢Õã¦Æ/œœÞ¡»«aD†òCY½¦6>~O¤Â—Éd»n2ôìR4ƒs—æÏýÒã0Á†û‚Ú 1D˜9„KIïȌɭ—ï®gtqÜ¡ep´J›£:MÈÉiÇ‘ Þ‡Éw@®,ô7•¿¨›±Û¶t¨?fÁ±üj¢‡.y7§ ÅÅà!åà42:=X3F„ɹgÎU”Øn ÷¹€ÖÜšFn¦/û’¼ï-rÀv?ßF¡L…ÓÂ|ºèÀHBÊkd/ŠB”è—¿Æ„V:.#jйŠË¦ý„×y•ÉS=lû_µ¦®ÒŒº\aîŽvU ”GB|Ž,£®>Ñóú1:åî”DUÌáŸ'9¦‰yÈ6Cr†%–’¨%¦¯{kqT3'RcjáK F®¨~y4EN¾]–y¦bY…¤56¿ZÃç,n¨ùL®°Ö)¤OŒÖ¹˜²nÑ115ÞpŸ4¤Ê-XßP`ÔSb¦8_™™¸š×%ÑCÑBu6+´èÙ»§},Ën†|¡sçFDg ã+k%Ha‘q_ºc–‰Ú®Ã–„àÛì?æ„‚$óËB}t>øµ²QðdôFàrßr¢ˆé[%Ï+ÅH‚]XÚÓ7^J|ȵàÆQÈgF¯l×a9:þ/<Ò¤êàÓ@ˆ&¼¥fűg8œÜ¾´;b¥ʈn­²1–Ï.þeåŠ~vãPÅ¥I0¸®ö.(‚ ß«(@C—Õiz6áB©ü>D¡ÀÑãônC¨ˆ””_÷4—oe_žV_©CeVºK^(øm}pwfBö–èªÛ/A:r?·ñj+ õìßÁ{‰!èW\/z¡é()Á5·ç@pU0IœIÔäïX5ü^—¶ÓPZ]2 æ´÷ö«©ð„²Ðë²4¿/W(–n¤+5üô`áëP1)l)iï•SÚ¶;4p~¡›ôYW˜ÞÆ÷üøË|¼7ý›"ì»#¯M´™Á ñ>z™ú^ªˆ¼²X½ð"5úzæÒzc}v&°f g×÷œø ‹öþȺa`Í6Ⱦ¦x‹‚ðk‡'ÆqmÊIzñB¨‘!ÑKÕZÙûl¹8Œ#( Šöè%acÅO ®`~y[Ùsï7\ÉÐ ð%”‡c´ëÈX๔6´[wåu²°`>AG®ÒÊ^'Êk6Èì€ò7£8àL“å5§¹â5E©õ{÷ ÃÿEÂŽ•íÜÕ¸ޏÉÉø¯ÇÓÔñ³ëõ‚4œ/òÞ>kØK_²®] ­E:ƒ #¨QÀ2 Jg6ÚëÚõ›¨yÔcö™aÚßKN ™ú6(À$c„úS=ñg-Å]WÔõvZ?1|=ìG­š7õßðú|ô&bTº€ÎØH=ïñêÛ“ž_¾%!Ì‘nÉg2J>cw¤Z½ &ûö’±BÌ¿Äïwü8}Ó~…åô©¨éï¥0¦Ì{$ý]˜ƒ;uÜ9ƒX_'bø¢,…÷Øv”@¹0¿0¢wùZ4¬…>TÜ̃¯lâ–ps‚”;(ÖDíÇr°Æâ—,N båeÓ)Y^Ž™~J»ÏÞ@„âsB–ЇF=1·Bæà"w_U š³ïEO§õIôô#®„Æ™Îôôï»æ0Ò§t5R¸¤¶~×å,j2ZX¹NÕÆž‡åÄíLõY‹M·.iß[Èåú!þͦñçÚJ¬«g5³×Lj^ñ¦¯:VbÇ&Ɇݙkú6%§d2YèËEmG¥µæƒéÃ+¨ë k ±v,|ñYKïÙ™€TÝàè„EæRôÿµWëeK‡Gmywñ”Ñ I“(ü«É«£â¹ÆÏ.êýú”i*¸yê2uvjâ)Ä&ÉÈ™!´™Ê9_óþí=¬u;1&þ† ¬Î;LÖŒ‚a2 ¢UöKò­íá.ûŠ9)‹8p¸JªŠT*û…4g?)æ ut ½™-e¥DƒòœzŠE ÅUj÷fÁ†Þ8À<¤Ê6 Í9Å‹+/ÏH±xÔõ¶K’`B)Ú9Bî™^¨Ç3¾òã›Ï§­¤á²æÑÐB¢ë@ªâ`Í3Mù€õóâ»Þµl)¸ùXG=Ø5|Süœ+å ¥™k¸ùü·ÿÙÜ'Õ5¼ 7¶6'Q¼=D¶ÀÈÄpsDƒhµhÏÙuË€s—ã­o¨&bË<{ ÷KÈôfwž/ƒª*®üû˜/ºÀ/3-ü_û ‰*nå+þ.àƒîЃ´3‘àñvO-ñÚù#ð¸I R`¤ÿ>\6lZ®ˆlâ›à_Ü¢wEÝðª‚è»ÅÏáÝß # ܉ôÀ(‰/šõ–™SÊëQ€ŸLë¹dùˆi.H¥FUGˆÇ½€rc¥*œŽžj$Í’¨/"IZIô¤Û-“ˆ¿bIçŸŸŠ§ '§È&8’ˆÚæÄòºÒ+r1x2ÉÁÃ[ÛĪº2gÆïvÂÊîîWIüƒFDÿ^¢?K„œÖŽ–Õðe.pŠçÜÜrŽ«f=N"Ïb¾ý$Õˆbº¶ÙWB{iî¾ÑŒ%zÙ ´þo+IgL¡¢WvôµÂÔÒxÒÇaÄšBÄÕV øp¾ ¿#98ºJ¹5WpI(ÁßÈ"ïÌÛl)0^²0ƒU@ÀÀ“‚¥×±Sve߯Ô!†ÈèR u7’—‡š¶U³ûþI|›¼ƒ•¾¯z‰é…gðòÊÄ Ã9¨[’ìϼIfáÈ“üô£Dåkà€ˆH‚Wê+*¼§…ÕÎË ë-Ù—]šz>k]pßû±]ašev ÒEáS ã[´èxÂá€Ë„Lb_0˜ÞÔ&;é°´ìOÁÅÖ†¾.êæ‚ìðõ 1~haèE—Dþµ/gïœØm$ýÌ• ÍU'éy$´`ày6Me7ësŸ…ǽ Ë’}X·]žRA÷#ÜŸêw6Rsåô«QNk~l§èC_,®½|ìŠ_úCã¸g"üÇ»%¥÷O^á 8cÆï¼Se¾k¬B4u†<P£Šo‡j¡JÙƒžpé·Ã€Ã‘²üOB‰N¢ùÁâ:•Ú¿÷›.sKQ³‘§|HJq“¼Q½ò†R¾¯mí"~ÖQŠM;=©’xD[¢€BXh5eF¹H²éö’ØKçöCýÄl'ܽé{Œé^G„¢‰¢WÀ¨F=³Â¼|?—K Óþêüx0ãÑÊ اD¡™§~¼tU”ñÅ´ìeшé=÷ÉÁ÷ï$ˆm·ݬþßM×¹žÜbC‹)Üš ~”Bä¿&fêoÁÒWÁ•Œœ “£ƒáhD.I¦5%MÍ5¿^ð±}/€¦¨~” XF†¿ñVU™ìǬWØâd¿@©R,É÷ ±O8zÏþzmÙ/uØØ¥‚œ~ÊÄ\*wYlÊ@À ü©'W*¸‚R~ú¾eã@£ì&1ˆÿÁ¿—wÙªïÄ´ïPûíŸRElgÚ8$Mt¸!‘—Ç¡òm§?ÊùËÊUÍÉTÔ겺NèŠÎܪ zýÊ9œjg ù¬%Ó[¸Gý½¾lºäîØYó,Pv_Fíp[»)<Þ®iÄÈf´‚â`ƘIv÷µí­{Õþ¼ÆØ4‘_®2¢…Ÿ €Ñ<àz…2<Ô«pìv]S¹£@üPšŠFùÍmQ?¸ÃE)XVS U¼‚å5aù»‘ÌËoÈ˘”Ú­`ò|'õÚcoÅp|÷(›2$8H—}ò¹HõšÛ¶ñíë(n?Ö—â¿Õ^W´s¶EÊY)¾]“A°òeÔ×"$Çt gÒ€ŸÀ¨˜7"nô°#÷ƒN|{+äq`eÞ³f9‰wŸ^|8[^VÀ !0^.»¯õÐx/p¡¿»p9X– ©W<<Ø ·Æ§‡/B¤¿ÉDº³H'Mº“ñ$ß6 UŽÃE´ý±êq•r^¡"£ÍoÓýf†eì¥ïgR‚ÿ°Å˜Ð»öô­ŽD4ÕG84¶š.´ý¡#JD«œ UU}Vó-h£ÝÁAÂê)‘¯ÇÜü¼Ë‚wƒ ÒFŸi¶„ É»S†µmÜDÈϨZ˜dÐÝ/êÔg,³lH] N˜=6«QÉ/öé+L¯ù³/éIÜ.çñL¬Óï¾Õú ×rðÕ¸ð"¤TeìýÊ­DƒÇ㈮ŋÌö6[WœŠáØŠñ7ùàÙÃlÂz‚ãÏÁO‹b¼Ë+$X‚ËrPóøz:L 6‚B–gF² ©æ;M‹0±pSªúl½g{ÁQãp˜53Þ¬L»s^Ý?'N,:Zí¿Bª8(¸ ‚Ï›Òÿ!XVnïO•øYf¶Ã¼Hâ·J-€µ+YFf~5¼zÉÃà Ú‰U7¸,"7ãòÂEjpr}ȸ=ÎN‘ƒOAAôÉým¶õNaBËRCæ£`7­oïm¾¼çöœÒ·åéêÎHžW¼)œ7ûõ†îDˆø™¢øÅprñô/á7M5 ‡BÞV°›™SœyK—º d¡ÿ ƒ×Ѻ°‚»‰|ööIïš9^®n¹ÖöìÖ[ ÀËŽ–¦ª¯*ØüÝêk* #æl9GBµI¶„këÒ8ÆRw©yY.Û%‚¦+>à4,òÆ«'2lÔmÒ@ç†Üù}É?_Íp xÕöÝ‹1ñÂøÁí- À;‚¾Ò„Úë™d¯û+Úèå jÁó#YÈÿês—üáGò­Òï¸Ù¼䑸âX¡;ÖˆGÀH»Õ(r¢Ý÷dž\F=Uh?Eú…d¼¤: qä²q*áPÞªüã‡/¢¥UYå”ké *{ö¨s°£²8­Û®²-`8ŒÙgZ~žáKŸÏ/sˆ0§×¬Ó÷¤WB´x7µ;HA‡-­î'kŸa}‘¾O3&×É G/Ïá("Ë:óÂê^eà*½OähÁ(§cJÌn¢Qóœm¨U®ÚnDô £Ùq»Íñw%Ëà4»£?ÔÕä"R3/˲³öLÑ*§öËŽ¿´Ó4T˜$Jù°{ÞXë´Œ‚šªü ì°…á„y oÄ!¶ï´1Oùò1(¶B¡uJŒÂÿ-ˤ’¡$lLôMeÖµéñ¯d‹·¥‚áŸiµrH“,f®(¢…(z¤¥ 6ǺÞïe0‘Ì‘a¨¤ŸrWº7ˆ, ¦é4°e›þ‹Yi”í Vš1åú$ăÛîªØòÍ5‹øN« òçE'.ÓçeË_ºnQèÁÍM$‚€I™‹Íx—£>[þTѰˆŒœÂ4yrµ~wàÄK¥E§yRÌ‘gï…°£2¿ ,\èh"ÝAäRi?Ù—¿&J;•#$‰‹›l;Ä)¾¦ÍŠ£HªI«ÝCá.…Ö7ØÑí“øéæÜ#WO®¶ÐAj+C2rFš „^þc%q6êªáè@I°´ìa¹ºb4âôr»°„öŒK lqÛ†*倅B‡—ÿ+M¤hè>¤à-Qƒåݺs+ýží'¢ŽR­<íã&­Þ‹øÝÜï!5[c0uà§?ùµÓA„ç'}’êLîôHøs—á¶¥O÷ÆŽ”V]j0¯ 3;î7LEýÚIŽ6áWä¬L"8¥ÍSđ庈Åï]R˜{Jåµ¾GAèéUÇ¢·#(»®qRö÷VHp¶Hæµ×úë5÷(HŒ4™=Fóü=à¡<:`'5 éèûL‘LÆÊ‚ìV|ËéÊšSQ®×X%Ú3…𔱋ænÓ…j{@¥9ãE›à£tpÉQª ŽO«c`õ^8e'³mÓ¦ßPï;âQ¢¤Ó¤ÏäÁ%`IO€Xé«%…"EÄr/•EÈ{ž"!ÞRtíÖ§Ó®lRz«ønÑ/^øÎ’Õ’Úzôcà(wÜ-ó¤ôÇÎ¥mc¹.8L2ÝŒ»µo×-–FŠöÍ…çXXø• ž}Úmt#<Ó‡X1^ úêÛt´#þÑÞóÍ|`”Òí:24ÕÏê<‚™ ÷GÞ'Tá6ˆQ˜ÏÎãU(ÅÛŒ*àIÙú‰¥pJÁô˜40ÅÕ‡ñQ‡c¹ËtûÌmÆeFJ{Ž*ø‡§’êãF]8Š,uÐ=±V_I£Qù'Tcq$e´S¼é{£õf¾“‡¡ ðf<ŽB~é ø-k´±èê…a¸[\U,p¬±V¶¥-Ä®f™ÁZ¢©¤¶Wý„77ò ÏÇÍ~Î^[[\‡G p€Ï£v¯ûn…ñ{ÀíÊÊ•3c¿ª.ËšõéÏ~̲µ„_‰ÍÞ‘ $Ú˜ q<ÿ~Ýö$/’æ íêj#±æ3NJû°1S9!ƒ_'—”ºÀ§ÅŠw-šˆ«B¸ÌÝ2Ó)vø%ŒˆnÍ[ÝÞO¥¿@–üü{•|¢ìÎ?ÃP0n¼U‘3 ê߈C`ÍÀ﬚ªƒœõAÇ¥ú<Šé"F»æS¬ªƒÛA7ýõÉj!Î4·»ÄGœ†Zc¡q>»G¡WApmJø§·l gM$L5ðO…™ n·[ƒâ*?àM eµ©|C›¾«ÆF XZ" bïÍÆˆd®IÈ"T7ˆ<½½ïCU#× ìÐñöõ6ø#Œµ¢Ëi}u9ÈN:áÚ3 U†÷Ò‹£¸ÅøÛâe£R´Wü4Ï Álj—| Ôv9ã…9,nrW¤p’”s/h¸fæó•um¾t|¯£³†Œ¾þï“„Yék+Z±ò‰þû6Q Åñž–Çš~&ŒÉ`÷a³ÞJÞ§œ§aºñ|´Êþý×ó¤D0ìzN9¨À>½óÐæ¦M_·•D%ºr!ù. ñH¹æKô¨áÍM<Åûsí­:†öñ5(õ‰g€:z=¿„©W׉ZûàÈËŒÄÑ·,ÙH›ÊÚßBŠI[….Ä‹ÈΘm>?›Ãù¡³‚æh‡8ÑÑx¥¾ >“¢ôg>òkè$K¤¬ò|:‡_Çu¿J0¥L´‚Û§Uc2'ܤ0LU¥ATôƒG!-3¦'ð¸Öªý×ïæ<ÄG§³õmˆBÍKûxe39½¡Žu úcB©¾„«ã‰lu_(ëàîœkû²sûl=ðÙ/ݧ9s³N¿ÈAÜnƵfˇ ˲Àù™ê0ǧßÁßÓ—~æcÌ»ÔüT¢TßSqéµÎ_Qé½¹cÓ`¢‰oT&tpŒ`9*Óå£TXýÏgd2åÐ*¼}¦é¯‚d›_ŠÆÿ¿÷…½˜Ø¢Ó2Ѱ¹%ærZ,!Öm? ŸrYìË[³î“Ên/´zN#M ; Ÿµ*`e¥xŒÀ§ðÓXÇcáw²™ŒFñ;Mo¸F^ãpœ²‹}<¹ò]OÄ #~ ^!f£Ð7šaZ#˜HûEmÏ.„,<^»÷vc÷ãVŠü©Ü9¹ l3žQ ®7‡°a§Vyœ¥G»·þLzØÇ$Dõ3Žñÿ/_`'HmN”ËkLø‚Ÿk]Î5>ÎlHç¾3ˆWm¢È%?“óIÄ;¸+:2šPÄãp«¼¨ M^p3ÿØ«¿¡@ÍW¤µ cC÷;DZ5™m–ë‹Ë‹,I™ Ø IݳÇÃAsÝE^ 2Ãb`9§d…â0 0L½ˆL¶Ož¶ØÖÙPž¢>XÃ\)5L9xþs¹k€oã‰m1§ê§â^öÓ‹rÕ5×zæÑÞeޤ­ÜZˆ u3DÂÌ]/Æ\ÿ­–øªWTuN‘ÞŽ›='–­~­)Ûà`•aQ]seA9õ4ã³)ÀÆDI*’¸PN÷A`N1¸ËÌé _-Ó‡Y.Ѻ¦÷Àµ+­~±s)ÎE·J_‹‡Í(÷ßy²+™½âOï˜7‡<ó%¾ö}qG„°,0”þâì>¾µ;þVV·¬¾) þ’8|?ÕFâÄìºØQmtì\ÒM,¤wPÛ·îtµc~ÐÉ:D©p$ÖlHíòtßïjÿ«š!iÐO®Gaà@ú„»—õÄŽd(=ËyHBõsǃ„ ©G\»U.SRj¸„d¥ ®ÈíMòÚ{5K™ÒqÖ €C·åª'/2·ñi‹vàÙ….[V.NS^ÛÒfiŽãÚ5]‰Ñšðcñ4E¼Œ&µçXV‚±Ì™…Ü9Žwç”Ì@–›iøeRçï¢ÅoœÒ’¬ûom½ìj›È8Ff_,÷Ù@üÁ:7¿¸$ïú>Ká ¾qFØÚc}—OÄI­ÒIboÃídŽœÔnÑtGþÑ§š‘¨øAš’¢kM'€Ç!ðÏxŸ Z5ª@0Ž)#_è•·K°øÇf–ï#ËÛëž‘ÝXðZÜåo ›îÕÞ`&UWd,;N²¢ÙK7LœD°-k˜q‘iÔÒû¯ùǬB‘²-ºò¬ûîÖãL³¤~ãI>x¨ˆwsÎ…wcÃÊÚÔÜ14IsŠÈ¹ %û¨Çö›W™Ó¦÷¬Vd‹«ÈêR;˜‹[à.jt‘çÅR0ÌÙŽŽW©h`}ôã÷‹ñ%q͹2¹¹³Œd‡7f§Dqâ’Oä$ Pâ9t<è.;—éëôp«®ì þa3£‚jBÇ«MU+(~'‘`Cdg´Ž/šâ ålîei’›½"Ã%›v;²IOKÁdZ(kµÊnÉœ‹_)“„Üñ UŽ©/½žêZ-Êœ¬Ö­¬éC¹C»ºÝ3 ô&’¼“X£4æIÚg å¹ Û’½q|×½³<áÝÁb·»éÜžïöýÛwwà‰™ê`ù“ñ®o×ldÛ‹uºÏq4•*R²ÀçæÉ<)¨S¾7­- ÐmÛ`æ«P_ØŒ2QV„¶€Î%Ò€-}œvb`äŽõ2.µ:•Õ‰öþ€ƒLÊ)ý¢‡Ø-•ó:ewWwƒ1`7ÆË/4â R‰g±é¥1eP¤]¶@þ^6‚©´c}4V!'‹k rÊF²T9|«œ¹¡¿RÐáò³“t+êu¨2Má ?âè ôþáCóÐHÆ"Õ‚§y íN;y“h›‰ü¶u'#—¦â'öTàù"FIªâÃüG:Ôe¿D'½j´‹I¤ùfô§  ô3Ó¯°¶o¤Ûà™ ŒMÁ»SYæ€È?+FŸBà,¼‚«¾€W˺ɬMø^ü.]N¤‚ÞeKÆ\°qDšÅ`ÔâKbƒ+ÑD‰D¥¢ÙƒfaKV½,>/ûj‰+œîBÅcôFVÃû+‹ËÐzE2üƒ`u¨ø ŠGØ×ü…®¦­;=}Ír%‡ï$!dïäj‚µ3-Æñæ,Ó=Ï»9X\w7º•B5É¡õÜÔÊ€eè(rÙTZŠ©¢°t FwÎÍñrÚüW(ö`&ÁÕ2X!x¦ý¤ ¿%=תɓu»³Š`¹`Ý¥tqLy¯A¶BO8=È‚à¼HSó5÷eCð‡ÇÎ=#¼4¼Bôb¦±jÖ²¥ThCÒUØW$iDúˆÆV2 ´kðkïËÑž¦£ª gŒ»Ü\U´jžx…Ý–þ¾* %¡­ÁÏÑŒ9Aüé¹Êµô,r fƒOÄ®iÏ1s^<„ƒÏ9YŠ·÷ü/y~ŠØ+ÏNþ¶ý›!º1 ³O6±"Þ×]pØÚ4Ï’ßQ~@yQÙó’°Gq"¾”„8±®ì1JDq{I†ÙGRÍžEï€SÉÞØÔ—º ªAJ–eµ}Õ(»bL >ßch\‰ãôÑ3ƒs·W‰¬”kì½6¾ÿáæ‹H%GUãtää†>}1gqîThÆÌ ù@Å__¯]ci€#•-ŽŒ‚hŒ‹=d1—ÓÓŠ°56¬zö›%Ø:+ù±æŸÄ–ãûñ–=`p ¬išxb÷Öå±(gÏ^Ó%1’eCïú}è/뇄=+5Ü 1€šMX\Á ¸A+ó©ï¡Oæþ» ÙùNwjêø2ËúØžÿ-y\®}±!ЭȘ–O?–ñønÏ´a.‚rR DÀÅg,û–sαųâ;žLŠ#òª•B÷™Û™2ùé‹xµYè(Щö#¹Ó'Ò –XcnBUd7Í”¿»u´}¤V†ÆZ‡X)«êÛG(±T}Ö—E•Y;øÕûÜH#L‹ÅCž¼x,W¶DŠž6Õœíz0üÅuW59–)QÁ”aË2{“¶0Hl.kê$ÉZ©^çË"üÞ Þ;¢ÃWò‘z{¬xÙk O@Åœ_£×xu‚ÝeØßz®ß¢p² ÝN¿¯µðÅD…#Û€°s7ŠDö~íøõ‚?xA‰Lï;¾¶¦ïy²x"¥(ºÃ5 "E‘ÌyšFÀ-“¸¯þõ–Sÿª´öINîE§7\£b©ƒþìÆ)á£÷÷ ïc»$G@],gñgr·trŽ|Ôë¾>¶ì ~”Qr0u o¥B gXEfͺaŸOJK„p_…p– ËcõZÉOÒãiÂzÜ¡Ãç 臈RK" Cj mÃqæl1ØÍæ¸ ²ÊŽz“J³·A}PŒ“î”AØÕøTcûõ’˜1¦ð½ßÿIEG/‡CI{±ÏUê*TÒÆÙŒ#2„Tõ©]÷ò… Y3\ èÉG ™,‡&¸ Eÿzƒ–ëµiÐðExQ¯:Kƒ;³|‹…,ª Î˜ ¥âÏ„w¯9¢xŸh9¿…Ý’Ûølæzb¦úØû«^¯’lÁj•ݧpU¡=Nºx´ª×>X“‘ƺBåhú"›2iè—j?‹ÃÔHæ<î éßÁ-`F»Ú¯ú/_7¸ÃȾËÚ°×vmyãy®THÇnXøP)– ÕØÞ× ©; 4[¿““bCø@îÚš#1ÿ€Õ¼_Þ¼Çñ ü)铊Ú•Å‚ 2±¯ v²½ÓeR¨h÷Ÿ3†²k­5kè)“Ïw9ãâyâ Õ´2A!ÚÄîé6…dz̷”CcŒŸÿÿ¡Ò¶Îy]G¥æ¿Èª ›¬#X¨z5þ,.È×¾Á®gWB­vbdC ’D†ï¡jB<žqF€ü!°Ã£&‹œã9k¹ôx¨W ½³æ§¥™yƒêYß/zš½ù_€í Èß8&£$øöüºQÊdi£+Ïïk Ó0ýáÀU#ú¾tžÛoÛ°ß¾(³FÒõt°³gõ(@²RR½w^wk–Sš€L¾™è޶ÂcÚ÷ÈåÉ Êj.ïÄèìHU‹%ñÈï‘¶¦fâ(ïÐ( =é®cçœ?GeWè盦ÚnÔx3ݦ†(²RA®‘Z@Œ eñ?O°:Á¦ñÆŽ§&=+lð¯?û:x² qfÁ (½£ïA¨évKÄ©š"d/ xô¬ƒvÇΛ;³Ì:„*,N éÔðš:iÂPLѦKPð& 5AAyh…zRyaÎ ¦î!}+ì<¯¯—,륞¤âaN¨Æó]z;a~mÀ£ÃìÆp#Iô:b«Ÿ¶DÖ§>ÍFAµF¬ÚÇ”ÏÀa"Œ¥H#A¼øôµªwCi‡»9Kõ‹ ºd9kg˜Ÿj[ÝÐ:ñPpdgæhKS2ŸÜø¥TÎ|—Pc:3Ÿø¥+©qÍfÈ[ñ@S€«?ƒCv +Í£ä©à‘Tߺ­®ìè(ÉI —@çjE¡pæùx¢¸¸N.LÍ,’² ÷:à[XIôÙ¦²Äp‘j( £²^$_6}Áˆ8 ø({)ÜËæiq®ž1bðѶœ fÒ˜²9òóðÚ0_•ÂP18̉§ Šå]Ìß«:øê'®ˆs^‡mŸDV^s á2L™Phѵh£FJäø-\dšu_›̉1«û£‚ò,€û½\—3t·¡-gåÝO´7Ÿ÷»Ùˆg•LLî~q\òê´¸KúòuÜ`.uEiPY¥ïÿŒäzÁlŒV|JÞú*3½`‡ B»(I¡^üßý_~W_W±`ŒÀˆÇîhì”Å©>*à ùt`$[i¦ƒõ‰MMA¢Ì^¤ê¬®K†bœDíá§ßü\@´u§Þ|=’ã4޵ܗ8¿Ÿ°j†;±IöÌÔÚš±÷˜è‹ÿÙÎôÅa à·¸ç^jŽÌÙÕÌY¹n<Ðä³ÌîZ~}”°/€§O†7¬F,á`Që @¡ ¾:çìu`åîLJàš¡myƒ<Êhê”U›™Ÿñ Rf¿ÐÍ[‘E*¤g~¡Ñ8h(ãÄGhX=Rëu ‹©‚%™t$ðùõI:‘¾B…_Õr’c›!•á{àÓf¥2Gj‰lrø ŽPïâ]­§èMý@×4ñ£Ÿ¶÷ödŸOïmß%]^_ÿP³‹þX¶Ñ 5Þð<@ÃR};¾€p°&GŒû.à±XÅwMR’j…†¼[®s,Ñ9®ˆ2ˆ.ÈšÇaطÿ×ñJúÆ>° Íl:z¤ûÛ ß^Ìi„ ´ZJ<9ú©gDªçÄìóAc¯×ü-_^ô8#õ¹•Õ6<î>5`ØU4Q(m7 Eaë ! kÊÖ¸´¹Ë–úN@öC©vøoI]{²–Û•À‹À‘r²Ç2¯\œ¿|—g’8oAÆÆt*ø8—¯Dü×'qú 3:ß.·{ŠH!×n‰èÞ $YóSBEAà†_(¤Ø4b¥5ÈÏËîÕ¦ùýkµÙÜ=Ê®×Êa¯î0ò4 71‡éžrr’6ªöayœ³˜ý|ÙsÖzCÜU®!ôãϦ…n¦iš ­‘B—Ö+|žÙÛÎ>AŠš+` ¾¸¤ñDÓIȪ](õ8`é×d‘Ácf˜˜71­Y¨C Ëf´Ä²ü¦ƒy7••~êµG(…e¼Q™b‹„Y®zíµX ¶“”óK6{¢,_]¹’ èÀ·šž‘¸1exµ@O~[ݫݎ¦'À™¦PºœþVü¢Û*^NǸæ¤ñó#7‹ Y‡þAk6¶ Œ±1Ôë #ïvÚm#¼ƒàK¡ZzX:bؼžÅæªÎàayÇR—Õ_ÞÐ1WÿC{LÝ-Nrgä[^ÄD‚ ÁO”åg#äÂsá’ƒv—“Í½ÓÆæ!ðCJQ4oâþ4 )X‚Àº"¹ÙQ:Y,Ãë+¸†¨›tØdûµshÑ.Ò hàƒü~ì«fƒ(2¨:ëÎmp¢ïb~ünQ—ËYxÊΣãñYùàà8òO „øtá}Ÿ(“+×jÖŠ&ðÅ<µqÐfãüÜT„BùWæ“ð”‹W³ëïàCg»¢ô|È>H¾,\¹c{“¹§¶¿J”ûü¶bÊ“4Ÿú™etëJ-äA¡2ø~f.I…Ó-ÅW3ÁÃ×b裵@ }Hh ݶ/}By‘ͨ/x¥ðG(Âÿ—ÍÕ™Úð:fˆÁÎq¥ošö‘àÊ_sêþ%F7Ø“ñ›²Ý³B˜%èS¦î~ð0{j•Gùˆ+e®Zšp[e×ÚÌz¸QÃ)|‘Nù“’& $üñ¶t±èÓdw s3UzÎr7úŒ$è:–ÎÓJ6²BžYKø$‰Oþ‡¬BžRA-éEÑ~Îî\%·5Æ R‡’7—4ÅG þØ[9ö†Dè´w$~òý¾Í€ø=‹Õ…¤U¹Íì™{X0BûÙoÖ»xä‘K|˜aˆó¤e#f¾âµo €Ò–LÚ¤¿RV0L{ɤ蜽8ú³ª]Jïêã8aIÍ:[eõ0¯ø(< q·¦:ăME&ì=o§Ì÷q·M/¸­ –ÈgêW{Ëtù1’ ?“þ¼— –5×5˜ÜJíþt]OºDH XEZ±;F£BžÒ8 ¤ûFò ÔIƒZ·±· `»áN~^Ò-Ðxr|éû¯‚Û8ZzéÀ¾Lg½ú+WŸºéò˜æ?C`¥WSwüª¢Ä$? ymÑ“öó›ãÔ*Õœs·oNÐ0›žº`gª_=  ?´weé>*Ä{Bs_Š5À¿¼ ×S‘aƃ‰–ÅÌÚ]ÍèCÖü\±Þˆlr _¤Ò$Í3 x¯¢€ChR²,Ç ôÎ'˜ë>¹!©×÷ʬ9ÕßÛX yWËSì¤ î¼ dëCE,®ùcŒ¡î)fwnµUØ!i!–kX3àÀL¢ñG_¾Ò_Ó |µ#Ž,,êï rEn91(¶zk<ß¡pÆ„'B:Å\kVga6Ø!ªï•_OCX(¯ŸÜ±,íƒþ C‹.pšå„k÷3}DQ3©È¿€ËkI7<Ö&j(MO/Ч^3«åJNõ<9>S½ñyœ"tv?éµ]$¾Õ—›“OPÂÖ†øaE‰~pbdÛ}È …k‘`Ì •Œì üª´ÖeDx­fÖºBN©b'­,’ÈÛ}‰âsÄ»ª›ÝU§Þ©f+%,n0{¬\[iÂç%8ññ*ù3j/´þ*œ¨)›Ñ®jÀø!_"²ëéϯeEÖ ›v…Ó- {f;åçšy`ÿ.ÀñRÆ#½Ù¹eÇ´£_øÙ°H•J_LoÛZ厣¾ÙåðÁá°þ¥3kgôÛ„ò[˘ó^ó•ø(øòb·¿ XzC`Ö¤‡ŽæJy•‰£:‘<æô¸€Ý9ˆaê}Í&Ä4Fz:$HåËÎzúÏ©ÓXÌþg=ÑûýûÖQ• ÎFµ ¢ßÊ1ËNà‚†9|½À˜ˆq²ŠÚêüLɹxg¾,ƹªt,o"‚MWg«|‰ì ¨w”^rç_à#¼˜h‰Esí¶Ókð.­VO_?»WòQñúO†ø¦&¿¥…b(¡äE@ç^6ß[oÍw÷X Žé€æ4;¿–†-Lþ9uà½×\Ÿ¹BÈÚõeÚ̂ʡ HÐÑ \W}ªž%'m@Ye«IY"Gd•µ‘®Pq©pR¼T Ú"Æ?Æ–­.hgZØŽC¨¸Ö´ïx®øÎæ“,±XæÔÍÝÛÜ¡€¿µÙL„­HÈ΃"®|M" D³a0t:ÌÆ1»÷Gâ³TÖ3ûܘ TòÇÎ2Cj (…ËY‹cÑ‚°R ñÙ?OÔ‰ô;[¸è­ù‚çv•»„|$à ‚Íb… ï¸ãª4—(‰ØÈ…qÝ"§G_¤ )T¡}—“Åðý³ 1ÿièäú뻎­¸ÅfâÃቨhãsú3°ú¹¢N{n=%%ŸÒa±!ŒG¸gEü¨û‡Ù¾a SÁ!È<Ø·EÞ[ÁýI´$-Ò‹|¿ pû›ãGˆw*ͨŒ·8zâòÁ†‘þ´eîŒÎ¨RJ¾;d†*¨Î«i=HnÈбPrþƒ”._%-¾í^Ý<ºBÀþ›¾ÇÿQí0pž|nW·jPlÚHêOiÍ5ŽøCFä,§=åÉ"RŒ¸ }·Ÿ Õ¬å26ÄÕÃøÛÃÚìÓþÕjœŸa˜ÏÐÿH=•zŽ3=añ†Ü˜V?†òÅÔ>0² m !?^Še"~ø¿ð˜­¯×$/Mn5†5µ»W¬Á8­×¾´º—Žu¾ÄV3èX$á䦤L™Qu«Ù‹n ˜J¢Øeqïøå oI?ù¨H¨-†Š j 8¹¸Ö½¬ëÞÈYÍ'Ð*«¥©¢B´€(o7>õÉŒ*üÁÁ"QC ¿Á¢a»”ÅË2G\õNÍn`gÄ|±iˆœŒV¹Mãü™3î~ƒ¡þ%ÂKcœ1ÅeÏ™e¶:]ÃF`CSu®ÌÁ©]Ó!Õ²~[P俨Êi˜è‰÷ʪU2–Bå5Šl›´„KêE:«šÀOŒ O³rpä#>ô Ñ©JXþ8Û‚O¢¬Àï°8~À<Þ°b^3±m–r£»f,¨ÎÞ ¾$Ó×i•4€÷ªüíü`6ÒÅ3¥·D)Ù.2™ª4ƒ´óƒø ÔÌû_Jeú|ÈØ[K«Ÿœ;3È$éˆ3»Ò.­UëØÕŠº†pH ¿äÉq§f«¶—_ÀIÜÝ2×+ÕBм*‡ÖxÜÙ¤L5MØÁ–»ã}U«KAþ ó”"1Y¤Ñy=qJ«8?O^tú¦Ó4øo}ü ãîT‹²|ö ,×'õ ÝR›×Î!˜ä+^»=h;‹/5eP‹NMÇÝÓ {-úû„ÎâjNú€M- =Âú%Df.·ÉoS2% (VbÓö.ÀO¢â~ u}y€v¿_1CVåqXxÚû4¬~¥OX ã1ö¹–K7l¯ŠF¯0Þ5¢{3Y¨Mm: è}´Ú!¢œå˜ÿ* Ÿ±L6³ê𨀠,2äQ•p-"Ú© Q ŽmIäDŒk ì #üëLÔ«U|‡w·Ö~i æ `­ù÷ ··pœ¸é ÂqX›"Rüó–Õ¢îÈ·Ç tq‡ÊãŽüƒØ\ÁT·—p±È^»ŸVIú\eêÐKlPxg®`Ž™N„0´àä2¯p}á¾^ìb5„„9“ q«úä\æ‚×T*òpyÈQumËn>xª‘Žû´‡#RôÙn¾…ºÜ1H3ëèÆÈüè;qN(·ü‰ó´Þ̧ÚWà4—Ýçñ-ƦY8~ºu¡øRR…iì4ÍtÒÖ*Ì3\Ê**hzWS&é5@üq´kÒw[Ž#¾üm£eÎ –|´¸­:Å$Ûˆ{fA; Á#ô?¿0H1\¶´ /<¯Yí§;æ‘%BC/@EÆÈ6Eɔʛ{Ø‘,$H¶ãÅX½Ý:.¢êœº#ðD!´ϯ“í’gîú`¹€åJrÝkßÁ OV¿5oA-™¼ˆàÇî·Lÿš¯s*ÕØG"ÿb¶­˜9ìB‚Ùôôg¿»BŠÆŸ¡³5)ÍÑJ¿¶ÚÖ¢Z€Ë»5yKÌB$ž·¼Xš‚ÂÖ)HC×ÄQÚÏØizž{â:áÝ5z<J-tÒBìs­¤rû–’Bt¢èÞ+Ú¤Ît³Å¯xq:vvF4©€¸¡2¦Àñ7D®nÜÈ}Üp½öId.&8y;®î–µ×∊üð(atªwt—ÉK2DU¯<#é#)Öh̉…SÆ7Ì ½ÉVˆøš:œß¡r娰šC€JJDåœÿ¤—rp²´“3?ɦHZ|3.ÅŠ8L_Krl§Ì"J‚lä¡$¯§`.jEñ Ó”d³e!M@&„“-%½v¸=€á¼åÃ-Û°Å ¥òç„5<"ObÖ²Á¬ò2]–)’»ÃHM:î)j‡È·ÕfÏrŠÏã†Ci“€­Róªz¢Z×õªJº,1z‚ŒÔ銟¤ S g-™ê;9Áû9I!ÅÃȘŒ±ñ“i}È |{48ïËlî6™§«ŽÖ<ýèyÇkÏ7½è‹‚ÃÚkãΥƲ Ý £µ,†ÕàëV)¨Ó‹¿ð2Ço³¶ñȧ±š@ÛÀiò¬»Ô OO9u·ÝD®5}f&âã„Ë Œê¬®Àï©êd|¿I»3³xó=åã°EÞû>ƒ/<ù=üª»¬ðH,È&y„óÕyÄ-ÙC¿AÐÐJßîH:Ä”…ötðé¡çäÉ\ãÖðÂÐë§pÄC‘ÓÊÀˆ/0ÎÕ«Ù~éå\’#Ìy>VŒT\¥ç°œ¢öÞŽFQ#¶ëœBÖ¢6ÞU䲑¸m§tVØæˆÎšgbdüŠ¿ÎÒïò'˜˜³îïÿSZѬ­Í§¼Øß#Ãã8¼³8Ñÿ:øU9àË…jç³2ÂÝócë­Âû$oo™?¡–+ºp®ýþZÛK/Ît8’ZP—ßD'œËµ½ZØøZ8á߯ŸHÔBѸ4‚&°9¿UëmåJJf’’´•7Ÿ¯PvËh@OEV6Üö)Ëú”î0fg”þ…P‰AOHn$ïRæ«p¦Ér‰`ŠÙEÀÖôႲqÝQ“•+ ô(Ûˆ{šÃ‡PBéì ´ŠX'TŽCæT³ËjdPýDŽa[ÞÔ\‰Ò4À'ïRÏ%ÃJ‚³Ýx‹Ÿq PEúÁbüÈÓ^¼4ߢß QÄÅ5d šò[JdÓйpUœø¶÷Éfšß;+â7ij›¹WgãRÈ)zLˆ ‹ø'®‚§‹&aò+™¥öô5ó8×rï‹IM4­Ð”–æíd;܆ݗ^ÔûÖú[á^>Ƹ·í‘wâ×A›ÌP)¸®Ÿuíž?›Íá‘Vøé‹¤Çæíã6uJÔ­ŠÖcÖd+3uaö¡|¸7ãÔ÷ú¬Ó›­æ¢§€>“Ó4/ýìÄ/wè‰v-?§j„¾pþ ÜÊ×2ºé1` ‡HTŽW–DåÓXe÷èwFûw̵:iÔåG€@ó:eŠr㮩rº”¤<ºƒ§uò_¤¤•ë[Ž~Ò¥Å9à ¡þF¢¤^  ‹¸3ƒÖ 'A«”&w ±dý³Â[Íž±ò#Ž÷‹ððñ†°GŒ“6ôøZ¬ûì0/ul=-`n}™dÿe©h$…á°×ÙÂ¥q±,ÙêŸþMDQN ßD{N©Ñ0ʽÝýw²®éœICBïÝ–ãXMùý˜•j:žÒÞxJ€‚MlÓX–þwø ›j‚ˆknñ89$ÃCÃvÙ64C—}dÍÚ¡Á›Ù‘N°>_qÿXɸçøÈ  ¨dî‰zä2VŽþ%+˜ñÉß‘vxVé}‚u¡Ž¯qµ?Æ~±LІ0çˆÜ TŽGá­Mt£§  ¾ºðüØ  é²q Ö€g»üÓœ¼‡zœÝld5sJìL(°p+# ùÚ ššÌ›/ QƒRë è|ýöÓwðˆç€Nwq•ߘýAEÖus] $1úš®=T[±î†³ï¬»”íìQ ×uú†o—]ÀØó3ø) ¢<¹Š$=¥/ìšèÐAå—FÈ-œõwä$ lµ• ­‚1?u 5eOõéZÍ+FѤd×¾t|[ÜÓ*?ºPŠg#À½TVúóê8ÓÈ!&äøG7–p%µ³Q¦(¸±5ISmäæŸZ!3؆ïé/˜¸òð¢fºw¥8¡ô{r;ÂJ@é<>„éÇ¥u|V‘½îJŠ´Cxú_Ýjo@ÇBÿËì%¹8>ÅOÎ¢í¦–?ÊË9Q·pWj¤§ŽÝ aZq÷ƒy¸‘Žç£•åœÂs£É¢ñ‘ô6¥’Tßàõñü ̱Ÿ Øetªïp,ŠM›ÔwTëw×~ùÞÞœ‘×$å±ìÙêÐ>¢Lì NÊäÓϯgGׇRÝФ$VaÓeà†Cã¿)_µÄ#Ï®â-ýB3Dýj§gÿ¡TH¬€ˆøoÂEä8úr³ÍtJë*ÂÇ‘[ÞŠ³]Q¤õØ~éa¢YàIx‰-6ÇOÁÄ63Ju&bŽðóø5³ü^  ˜‡™ÈF0Õz)ø4œMû·gßê`tiÇá1hi‘ ÐbáN­ülJUÈ6q€‘42H™¡½wÃÀ~ÐquÒR“çù²Ùéw/ÄÌ¿ct >¥Jìë×cÚ›u1[Ï÷A¤oƒËÃÀK)Àjþ2#¡&³Öµpß‚¬˜t´ž"faµ/"`_[z#›DFÅD†6ƒ²äÒŠ$ËQ;³ÀºÚÂÕè—ÿdyë=Hj­Bë’}"Ý™[}ía;à 8eùä~ÈÎ?q;•)î½%-÷/ŽÔÌAR•HôÿG^oõ»¨ØñËÓúOá9šðŽ|N”–sº•¦a#‘8ÉßâŒÒ6ª•À·in?t#Uâ>4ÀØŠõ/( /KÆæŠ—‡S[¥¹y‚yu(üDñP «ŒãÚ‚Þb_sá…5Qì™X~P}FsM½Ò¤”DWº¶ô;‚“£‰÷ûf8ÂÇ™ÿ¶ÀQtVþ†(¸¼câ t¼Ãc­`)RGK¬lDl¡Ò®©› Ö3AŒî=Ýq7õÜucs"Ưå5oKžoR 92-é8ý‚˜XçiF¶Î“P:È Â‰€¯,‰NÜ ÇÑ–yúÅèç ulë3PJeó4ñ,‘£[(Æ{ OlÖ‰µBlÜ;n"~w\å÷”ka²h—¾S?°Û!bƒÚ¾Ž×1»Ì×Lh:oêTùýP%¥ æ—÷iÊ™`RÖ~Þ¿„¤4y?éÁȤ[îÓ½W:ú^‚Ñ ×4!ÊCãÿ);–ÄÇ$zñòŠÔgÔ~v%S?@5Ôv¬H›§µÜ¡ alƒ*>ÉÉ—9Å›‘ð8b°©-†¥‰˜y šê´tk”cµª;gòß‘KIïQ\pu¬y Ð ñ<’²Oüò¬N|E“À EÈ…Λ¿•ûŒ ñˆy㇧¥ÿlê§€°)Å]AÑGåJõŒ{Šo`ÕòË^éVB_Ÿ;!?ØRq"ú'×CHãÀ:çgÌS¯ Îv0TŒˆ%a9uÇ-4±°qΤ .Öx‚u_½5êV“4\Ãqgä¥)Aˆ¸ùŸ¼Ð'\Y/»ÿÌiîNTJ¢`ÈY<¦¼}…‰Qšß”Êâ!áÛá¬ê£Uçý;ÞîÂþ¦òƒsfgØ»L©÷©1â@>ÞiëÚòóÙ¾VþvÖ¢Œw±OÃÍÜïR)…MOîF• æ+Z£G¦/C¾oó}i˜'1 ¥ØK-»Ïå·ƒIö9¼%†$çq’'^m^0fÂÌMpý^ohäOœ%s˜—ÎXôT% û©Ž*‚æ¶.aÄÏý±Õ²åkùUB¹âÌ÷ß¼®él>Ák}"Ù{>“¶J¹ÊGg{Ïz!Exª³¤Ø[+JÙÌ0À–lŸÈ¼2‰]'n#(¬R &Ó;ýu|h÷áù’ïð%c!Ï#8Þºø¡aýX™/ª\ù…ˆLdúDnÿŒzñ3ƒ JßÂ6jÈß(œ,ø†‚ð"üþƒh:ú5ËMa!‚5¯ž(-„Mzª™èú2 åܬàâ^™f‘Ù,7įfaA'f@}”†]”q4ÔcK_ËæuN#Àà†Êy'ïÊò>Lw¤Í( ]m½r©FçuÆ9)¼ñ_¼›Ê)èû×-4y·õîEpa‹§»%ΈyÁxÌFa <¯¶Ç£kiôpÃÕ•° êhð‹ƒ,ïÈÐÙ\¤/ÑZïS_UJ[9¶DÊ1 ŒÔ7@kÅx5k]ôÄ3ž5´†º² CðL©´„1õªe2›^è󞀴^ØÐyFöÕljŸ £ Ϋ}"bRöã€ÜGksÿ#M?‘lK#ÍFÓA=^±RqÜR§F$ú‚Ô[êUœ°˜EK¹`BñèßI&(+ðPJkæ23•e Ü-Øš°‘4óÙóSëƒá§ëÆÄyr o¨¹ŽžO‹ô”ΤØ-éý`Œ•ŽÂªg—{îÎäËœ‚Û·(U1J½OT—1Uˆ>À7ÏÄÜìz:…öy0$™¯ä~|{ò”ãÎá=¡ÀÅEØA/÷YdC"‰®jŒ¨ÚÈÔcLŠÉÄ=ìAßIž¶ÿ½ÏcŒöâöÀ›EkAlÏFšØÊ‘踢»7aABÄ`ίÑGˆöÀ/œî|I“ñ,ˆTnÞX¬y1Å`]búéxž« .äÙ) G˜¤Æ^eÍ"Mìšì`#†}}ùKI.‡æ|„hXƒ ´ÝÊ ?ëSjô.’y}Zÿ«õW˜ol¿Fµò†.=¶h¼ü+À ø[^ÁÀnvéÕR{ë p”éQþtó"°­óŒjZwÔÿªˆ[¡Â*æÙ0[Ódó¸©<šguõ3œeppu â°Ée¦p>#d+-kMùC<äˆO'K»èR²AÏõ]Ôçb7ÛBê4“ØUèºwù…P6æ¢L‚y;ò@™ê°±ßÓáÈîà‰Qb@XX,¯4ô‘prºkE–¹TÔàoŸ¥.’òнK§€wÄè¹mZÊr™r9ÄœzO4Ë^C,ààr†_’(…0)T+©‰©K/uŠŒ—2qÿŒFªU‰®ÁšžÆ¯·,éK¥f±Qû÷9²Û y,Ýýtm¢.œ/_—$eÔÂ9êQEГ³ïr¸š¬8mÕÍòkRÝCjøª°}«ä ¢žÁ)öƒ­ä5ÊÀß=ÿˆÇµŽUÞFÜ‘¥j›Þ BîR²Y]:=ºlOc…sJÇBdQUcêPqÃî¶çlü)#pÿD‰—õ™O·8 L—±îó~£àøÓJ-Ô¨”úx¥BH+>KТvµ8¨^m7RJ‰Æ÷tt ÖÚwµ}~ÄŠV ‹&xâü¾?oƒ•‡½I¹…g[Ù'Y·r¯!E5%&å–}*¨Jì Qª ÐÚoî· >=“ÀR‚Ÿ6úøv™àœ¦Áq`%§å‡BŨñ"*ûsˆþ'ÁBv•͉Ör‡Ž:;†ú½ßcZ¬¬{6·7ܽ›UðH_C/bR9µM zñ$Ý ÷éÍt¹å§b-ÁE%ÁZbPÁ­ºmI;$”äsr¨pÜdx?[ýc½^y0@æ£3Ü2hjKâb§èq´¢È&Z÷hRŒ+ŠÉA-Òƒ‚ÌòiÞGXK$æÜ‘B¦Ù?‹ñÓ“¿t$V«£…|ŽÌ·iG™•o¡•N·Ï‰€z!nÖ#¡¹°¼ÇÖ Ù‰Ž”õµà²sw–õ5É2yóËÍriŠ^Œ•Þéa¦Û 䀴®¹p­&¼X‘Öç’ˤL¤j":ç€%º}³¶zÓé²°¹}Óå1Þ«ZÙ»™PãÞè ÖÁ;“6¹ôX7⨌Ñf¿ºéñÒy›ÎÉ‘´3lXX´­ßàÜÎ˼¤éƒ»1;¾wA¹W®‘̤’›Bg~& üWVó8ä­â°÷Ï@MÍQª“ðöCf#Ý{± ÖÃ\â5Ñu§—}\³Á£67e@/{G‚Ãù|àÜt’+-ó–›2x:Зûɯn7Ed•é(…–½d["ðž—Œo?°Ü-ræÓ»— %˜[°ãOœÌôkêÈ?ZNSªÂ&fç;îí!eÙ%—TÑ·ò'’W,r5ÓKOO¯™õQ§±¯y(vFi†Ðg43Sßr[ˆ—=»¨I‡ˆ" VňUÕµÿ»ž×¼þÑY^ð»5L _Q1ý+*þNöÕÜ«À“%-·iG¸…BÛÊ&6~ŸçA0C ªý8~È¿&C"%pÞWBûÜ]’€„˜;ªã Ún H –H`² ë!ˆ3Šno•2ê:2¤ÆêV0ö¾ÿ Jª3 •Í7$¿Ü_£HɈAµ#bé}/FâêœÞŠMrÕ[ˆ õ[<°)„ºZX„:8‰RÞ1ÄAW…©ÚVÅ[SçWcfß‘D•ÿIzú€ñ~ÝU›FU½lJ£`6Õz±4¯ª…Óé‹=šE£Ÿ2ä,J±Ü/7jâþ5DìœÏÄ€„_6xŽ‚vl>ù§ÉyÊ[ƒ¨@¨‚ó-»m¼ØtÌû±wqëòJvrÄûÇÒWök›k…wó¸¯¾è´ qšL0@,_ÿGdÈ¿ð–T³ rtÛMÃÍãg(÷XsÚXÕÍ1ÎÊ wŒì+ÍD~:?myÒyE5H ä×…mMô慨7ã,åi¶sÊ'! \¬=ä8õ'òRßoMpÄ{÷PµL ó>+Dõ/`ŒÌL«È´7-c.²Ë# Ípô`7›‡þ¥£@*• 5‹Ù®Å”#¡¯]zd·XÇ'׸WWëÍÕz³Àú œ׈Íb#ø=ƒEÞŠ|‚Ó(óÄëhœ?Üp´˜7£±ˆô6Äp¬È #Qܦjâòå¬ä=+sf¬Ù@ Þ%²žW õÎãŽwÕIDü9Hå‡ïÐýRpÀK(5ê[B°p¦x©ŽËàÿðèúY¼(!4œñLò†ŸÕ(„²ŒÈáóáÃûy†ÎZs~ MâaN¼¯[ÖÛ·o~³†<»Ü2]¦o|GíT¿¡0¶N χ¸,ýHòß³m]Œ«3!2+|ÚËI´A±Š“ìhür 2s>'³YCs€]3<°B ¦ØÊp°qу±e¤ ᬬ¢WvïaäL"&5-ùI–š&yl×Û£ô¢+è•bÏI5 ƒÑ&ë/K}6­¸Û˜<«ûùuìeY[JS­”þ ê>Cc|µÀ=•1J ]øÎŽÅE ¯†éíÛs6þìF f’ïJ‘vö N‚VÉ4¡À'›jÝûNÿã&þ’U±¼4ÜåO…zåUÉšå&=§p)VêvN@ݸÿvgh·ŸLŸüK–ÿ ÁϤZ=ÚÐî¾èž>õ> é\j\[j{òûâúÏ«£n>Žäa~¬M;Žm5vV’®Y.òqö;C°q»RÞg~5í´@Æä"æ’üÀðåÈMtM;ÉÞ$†–³Ñ÷Æ[8£nͱHÅ«üZÖ©àþ{Ú£]67Óᾨ7˜Æ€2ƒA2¬ÆÒ¿©ˆã¸›$¢àvöä:§¤þSðdXv;#|nÀä¬["~táÎ ò‘öÖËž E-dÏ–C—›ÜFixèìL? 嵨E´;"ïN› BAÿâäÓCÍU¥ÆÙé8áþÆ|;R©®Î_›«IÝ7ÿµÚ¡q@"ÔsfÊØwñ;æ:™‘÷¤Ê Nö=ÌÖ°XÓ³sæhe–œ/¹ü{º½ì3)t ~0„U[½˜‚-Ò„#\ øm I\0Gs"iƒd%üŒ>>Õß^Õa®@ÙLû^³ÍäVËíï{ñ£oîù=Ž£ ·¶M9i·ÐOg-0®æÆPoLdæ‚&®” [cÕ½}äwá î¼üÝ^\à,6Þ§bÄ3/–Ê“‘/b÷Ií@ÕÍ–åÆ#•Ó¿€[j¼8âª[Sþþ›²8Í¢„Ê\¨t§§ƒ·0ŠØ²X•üK:Ýñ´‚nZ?fŽi7_rß ½ÄrªŠ ø«ZžbÆußùÿ^àr°ªÈ.IηǫnúQwƒ7JÓí¥C™¿¤ÎZ€QÌ5…ÐÙ£Ñmp¦>s»¶WC ª«ôµÕED’…J<!Ír9Jð+c¤Ü<ñîý?aůw MÊÊ0IË/‡Ìý;M\zz_ÑäoßìÕå¡4¢ßoüøÍ“¸[Ñç[7«‚°Q¸¸yEl¡pñ¶V7N÷Áò Œò"â¼Ì¡VA¶;.ð9J©Öp ©S^²_‡Ÿ!A˜B,‰<âI(,s T¨&MõMôÝ¢Iùeé€Q•” àR%i`vDAªe4Wä11Ëw®WÎÎóÝxçbY}QïG ¼˜ëmŒK‹ãJ’ÏÃàƒøe(6Pq€Ñ ‚uf ¾Þ'6VéÑÃÇýEïÛ³‹ïkµÖ°ÝS&( ~ýd €…CnTFüÈ€”üÑ¿à-ÄR\Íðó£qqU‘œ>ãýà©Ýоf S_\ù1)3æ8®6ÞÒ³ ÞR%»¡?w((ÀYÅs€ 4øܺ²õ(oæxÀÝ8õÒE(L3:1·6"±Éø-÷ˆÅv Ú~âæWºÑ§¬UÈŒ2œ8K LP¹ôO eóÈ #vvr®Qª¥:"7^zËÒA(2et (Bصp©¼ƒÓ25ô̰úÛ{ã¥ñpIäm ªl)y;Ñ•ÏËoAÿØ.}iCÌ¢ÅÔwŒ1–ÉÅ»õµ9f"ÂÚÆÞÈ7+ãèÇOa_T¾eðôÄ÷Y] -¥ iƒ[…>·€Öb0Èššž3ƒ'j?áþøR½e¾°$…j­&ÿÒx=($É–Z@˜ÿ.íT…IGX£mÌ“]›%Ô°h0 QÆsÀ,цf×xÉjÛkÊÁ‹[0 ˜-£#ÿê‚Aó|[ìÐ?übÎd`eûpï5¾ Ã…‹;ÿ–¾xÍÀ·ðòäh\^dLå•$ÚêÔ÷ÕzM(·;SbÛØ®¶ÚüïÐ qÔÅ€}†[0"šr%þ^a÷X¯•̨Ÿ³ÞØØ=;Ç‚¥§Ur»Qø Nv£R‰6ØÃ.¨v…Š…š\yu[wÉ;Ý„]`ó …T…0Q®Q%„YúW.1(šNGZû‰q¢B£<Ê‘Ö?²°cÜ魯»²qdpÙ€cR}øG´ ¸iÓ 3JÇÓJXÉE-¯‚˜^2=ÏøEü?²¤C>´{™5¨Ñ6ÆXÅ•jY7”_m°”ïÍQÀþbÿl“m>Í4iŠJ=J…RrùÔŽê&Yê˜Ö&·7ÄEMLñž1ã„Þ6•¸€2&o&åLœOU²ZNÖBtæëFò%±Î¯£U±à׿ÜD³ÖŸ#dx¾e²50Ï€æ¨âGe¥6áf]ƒ´´É-BñÃlc¾à&¿EÁ°áü‡L«*løÀН»‘?‹%5e6‘4t ü›k|$†Ï·àVeÚ'¦ àÏã@ +€¯í¸± Ô04lA±³ÞæWž÷„|&0eÀ°ÊÚèN5[ê¹yßVsZ‰3xωÊfŠ‘ì¶ª*:gè¢`o›œO´òÅM®EþÔqN°0Ñ6ÿYx Eƒ¸Ò+ÿÖ–ŸÄÕÁ–s£øÈ¿GE©Ôܹbtd•;¤¿™ý/J9>DÒï{‹¢©9p¬—å U7úe]/ ö 4¼IËEHÖáÈó–¼o÷-ÿšVT‚åú2]pÿ Øï°—µôV7•}t XžJ::LêA‚J– ¸s¯YVÿ,¦M¥ÞìÙ“TÔØ".‡éš¬€/±BFŠ#I*ÝpSv™â_ן¢ƒÙõ¾}ýè¤ìx!q¸=0™6íž„ù ‚¯!¼—Ô:Òz9bnÃr”äVÂdMÛðäQàQu‹ˆ“P‡6Oªµš·x£ƨð5£-cP€ar×µ€üð³°ÿ™ópè&8¡‚|žÅ”LüÃDÊ›eã:Ÿ²À´Íìhö9€àĬú›jm{.Õ“¶:Ò5vq:‰±öW÷Oú…|cÀ²Š~g£gM‰«ó jâÊ<.Ï9ð·i}Ù–‹2 £ö?sPÇzPÌÆ,%v$ÑQÜk?e¯QÈ¢¦º>ïF£•7‡tÓOæº2¡?SfLÒŸ´Ñ‚ô$%a’÷ÚööÆB g©sæÖ;+ßw`]/©^¥™U:ϯ=>Ä æ¸WCãéð?Ð@Ù<Ÿ ÑÞ#d¾‡£A´ÿz%©À§©ãcÊùû£x·ûP–ãzT¢‰.–»ywO§®ô×bBÈg!ÐP›¶ øçR½Ò$‚0ÖQË%»–®@Z°¼âª»Y2Ë•‘ºbµ1à×òš‚¿”±úŸNw¥§½{ƒdhRôµ<¹ªdÕ¸êÿ3*€Cv—±²~3Î2C‰Ö‹ÂY§¼Mœgcg£ž½íà›¶c#„Õæ¡å+¡H° 68¥îõ»ˆ¹HÉj{\ÓËQ…ïÒ€«g349¾¢PMœ[æ <‰^:Œ†k2]ëëýŸÞX˜•Ê‚#$E„mRZÒ»È?)ðÆÚ”Æcöm;°&B¼¤0ª9«Ž`¬&œxªÕv+¤9}¸Åá“«×çÜ]¡™Ó!ë ýH•—A vÌÔN-Oæ¼ ¥¦ (ü…ìÕ%ŽÕoQÖhûx2L¸؃wÉ—ŸÍÓÆ³,sÉÒ YƒPœÎ§mÕ0ˆ ksÍ¿ÐR§¥]¨¥4JÈ(ÍKÏw›™ùAÆ&¶Žw5fõº!(ÏÀ7 )²ÿ/‡³ñ%Þ¥á Ƀø_:‹u+ú³ˆæ§OÅ™µò­æc/Q…iå³à”]ï9`þѤhßHD5v ¼¡ŠlR;xõW)D Ï0u¶ >zq³ì]ÿÉ&í7ƒQ§Hôæ­Â³\Ýè‘„çeµ¡¦YœD ç4кy½‚4m|½2¾Ò!ÿò €˜áX K'…#=Fp.¾À(‡W;ó1în°‘bÜ ¨6®³S^–Ü6EÅ·ûÕÀÙ=~m?QC4’<²?”X„î|R,bÊ"€|ßð±/g Ó²ªÁ8/¾nœö=[éc?‰stlŸAÐÅg0 -2 iE„à‹Vœ1×1†¬Û(ÿ öýø4ZA‹ä`AŸµ,„»Žæd‡&mZF0©·½ß~Ÿb”é£]ä8£%:{±Ü£N £&eé#’ }6”7¬ëÏw#“u“ÔÚXÑid~šQÕ ÊìÝUŸØDËpI™ly•Ó*´ZB ÁÞ¿ºnJ ÅNæŸÄpýªÅ_[Z“¹”hMÐ)p2HîìPåLz-Ýðl4î“jê%Ä0oO ë >¸C‘|ÆtüÍHR¾àÞB »k¨<ä­[ ;Ũ!«Ëpã¿ cqšº( ÕØle5Jõð°Ë}µ‰ô3l˜â]6)Ø([òeÞY`jã9‚ŒËež=Ít4µ°ÉŽ{[`°­y`ª·æMw2Ü^$Vñœ"íýŠ€a1°E‚çЬQ0Õ,ùl„í ˆà~]£:Y}MºõJ3zW8 .÷2‹cñ±iã}ÔseÃŒä!†lÓ‰ûä™Þ7ì® m&žÆýúen;2ÚXdí¤£Ê¾Î"á?ù»ºkR,¹57Ö 7¯€¢Ÿp/I0§j6Û»~šYÅir+íµ6îã{ë0?íF_öD[©Ö ƒ!ÈÿŠî›E­‘ñy³/¯Çá~Lò#â9 5yÅçfm• Ë’Üò5ÀxÍq¤}'}´­hzDé¯×™t7Ã3ÙÛÃ1ŸVu|9ᆥYG&:Ls\ì ÅÕáAm¯^ÃX¡ª' bãÕµ&\¨ÕÐ:Jʸ0þO,7Õy^Æ™Ùw¥•OÁðÅKÔ¤c*5ËH$aþŠœ}nÜh;åyŠèæš6±qær8Ct¢½k¸Ú‹á3XÖèÔˆK=aPv€Ì¬æÔͮޙ +õEúâdodqÍ¥®%{'+¯¬²\½¸ˆáÓVÆEçÿûÃp£yEÅk¡Áé€pBÊl <º“ràg½­·»› Ò¿Cîˆßw±y%w+OîÛáŒwQ9ŒAL¦ý”IÅD¿>]½è´t™Ûü„J¢YIþ<¶áTªÒ—7„¤Ý>Ut¤—PG±vˆßBã~zE Þœçÿ"ÌZÝåš¶+PûæBإŲ# á,ŸÈm€iß—d€Xß“R¸‹ûJd)Gœ\„¬ cv£êuG±èã(¶W6´´”:̦ ŽTdØ‚¤Ð£˜)ä&pôŽã„ÐÅÍŽ4PU¡¦ôf…=b…–ÃxÆ{\ÈN àn¾×Ï{— h³à]`‹Œ*­ÅwÐÞ°UÌÕü‡ˆa§Sé¿€µ­äKdE;ºCf»éî„ ¡ HBe˜Í싊µ© ;äVI{jiyÙ„LñÄÝbkå£d>'lj[-3ÅÑ…´Jì\‚§•M(F®¢€·j».~åIš¶P¡Z†H Ê°¼· ¦kPnHž5GÛg%ïVF‚¥ ±¹R–óoe|éû×IKÎ1$Â-ŒÆ«>Ìp€¹\ R=JŠVƒ¤–sH#s‰•™ó2—Þ?Lc ßMMj‹ÛÅœÄQ-¯—m#šG‡FëöóüõëpÙŒßC÷Eµ¿RÜr*ã¢ÌåwÒMj”Ñ(ûÁãýÏAçBJ]’z´3 l6Ÿsj-®w#lDnäï$ˆŸ†˜õÚÅÌ?9¸ÐçÙƒEDYDVL¤î öužGeß.÷èï›b·‰m·CÌÀmȲ³;ÐÐìöbá9u=a;Ûv`§KŸbb6ò$ „ªž.Sôµ8Ÿ8õ'€†jÉ‚óLÅebêÄC¹&‘˜ÆÑ(:ò§Eû§SyiŒfyÒè_„ƒ²ÇŒŠù§¡™Ÿ°ó¹‰RH„ºÛ!Ū§w·©ü¨õ>ZÉã¦ÌÕ›Od¡üLì¹×ìÕÇ×`)>-'3›1Á^} ì±÷á‚iÖ>[Œ?O7Óûø©ÆUl”¨F'‘pŽC›­KGÍ]dŠ!ˆ¬RÀÁÑEÿêX¿\Kh‹Ì0[eÏXt.žcuNBè³™†3çY]i"U2«Yvõõ[‹ÕDE¯å‹D†é=Äæ?è˜#ápÁQr™j7õ—µ¯í^~[Ï7óµ¹[«ëƒ°^”K=7……“4ƒ§â6´'å;Šb:Òm½™\xëzŒa «3ÚO\Xp¡ŽåN_Se§k½ ˜[/³3ðPéÛ°‹ú”“1@’Q­aç–de±àqÀl’È~Ãbóêa竬Ø/Ÿù´…q©Ãc¼±½uRŽk'Á0„.Éþ¯þ|Æù²Qà…2`¼œ? +%®Éб•;“”@‘Xå ‘¿ßI8õ GGôŽ¼Â Î¡øFºÊk°æž‡<¯ÉŸ86™(yß2™¤d½d8Z>5«]Ð’ìresÝ}•ÚîN #ûDW®™û«zÚKìŒ-GƒÆ öÕâæ%8ÿªðE °êpš’pÍ8ÂL®×+Ë%ñ‰¿(&<ÏþŽ»1ÁHðÇøíöÏ?Ö½9uw·‚ÌZ[I¾—Ф* Võˆ{kõ²<„VC3_cåÞ ï¬U/œþU™¨R„MíI Œê¡ˆ¹Ìùi+˜âÅ;0’Áw#uŰ{ú=ìæo§8ÔÆ6Ž|IZÎ>Y¼¿7™]Þ%έ\q¹6Ùάȅ®çŸÎ–Ù>!ÞR¶2dTœ¬©Ÿ.̪yæêv·“?¸‰™wþìRÆyâ ­™ü03½´ƒúÐÊä¥å-‚µÕ›BØ…LÓ·"ReWQ»ƒZ"¼³JÀs£ë‹Êu…ø¥•ð¬¨;+Ù ÜÌø^:ŸÊ’ úíªP zW2s?Š/pçß‘V ™¨ì÷Kõ¿+Oâý@%5ŠÈ.-3ƒø¶Ý¹3uXÎ*v:{n!›¹Å£àª£†ôb)Z¥I!eÊ~+µK{è–kRܼ’àØ×ô,ª'BåHT‚Ï€Ï4 •»ÙR“Ê"L™jÈ»ƒ¿?:€_ ÓdÑMñáò4eSSq“¼Lsð6hH²•sµ—™ƒÙ°U¦k7:~¥ƒOIò…þÆ)ý_Jê'õ&®–¤Æ ”f¦øÞÑY¤p#Tÿ}çö§dT?áöì:¬¦L—¶%\AàtÀ½;÷H~ŒšÖämñËån©SU.ºfÜè¢(õ/!ìÏé(/õÿšÈ ޏÀÁf@ô±?-pp³!xF¨Ñø9; u$ÌüsE„Í^Ä,ùÛÌ/ŽÊõ×G¯­å[e-Rü{ø(Ïlܲït‰|*fU‹_zÐ{K_D¿Yb ÚóDÖ[IŒqN5hO\?¸sW|Û¾QÌÙL Àýíÿ’Øê: O¡yýnìÝÈ7Won¤šu˜~ŽÇ »¥À<[8·2êj›àÁ]¹ã–Øy'ï°Þ(˜dXj‘ì·êÓǧiæË° )˜Ö~æFâÄt=Ï…âÕrµ?ñ˜ ¡Z/ž#.â€KBòoYâ`©t¨âç†êFº=s5Ÿþ~)Lîà Š‰÷¾_ëÿÀI§ZÆ Éd(*”;m W®´C½¾Ÿ´ÞjŠÖZ€˜eB•OTHâ@ªrBÄ»‡Êòq¯îsrˆ .üº.õŠ–›ÕõáÂQIƒ‹¿G-o±ŽƒuºS>LKª»¹'3>(àFCÊ…Þ•ª¦ßMIš.d/¼¤ç¹Ç¸h¤\!uµÖ(iß9÷ì#Uwc\qD'kŽ žµû‡=ü IÆóüÈä‹-,7* ý´ ›_?ntFQY”žUY`^þ2.h¬’ œ»ÁÞ”Á U¡cÈäÇôýÚ‘“ÀóÕlDÑöåk½½šµI8‰Ð#ÏÆ°‚˜ø¦‰ÔàÙàÿ“3qS¸:ÇM¾o|û,’ö+é5ŒX¼û¬ªž ‚ç0YjÔw–#yf²ÏŸó+à.¾`å³)g¼e±c¬-±¾¥ëÓÍϹ‡âŒE*èÍs[·hšK¾µAm¿úLøÙÀûñÜû Šû™o_•8ž—¯‚nn׌ñɦ ãXpÐ6ûÕ‘Tý+Ê8«ÙÍÇ -RVäÛ¦Ù=e`™õ&Ž'qNuJsÙõ Yþsº‰’öþ²„U*·¢^xS9R2ì}jP<£B§!zl:Xü^»ŠEy155©¼A¤®°þ$Zý¤±y¾ 7μ”pä˜ÂQ‚¤Ž´rŒêU=¡aîè4ßeo¹(´ÖÈW‰YHê§.­u3+ Ņ̃ãœÚ/¤C‚ƒ2¶R»€ ð\'-1ª2#Ij5:·ÁÞÆrG<TÎÖî…"ð…Pà†ËéWW½w<¦ý:ˆ ±îóÄk=MIOJ1ü·Ùq^§² Iî}ˆ6í†p@HWtu;zîaÆèeâ£0™iy§Jåjà'¾™&”óbùêÃͧ¨˜(g¤äæ´Rþfµx>XùøsìDD'kT;ç;;¢pÕdduµ†jNâüCÊAa¯a?*‡r ßzûhLŠ”9'_r½õÐ19²(,­ç‘û±–>X²q¯{Å•ÜÑ$u‰b ‚,—ˆ~ŸW.©ÍÛßÌÑ("à 1o–LÖÒúpg[yÚÄ éﭽȊÎ+ b¿þsuîÌ•0f"¥;Ê icÜOŸ²£ “i×À¢¥SQK:µéòñŸ5e 㦖»‰!ã©©âsÄ“ú·Jø½¨wÂá¹!Ðë,&«˜@i"Ñâ9k|5ž¾(’IíÄ»ìu÷¯4,èÙŠx>Lnÿ+‘Ù€¼ô;Åi¨êëíŠzÑW.çñ‹¶4K¼ôcéu+¦€Ò`C©_áŸ+þ rq&Η×þCð¢ç~Á+A¾"/ꕉ|GŠ dl7`^eŽ^oƒw¢Ì¬p»Ý‘r ^C"¢Õ6à3cM”lYý°í¾t±žØ[ÖuZ@é}ønü3¤a#|&²ýÏiF’“Çž×â ¬<•>Ÿ*ð¦Hº‘U˜ÓØÈï¡$¯ú?ÅÞH(eB›ª›çŒãíÚÛËU ϳ 8kCk'}é¡\Ý ôñŸ2’¸AK¼;oAçÜÄK0/*3uÌsÖÞrâ€IÑ;~CPƒí’ÌÃDEÀËGøY2t½7 p±ü`ݬª™©¨&XŠHRë7z/‘C9Ί™Aú.´Í-eR&Oa ý…¼MWÚÜ{^0<7½LÏ´óÖÝ)3·ò›Ü”l˜4~>ððýȰRDlBð5)ÅàÐ,?_Eߥö0wÆÜôüÐ"YƒÔÅ“ð-—MjŽÔ8ëjT5ügt× ®qfþ X°Ü!wµ5£°N‚Æ•nô€ä 2étÇê¹"€wcéÌXvàLZoß ŽåeW‹6ºß| šNŸa©zìÇÝ(YÅQéééÛi\EGåu¹: ¤‹MMâì¶°Úþd„¦â¿ˆI¢œú4™Q^GùB¢U1ó õr9å!zÉo›^Ò’õÙå’7„QâÊ]è{G–hÑ ¬‹ëèy£1€&ƒ[NJꪮûÓ”üWµfïjK÷$ÌñºLŸ&˜´Wo u2\í¥Èh!/.yÛ§rôø3Z¹ÖtÞÔ­¬E…¾ÃUñ(qm÷bPn‡æ0œAª^çÎ*³)lO¦:”Yæ©d‡“%ØrÿýÉš¡OÊ$€²Qˆ*7†Îí°*œr+èvÓòýrÙ€"`—äjïFÌ Œ3¢•ð Ðê¤^öV˜~…ëRjÙ0Ã3MDÅàRlaGyµ‰¾ó@%”`Þm¥Vy0»ŠÌí8%¥žlêZc´Vª1à;„ûo8{Á¥„+cßÅﲄå5ø§«óò±(,{ô3èO´ÎñC7¿OC¾ KT.ÂÙ`µ«ôÆÀ¶3]äûàƒ #÷{.ÇJ¬`Êཪ"e`È0î9LÄè‚Þ–ÐÖäå\¯"·òÇEëàmäß2^œø6 ‰éê3wŸÖ?ž4¢¾,êQ0¶®p3ÔA¢eàX 6ën¸ü­.?ýx—‡üøax´•ÝšM•P‚Ù–µâ˜Ð•b¤‘޶pÀz‘‹gÞXSv¾'0`EÔïVž3D]™G~94·(ir,‹òcHyœB¬2VóœÛrÄyh¸(\ÄV8÷íÿˆ¹Â'úþÞ¹6x,ÅoW~!„e²ñw÷`£…@ãkû#`Ò|bo@3Ñ×ç þf~ ¶åì NUVúø5Eú›cQ–L̵w0rÊì°]=dX¹ÔÕi¬ƒø‘(2íÔ=è–Ñ©Íj§¦Âó²!ÕØS•œ »,WíbPÏ’ÌhÐÓa¤a6XÁ¥ÝâÊ‘+²^É‘­ßÔ ,ìùƃÀåà›ú|á¿PF¡#µ@¥-Ãíü3ZÜžj8—7Y•¢–½×) OHr™ýw,NIg,Ö´rÎ1ÞÞ#ŠSg"°¹»bàHŽjåÔ­ÓÿŠëýòßé H"úÇÅd­xƒÝO€«U¸A˨èI·è¾3‚ë4œ8…ô÷éõˆ‡ÈÏ‘t kÝÚ-ŠòïaÜn-ã³hÚ¾ƒ~Úº ¯‡À¸]{ãx5Q~3{a»!±S–†@`+íék¹^lóË]K¢*zRçMSœ‹ÙwFGI¸ay½¹LƒPâT÷s؆ ð„Ž´ e؈¨º¬HJí)R•5ukã:C\úW´žF¨d4”‰x3½¸56 ñ zžïܦœ“ õ[Z" UÈ—øð¡ìä°¼=gÿ϶ ¢$aùá0@tÔeî9œÜ¬óÙ”òNŠ^[«¡å]- Ý«X ü+œ½Ò´-×x:–Ä+ĽFå )njh× q1”Ù¶ÆKL²‰&OIµ¹÷AJºæUxŽG@ë”ë¾»Z8Ä=R|c­•P.:Ge“ ªØ—´ô•(Cžñ¾§Í—è;¸EqrMT#ßNĉ÷’±—,ù™Äîð£œIðlP¥23³d…=fíWØÉF}õØ¡2æI,½p¾‰ƒèÅôråúTL;Ÿ”š× Õ¸½I“Niû-"þpìgÁõZîý£t@¿c/‡Ìˆ®ŒŸöu:ïZÔ–l¥H @ŠëQ \çñ ¯ð#N*¼†Áî‘€5‘R”Ø,>ªì­ŸVÍužíçCí{û}‰¹½M©VÔ[8(£ƒýDݲ¯rêùðF,ΟªÏ¯m­ìëyµ˜ßèT궪§E}Ž´üf~Ÿq5ÌC¾xáDD¡Tw¥£¶î±Xˆv9IÐËMcî¶vÇÒ¯(ì[\z;Ìݱ“‹ö® è±hrIuÕÚÄõèäà2¿.ø­ç0ª]osžìôqñú©C±SË ÔnÖ\~z‹l¯†uq®ÕÊœ°wBR°][lùŠÝû«Î5¨h±ÄýqÇúì½8¸nê=”^qêpþc‡[ù£òG g¬lêm•LkD”÷„jyM¾C•Ð-–†«-n¥BîCî/[bVè÷³ïÜíÎ`A«ô8µ›²)/'9Ó£Ç{Ãd cö¬üT|»hë~%0g=–)bØóˆv~ ý¨¸F¤v^‹Ÿ üPóYí“9‰¾”¢ñKñj~Šõ´E“‚å…5ß¼biÇ"/LÅB¦pÀwÙN¾>êüéG-'$A‹]Z¥Oé2í@ , âÁ"¬›É*ëZ©…_Í,'ÚNãÐßP쇯ÉüµÏɘŸÜmåáœm¦Á ˜ëM{îÖ׃ÆèïG.°Œ-îók*ušËï<•˜ÄêíÚÖÔ2Ù)€¾fnÌF ©*Ÿžœð“_o;¸ÛºˆN±ÑÚÓ&k³ªMá¬ÆŠ€*y§*+à e=À4ãÀ¿=â£! ÚHyãEÑï°Óv¨CÉâ‘û-R›'(î=uêEïUOh+w¡icZHi×ÉÖ:Z}¿ÀÎýñXö‡Ò±‹G"~ßôï0:G2by·çýy jØð©÷ ½?>~ÓÞùÔÓã8›­ÜÏO;4ÝâœõŽÄr­újÞÞYí oÁ˜šç'¶£#>ä^ÃJ¸(é7WÈdþ£æ¥Õùkõ@¦$Á“LÆû¥'Ñ$ØÓÕ&K“Ñ[#{Ü­ýnCI¬{¸w²¾öV` ö4¶¤GÕ7Ãn•—&?¡õz[˜ª¡‚–Js¥–Àᵕ¼¶_PàŽ ý¡R¿ä-}¤ s쪶zº"¸úŒ øküáVûÉ—¨èMÿ–z–:»V:‹Yü¾­ö å’nt¶‹ÙU°Þ˜ÿìÚO& Ù}Wø™\C3}›w®ôV!rìxl6_šH´D} ÓoÉöTÌpõ½–cmZÖ%¨ T”ùôh+$ëodÛ}gâr™‰œxuÃÇi†^8”9å;”W лe)®i‡Ë¿H8ùÊu¹ãŽ ¶ÞRw½n#†§š%œýœcüjIÜøÛ4vÕRÒ’;Z³k~Ç œÇ£¡©¹»¤ÿÝ2œ:´wdÍaB„··¨d.'B'ïðpX%þǦòÕˆ /±æG<° IiÃ@x =zý|4kAÈ&–|ð°E,rv¥ÍE‰ÀxÇM'ø™÷M9‡#Z9Wm‘é„Á}ƒ˜•àŸ·€mÌ"Û$»¬àk„$øjG‚0àÚ†Q·À/9‚±¦3¾:R@¦K”ÝÝÎɶ'od eQ€uû!{I†ûQI—¼¨™C¦òÎ ¹äÛT]ösñ ®m$Ž•O„…¥kÿM™‘Ñ“X}ú"&<áó}´ O†óÁ¾Ý} ©Öƒ7Ô³®az~[¡}¯XxS‘V™]ˆwðíTè†[Ϭ¢Aq‘;T—¤ç+ò¯‡¯¨9R˜U*«[£;ìÔ÷Ú¢zTÂ7‚«{]N·¥,¾[ÞDª«öjîbà^¥z'TÕg‘µw¥¸ý(0Å_†%a„É þæ »œ‡ºnp(á¾ölëðÈUÚ¨œ¸øÑ¯d¢™1~°òN°‚Ëtº÷;íæ7ÿbÝèl–¼Öºr !¨q\0WC@~ 榙ü"e…Þä“–SxÉn‹Šr_±ÏÒdS ŒÿòAtmYÿš¬øù^¸r”9+©Ñ_1%³• Îz^Ú¶x—*fSºÄeÛ/¼›oç¿"ªVz›Æ6~û\qæéÊBj™ÁŒ®¶ó½hý4»Ê6nébà]pq°ÉÙ rÃl÷Ó1>úa Tt\XLXB>®ƒnƒH¾­®ÔX«F8fºÔ¹„…+)®2ÅÉ‘i@—¿DžÛ±ÈðF\Gçæ(,¬r(ˆlýAœ’SÈÿýi ÂÄ0ýn‡õÜ,¹…Ò%8ã¯L ¦˜I6Ùïï†M§ð@æ€~,P i5a,·±q±9+ë ˆ‰+(µüO{¼V”mÚ nå‚WÚåýVcè°h¡åJ²y> X¡ÛÆÏg|,&uÙ`¨ÿ²`g“(Ì7~ZßüEç-]kIyýZS(éÜPP’píÔGêÛ—"z·évI4Nó`b(ΰóŠ#­-Mð[b§±°-…6£'︛0]Yð±î¸‡H2ßs* áë@DmÈ‹CúïœÜÔ.eÂPò¿’à+ÌqØì1¯á8¢ÙCCm6ù(ÃXƒËü|œí`I½ùƒ `< æ·ÃñÉï‘ó‘„fEô”€¼"çici/<’ô† åËô(&ÅòM¥Ùã„Ë"š•ì9lˆÞ¶hûL—Ñ :üL×~Ø~Ñf xÒC’äTÁûTh°§Y½UðÝj“ÊWgÛ`‡z‡fj[ÔeµéÖ6ë¤Ä@&ô‘Od"v¼Šš(¤£Z]E;Ô-Æã³p+Y™ý3H™WåXÐh'DI‚ÃÐ2QºÐüœ-Ñl—]Êú»ª«œîN7ŠaKTÚÕdÆ5ô ¹ÎųžNÐO[òÒFô+ì¢/жÓQøâ^ýâ[£•¨ï-çI|LæÞ]!ŽX5Ùiø—›‘˜ß¶gpíì:.do)2í´pàíº;FÀͶzjÒþÁè‹YÌÉI÷*BÃ|%'¡È$×ZÆ ‘"¨+ÆàÑŸÝ8@%WÂhXU >`åªr wL^i÷|xKÀØÎÞB2LÔ>Í”õaíÐb&¸Xxrll'äÔ[ÃÜ“ <7Ü­V›“©ïêìÅÅò­` ÕIÙUL¤.;¨ °ƒA²¤ÕwdòŽ`˜K¹–õk’ƒ¾•žJ аޭWy6á2H.ü* ùfä¯ãátŠXé–ë*):¸»WxÜ8¹ûæzÃmÄä*tü´ ŽÁ›Ì—sæƒGÂ~®<ÃUvéIL3Æ‹½ÁlŸËwsTç­é D–¹ïQ´-.Å ”¿†çZæ=uýå Ø3­yŸóH$÷%°£Ë„UîG²g-^Á 0æÔÙ—ÉI·{ ¬½ˆÏ¡[zg€²Çÿr8cU¹93Õ^]®J?ËOs(©Tè·¡œž¥Â ™¦½'xå–=ž[Ç­ AÆ2¨Nû¨áÊíÅQu.°p¥1iõÆ6ô†|›4ßyäÈÏ·É%®-dZ›0  ã­vÓ ÛY@ÎÉ×7¶ ôöàœÃ ñÚôi¨§àgc¤ ³„ûMØ›ùÁšó–oPÙw ªçÜÝäz¤Žêm¹ÓJþ|þ@Z”´GFFä㢠̪¦bòÓ¤Htâ{Aá>®¶œÍ™ ø|–ÔPoêêùa²ÅÇÍRIWU†£^AeÐ÷÷ñàá· `…ö¨ÒàÔìÓ5+’=, ÁÔ´«SToØ•çI®¯òWí÷È;‰´Ò6Ö“#º:¥ñu–Ó&éðXû;U¿.4.æ™’mÙ¥—À}<šî÷¬»mrZ†×õ¯füýc•$Úº{Q]Ô4‰^ŸåqÖu£Ë8¾”}âÇT7€;¤ #éJy+Up£¡ç&nŒèSyý”?ä°K«! ¨ÔF¦Â™`‘A÷Ž^àÕ€$;PFn!I 4HÉ|†÷Ái.V@­·ÜÊ\6Ò]_U±nÎ’­M8©™¾^ ƒtÀ“‹ºò¾òVJ‰5šú1¿…ªAЫϑ [Gq Ð&LäñæáÇçF ÞÌ’NÇzñçD9Ú _xdÕ~ï”ê@ 4íuÛ<‹ø(mTI§òõ"þx‚‰¸ ¥úÐò*QÆÔJ߿ػ¦W‹ƒ¡»Ì©èƒ|ª”ä @‰ü ©€–N'è7âBÑÿ;•e‡ £Si1¾Ózi޹XÐDMÌ玖öáM¶Í Ê Ð?˜{±ÉOKh’ dnðvO8j“ŽÓx^°h)šhºüËà®Z"ù¦“ïÙ3Ô•ÊnÝјå+c¤wÈB³HK,k×ɱx¤³œDš„áùÓ•ûE§Þ$ß±ÛN–¬ˆAÉGûÆó$Ë [OlèÝRU\¾¸&‡¥ïÿ†µ…EñèŒAZCno§éŒhïóẃ)Ýö!`®|<Ö¶–µ®,c2ìä½T—ëÎi¹¼=ò"LÚßZÃX<‹À}ìœ ®Åéûu'o|‘νGT¤â¨=Ïä"P´åÂÃ)­ }„kÅóL3]nq†Ï2ˆ´øöÌt&7)“€;3½ôü¼æX9³\‚`Ø̈õö¾()!¥­’ ìCŠÔ´e߼įß]‡”ÉEršGO·Ôê{ŠÑ` „*_…'ôùêó¯vœÒHŠ2D‹þ¡ÆäzÛ®‰ü“;án÷Å >PÔˆ¸XÙHïO0?ý²‚ÌÃH;4§ó)hå"b¦×(‰äÙn›–´ä¿Ýæà«òœÎÙ‰H»BÇ=lø†;.†&Ý„»Ó‹:È×'G£‡œø‚ PµÛ1ÿ:zªï2K&dš·±/pr(ònMöp-×¢’]’©ÝOs_ÍÝS7pq«` }¯¾É!ÿ ä½! {4]U.”]€ÀçÇ/ÒBÓ¸x}ÁOzÿl¯ëDá[Øèš%â–z|†?,»Œ‡o… Ôb¸ï¡ñ1I– È„ó{KÙœêµwæ:²Å†ëáº-JÎÃø…±/Mø²¿<"O?¹~êegcÍ«ffjž)µ0¯§ççN‚éOaW4"^oËœ_Ó¤uóa:Ìž›Xu[æyK°þ¼P„B¶ÃÈd#ÐçûJ1AŸ'`ò@`.Ä.¨SSWïÊ‘®xŸ®GU¡*¦Q<} çý>½†îÕ÷èC  ´/Koˆ»´8™A2”%»{9@RûŸñMÃ8€ØÃ§æðYñˆ»IÁ ®*ÏõuzQ^×§¼ù(X‹û(i#cD[CPOo™ƒÛ¸÷ÉÊlÔ¾¬å‚•ŸÞ1±kÛmtÅt/c–§ÿì[ $¤¹c5r€CÖFâiÊRB(=ó³?mY;™¥ûøí:E´Ü «®îzd…ŽNzZíð˜±W©ßޝ¢™çwJØC|ä.yÏDDaH¡Â4÷žû¸/O‹ åÍ™3ÃBð&ÿš©„Èò ©š ô‡ñšÒðW¾ƒ{mÓ µœuòΣˆgÐ…x&!C¸5½4E;ˆÅM·i$Ëó7̆ìcøëa"»Æ$dnΔ#^ YÙ“c bI(r™ë¼`0k †é/á@ )Þ çúasX[Ï}B‰ßmP»dÌi ×¼>¥R›f“÷LwæÎÛH"š­n\á²$ÅSJ°€iâÂ…ÎBè×Ãì­#“Qï5ãòM™Yôu¶(¶¨»ÐËE%šyj·¶îzýWÄU”r‚s‚§;¶Å¥U…|ßžðøÓ?[7«éÊf47kãH yH´fÝ®ëKoöûR ‘ˆVEo[ìMN¡ h–)£®g O#Þé_ç¢80 ·Ÿ¢CL·5»®ÊƒÛå°užV{s‹q;øÇ,l”‘Nï=Õ<¬}kš«aPjC!¢|_ˆé·Dx*æZkêð:’‘GH¼ð_ßêÚ+Tß·‚œÕÁ`¸Kè©ëåü^;¨™ È%úÀ5‡”b»FÑ”SDZ‡•Nès~k½²äR>p.¿ Ü i^‹ÍÓ~Εî׈·Û°¡uOòy°Q 0ïçík²ª(Ë3é„Gpb5ŽXÄÄg6cÊK¼›,ybIè²|ž[Î3c²TƒE†Ó@ËgRqì´{Ö8 {Öà×c Ú_G‚6.(ÇÛKf37Gù$Ðßð޹+€`çäÌq6e’wì Å<×ÂÃÙðVIïæ{©‡t¡×÷ ;íG²(§?¹üàÔPc›Ë®eGäZL„âJ™¤òÏÿBÅãb‘s PC¼® kéÀ ¡y;Cþoroð— ¿[ÿbö]o WÆ©(Õº Ûçô½*#žs«ÌzY‰FÜ @7®çŒ6]_¶Š{ÖÆMf­$hÛœ\u«>pHÔÑÿCC‰T`Eþ½ âC°®È¼I2©t1°\™Z~5VÈ´Pš€mý’à‰#Aû;æ^Lû`X”—¾® )š–˜ërF”Š;÷ü"Ãùìm4â=y>ƒù«=Þ­†Böòn˜=ͺ‡?XH¤Ýºï&:¤´F„€|ˆÒ µ•b@îd2sÄ#4e %#j—45‚ÔºZZøb?ȉÀ§—ñ³«{[èômPYœH‰‚à«“»žÇ!üî†õ¹kŒGH äÝ`èùÒ æƒåµ["âBˆÚbwåß°Ù‘«‡*yqÉ?1çÐË\“ÂÜ‘d†žX’[×Y+3õéKšbóôfÊ®}»äf;[9@X Å?«eŸl) Fâr&"š?3z’núÇ××i­CQ¹URŸ4`Á‹?ß/Ñ‘3ÅŸt„¸ÁEV±Ú0òì¼x(ü7¶=-.ÚP…“ÓJ:QJ¹3°¥dX6 FǽÒµô‹çsÂãÀ^ÐEõ}ªPœà.¾‡ÙäoRq¬™2£I“â!UçUuQÅ]T·™î%L-H#ž:“/B¼õˆ_/Xª9}ñ¹ÉZx9;}³Ny£^Þâ8!”ˤèÊöŒen½Ã`/:‹|ÿZ¶ã–XyðšÈ¶Aº–” · Ê6øº;¢MVßE öÚ™Q#š¡‰Ÿ5º~Þê‹—v#öŽšV^âx˘:¨óî),¡Døyæ¸EI+›ÛnÔ*ý–I™Ð&9Àr}_\Ó5Ȭ@Ä :Ø9 =ùÛ§ý T”ݤ?òý.Þ| x΋?,—”%áÉM™¼VŽÇ•¶pj/ÊÎIͺmáÿÝè Õ,à¼N4Rqñû»ÇùÊ44Ûç4œ…›ÕÓ§IA#E1˜ó¬lO£Žfô¦B&&¥4®¿g„ØÂ!b‚/gri¼´ãï¿l³<•ïzñnAÚ'eœ=Å¿a#E;Lûfz£í\ô¬¢N™Øñ?‹Á'* å#fþ‚ëO‡‰Ol8 Œ³½¼¯¡c²]6HkKó`Æ5/ÊNc…ùlXìû5#ún¨ž)Q (¤g]#ʹǀ¯fð¤«"LЀ”O®ìæÙZ·ÇŸùØÈõn<ˆ³Oi0Hš¿¼‰¾ñö$e /¯/ ±ìþ—bÎæâÖj¥CÀ”"ú»f´¶®Â@Ü&“VkªGuߢ}0çÿ!-ŠâlCþ~ÄfIÔ ¢†K4·æ0´SþÇ Klhë˜kÁÔS—õÁ÷`lO?mSPáÁ3Zè_ã«*M%ƒTrÔ'+ÑÐÈúìšQïlœ™Œá þ9ç^›Ðè3F®/ªiˆí8&/ZTè¦U0)Œf8sYi+ͰWº¤“ôõ éUKõRáÙ®>5Z¤!n„¸4[ØE ç}¢"yÆðÂüµÃü7ø¸ „Û^ö* ´ê˜e+Ç(ù &§oQ·óR5ãNÕfÛA¯/" 8!\0ð®×&eÉa1ú˜ ùù5†»¡àWª™Üm `TîÚ]nZ>(' TAŸÜϦ¨ß/LõuÿúœŽªtc”õFˆç;PgP_è’™;lüÇ›¦ïÒYßä0¥ªzÀ½<ÈêÜJ¼#!å0¹üBl¸(tØíiq…Ë¢™^íÍ—º™/HÝq"~C`Càüü9Jëuƒ˜m ‘îû(»|äÃT^ü_Uê:Uj<€§ŠÛ@ &ê³ÝvWb™Óôy¡õ(p:\:N¬|ÎY윶šlÇóTÅl,=Æ—'þ Øí5©#_Éw#46–hÛw?É(ãj]¬¦at™ví_^¸)œã6¥ÃT{ vá×¶lµk,—¼ÈRœiŠ7¶T"4$ž$·74±9Vþ·/’ôÀ¦ÁD¿2½ÓlQBP‚O— ìŸÕ–]m°r 7“.T]HH7äCBíû¥×F°Îh60ÿ!i{;»lÚ¥> BMùªc|U÷0c,u½¢HÇ|K`Žt$uJ|áR¥O†^ZîÏ,º ÇœïûÐUœMÁ=Q“ko‹£ö×­˜òŒÉùµ£Ås® ŠïœZiûÎdÇnå®¶1…œ_–òiâEݯãÆ&Xm¡Q~¨Ù’Åqî&:FVŒgq‡DZc¼:ö£úéD/ö5z¶ÓŸµ€–j‘pÖ”ôò>ÆœT&«º>\E6d× ðζ‹Ýíÿ›˜s߆Ýäà–÷›>,…€·‚â…èñXH>Ýwºž»®œâÔiµ”'â$qgš×3ú×¼ ”[­Ð ô9mêÖ†‡pÒ£+¯z†z%l•ŠùDèøØìÞ¾¢çÉÌ:ð@±S÷;3£Nñé6î@ªëÀÓ[L/’ôóuç‡×?ÇCïžMkʘüâæCÈ4\­q¼uHEõ›H/ëib¾¸tám ±¿p{cpH}ÒPéÂH…c€™°1Ÿb|ÐñPn$æ×e½mæp—æ·‚m3Ú®;èµàNih'øWDZÞõjpT*4Á««0#HYyø¾x!ˆ³“äb’AiÔäQö.>:ОŽn…^þ䟊í-¹‘šŒäÈEÚ69 }< e]#_\á´>åh÷wEV޳¦™¾‡Á–è{iS œátø{ÛjH,zeï—W«‡;î¿í^i„µ’®r{Ìm#?“›@ÊÙ<4ÒæÜêÉüûfk»3šD=¶f¡ »ÒüÜ?ûjV•™Ø‰ƒ ØRÜ×+=Ú±±iÅ™†%LýSóNæ© FÁ¸‘-î“z\ð¦Z¯‡˜Æ±ƒÙKOËÃP•·1*ƒ£r Pç9 Ÿ8Èø²j;[X` Êsd©pÝÓò_[OÑ."¢J‹{Fh·©+8Õ&¯Z`ªŽ¢éØËÌI°1,ŒÒÖ‹ê¹nUϱë]xÌò»u`€¯¨ºûˆ¥¼§aV;PDg7Ïo#šW☴´v’*£Ó ú"~`nÍd²#Ïew@’*Ð×ÓÏÝi;É×ÇùµÂ<™Yqì†K×nò—^Âû ¦ï*ÞX$™Wƒâ¿_[ÇX^ $ U+‘ž/B–.—É÷ o<ƒcñÝ‚µÅB4Õy>y´Þú_ÑÑ(Ù­H’^©ø®g{úûU®b÷kqv‹X…pÝ ªŒeš`ËÈ„*ˆxÆÄé¶–]ð‚Z7 "qyky9G(ú²€ðcïù³øæ)”«k@y&À’`‘;Ü]’T5x˜âÐS_–žex™N°ÖD7L]QOJòLÌmÛ¤BKÀ¦Œr#Ždsäʤœ¸å ýÒFcÃÕÉWð¼àa3í}1†MöM5Tt¨ó.˜î'ÈKçéÕ£ê©wJÿwÎbzË”ª´î?"h/ ™?’‡4>)wõðXøjì;ò‚„Ç™x¿®§J§>,ÒÁK:Ù¤®²å4mb™PœÉ×°©{vX%™ëí— ®´èÙ íV¬'è é$ sŸ³;>ŽX–Ëϱy%Ö±L’kÇ Ö¬U©WSÑmÏñT—n©ͦ<ìT ümý›‡²Îÿ¥®O H(°Å´íÚ4’ãµ!íàÉ>U˄ƥåͽtÅ)J'}Ž Øið½¾I3ˆ‘w¼!}¨‘)ád[áa6¸ØùÕ ONkF̰a[u< +1r'• CºãÞ—âôI žIˆòÌ¡ Q^¬¹ÊÑŒ]½Sÿá†roë­Va7‹3Sü@¡yhóXrR8NlÖi'zøt÷+a_ºp=n¶@-ÈçÃgËÑZTKÍÉ’~Ü÷,»}ãBw†UvIyÁ:!PkA^Sq‹LÏÐÞJa$¾«£>¢ô»at¤Ã©a扯çbŒ2ÿI—¤":@6þP­GUßä)+Vp%¿³.aØ{ ,‡?r¼%"Ë´Ts~VëW’‚ÿZ¨w-^4QN‘H´°\Ôë‡;à¤A'f(0?úæŒì\vªLt„gEµ8V“¢5®ÙOI%·Pg_^Oõa¯G/œNŸ–‘\ú´”ÒÌmhIC¹›`}¥õ )/Õqááš„|¡ˤ Z3…ÿ‹q4wˆqûl[òÝfPFÝxSDÎÏÑ`òö{£g‰Ï™á8=XQ @oj¨Zƒ™’å)Šiȵ~Οêç›’ó½¤[¤¨¸T²ú’ªøhX(µXD΋:º£¹ÅeKzÅ`äíÆVã™ô!¸z/2:Ž­%ßß0ª]2ëT¹¨cCð)«½¸&pÓ›C*•&Ðo´]ú~Ïvõ«j‡ ³S ¾&û“ƒºL¬L˜,·ØÔ y÷ï û9a0Á>)ÞG‡Êaƒ.í\÷ ]b@C^ mÎߤsf"izÍñ5´× MÁt).xÚ¹BöÜÍ`³DÑý š–óoG¶ªp¼ÏeïÚË߯ªú8gì=jÎã³lÍP˜íqD6Ķ-imNªùeDy½íŠoô9Hk.J‰Â‚ÆÏ7YåÒ•W GïgrØ: ÆŽÇ yYAÜùÁÿ ×Ñh ~¼º‰4FËÓcó)¶-êÀÖ<ÛQ–^q±¿Ý\%3ô¡$pÉ­¸Ž}¡®ú¡þiò~°Ç¥«‘¦%'13Ãüct-ÐYK\B)À6§d»àº4 ¡| ~g=Åó´9Ë1_u ÜHþÝ\Q·[Ù‚Êä0TcQ ÃVácǸž7½ÿÃà zκ´–E¸ÎÚ•™mÇç©}Ю’°})8@eíVQª„­O1üÓ÷®xÓ-o9#’1FÓá}†t†$a Ëüð3Sª¬|:ë¯nÉJÚn‰n¥k†½ê|>hlίï¡*0ŒDü˜¨nl¡Ÿ“¸ŠL˜FrýCñ—ÅÛð‹ó6„C«èõñ|ùñÏ~94N:ž\o_ÙÎhš½ØÇÏL$ݽ®“&š/TÏtý??èohã1âmøL±Òq°î^ù;,0éÆÞfˆß\uÅ;Öv‚~ÄÊ™†¯Ò)€2|9ã¼¶â9 2çô ›ä‘þ¥Ú _–¼)ß­¥ð„–ÃÇH.T?(ºÊýSj‘L{Vím¦Úú Ù'¶g"UilKø‡‹U¨Á•²µÅkîlb47I›)¼PZJ8‚çxÜúiªœ³â¦ Öeøk?&HÐlZþƯ«D&ˆ/Î#^}:¦xæ÷ˆþª”Ô5j^·D#\RÆ—% 5îûÜET1cmnž‹M«Di¼ª_pR¼¶•‡Øª`t_KLïðFTúêZß]ʱ¿áz¼TÛüèC®ñʱMB¾ó‚š.J¡ hg¤¬`E8ùé3¼ž[SEï+ òi¿qÊ9„5Ù´éŒû—¶EúûDOU=Ã¥UH¹¡ìÝg¯”?€vß¾’΄zn¡ð™~ÌzÜt-‡ÜŠË!Å#qGZþCÌhÀ#ä‡èod¿ßÀL"¥¬Ý‡ p·óÿëk"‰†àùrèI¯ˆ¼‚2 ü–ñ þ1ó¡8ƒ‰ŸÏÃOҮÀฆ ªÏH/ã Ö…éÔ,'Pz­ Ý™ ¹ïÌ1Pñ½ùÄãþ¯)z¡#AÕ㱓´ BÈNä¥êèÚ‚aôÏiï%4nM>›ž‹5’˜%; б=ò:ÌgGU6¤oiñv GFø¸0‡ nëî’v{ñÙôðe)ØY«eŠ€a87B„'zÃÑ !¤hèÁ5ÏR?cÛç¹&X£sN„Aª¦>ÏñØ9oÆ)½'jVRj8ÒSrX:Pƒ ­àòÉEû˜ØèØ s^=o&+©$ ýeI®Á‡4g>‹M¼øêÿí—³KEOåòN¼•À9ú¨Òð¬Â#_£ f:×M€hVuÈè¦åùôoHr\¾pXþ’Z½?þæøÍc’E˜„Õ±¿6"™D;@ŒEÉ{Ð|Y©þÀY×CÜÿP ËÝÔÉVïÖÚÎÖaÇÒõŽ0ïƒ$|rí(Èé ~#(>ÄŸ_oßÑCBÀX¢D6üïNɵcë¥è…q¾F1;DhuˆâÏÜ%%€òw¹Î´‘Ÿ*ð³Œ%ß3ôË2È\nzaŒÈï ¹RиÏÒ“%Ul8_GS¯>†>uÓ.Ü®ä*Á[œw=$ÅíLªîÁO\Hõiò9' c»‚5¢¸Á"Ò¬é‡u§P¼‘âh)ÓPŠ>K×¥¸ÞœÙ_M2'%ü'Tc“´¸ª«qÑ{Wb«×tFªŠ»ï•4 Êè,°`X3¨ž:W-+C0ð/$ìðç„¡©Ç‘~zÖy»OÂj#êUýQÁ=­ÀèV(¬>óŒÜ·qµæ¬P-TÎX_³5è`Ò·\¡!B>ámÊY U¹IÈú3ui #ƒ< øYcv`~·LŽR{І‘ŽÏìËf~EN¿üûy·ôäHµ.j¥y75þ"qò)’`ø Ä<Ð.öÈ ¥&ýÓ ™«Ix’¿ º ‘¡Ÿ©µK¡œ>øÞÇ›i}òg£Ãlâ^Ó¨WÜõ!ÀY“ôIs45¯ÏG‘+à†ÇqIUrä¤ÞŠûµu•èæ¶;>+ƒR,}Ìs¢ÝH[Óv*6ÝßÕ ŒnfÕ=Ö}™äÅÙÀ]²GÑZÊÓð£ZÓ!5=¿x¬B¡ %è¦ÿ)ÖIc‹±Ù®Jö,i—NmÞ£zr•ñ¤L6¯HøCÁ-‰Ílm5"¹º÷K$¥ûêö ó›Öê r1DœŸ4ðæîtKpn!—½(¯å÷ÈþŽJõ^7µ1Ôz‡F/Mï ÚÌydǬ™í÷Q›!F{»—­€, n‡šÙOC|?€lKt!umð¯£@•9Z«yM+C¿µ‡ï=îÆÁ͘}­;µÌ¤’e]-uÓ˜hôàût¾£âÑÿ‡’Ö¨…1€ñò½ÌUºO¨N¦&,€+–o´açÊ8O#¸‹²ù•ÑùÎk˜N) È›ö3I¥ö®Úf"á$CØ…]bRID´¹ÖnPû“†ªÌ ÁÄšj@Ù¡ªbsä­wvói=—jJ‹gú“ŽDXšòûѼÈÑ›Øññ8©@ü„¤KÅõ +—€L`1I難úÙ}‹e¢idwýbºò2À$|jþSQfr4ì¾qÖ]wÀ3Ëæ÷HK¨"@3ùô> ,ó‚Ì l$ö²A²8l†›¸pßpuJâÀÍžI¹ð6i®/ò3 ?…à!H.´‚‡iÿ©½÷šçAøxsÙ<1ebœÔa“³]— `…¸ÚÛCëÐj*Ž=‰¼lß”]¨&;”E¦ÕídQjÖˇ5_ìañèdåμûŽW¦ ¾ ï-L±Ë8fÚó.)UPÆYÌS=Ê…Å2³¨“ÙAP‹üzÝP ¸ú†øûT!›*‘T¼áø0·Ç8½ÁÈA~6IÉí¡J ¦¤FB\Å]  èõ¯Ôþýœ:QŸkŽ=7Ú@y\J¢o1nM=Åe,Â}Sª#U› sMiï©ySƒyé•ëÑ@¨]Ëô 螨GùÅ  nÙœ…t6•Pö£åÃ=ªÆ¢ yÙ|·;”vÍú–öÂdÊs c)CÊ·Œÿ¬ Žò¢ò/ÖQ¼]Ñ«ð)æ@Y:si èx‘/ïÚf…xG¼qkàìŠçJ¾»w Y*á±ÆR6r¤»xãQOïð~ ª3ÓU¬3Ý5šJŸ¶<"!ÚÍ=¿6ÁuÄש&'ÔÛ•»ùþAQ¦ú¼)L_ô`ÔDux»Lµ©û'J@;®.ß-鑿8nè–ö&GnÔÞü8(Ÿ™.I‹ 1 Œ)µI²7Õ¹tôFA«O€4€¹ë6æ7¦àPÙv3GÒkâÞHUõEÞè´;HÏDÓä@õDLç}dT÷eò›©Ñ¢ÏñdžuL9Ä=ª ˜¬8#ü€áV<³ÉÍéÔé nwW së¹sZ¹éBû'®nƒ o:¶\ `¬B<ÊäyA â†é»”x61ëIðºÃÀ…Ó5òöi‹^N{Ãqnðº&ïÍ ê8•QÈWO… ¦Bc¬|qEƒ·=ü/zˆŒéYȃ=Ë2à|ÉÉp™À&ÀiŠVB'ÚKuì{ Û%@áZu·ò N,À­µÓ`­xQºÝ’xç!0\G5êÃêꆯo5È‘ìô°ëx pLñx9Ú1¼˜®°¶xÈj4±ëœäƒªÕ– «B`\Ö­tuL¸'=µ²¯e+ÁÝ÷ï_á|l°Õ²?íÒk¡å¤ª0ÚÉ§ÃØdÌ9TW–‚÷*ÄYGWµø’“.#½4Gtï,ñU¡H¬ÓßW+ØÈs Ò#KWjHjÀÆCܲX2í¸¶¹àÀ²®À‘¦+]æ¿qÌ1ˆ’&¶™yò ·0Ûî5½¨É à?€§•H.F»°£Ñ¦pT®2F©‡©ú_nçߢíóŠÃFQ_ÃpNº8ñöL¿H)Še¥‘A̳]27¥¥ƒgë»É%ÁõL[w¿ÚDeœˆFü–wz´€±}mA \ë5-Fm¼ÆUà,ä–” 0yka¦ÛØ©&/åR³€Pã]Àj…U˜Å$odbo¦ˆ¡Ÿk…Ž}¨ãQ½˜b`^À ï éÿæ°ï²«]©÷.ËLfÎU™þ¯½qB{À*‘OhRÚ­ã_Ù°òß7LñRBðŒv{¨XgRˆÀ–Àóë¤tœ2Šƒ”p¥¶ìTN5C Ä6®ìnñÊ £êTß=*¨íék' ƒ½³âŠ® _ºŽ<óŽ‹<ßMº!ªöŸ6Ö%¸¦¹¼ ”u©Ã¿ZwÛ§û-æ×ÌŒ¨©Â"'KöSìѹÜ->ô8À†ð#¦xÜaÐþþšÛ(ÿø\Á{¦>¼þm—ÑÈ^¶ Ë•š{\€ÝpÈ=两vÍs#ªJâɹèÎp9z%Ê2B),a ~J¨*Ï@E•7}ëyܺ?Å6›2KáSÅq·ßQî¹C“ø™Ófz*z»nkrä?JÜRá D¸É\„ÁW{qDmú6ÀûXœ€N»›â¿l¬ià#BD»ãÇug—|'ÛášUd.û} `ø²…â¤]9ç ×é‰ãáG¦)[š`û^£¼Þ{Éæ‹P>òçBEs{v±É›™œÑÿ±¼ äÞÓ½ôM†cÚúug¬ ²0;©a§1g÷[Â$é²íÔ¾dǾqú9³„âòT\•A=ä›Yäñf9³²£ ð¿7+%·IGä9—\á P÷o‘j˜œ­ƒm&ä’£J¡ã–‚+Þ|q£Ô½x3 °©)ð¨;iiŽÉ{|-N°ìô0¥Fåj…Y1‰ŃxÄ}²÷În8ð9tô—ç]{ÄoÓ¡òf®kd—üýÁ^6›X›Î“bYÞ-õö9J^LÛ,ËÛ|MéªÞ=åÖ–”¾'n\4 ÍëÈí#[X†Ó@KùePÎ7žwç5;xÃký¸W üj›ïh+y„…,?ÍÑfµ•ãÉh!5ÙzÝW5¢˜R÷P¤¿AÚCsÀ×ëÞÚb?¶u´9PØÃRäº*ŸÕËV}m¸?M ÙÔ=p›y«Ô‚}¬Ïv ˆ§Ý¿óªÕ ¨æ5 i›L…qÂîj‘óE­Ã;èËD–,ø¯m¶òbÈ-ÖxYo~pÀÏ.*/hhœ%õz„(˜xº÷3âŠbGv& Ëþ¼Tú }w×F+¨“Ë'ñ·kUYÄËj©u{Íê{‘óüÞ©+Õ&{Ãl5FY¤¢Wà¶•èÊÿódü´jøÝ&èä.Íþîx"AòNÛ-ì U6™u^Õ¢s‹½£ºúþn |¡gwºìúNŒ¸òñõäµ™'Ùh¿Ò;ÿ-ÖG²ÎñÅ'@ðà“Ò–~ Š…g±ÉM§’u¡‰rÃÉG€F-AQÏ(„(-€Ñ?Kz‹]G:”…><˜=vòÏ iÇr, c0·ºÐUåGv¥Pk¶÷:KÌwMg25”Òàh˜‰WÕ±OHÛ"vŸ @®çÞ–©3C¼‰–ów΢¬p-ùZ®H'æ2^å*Ó#ýþH?Ñ· 8¡`ʺ)lÇ‘îñ6϶`ö-¹YC”k Üõze©q¡klº_Ȇ̘µØ(ÿ<&Ä4Á7²‰âùãÍ‚Xï(û1Bu1†ß 3VÁŠ ù÷4 pÚõždÛ’ð.T|üðsOÙv‡§, »é< Cž¾Êgp_á?9ÖWß°ÚÔË™cdÆ ï,.Ãã†C!p³Œ]âcdx*Ù[+®ƒ‰KåÉ9 º¦‹jÚ‘fÐ W_M(ÓO„)É­ ïü<Ðv ˜í$>[7 –ˆK:Ü×ÚèoL¹jRÍâz0­ÌîÏâÒÒ@šÔ´ÎùVp©},HƒÕ zM_‹]äÊ9h¢i(¯G}‘8öÅ»|Øúï|×ÿØ‘ÖV1€:g¿Ëj¦>q&8rZÍ„~lR)ŠN…) Xü~àÊì; ôÊìŠJh†ÊÓB¶JiXú6õ­û 6µjç|(ÈÕíÏ²Š ¶5DOO\nÞ¦'O+º>+É  ,/båO%Õâ¬áÞ㟿ÒojŠ2‚ Gš[W9['g‘· k”z“·–Î ¨(o~Î"'/?‰»H€ü>dšºå¸'ÿ+*´µiTšf~‹6…" ƒãCœ¤¬ª{mÿÁþj¾ÝzIµÍgÌö¢O¸m…H‰t=`Ô0Š+ÂøÕ5r`E,Ÿ±\o¥¿ ¬‘ÿ-'[5Eµ`g‘ÆŸ/îš0ZÍîí­Âà4+îIÙéèmT‰lÅšˆÞ— –óŠßóN}2´0¥m;èì;Ëõy£7Æ~ÖNö-;ØsŠß0-ƒ½É-T›lmû0Ä )ëôÀ_ó©:–ÓŽį4/‡ÌB(5[› Ë‹M凉qž=³BÈR϶ì®#©{ tΊ`G¯ê\Û @}Àøƒ†^QG‰G"6ÆÖ û@ðôomþÌÊÿ†[fÂѽ#Ìo2¹ñÑXD÷ÍFqÍ$n!ôß‘ñ›a†i ð“w'd/åŽÓm6+M4Q.ýP*B5 4ý=4AÛ R‹WX{äG<ú~Èv;%¶¹¤‹RCÔÊôYo]l§«ÝkäQ¤16®ëÉy,(ü, !Ä·hRû‹:<}bz…ÿ¬â3µ2-ÌHEØß‡çSZͳ»×AÚèµ­lF®ô ,ÑH˜n¹osßÛÒüÔ¿ g2&%ºÿåWvÚUJ6‘ §e÷¬&€öÝùÌ”Y¹\/G[-Šú¨¥IÝŒa–},ž\Ç +ÛXÖº‘­ u» eîïyæ®Ç¤5Æ- J+CK4=¥æržþϯ$ž>êȵ`ÎtõÅìT‡®ºšµT6µŒewû+ñÄ™®"eÜùÕ§4ƒUFý¿®Éãæa›ŸÃª÷ÃSÍ+Y)@õ½³;#÷÷ÓEë@øÏbÅ´%”ý66…ˆÇ*ƒPžG‘Ù2ôÝÙbý™ß9Ø[í®€—þص²b㮫¶=IÑTËŠëh¦X7›ªGi™TʱÆ;º(4¤ñï§ÚwéUì3)œ­z`‡ƒLS/æbÐ5_þƒ¹¨²¢Öï§I±$Œ5¼“Ç$40©¦e„%±¡'±R U% “Æ"èT8 ºÆ³=¦•d‚ÇK ‘ž%ÛŠ;š?M¹Ó.é…σ)†#päíÑ"])C:\ÉT4©óú€À›õÖ‰¦¤Lê½A¾ÅG¹ŸgЫ6ë«-k_9¾^ÝýþùGÏçÓ‹1”pÉ®¸„W”…Îq-3‡ò£r«k¾3/ðcÉAüC/5Ës“ÊÑ8óãÊ.쫺:cBÒZƒEú‰‡Yð«aVq°""+fb4—®¹ü'Þœê“óþ ,_Ia‚™Æôèk¢GïN£n{BBÊóÚ r(3*WhŠo NPç’/–»»Rcoï!Q‡+‹F­ãq!QBˆècQÐäIݺZö¢Þ™Ã9—ˆ¢‡ŽÍ£ ÷4•¯š´ê¢K™Õz¤¡‘x/Ê?[{8Í#2‡N›l½„=§mÔXõy×™³Ð¯ƒ<’Iðé<êpDì{’—Ãäœmîv¾‹~îÚ×í?á-Ûå.ˆ˜ ªB”ší(å€Ö Võøˆ<¥À÷S wƆ5]ý73HdÅiÉ ’_Çöä‹§\ók†€×ÇgpÇÏÕî4|/OvN/LÏZÈã8lµž.îi$R´&yžHyÙÁDÛ(ÇpÁŠ™CÊóŠåɃ,ÇdW¸»\‘b•7Åv„oҬφ@pɘH~75œI$k05.¸%÷[Ô¹XLÃÖ¥Wš€€@A£’ü±¡"ñÛ%½T¾F°×ßïÜ6F©WçÓ®+]ƒ×\Äv¥°YFEB„¥j¼‘wn†[×N> P”ä»ÈÚÅÂ*¡e°+G}½alL©“¦u÷eBï4•1dëFÿ7‰Øe°w…ø²¹6“+ߤ¹aå¡6Y¦Ÿ—ßý3uñ(ÔENxŸ:K\àb;hbq¨çã f xn•÷Ð;`‰žz‡óí=õY2§)ì„épϬ²;„ ­K/?h·¸Ÿé•>‡¨RK(\ªysL†UƒOÅ Y†k³%Ä[ÏGŒ mhPi¤²cz ÎÈHÈû³-òÏ*ñUÈ­‹ÖGÏËÇJ¥Òhù^0ª)訊lk,|Σ_²8Ù 3Â9W¸ÓJ¦äI4³kwq ܧ:ðÿûÊÁ†A1ŠJ—ù{wQ¤§šÈ“'Šð59øJÝ—µ7 ó‚üéòÍâ%c>—îI½zPæ)X¤"éµb%V»²ÒLdž:993ÿ¤´‰‹ºÌ¿­4[b¥ÄÌÍo‘gK½´Œ$`“ÖÇ™ŸG¶Vm =kY߳샾¡þ˜áùGteÉLe[ ¾0$V¯°•jI:jíx—êY %,TEp4µ­c¸üÏ"A÷!Àø?—ØHÆŒ¢–C^OUôðêÉÖ-;µkBu´#·ž6gêlžE¼–ÍVaRèéOÛnë3yéüÊZY+L¹Y¨ÉÒÄ Ý ‡A Á…9ßðá­H2l㌺€žæhv eè¬ÏĽi"¡O%RúTç|HÍÒgôÿ„&{ŒZ±ˆíƒþy}GbDC‚hpÃù˜lÉJí–”ª9àïÇ yr š½¾ãM± w§Œ–Ùù1\W± `j¢~íô–Ytw\ 8lÔº5¯a<üÙyc;ÃCÞÚŠ WéèÝ$VµKú7ymò°¨Äë«Ø¶xŠ-Ø€ñŽžnس+øðs"ÝÚ4ÿyÅŽ©WïH!˜ÕÓ†”7áÏR=ʈ6ІIopžnõ,IØSÍ.Ý9>Ù§+'Õ¡vF.lorÐxQ匡šX§I²0PQé£/dfc…¥JR¤ÔF¯}-ìXL}‘d_oŸ,ý¼³»LÔrîí©ÍX(à$³ÂØô@Óªý7á_$yÛá.XÔkYÄ ë‘UØ´©ùm8°¿8 çÞš¿]ˆ5¸´klL0Jç®DýJøçŸt á[&½[-®>ñ¢F™·(ðS¹ÐSmµKþµ—.o×sܱûí½.ÔõàrlR¸ßÀ­}T`!ž÷¹£ò}ž(_ß",š·'†¦Û¾˜ÌvôŒ:¹Àf’:ªˆ"KQHËV†‡`ÇÒ€u,|lu³ú+u‘ìÃ2Š\ë‡Ø‹baÖ%î£1Á¹’ÍO;»ôw@wÑù‡y[íº6D°Ì0_ªBYò:lHûX #Q´0±À'z`¥^åö²(ÎwÚšR®Á†Õ¬?íKøq2dŸŸ¯˜ ! eRáh|gÀÎ Ac^l>åsûYY½$Å6¨³Û¿³Õáô%äöØÞv{-ç°¹£Ÿ˜IéUdqe¸¨‚Zö9.\¦1òþ2;Ìv,H_í1¯ͤUcÉ@r`U#Ô˜æ3©}he·X}Óܪx½»…àe‚¹Û»Iß5}ÇPp¹-ÔULA¡¡LÌQ±ËGE„&‘+ßè"lP¿î^qƒç@&±ïÊ7Ãî~•Ú²;—Æn¾mIy¾{A‹P”îž~ ¨³ÒÕ‡}"¼N2 ‘ã/^3Àyÿ« ©(Ÿ …6Ê~™FnÔ\¾IO!om¦‡Ðµ3òøŒ·oc’çVÐ{6ÈR0¢¸ž@—¢W{Ï@Ø;Ðø-Ò IÓ„aE˜ºïˆ$+ÅÞ_\a±®jeïÝv°]ëU€% ¸ÇÅæg•ª\ïAÍRß%.•)¢EâF²`¯ñu=43øyjZB3å*˜®€ñn¿É… Œµž‹ˆçˆº¶÷¦š'üñàg™ÊVð¢Ž2g¥Ù»jW«>þ‰ïæ$*;‰ÃŸâãUøZ’×Ö¼PZ¯Ò‚‚­ïyÒ"P|’,Šjª›Û{qX.0š·2xAò»ò>jÙÄú¢IÞ µ¨b”¢`õÂ/ ¤lò<4W)íZðrꥩúΤBÿ™ÙÙÓ…ìGõuåJUöºq2”Ä0­q¨ÓíG>¯0‡Dƒs½íRäæøNŸ»VM=‚&×`˜ëM;ÊÏì$»îCÒð,^Q¼Ã›wŒ Ò¡@1hüT«©]îz7ÿ–ÚFbæÛ*²PÿxǰÛ<¬Ùæ<ÍJšú¶³ÜÊiMü¿fD \dTRû¥ƒõòJ$À1ܹ„ˆ°#µ-ÏÄ8ªòq°7ŠØ9×Þl+Î]C˜m4~½ÉÙÀu½e”¸þD—“ ûž×Tpí¡vš‹Z“觬š+‹j ~ Û0(‡¾ÓÉËrL{OÿÏÅÙž©«?LV;å¶•H´Ð! Ýl°Œbsä GxYü-–9Q¦…-:.{æªgñY'ð”Jƒ‘Å¥D\ºFjk¹ÛNì%Z;9àú†Ì€Zö»}–j†â#9žÔ¢,lg‹Ü"Õb©VRµ9!SR^TáäúX6rÖ£Q¢ ùîI×4We„öô!–RÎUõxì ÚÁÆß˜uÌ{°É¡Ç¢Á㨪y.ɸ fFXKC2¿ÎR•w†A™è3£ÑLÁ„7ŽPÔ,ì|$&5RæN6‹(øô8õ²v£™–¿ÀÀûÞ§#‚ ½`úGôHIuÔY"e÷†ñU©÷æ91>RÞ8ÿx^ põ¦ñÔ©šáÇûÓiñ>\6y¹’Åf«PÀúÖGkiÐò“Ø}1ö$6L ¨ÄzlŒÃp¿ð¾òßG 5ñmŽPÉ=¥ÃØp“À]n"-=ÿ€ÊÜæâãýYV¦UV[Þ;’0]Œ–—‹²'÷CäžÄù“MˆãrJ[b)2r† #zÑ…jV¿ú·HLkJ`ÆMÖxH+ìJß–R¨Ý_wDŠüO,þ9[² ‚<¿dšÍ$Ï´Ëc|mWþjf»ô6þGqºfU(ä>wòôSïëçZBǂ˜-Íò‰¯âãó;ÓCyöÎÔ¤¹frusJ/}VÆŽyÚgxæª'u˜ÛMï šœ¯[KBmcQÄñ’—Í¡Æè=/ Rí”DͶ¢òB‹Ùuqq|"c IÎV`M28ùÀvž°Dí° BofÂ=íIõ6 ¼Ã„÷›òQb|;v"òQ^‹“ó@K$‘êThïš¾£éܾaÁân Jwy'º+ÅD†tÒQ›ßÙÀ:ÊÎI¨†H;ñžC†› t*pOÿƒ> PÝ`¬e¹M D§_ï9zÌÊ•ó*ë0uOë¯LÒöç(ÑÈÐñ#AT\‰ÇIDnSaR/øõâÏðøc¤ž{±¹Ÿêš BWÏÊï _Q§¹&àžù²FnÕ¢;LØSKîYT\N"u\® C¿ÜÔXYp^>(&Y&²úÂüsbJ*V‚ädd1äõ÷%Hp11«¢l7ˆÃÂ.°&fHF~üWï#JŸƒ~u@Æovö+´Uu²Yl,QU¾åà{7]+Õ°£·õÕ]ãØï›«¨ŽŸCBËXNÀ6œaçm¨IË×KØûj%!Š„¬¦{î"0?ÒÈi¬¬¦/}>¹W»Z” Dm:0Js)Ü­N.ä×È•ƒEpUeËßù;OB6ƒh‘Hðæ®c$¿=ýÚw~ÀðãÓ²ÚL§Øw 'P¾Àú*ø¦h nÍ&ÌdÔã-ÁÜ Gk™f¢Ô´æÉRÕbgöŠx¨™¡,m§´—u‹4úÜÛÚá×쎙Äé8JÖìNËM‹7„´C”ŠŽ ƒHWql ¨úÍèOhÀÍ\P<À¾¦Jê Û¾Uˆ5T>=l÷Õ(׫äyg½ŽÌó“H'…jav[?ã¢koˆ, ºvä ˜7Àx5•bLôàèt«è¡—bPè‹™žU…ˉ¯~¢Îý{I¬¥ÛʼZí·ŒÚƒ¬W28®±R½í*Ñkä €’Ä*³*´»¸î±“cÕuè_çP3ı}ð‹‚9á A¤dɶ£ö¥ ]üX £¶qÆP£Èº Jf5þDÜÌž”¾bfÖÇÙw¢^}¯Q·çBÇ«MI¶è6üšÿ@]D¾ló(Ú›„$.b±ÀKN„šá)ù#ìß.r:$C dÀÝQkÔ_ÈUžN°4sãÊ[ØTdáy4Y• gúk:Ÿ—ä ¼ð!º’H»a»èP6ê—Ì.|\ùm¼>`ϹÁ-f«˜ý¤ Q‹ä€¥Ø]œ&ÆmSq7>õR_^Ÿ»›û¸o›înZ½Î'O&ÀªFÓñƒ*þJ–¡ÀFî¼_†ÎÎms‹&cÊ»£]f¨èËLÙ´UÞÜ(ªžU[h[2•x¼¬õso¼³|±©YçqÙÏ>x÷‘˜Ãßà|Õåæêyœ:®q ¸¾Ò<¢øÖ`ÚÓ$f¼›PìÉ\Ô|Z¬ŽÑÅ»œ}…¥^À¿ÓŸlQIIéa—ÊVÚë‰SÞkœBåóy—NÓ»«ª#–.­mû&ÛM4ã‹@¿Û¦˜’ü0`Äù®§þü?hL]bÚéz› £*'M|o±„ITó(ÙÍO™£ ©.FLÈ?‘îLO&,á!rî±æªzkÑè˜ÞbHGGˆÍL¨¤TMêÈ~Ø¡GðDæPäE­Ìì:¦MÅóƒœdäè)Õ/ˆUöDÆ€‘~ÛVŠÈbY¿æKÑ Šxôü¹¶°Žd2Ã9—èc˜Ly³¹šsÞ 8œ[ÕŒ%úy6år»f/à»ë)Vçúíæ2ˆ‚3›ˆ›§ÙGv–©ß ÉŽv¬J“ ZŸN·ì2[x†† [Öár$¾®InðR'y=¼ .[˜|Û—Uéí­]¸ ã\ê·¥-K¤úóÚwÞgÀIÂfî¿ mY(¿»ñrÍ@©ÍÍ¢Åö¾ ‘°;MDfx9…gñÍ'Í‹YôÀ°f‡§õWWy5Š/ŽŒ$Û­ÙrÅpòbÖQ, à°Z¾šR•Pê°}ôÉM<Šÿá(Ò•d3™A‚u6°E=4C0³Gƒƒ¥+ÉxFÛÏʇ‰EPY=£a“z›ãLÚ¼Q—%ÊBd ªö2ir0É  #K,ŽÐ"Áh² ò6iZ¸e³öª%ùÍŽè(ýÑ’œûA§kë,Fm9JM¡L"vq/£ÙÖÍ"ªtB…¼‰$©z]ì\:‡œÉÈmëŒ=`"+–ÔuX²‰Úç„*?ÀxðËœ{[ÿF·x¿Ö£´ƒ=jo¦ˆþï‚΃aF§ò·;[–ÿ­KLQövüLQ,²kb"Y }Æ4„›®¾Ÿ3‡ö Q…AÙåq¤mB5 qi½}´<ñ”ý[¹Í'ɘיÔYF¨{£aÅÎs n2æ¤ \´"ªe°è¾mšwVãEsq76¨±N}Hëà k×Lu\.•’»G)ÿ/Qt0ý(ë£æ²ºCyîrb²ŽíÅÅaÇÚíD¿^L< §|]Zìš­´#-éßíXû3ç…äPÄë.‰Ùñ´½H<òz¸ö÷`Ü8» '¤)A¼ø¯ûW–ä4m ªÜFP~¿—„ 93|¾õêÎbÅú¬J_žËÄ£‚n˜Àe—6ÀU|¤=L‚u³ ï0d½¨ý65R©¢£Ø9ÉÌyͬwB:åáiÒ· ;rÈ@S¾>¬•ÂíOÁ¶²;MÞ¶U¶ÓÑ-®ŸŽëWo\=žèòwd4\1NÓ™zZÈ–é³.}!l²Þµ±0I³¤F©‚ä²n”r%@ïsL‡#³¢Ù£¦hpzHƒó7&jWb¯÷`Iê~ó2Ï,3å´jáÉ3Àú;£„d€XUj/‚7WØk]v<)M CôesJ9O|°㲨*MC?ƒœFW£3 ÝGäM¬ÔÚê37¡ŠñÁ˜Ša°c_jz ²~ÒAµŠŒ>-"–éZ…üör`‰°ïóo;úfñ43:6^„+Áħ4Â÷9"$vä‘»nFr)?Ä3T· ‡˜/(Pá^bZuFjÊ` ­é>+a”…ÎÈÞ¿‚™Ig–æ¢XŠG™ „øÙeeð”%-"82#àŠ°˜¸|à>©ø°¼™ñ·Î7)T°!A},‰P TR:‰Ô¸úýSãlÇšU&sЉñeyLÒ†±† ~gãúOúùHÆÍ ™uß“ _$½Þ!Xáÿ§èû×ñ¬ñ(4øÒzPïæÅ4wÜÛ4_ʽ­›­ûªàQô'ìþgýl0ñkÑâãËɽüƒªu:./I™c\1ÅY×Ñb-b  ,µbõ³/njzÓá¢òw~¦DtõRÚ¨ÍVÅ¿Yek¶ úœ :<™AþœJ;[ì8j S÷üŠ ¥¢Wdz4=R­ÈAEøshפd½Ñlp²¬«ÝfÏ3w îF8zƒ ýcßGЙyiåŠÏI¤¬% ‹=âv’Yמ›­†Ÿ@3À¾zÖu3°{zÄòrH8¥ùw¨g˜¨BÙµ\¿Ô«t:¢øx,*ŠÛ>/ûÍ+ÀPÞ­ùCYÀ$û¢»å/–RXù8~¬48“YtŘ´ïe®¾žæL®ì¬‰0# ”aŽMö²ïÿSØÎu8µÕ<ŠÚNèSö `”‘qñOmZXÁv_Ô'€…°S¬»õœPæ™èñ§CuÓóÔî@­"7… ¼ÏU|5’ÍàYžuÂ"¼Ø_uâRß0&«›¸wœ$àÖ” Ô¿_µ—îÌ=Òvž»0Ã,êÌch|0=ì–|.Ïà™a=V|n!±§ñÔÛÚ`®a»Ïw”‘­ˆøô| ³œc½NÈ [O no€xüŒ÷ûãM&›0QÞæx³Ö—l»ÏóC¼æV£ƒ—í8p`ç f–MŽKÃè„μ.//7~‹úxÂDÔÿ|õª«PÙôu@æ¾²êÙÕgÞ.£FtN˜¹Ósònû§£œ¡‹ŽÂaõû6ÄÎ?ç½’‰Gnúµ•ZX’ßð<’ïa§Ûöç« ;ÎÄÃ;† F¥¸ß|ºb‹_ƒK(¬‚¼ åÇhÌš:ÊËáÔIîÝ~IÔ¡Lá (Ø6Ãa#Z”á'Ù>¾z*d:nI9ÒÅeÐ" s§ÉnI°åf´œ¶ÛÕ æfxa//›î€Dó6«²óÒÕÔ( ³¼r¿2„ ø]~s||êÖÂüY¶?-o£µ³A³ô•ç¡ÓÜåÌÁgHU˜^}¬<Á·ÒrÊ00%M ‘É;±¼;!Ô¶„ê(agCTÍòMl¯t?ËÑ4·Eˆ^X_m.½¤¨ÞP{¹ê„¯äñ)ö(ˆÝ=xŠãï1‰ž6KüÑŒt²KoÔ° ‹MJ U9Éñø’ØJ’›¤Ò„ìOœ;ÉæÖD®îì0Í‹BÔ˜þwî›1ÎÀ/`±¨Ñ Ãìÿ%H…`â³6«Båø†üÀ>PÄÎ/d¥¿ܰ•êÇZž¿KZ׿”l¯Á­‡ƒ[òǯk2s:Ôë§ [>aAFmõX¾ö¾XAŠLJvÀu¹æ ³×;µk¢0³ j+ž;Ó"jÆô£¾±t¿ ö=²Îjsã,S§Ï­»Uó,E}ݛڀ˜³†'>6êè^¦¾žU„fJÆ^Œ"ë¦D¹ü"Þt+;Ü8œ*,¡‹Ôôr2sÜXÐ&´·¿°|ë‹PV\3ªÚÑxnЀËUûÖ¥t¸8BÇ–-FA»dëfè]ûwüÁ–éíÇßñý—Ø7Ahï[H„ñp@©ÁÝS •^‚x)GúI–⺃ÍÞ`r[?¢ï!Ô&Ù²ANûê5um0F{Ìq¯ºŽYÙ‹íŸígðN|”ÔÈ`ÕØƒÝ*énæÙ¥cõƒ/‘èQ ¾ºWs@ [d7·ÉÒ£ Á°÷ƘBÙCèL1¶ ×3.‘E‚ AÈúzjû†v¦TºÍ¸ëòÏ4ûÞdݽ“rW÷PÓÓƒÞÛ‰ÀYg®¹k•ª ãâeã–ž*þ &RÍÚÉ«ÊwÊkõ¦0¹eá~âŠr KÈllžºÔ33J‡ÐÚ¸WœÏÿ<±ÂªC.¯ì ­Ä„2åùØì\]·?”•­%2À áH‡êæÏ=ûÑ4­ÛMÜÓƒÍx»ˆX‡Éƒ‹rŠý7Ê‹¾mÀ𴘙¼áTÑK[—ÓüN÷W#¯ž€ûÇ ú*ȘvI4¦õÚ´•®j†òtˆH”²mq¶‹À´çó¿‰Âˆ˜ÀjÌï}Sð廟k=Ën'7‚ ¹rZåј7Õg èG‰Ô²ƒ¼r8²ïEUe©¾„©PFÍ]>1™SåÈÑ–@¤ÿ1º¤u)® YÈY’Ü,ÇÏh’vS½÷bÿGfñ>e¡´“4«HR9›ýÝÌlqNw¨R8ÍLÃMHH‘lc«¦ ‚µÙ žÚ€¼‚ƒõR20T7YJœD^êÑ) ‘£±Á ao:äêÈÊ`Œß …aêÞöŠ ´Ùì±eùƒ+¾ðÇú€$BzBJ5ˆÖÚ%…´=Ùuä,^€ÈR‘ÝäÿºÕðÛ9p¼úøá|^v¢% âdDó«U¢ k" ¬n"­j~å.×$iÁÞˆX¼«jÇ+£ XQ(¯â=KGK›JÛ¥å ¹¢Åžt*LF“7r!áfƒ\ì\—ÝC#'ÿ55˜­ÉÊdœ)Éç¯+©â"Äþ0[•ýÒ¥æƒÙ©dŒ_jÓôðº›ÖØ«p…ü}ÂxxZ~žMhôgȉʼþ”‘–JˆH¾uð@fTh´®^D|HþJš:;@kÁ½ÊXÅ阆ú÷Þs»â@äñðÝXë¥< Iòóë¾¶ì…aHçÔLP\·XXÒ,µ`“,):6{ÁÅÈ^r%uÖº5®Îlö’ÓT*AY´8”BÑ.½>4cÀî3ÞIÙ‘ÈHù†}éĤè“~r G¾?Â[Cgœš~ù¨ÆLµm$_µxcI×N…xyQbÑy³XÅì÷, s2Èœ·Ô6Ö Q—<’.*ó®r^ùIMüµ|zvn€} þ‹B¬yø«³Ÿ â¡Öšs´ÌWYHý&š MŠº¢æö/ •ÔÕз´p#´ˆnÛò˜ Éå—Oý7€÷'ÞmɾpKÖàœ ‰µè?¢F3¾vøÛ«³š(©V.v fŠáÜÑÌßàDÕo³Ýœ_P4Ô~[ö=(ˆœqz16&õÂ@yÀ囟$Q¡  §9¨­œþ' _¨È3ÀZáu"RuwùÄ»°ß¤u~®²þíÄ–„ÞMí5°GúÒ¨}ßss«i‰ ûæñ2ÍHýËßâüµg#Éog»T'| 0Î|N.€€Øß,…¬l t=fÚQ~ƒµr_µö»G"ÇôÅ}Åëx|TÛaé—t¬Ú‰i΋}©P+íM3¿<ƒèI/\´®Ø†+jÂ&ŽŸšC_«@x{ÌgGÜB8ò±Råµ/Å "“b³í™CfvUOõÚ甑.}°6?=e¹ew,†›ER†‰¢£¤Ò¦(ÍÕõ$Ž34»ÄШŠ$ñå Æê¸—öWcz ‰Va:ûp#úþ+¨Y󔜑@ 0çÙ Ó:Ö@íª3¿ÊÇŒmˆpw¢(Øß»#?»·k0šÍM-`=ÞVçÐÙXëÜSØk sÄÉ‚Myâ[y‹‚u{â>$t‡X$ÇÛ¥³¹fżÖe¹PþذPÞqGŒ¹>—fKhÝ0VÊ×M”=oê…Ìû\Å%&Ýñ”$≑ƒlIPFOgùé–\$›/U̦ò|$Zw5!ºCVÿübw³@§˜^Ò[–Ðvië´Íæ£Ê“­Yòƒ6±w½³ƒa·R +íuqAGÿ1ˆIs³…;b&9ß.¯žee•ŠHi.fšEaÆ[ÓEx6à”]ë×D0§ Ögn«ôÉø”âº÷ƒ|­âÒ÷ÐNÌ«s)¬ÍÛ ÓÝ÷–ˆ|©÷¾ìçÊqúŽ›FAν:5$ê0•,gjó\â!Œè,iŠ#z‹Œ…y=5‹‹`‘ŽBõT^Ç‚ŒSÀXœ•ƒ§D„¹)Úî%\%›¾à-žr8çÍd¾«íö{̃ÔnŸ$(¸ñ¦P³›^—×»ãÂcágz;‚ƒ"µZZÕi›Õh8¥—Ì㩽¦ô]̈3’¿×®£æmÿpeŸß{Améö̇¸Æ”KÕ§QK­Ø§“ñÌrÏÊõ̲º³v··™%…¡mT-¢_äæàÂóOÝIEŸŽü™ šåDSÔflúŒ ³œ–T­²y»Ø,jÒ‰Ût”T¶›3aÓAz}o¥–0wh°”ßÕ‚s1$ÝL Ãgåï4ô­J‚ƒP^\þ;»ú” ‘uÝ=›·Ž 0O)Ï€íÈT9Qöï—C#ìW®Ìd ãI? ú=ÑýŸ3^d‡6%-kç­Lk‡ô…óßö°ð¾_ZÐ…p•†ñU¯kÅRc¬á<ù‚éeQî÷¬p3ó—ƒ–¶_zlþ3eGX÷µPR”Šw½ÕøM㦪9? ©Œ•°ÓÅÚ\§-ž¶Ô*¼ÌüÕAS”‹“íl”6ä?¡9Ùnrzx6ëV—Hï”%¶Ø)„%L†„­ÓmÊ)âḗýÁú@Î}^!çê×òhêÏ+¶“†}‹N—›ô[¥~v¡¸$9xá]ãÚMÃËMmg4œzÒ•älÊ Úå3uí¤ñŸ+Ÿ²J—pOfÆ6aØzaae6¶‚8ŸJbWH)„4ŸÔò–ï²çµ a$ŒãC×PóyªRÞÜ óBf†’n!þ7 »ˆX…¢ý½;h[ùdÏÞ_Ÿnÿ`£[qQý ±¨_†”…ˆµÍBG(âÌ,Á†ÏUlvf~H50ÞŸ£ˆGù®35˜ N‚Q‡ƒó@C!Å]˜ŒÎ©ŠV‰ûΘ±ãhZ4G¸öÁüÅ*ähR U|ç¥RHÞ‡˜Ê*â(öÝû¨)r@€öÚVúh[I?AÉ?ð û…ÇóQúÒÕàÞ¬b†ƒ ÇWºñ±g»Üb.si‡š¿Ýø&×h 8~ ò7£hL#ßîGfPÖ¥­i“«„ɵø­s³úšÑL®µÔ4Ô÷òmr¼ª£Ê>O¨uÂ÷ð™+.${[7‰µÄy°^s [âJíªŸzìrlqnžO9Ôˆà¶ïp9O¿”Û¤•t%^¡Ì¤3Ò„¨ŒÃÈøre¨ã o-oÊ)ûLe;ç¹!ú¨«­“Ô‡L%tìÍ2=™Ô4Ê'Ý“`ý0¤$µžŒ™Ö´(u¼ø!ÎDîdýȾ76ö'Úèx­Ç™*r½0 hB÷à¶²-ÌñÆr¢èm‹ )&øço®³… w­ŸÁYçùÆU8% Èk;¶²—¬~Äâq€ýGO—q'—"±Ã$$`ÆT%É•H] ¼IÔ[à…úì_ßa ¢N…qO4E“Òh€D«x¦ -—2ÑÖ˜Óu˜ånúnJÎJbà3ÑÑýÙaÑŒbßö‚OÍô}ß5’1¬ó$ô¹ á¤AŽZðóñŽ-CÛ‰ýÈ·€:k“õlÅ~aŒ´>x³€ÝºÅ#0Á‹ì¬è‡w (Ï£`!†óØÂžƒc®íx hY$Ú"²bÐ0 XdH­Å×õe-°Nc?ê$á¼÷o†e…Q)Ï~˜òTnÒò#ÈõÔ+ègÆLüîÆç(l²H‘Þ“G›pñ~¬×_‚Æùï•9¹¯w ­ö(D=žëÓh²Û^MzãÌqýŽî@c\cË=¢ aÊÑÇhñ$w~4’&ÚB㌯ߡhX¡ä¸l÷#ùð•yClQ»t$vg3Ñ¢–;ϳ|eç´0„’ ?}÷Oì2>ßZ Ï[nôn7Oþö1£½+-â{ƒ¦×ð(´VîÕTß„ÑÝXbåNr‚ò‰°8žÒ£Ò ­² Ð`³7ç­ï†Ã•\UÐ&2µIÛY+©º/©(}d4@½«Qò”ôKwʾª '±×ÐÔ¶”|Oð 7ùð‘³pfâ&M6*¢ß”«4×/œ™-{k£ÔÙþÚ» 4¾éöGÐ%»®wÙS¾$¢j”­‹Ûz£“jM¯U°Ýùôxl?ÜÇå1!ÒjxÏ)/–=?6Ÿ›Ýz˜µ`èjª,ÀIªíIBÞ*’AÅÛ¸|dõ è~8ÛçC¦zÇH'Âe¿#I® 4G• ‡gÆB—82è wu‰jÕ±_­ Ë8ŸˆÃ~÷däéÔ…o‹Bƒøè?T:q¹ÑâñÝy½£SëçmD‡“‘E&“•¸À_ëU½>”ʵO?dëàj.-#ýæ®õ˜Qž¯å ýþ<Ž‚.£b,­D3 ÖÆiÛ®YkºPhZ½ )n]÷¡¯áSãg|3ÑìJètŒÇ£ÓUÎ?CjÛÅ¥ºƒØtA3ä›¶ ¢Œƒ ÄÛ3ôóÆîú½!ŒØgo¥yT÷AÁ·¾Ú¾Ïa¾p`õÿ­yÎ?ð8ª6º¨ìÔþ( „Û1¿vB5£Ü’]`ÿUË[}ŠL.ƒ¾nUJ•ÆÝ‡2¾MˆÍf®Ó4¹*K®÷Fø Ê=J¿fg®¥Òý¸]-ìЋ?ŠÊ@˜Ý‚1¬m`‘¼Ce°!¯p=s_„/¿·.Cï¢gB»}-˜Ìë‚ÉxÚS‡,K5WXÐûxœ7Õ«3ä_¦%¥>Jˆ«ú }×\éÔ†*­½ÚCz[…elh‚ê”A‚Àv@z> ¬VRÝÈî×-3æ ŽW»Rñoë*”uù«üΡ¡MuÎÅ/.”˜‰îã ú>äAAÐZ±ÆÕUÆ÷½8è°¥ ŠzÙ-ô]Æôݘ‚ëøÎuñ>N1·½qŸ#©ò^u®td´¦,,¥#±ÊAšÉf]ýë¨+PÐ:qÍÅ0–Â/’>€ðÎÒ®1—\YNÿéôÉØøËŽŠŠ~n+ÊÓŸå–Žàc,6í6 ¤Ìµ¿ ®“F½F.Œ9Pµu—ÂsÆŽ«GÉí¬”d«½ðÆU‹Ûdøº')@qÉU‚=Ü?s)ÒÓÕº‹ˆt³—!Qˆ“ѱºyöàb^ÔÞ¼’ íå¸ñçtã8–ŸCúžGñþMÑ©`_¾œ‹øêtÖhªÚ#ŽݹµûôÕ6z–~²”•ÚAV€°È©m‡F?é~RpÔY5§ÛÓnx6Ÿ8 m"“ð £ btwm.).ÈJ\Ck’¥È¸;‚5(»îÕû:bhf§¡ŸÿDµ*% N½5kL$¼Ä[T´]ª'TŠ# )üò|SòlµãõóDKÄCA¢Ì7ÄâÊ¿þEHnd‚@6KòÍ„éYo‹m™qmØd%@2¼³àn¨S"IÐTˆ©íEùðÐQóïÛ5†»×»ÎGI͈êv±RqEñe<‘úoAC"­&"üVoþd‚¸^`ÙD„ Óµï"d°}®-j[×Oö΀Օcïw½ô¨îÃb]ö–ãê§l¼ï&*Û ¯êFT©¤dÙ°(˜, ²êt—€uºS:V¸ˆë≉˜Î@^üy²2#¨+8ÄE>!DæÞ|6îî®:^–”ÐnMei#F;ZÏbiÁóO6Yk9AÇÀ°àº!· ]ótß²µéªOPH ÙPl1`å½{ñ:·6f½ìØ(Ô§ÅHTcžÇX¾OSVrïI÷DZ:UÔÀ$ àì¢eó/ëø¬E‡’OSHƒkÓa,tã$Kd[:Øò¤…á¶(¡´âø„÷ /1ÐóüŠ©‰—W`-,Äc3 ÐáÁµ8½Ü©P%Áƒ^WÚnËkDk³o¨àý‡ÂÀ!ñ££™Ž¾îkÅ—ª¼¤z€bo¬J\?¸€ ®€þê#¼|´¿úÅO÷0@kõ³±Ù¾Ðý·$–öZ´vwô‹>¿…œäj÷Y¯ṵ́q(>†Ø!šð¢Åüz¿Hòç+Ó2É£¶¿±€¸©oK”ìÝd2ò»w|þ†Zþð®’ïØ8æòÅøK½žy­v&.×Úu…'ETéh¡cáLë)¥>´»²ìQÞy³.YálUÑJØ—e‹ÁóëIÃiÖðÿ¯ÚžÑE;¿ŽCc£Î· dÑÓ ó•Ôö§>›—Ï4ðËÃYškÊèÇ©0¬Ïb@2}ÐwôhòÇøÌ¾“õä÷!iÑcž1bóªô± ¡g³rªÌ| Ñ‚ºdTÚ%¤m: _]_”B€€ÔR–Ü´À:a–îÜUAÞËtWÜçbk3à÷è÷pC†·n@ÄÖã´öX› az¼®g5n«Hmóãó ’€¡Ql¸àOZÿ•|SEa‹£Ÿ^ÆtHÙÇ̨ kh~ÍÂÁËR³Öb÷‚ +iOá2b+Uta°vH¸§DÕÌ®>¼$«3xê2WTº E!¯Å$,Ô-w¼ÂԆΓí²GÇï¢:ÁξB5•~ ½¹üt¨99iˆŽ‚Âݪ¼ûÈË¡s-$ôX.3ÔDü~z%)_Tžmz”ÏA*y~ÎÃÕ(uƒÒ>†ZܰÄás}W‘p2fî—¿’u7®”÷wL1åÓ5€à³øsSÄ%,Ð|Ôâ•—\•‰ mž:8iÏÛÜwË+7‡C0h&X‡•ÿp5ú]û’’þ2ÛŽìª|5¼”ax½9Æ:EP|ÿS‘™ä¾ÃÚZ,ßûÅEŽòÇ1IE¥yy»áÝ´2̈¸59q;K+¿Ñ©öbûî˜ñø¼mz¼ƒâC¥—q©ôàcÇjG}W¾Ò„«>e$ýߣÚUÆýý¶ÓöÄ»ºShoý7½m-²*ÁÝmx }Ío«­ÿZ%®PŒPŠì_¸ ¤„|g <©ò • €, T,ÒªEÃoÉ/.´BeE?ºîvKÄÚÛY+£_S%uÓh~ˆì•…_=w+i‹“ 0ÐÅO9}¡(Úo x‰Wúêí®àá¬V\D1 4Ã#ÒŠJñ„Ú—'ršN}gR-ÿôß÷¼ç Ï ÷g¹{‹Šs´1w>ÔßÉ#z­ U$̔٭ˆÙk!²´Æ¢ÛÞ(G‡Zp³—Ê?KÂÛÅ`¶Ê !ÏÚ}(&aÑfLDà ¯ |Ö9XWb|Qˆ•(pâ)Â’(Æzv®=o(ÿ=¢0Ãä‘ázÛÃÀs\ *$Zkå[èÛ‰é ýÒǵ@åX+.ÍîM—L‘o,æðë]ug¢ø³2IðRŠ\!>ÿ»ŠõdŠZá´$­Ÿ”H¨*1òºt×K $!ÈRåÕرnž“[C6UhÍÑœzÖÖ Í®~¾9µ§²D¾“têï¯LR³MçùЪ¿ÿ¼¸Áòõ’$=Fr¿zn¦àÊ}ŸiæÂNéóqŽ#61úZãÿW†ai74SýÅY¶ýw§§ûl=™ÀûÜ’ª{!ù€Ü«åºxMdåPš#ͨï8ä&x HÕçp²§¶<|"Ö];/ÉÇš‰C»?ÅËíîÒ €ßH0ye_ ÝÎ[ÎRMõór²³ß½“·ó˜y¡k6ÛK*¿jmgnm¯ð –SŸéýg½×ÌÊͰˆ=ž;c„Ó@1<4g) Aßùz;îíMÚ›”Ç4ÀRç†2Ü›™sRæLù\½éw™R›--: „s¦@þ´ûZñöísÂ.²2 Øn /ÙáaÇãâš—)‘J“ëHëxE2Ð`Øåµ†Ž­Ÿ¸4D´käØ˜|ü,Œâ›:Þ”ýû/›{í‰Ì™^ÿÈÃõ^¾¹uÿ'Fþ Ð:j'“zg»î|r´]EØŸ¾,Ä+¤©}`h¹¾]€vÇS€Ö}¸£¿Ã€®­åŒB12 ‹R íýñàÐúÏ]àÿ2fft;¾,ëÞD ÕøcÏö{eØ2PSçˆ{ß›M}ã‚…ÉÒIþ¢Ç²,'67Ö@3)~K¡va«Ù£px “ñ„ÆG’jÚÙÿîzÜöd–fk¡ ÉH$O°B"ñ£JLhYès…S¤(ì#rëýhêŽE{Øaì€\[ÀŒú]qé&Ÿ/ÆÆx;ÏÔëM €‡I–óEõ@9O ÿÓ·a[røî²Gr€ÿÄÚÍY³["=Ž`QÜÀªgqP†:>¦Úp³¶W{‰ÏhuLãTñPyGÿŒú„,û~%¬FqÍø4m-è wÞ6ÚËÍ[Lá‚®YŒŸháå&J|m@ò½—¯`Ž%Q1R$N±€2î9/àø;‡ê˜Ðu\Ã_¸¨ðZï>ÞôCÙ ½7SYÎ&ÐsÃs}GŒŠ¹QäÍA±ü ˜fBÓëÁáªÐÂñ”Lh®,ýiHG£õq܆«É˜Uˆ?e.9uOá.Â>¤WœÁŠƒ B¥WUûGä•R7 RÉ£^êþÑN»r©l¨»ÙÇ‚0cÎç‹_5ÀÚsS‰Òö»¥ ‡üÿIšïÔÖ½ý=cA¹²·Ïfî ¤ß~¯¯ua¹¿^û›zm\˜, %š¿©ÉÌ¦Ü P˜øyºZ‘¨ºh€Éb°ò³Nõæ#-H ú¼€LÅNˆ“Ç¥:K×Fµ³ýï\‚è¶cj‰Ö²ÁÎýš½ÿßV5óÐ¥GØ]AkÕc°'¸æÔIà/ˆ;>Ø8ñPO|ø0†,MôÇß!yÝ83ÚÐÉHÖ #–˜ß@az™¿Ê*6D=ýrá¯Í¡æ«í}Öø¢I¨ßYmfæÓ¼°!‘)OÆ1îQ{žc¸%ë@™©Idžc\–ò²ã˜ûó—¸Ê¾tZPLN;H‹ow)êîOV¶[„dªÉgÕ{@eQN÷ö§iË~€x¤=¬6s A4´NkDFI™?4ÜW•/+2™y×ù ö¶§‰~<Îe—a¤1'ì9ª¾ÌjUþ{ç®ykÒxÜ^¬×¨ ŠÙ¢ŒÑŒ¡aþÊV“1N¶Œ÷cÆ0²Î¬!»»Ö$w`÷n q?*‡øœöd`#~ìg¶#)·j £ ˆ$qÈDŠW:uýTéMºÈó >Ì&œâ™²qÌ™î\°/üT`ù²È ’åSÜ¡në‘p*©É~—üžþˆéðÒ‹ |V¡VX÷ æM þüÈŒ°Õ[€‚E‡ÿ•~ÉkÓ”¦÷eÇb«¡—bdš}÷E lA„jQÅ÷âJl»nÜ ‹ì£‰J-ÃÛ}÷¡íO‰vÆë©®òµLƼ{ÎÞülrëd Ö\r”è´öúAc“oÌšù8ApëÏ^Úm¼˜ê! “87Èê¶*@o&¨ÉY²%ð¸F’±»^¤T˜ûÖ·¡%&+nË¡žúa3H,ô¨ c-3ƒÝ;æ6ŽÈ8ßó5§SÁ£}0¾\d‚øæ&)«œ9ßÇrpHB3ÙÊêgNp9²ÙÑJF?úÒ~‰H•Tš ?ÓeF2MG +:Žî°ì³›eœ#è¯l•ŒÊü Ï«ñî"$΃d¸l‚òÜ7@T•W0qä¢&$ñ:ÀëûÑë©VŒàŽÇ•_"Ne’Üi–¶±dÉïû+: ‡Ug²ìd¯è¶ Ê膗R¦U=h&½ûÎ`oÒ†²üGV#R£ÙÊ;v­©‚Výk $ÙN{ÈM·CP†3âOc¶ó¶…¡§Ø¢ÈnÅiÊ…=ßïž2é§·Ëœ·a÷µËs1%«…§s’-Ä?ý´H‚`iýší³÷Á£«ÚM¯¦!1ž1\a%Vž¶h36}-„”AïÎÝÓQ¤·ÞGYÄ©¼§.]87&´kÖ8F쮆è±|¶ƵÀüö úµæùPH¹±Cæ&ÆÉ“Ý*ö\F6Ãç(aãÄ›t²Óºð¬Â†)2E4YØ8«´–ê Õ¡—D¥m(úk",´9Ô<¾‡z¬ƒòS]EÀDÛCÔÔ£Îd¹5PýcQbB¢`¢ ö.Ýb»‹ÿ±©ƒ †§ø<Áf)ë­8¤ýcÇ=+’íx”DGfV™ù‡Eß kz½o£šXN7ÆÀ–íœna™®Ü^ ¸ßK#:µ´P-ƒâeàšk­ò‹†‚¼M=†Ã;ß]Ç%ì^c¾ÌßXˆ!'ξ¦šD-}åC šå_vP8Þ‡…PFÞ]oúÜ fmøXt×/G¼ù2+òèT"å´b𪠆¢¢M›ÐøÆ@×Ç[” ì!P´3 ò§Ba~<“‡¿¤åïŽÄC$~e¶ä.Þ ë"?8ßã#æ\VfÖH’ ºƒóÿþœ¥{RU¼™ÍÑl}[HZʱ ¸C_ÅîÖžM”E¨7±Ø"y#x­³Ý¿-Í£.¯|³•N·[­ªµ˜q @vy¸#6«9³d~°Á°3ÈÓlMtm>+Cã„ITôŸ{¤B²ëÞø•ýöŠ¥jTò\.±Ÿ°ûBòÉUF„$WmŒ¼JqIaw¹ísʦI%Jɰº’VrM'v°N v×Àøœ7 =IR[þ›Eô¸Yº¿*tÖ’Ä æ¼xÔ)šLë‹^/0o^,²l m›{çìMÏ3ðÿÏ4½ch<ƒ®Ð¨¼]~…ÁT:ãÌ\9KÃB•Jy_ãwã^¨ÓèS•Æùp’È·29Ø3-T “ÏŸe×1(9–”Fu’´™YÛ˽§øŽ–,cC6FM¿9š)òátïâà=‚YÜj* ÈÓ%ßù’ã”»I¶ÓVáæÖZèäŠe+3_¬±£˜ØÚ[ZÀuÏﳤð⸌%zÄþ5•¹ÍV•–5æ5‰3Šjwœ]ùÿÈ/׬ÃYŸù¾ˆ3ŸLZdš|Öö!DErÖ"ó ñ¶-è) S:er6õÝ µuô|/ðUƃ´ÛùýNÕ£ÜÚ¬‘ÓÃUÌÿ±bÌ2†êc ÿ›ªyœ»9 3м`2`WØ2ĪlËÂmòã’0먹Xƒ€ ™âÖ‰ ã1·Yú³É¯©T[ÓËÉ®+ÿ¡0Ï4óÅD÷¶éÆ-.Öò’æÌ¯ÚÀpÂûé!,¾Â³LõaËh?níô/-¬vÄøß÷‚Czg –&P#ŒÁÙѱjÑ«½ì$ˆîzɱéZftû-%}˜£é™e®.Gù· °õo ”vë-|ÆÇ@Õ´Ô¬Ž)®·R;—þ´¦ÙmñE?o³¨F%OX!W® $ª4Cg›‡'? $¹›â<| & Jjè¢brˆÔz|}z^Á‰]o ¹Ü“fÞ…8hL¯B+pÅ'þâ)K{Y×—©wšÎyёਙx{H}R¹ç#™ –l=Z€ŸÿPš½`¨ûÊOZ?5lVÁ¥mNqŸhD¯û°®Ï†ŠºJ÷ôž*\ P(ÜÇ‚l¼Š§iäŸî 2}x˜}B¨¼a¡òŒ.qO>è¦Äô%³::JŠ’›z²®' v†¶={‘êqœç¯îÐDÜã gc~Z.³dˆ `ÓÐƨʹ¾ªH0KDŒh›ÔŒ)KpJk>¦Ã1@5@Ã뫎餪ÇiŸ8xØÄ꘱n!¾G óô\öȰ§öUæ ·š­˜ÿCÓ³&õÚE{ŸÅ“É˲¹£;Í>2údÁq *ƒÎ÷jÞ‹«}ö”*0»èpªœZ1_í–"ÓõL¢çžÈõÓÆlŠÃ­S…xíåá7‚?lY¾»^ø(þ î:ó¯5JœÅ.l^rJíû¿–˜ âî¾…xêU8ÛŠ1ÃÈÛûGYl,3q_ZØïÑo.jôWè¾Q/NÚbHùÉô‡×½¡Sý¸€{¾–¨3'ÛQÐB^E!Ë®¤‹h»}WËœÊqnq¨!Š#_`I ðX çp>ÇŒû£ùyõ²\épõ³›AÆf®’šC‘ž¤²ñ½¯ˆ>ÏÓ“žF †²ÀQ°„¤G\J‘Si¯³Ô%àœ6iÿëiJH'KLv˜*S…¿Âòús…GC‡ïÿŠˆ Çš2šîš žˆÅÍŸ'$Š¢•´l ¢ç¯>Ä[M;§ÚJγ(Kñ×tIƒòÅmYN|µÌ¦L«U^ {¥šÊÂY`b˜qF@õY”Ù-”Ùß"û¢Z` ‚Ó4½Y7$réºà}Ž91õíg¤Úó÷\šÓ¡0Òæ,Å͘`¯W¨| PÝàG‡B®èÊ”ík_c®lZ‹H»‰¤ÊÙå(ÆìÇй«¡9P| (h1¶ ËłֆT>¿Çq6,àM’Æë%^¹È‚=Â5WÝÞê¶ø¹Ÿgd£æœ*®—_¥Wõ`ƒ%¤\䟟•²¾ã|#`[ðº½í¸è¬Öp%É“؃´¢Þgk}a¶©ó 5AKÚÄÎDwÇYÈ # €KXöÞA6äÉäâEÙo5’…¤ö¹”<ÃÅQ 3éâËDWÑ‚ó%é¬ɲ{Óa¹9÷‰ãðýØéMˆ"  Óó*£&¯~Þ4÷*º†vTKBQE?ŠÒœ³TD5QáÄH—€¢LcKqkå 4þïæÖEDjàCqä÷`(ÉcÝyúc&6žÀÜŠtgL¦s‰÷,’®tðÄ%öæÕ¶¦ 3ý×|nφ|e OÖtÇ÷þ¼='&u@Œ¹xB‹dKbÞ³qåí±VöÐÐÐͦ‹}aª/ò¿“͈$"_ÿœdeLhÑtM·›˜Õ‹;æ¼ûoöMåVÜâ¸+úËòy¹—±ø{žYsë<óˆë ¶ÁLÚדð×xs‰æÉøMPv¡É:ð–\õÁò‹äY RøDäqÛõŠ=­ŽYõ‰3ìæš ìxÛ÷5æ >0˜Ð?ñ(QU5ä°U¸•aRm©­¼Gk{iD™Ø#ØÏ^½|{dÃY+RîÝWÝjZ@÷H³Æ‚ü(KØ]ÚãªU¯br¡“LЧÓÈÍ¥á£+®ØKø©dµ‚ Öó«Ã£ó‘¹>|Šù‹‚‘ÙA^õշ鸾§åâRÄèìÞ™s Q²dæ¦ÚùÙ>dakaZúÜaÅ…ŒsFÔM9y¡ÎŽKà]jÁטo¹±Ó‡-…¬N?X «áóuøfåÑÉz\ôÕó†q½¥ó†Í9qm¨ŽÌãHY¯‚ö„<ð$ÄüÉU<±f{xͬe·¶EµÆµ§Gúj>ÁŸ° ¥ƒÃvÌAar‘x.~±µ§M¹Ž)cÉÎiåçÓ’d¬rÔ.S»[¾ ݱ*.%;ëqàž¹z°ì!ž/X~OUÖªÓç·§}Þ—Ö¢ŒæØlö$%k[!óF½ưžO¡qn]±YH5cÇ&ð¥d0$zíEð¿nýÐðûFª¡)A­s’æôÁçÞ’8añ.{RkbùâxkÂuRB¿GXìü.´ È¢0‹¿»Õg 8WzÈݶ&”g‰ÜFpÔ·d3 @ŒbA9"ƒ¨fýRïm¡‘΄â¦XãiOpšÓa>jW ÌKXœ•ž-"ªEUË ÇÑÑ“ph1«®²E×À–z÷=wt¥Ã¼3(”Aß@ ðcw* 04SœQ:æóýr]¿2ÅÖÓ˽â¾ö+dšlûÎ{GŒÉŽ£GM7ôý„¯÷ÙU»õ)Ï/¤¡oP•çNÒÌÈYÐÔŽUŠPì~w¢KCù¤d‹RjžÐþZ²Ý–—ⓨgÂÞæJ A[£õfÕ¢”ìmÃJ4ý4ãÒ•‚I0DvK£~ f¤h.͌՘J¬hR,„;ãñ¨ÌÀ«M+YÀÓ‘ ¢.Â0©6¶°Êœ—]Øtú½ª‚Ýîù´hÚSbŒ5eÄu¾«|¥6Ÿ¢ ®EcEšð¡\@t“*Œ#WGÀtÌÿG=b:=̺··MÌĸºWr(‘cË•bª*n|}rŠ”IØ¡"glµ°ÂÇj´&f—­fŠçÚ’UÍ[Ù–.¹kÚú šò ön>ÞËBVÐlÿÄÒ½mŠ´°Û¹û› :ãÉ÷¹Èµ Î=¶ïÜ,ÜåVõèJïþhDuÔkUýïA<‘ðûDâJ:éaÆñšQZë˜<[Á0~ƒ®×"[’¾R½ÏtêM­D“¾f¦†ß<Ñ¡¶ºi~½HPÑCB»§/M‚9…v¿ìÉàXú¬aŽ ) §?“mÀíü)_îË`‚ÿüœKSSôŠPâŠØXüúL'6ÏFl•-áþ;’|Žex(–½ô­C•¹ ý”ü*ä¶ÕÒ˜ñþ(óF a¼¥B…M À¾›âܳ:u`× x0Äkæáüý;Èâß.ÝMÉ®. 3Grx>ë•——oÁÁiÇÏî˜"¼¾ÆÛûQàÅÒpÁW¿_u2|%²‡oÕÐæúÜ ›Ä¡º“ÑênÃìú¡sDÎÞÅÃ`iBB@?"@Ò5f£åj¾q‹ݰ›Lž–§ @5Ç«Ð5º¨¿I  Ðbµ´8"tÔÃ~ÖÍ…,-‰K‹±ÅC\²%\¹œ3›Ö?¸Sµ_pØf‡%;˜”?åŽÞl• úB2—Œ~Ì}j0Â(ÿ7Ú\î· tábïÿæA׉jí»t1«"Ξé;5ihãE?ÔdÕ¼‹µg¨‚üy™í ±ÞÒƒÝêÛoó14ß´°µ’’úé¨Ð*O‘y§ù&Ú™¶r$|u|=àóûö™.Y´ÈgžÿVì€Gpï]J®K«Šê€*±#ÝOHAÝ*¹‚rä‹iUÅ#Ÿk6álÕ æJíemf T€£Óc̰MaClóµêÐy¦×(/:W°²d(¥Lx_o§Œj±úÕ­NT{ª„X­0ʬæ„8l2inw¸‰•ûqjDÌžaÔbãS.+ÍÂ,Ç‹3}ȧå®bóÛƒ`GúJM&Ušºñqіü– n~ÈÁùæÏ€ SR Ü\ƒl~·B!ó?2Ã}I¸VK€óÂê)*ÕЊBʬŽ"“x±*¬†Çæ±Ñ–ÔV™å'ÈýºÄP¶€¤ß’øO!¤õ$ J±ŒsT&UdNè*”‘x1LÕyÌ£ê9TD>8Eùsðàx0{{Î gŸÁ¢B`ÅÂøònÈó¢ûl•äÝÒÎq‰!IéôÄüÃçùyoHä“„E›D“®ÓÌ5#—ñ*0 B—eSñRß3±Å„댫¸¼¢.ìÑ%ù„Ë“>œ’cÚ†HVSÌ~\öàOÅN¹1ÎX¹ÁÇH²ž*6è_äÒ—=c1ÍüÑZýL£;Wò¡^ú̺i«;˜Â`sJ†Á¶,|’Éݰ`3ç§cŠ‘#ö¡^‚Sá'"Rè¶P>„n€ïºÕ…ý³wÿLÅ3 òí§ð ÕÌÓÀkŽ­C^¯Ä^®¤Ö8 â^CwõZ¼í©¯‘ñåi¿ùRnʼn2;å|–-<¼¹Èó$p0%†>*ö -Á´ù·¡ÂÔ @ŒoæN‡s;zÁOeOÕèxF¿6‹Ê×vˆáAGÜ]|HLjÝôçeš—²x_½äÁ’@®–êßVe×½l>Í^!Oig¥ÒjV½×óä ™e†F]£ÕÄcµ7 ~ã_̸.JK_#ƒ’–ýôà©‚‘’ß„¯Aš']|AÇ l»ê“®/Ç{Åÿ<åï ‚ ×­|„âßR0 ÎyÅY@AÄöîÀ†˜äÙÊÛ—SOÙ6N®²ÂAȣȌ¿YôŒóà¶ÿ$hº'ÞØÿ¿š…õ¾Ö+æ@Kº£Í8ˆÍ¥Ôæy5Ö^˜Åí£…Í†lyrI|ÉÉBÓ‘®Á0W’)…IŒ§qÉÔînJ‰:ø3' ­øSÖ©ÚV?,wûÒ³ž ï‹Ë, 帧çK/eç_í =ÒYâyh‚.Ý£2šgm©óÛäÜÒõzçk“Ó¡IÀÔø!˜,Óô¡ÓÁäìÖSŠæÔp«4Š å¸2õ¨OGWJKõ5£|Ñþ/Õô‹c‘6OU€âÁ®•TO­a~ñÌTh BâJÈLqqúy/(¼ÇÖ3ÜGÊÍ#Ë 35"z,·úK22Ô= $ëb/Â]$eŒkäÂmR¦ þÇòÛ©}’›K,áß¶¹Ùs0(»UêTŽÖ™ù̘ÝyP YM(i…r—Õ2nöi3YÙ¨† Âçd¨b/œ¯÷ñóʇBëÈRðx¤Ü†ST^¡•F“e0^ ‘1—w¶î&aw×5¾Èr™±²qxå‘}¡6Aú¯®ú ÕH8<¤òý Á P)tîýy*<«KÚ ÒÜ.bD S7õ¨”Ì(ä=h´*(ÊÙh”£nSÒo1«©VAØ“¤é„IOø4•Pà?a×àÿßû‹±šb2Ýr'!gK‹Øn]X q9®‡.:Øaäg”š9ËÉ«IwíS›SEI`æ°ñøÕä³” í” 5b¿•¢WÏã~*¿åpì­_±ÂÉù° Àyýü¡hÔˆÙû&fcS}ç"a«äy3—д/ÈÌ’^vwu“¤ù†¦Uýý,¿-Cßš§|̃¢4²-¸¾\QdJótHdî7a|ú÷VÃÖ’¡€Û6Ù`]7™:]î;ϧÆßŽÇ€æV]iZ+ò2<ÚÆ=`¦“õ`ÿ4µ›²Ú(ï‘°}³BÞ8WQ!¦î¼ °_†Ùv{“²AÏ!¢ ½Ù-"êê}ü•;Š.›¦ð)$$øÄ`DFaíWÐ/L+S²,HF¢¼8@ûÓ6¯^Æšúd5_ßEìó¤7éÅú”»NM Õ\"Œ~Ô¦m6ƒ Ì%«Ô.‡›–8»óÎéJ'Â,*»y/‚†çCA Q™] •%.,Ö.i½)Ç´„†o#•àV¹V=A_d'qpeY†ƒp>š› Dg›‚këU¹Gm¸¸ÓP;!¥tàWŸ¡.þ1¶WÛ:ç±G\ßõÆœº‹˜yS7ãZË=sÇð#ÑáýŸëæÌ‰ Pöpø«ox(] ƒYN_I)úÕÙý$š£h.I'à9:ª£A&¨‹Ü¼íü>ŽΆ‰Â»ñðÆ‚ÿ¥‘—ˆ «íÆ<. œMé?û34 £l¸ÃK+mæ¦ç™ÏË6pf¯]éloåB|-mÿàÝÁ¯½ºÇ\ô1}ŒmsJÕ6C¿8`£íúTï`½"°›¯NÆ\"ò”‡½î¡(ÑS/̓Ý+`.6zæœØÃc~ê^öz¥‚ÿþîOê}¶ã$ê¥y„âxÊðmÇÝJ…¸ÈpÐ1ýä#Û [rÑ%"¿’Ø–æ2Üz 9,Îu•Æ?ãL£‹9tùߣœþá2ÊB¤u „õ¡}ËjѺMòáuÀ¡iáx#DÊúÅK]µš0Ô]B f˜+ò“é/h@R¾žËXÆbHƒ6{öÙ1Ñ9ÃÖGˆë½I  ƒ1Zy `¡T°O¤NÅŠ†,BQ.Ú.T4=+c]9»½‚FÌõ/)oí4FQÇÙ&‡¿<ô·e±ü_ëkª³'Æ‘§#Àáuä._C® O'UE$ŒD9ï‚laœéwújÖGë¡_U¯üˆ}²¤Û$X†è;›éJ¬—ÛAP ÷l÷ÓõÙõ Zsµý3k†[.ŠýÐÿ»LžPjêÍ'æxLá‹Øÿ¬¸5‡qiym5€'‚’l¨.œ@EîNö}ôØ¢|0í}jeµ{­Ó«GBu†ÔUíc˜å3‰^jY@ÁÖ) ¢¬-^7¡ö¬×‘@ðâã9ö›Õ—-ïãÚiÇYisDÖ©›ŸSô11 FÀï¥Õ ø=¸_`[ÛûØï å! “àõä™4På4ZÐT‹ÚˆS ÌÓ+¨gë6¢hÖrR¿åI(¹7‡ NÎ_¤³=Ó!uæZÔU‹¤VPš˜éVŠàδ2îi*¹lê]ÏøÏÅ<}VDzé)3›öe«¬sCò}<êg·‚Á5ÉFFX ;»¦`z¹ % J°ÿNaÅÈ"ãDî"ïël5‹]ö»õYÄrV²ÑÖ\â¿vuÔšên ôAbÑ”N¢%|«ªuÜM߉™ñ’á‹÷DùêμW¤EÓ~熠Ž&¼Zx´Ri^ÔQ( µ\;|z±"`¼Cà„$žì»OÖÔABÔ¤YK$¼ðÑø-.2ÆÉz !#¿;ðQJh i¹>¬ö ƒAR‰»¬ª¡þøæ*hVªK¿Kênlˆ.Ù”m‹—!QÝäîkµ>wÖ2ôãÌ8±WÕ²ýUã™yáÀya—lÆXrvúµBnP%¬ÏÍïnI† Zg;–ÏÃŽØ œ1tã‚Áæ½U“DÆ£Ç Ÿ®ñ%Œ°]}Ú6à‚쑌ÙaP’r+Oÿ©èˆ+Ppžã€*,¾¥t¾à—Úæô袰“d®ÖsÓ4¢8]0ãƒh:<©¿Ÿsùؾl½¯Í4ê›Åä÷¬¢ðÖòå¹ï´4j8β¶f2<:T0ô—Ä“XÖà•)ØGÀÓ+Þ^`9M¦ðÜdf“H!Ãhäÿw©ƒkî#&ÎâàdêM:'Õû Ì)•Pª«ê›Ø¥„…?Ædãâ"Šc{=Œ4ˆÃ±$¶™w¤Ðä-q¢@/õ6Å?‡ßWU±0Ú†Qn¯C®Þ92É{l,N)Äè­ËíÀþËô©cò9ª¡.×£)yì’îO¨³Wì©·t&×jWâñ(}ë.O^¹ç¦eÀ#,,_¦Ä"Yæ!<Œt¾i¯u,%XV-Öil›>=ÿ€œÝà²òxµ'8à.OV]WzSÖˆ›¯ÊcOûeÔžNÝVÊ:ž#ã/I IMr©§æHQ93ÚMÑÖ笤…¢[qÿAƒa]>g®á4ödn¶”¨-œ R|QVF^ÒrÀ%»¨%aæP r'± «gªòËÛàó5k‰.¤ÔG^‹@Õ3Åᑜp–R÷&­îg²óìæÎn9÷üu+–Reâƒ,X°Ô[ìPîf}+BîI¥Ó*+ÊÄ;–sŸ èJQ«ª7’rºld°HD«(žZv-›“ƒò5\…š¿¿Ùõ/è*ñ@Æ*Í›´Å&Í˲˜<*>ôçnÏëz©>W ¡õÃeŒ|=ª%ÝÅ-‰TgÆ·íª˜YM³ÃŒ!3&2åHx R]¿œ ÙP‹C¢ñ"CRè³° {Óµ„âÂ}A(Vw'ãÙûUKÀñá­iž‡±IÈèi¡ëXðÙq©PegéxXvWêœFçxßT’ôëCr*— <ãP¬ºÛž˜Y×t®nà‡W‹Ø|gs%h<›~4rŸäþƒ6zîÞ¾/™!3߸.>rV ζ¬t¨»qÕºšÛSÈ=âgäM+ÊÊû4ŒB=ùÚâ] ·Úh|00D*ãb ä2Û2v}äµ…ñǶ]·?­ÏžV¡£sÐR‘iÁ%o>ÿÜÉÒ± UõàØ,4–ðˆ“Ì<âºÐßÂü‡¯.&ŠD¬Sä€Â5&^Oðé Cÿt‚âm'0k—gTûg*Ñ¿°c-LÞ¯)1ø Ñ¼r§^†÷Òd€oö±äõH"hT–þ)1‰é£Y‚\‚8V#[~ 9K˧º`ípK–|^“5Üf+Ìn*óR^}É ~#ÄÔ¾r‰ݽúòñ>T˜IÍž÷a²®øìÝÉ#L®F`D~ƒøŽ…þi›1,2LÜ£ÚECéæ|4^éÖVÜäs'^û¸bí>™L¶dL¬™í£¤„Þb¬äl94̺ۂ‡dºE:šYO2Ý;–€Ý ‡bj%Uý€IñìœùYî‘f™4|¦¦@Zë9^ŸÆsMe<^Ä]ÿÊÕ˜<¡~tü^-ÃzH^ùJÃFFÏó†µM—©W6jV4Ù=KøõoK$#4>s¦Í䏸cB_µ@Ì’‹pv[“aú¾ás{Ž}í¨ý¹»¸[L@qq²yàü¨†$"ÔÈUŸ¡Dý¤’Žwðqæ¯; ¶Wät€mÌ£¹Þ–Piq*ØéG~dfô´b›C†ºR×¾T+°¤^ÔQ8zPŸlO[ÀQ¾"‹jZS~ÙL&õxÐWŠ=êÀP%ùϺè]á¸üoÙ‰çUg_TæXy¢êŨ{òþLwR¢ÙaQûïk¬cZ±› ÛIÈ>N¾ntr’µ"BÃÂ(}ÄÝÅ5­g˜yœšö~”àQWW’6wöõF¨öi‡1úÏ©EÐgx@ñpä„È|æ³¾×Ë×9ýÒ;I‰áÁаç¥â[¿ç<æžÖHÂŽUe<Ã6¢ðÎÿ˜TzÒ‘^aI¡Lá6à$å#ƒýþ}ùu…÷\.¦ÃÙREÚTvPçX…Qid|ßÍœ˜z¹m”˜@Œ¥›Û;Pb¤¶öXÅPk<+¡pþ*¥ëÛLÆÄ5fCâ~¨´ m?“ºQCê¨N ##•¢3×wzKp!ŸY­IÊ}Ës"øÎ0‰ÅÔƒêžWOåpÄU´³°œ^Yõ™:¶ñ7á)‘¾RUåããŽr*ÛŒû›¸þ LjR14d“Ì2TvzúO)ê­»ùpr K¾()4fB6 1M²uçÀ'¤ÝZhòTI£¦s’†la­B/ë }2:ñ€ŒAî*v™çíÙákBÔF=œa_îDµ}P–þ#óïwCôßoäùÞê9én%=IJm˜«(ê¸@'ÄP OÅ2ë.óƒ ~&Â}ÿþŒÚÄQV”8 ¿³v¬p’ÜlÉŒGÝÆ‘tíæ¸";'°šÅTq ùöºá>ë¼ ‚2r»®b:Ö¥O5ó"ëïe×+éá]•D1U«ž¸~Äý¤Dn•ÜÐddOGÃÉMîÕˆo¯Š‹A2ÓÌÅ.þt¦ÎQŠÏÆâê;éŠÑS¢ëP¥lЪ˜80«ÞO4C‹`?òkE8¢f¸ùÑBÑcð"|b«øWê( ¸–kÊ…OÞX6ÜSUê8_áF¥ê޼ú mN&W‘¦Böâq$"^µ¸vÈõ5ÞºR¯µ¦çü+‡"ÛÊÙ&¶™n»ERŦÖu=š+›|>6P}i'b{À(’<`ÈT¸õÐÎ ÒË>h*Àïb©GîC%|½äT€rm‹sCl‚ೡQ…U)n¼~8ä!·ÞûoPN;ë°)2Ê6 hóMØÁˆçŽ50lYu,Ïáläøä 7@ E”ñhËX iS°0¢-Ãú-—e;6ÂŒô³oŽÙüÇ¡w(¨ðwk¦Bƒ³@0Á=œb]ÜjÏW^ÌíŸÈr{5pÿônbž$!¤ÖÅ f$÷/ô|)™´áâÀ0¶á~ќɗŠ^oÄ ÔÉ£#'˜QîÖ~]ê5wJ¾`3fÇЊpP =Œ®ÖFÙ´ñÀæÖ[3b.ÃÄ„¨ˆº&¯x·?àá9ˆ…ÆŸÿi¤uó7Ã#v^ü°™¨«+L¾pÎoû½QÃʼ¯QcŸÐ{k¢Wip;Y„ÏG”§B¸5±»ëÁÞDh?®ªjWLL`7ë’È#2å8HúÑþ;Ù+à.·‘‹OšjÁ}½4·0zVæÅyÚ‚+@Ç #¼­ëd‹:m®Ω³×øèÛžL)Ýž´òÖ|Š2G¯˜†#|]] }€±<å^ÜÃ2ÒžöræAü~—ÂåGïè§Ð¯‰ˆ’TdâÁ\a £at†¤dŠò¶ ¦›-€;cYEµ¹û.£¡óxc&®oa;€­‹™-¾qö> æ!óBòâF•Kcߺ«&Ÿeƒ4^‡ª_–ÞæUÓj  ë1™J xó¥ñ°ô™ÎÔ£{í5Š]‹ \$LlØûœµ§N%=¸¯ÃøìLºyC·¨e¸·Œ"® ÚèQÌCÀ/lôÒSU†ê_Ûå•SSú÷Ó8ªÈÂ7‰ÆËä ep0È’»>Ó±R®Ó”¸æÇÜjìM¨u'g!µ­NA[yßõ¡gí*¿ÿ\“¢Á‹íĽ®$S|¢‰Xüc74„À9bÒfY>FTҹђъBšÃ£få7fèý€ŠÔ­œègÇ’‘5‹]!`èà}Ýþ÷ÝÀs-Î{ð.V¶¯Ü­ð™§QB6æÙm"WÔºQµV x@ßégd0‚œ¬A'ü²p²†NןˆÎ(¨RÈGþò!ËýÝ=ßB0]MEoÌy»^1/–ɹÄe¬þo&&Ç˜Ý »ÁòI—Vü r d•vdz· ¿FÆ=º'í¥‰»k|ß Øñç¼hƒ5˜ß8/v‹@AŒùP¸†1ÙÆM}“<¯8po `>š††Ú7ZÀБxbJ|ÑS€¸ÈOèîC©!À´nE}E¯ìŽnÙä&WáR¦&ÅÖ±7 ¿‹á°© ÆsÈjxI½@+à/F©Í-Ç»7§Ò\çi/ÑV3x ³ Û“™Žøæ”Ë€ ¸ˆ0R«üÌ"õ4é'Xö4œÌ\|ê‹%×$}‘‡pØ,Þölæ‘«·ÍP{'Ü'9Shg·Ö s7³™[ 5ãfcÏ$ôs­ý%,F»p÷G)¾B,ìwR¢·ì–[<`ŸÇXˆ³×Og‹æ² )Tâ‰OspJì-’o‘áŠ#ë;åvZf‰ÿƒÍ%ì’ßúYq¸g§m:R½»:gíøË¼ß †ÂÛŠU"ü:éžÅ›Ìu–Ø:ÏÖó¼ÍvßW«n.07³Ô±äKÅh† Íw¶ê7N)k=ÌjÁœe°xëÔuMÈÌMNßÙ[Ø‚ ÁY® #@Z)†^§3¢ïcÝ¥ l¥B ¤ksp?‹{ùÁl¶æ»7’€ÐpCŽ~`Wœ$zßHËÈœE•.Á?21Eí¤õ§¨™n©ÇÚï"ó ŽlÚæd;s Fê&Á8ΊA,ÚR‰‰Ôp+®»6‡­ ƒküÄÆ*¡¾ îŒ£Õ Ä®MVc!@²Äœ3NAY)y¶t周氋i&É•äl&éeç×h°‚l¥÷JSM¾i¶ƒ×îxëŽÀe=Õ\Ž£¨ÜÃ[@3üÚX˜; X-†MX]ÍC42Àåã P$CÏxÔ–Ãòc“V¯ÄZ¬QÆÓrTœfl"‡ÄTìnÇ „¿»ÙªzJÜä†Aà ·18æc%þ'rqFè*Í›>“Ò§:±¯¯j`b6‰QɈ¦¨d§i—푳œêG²Á—'-æTMØ8}ohÆEúħO" þò¬†´Üá¾B_HjÇŒ:¶Î÷ ´³I¾\äM®Ü˜³sz’ÝÙ'#㥠¹;Áq¶¨£«Å‘wìþX•¿ø3Sy.ä§áP49°9DNÌKOb”•L3ë¶zz|eLo¨l @øÒÅbcÂ4DIt´ÆGzwÓ8Ë;lø,ü»¡ ‹ld)vÎ/³OÏ£Ll(ÍK†ò6Êò¤«B4QŒÃÛép9®¤cLox{ëCrA¸™Ó‡Ùïžœ19Ñ­ÒRO3»‚m¼ƒÒÈz²âh-Óž¾ã¤Àõ\ B‡¯ØŠL¨#ÑÛÓ8ú88ýÉü@˜«»Ujx Þ)°)¾¶&[FÕµ\l\‡y|~Õ7p}ÎÊNwÀl/z ä9OË€i¾û¡K…Êì3þ»ž ’˜¶|kRÏ©ÉÎIÒD–À/¾¬ò¢[Ä7oȰ'¸¬íAîÃ,„1¾¬Þ¿dÙ¨ÐpеbÏ¡í,)sÖ¾?¡éuô¥nCìxêég3oiDóûµûÕË ´R§$dþè¹ä¼6®[Üê¿¡>îm1Ekí~¿»²N²ÈˆH%)Çf Å­¶p".}Öà–뛥g¡øó.Ð/¸¹eJ£zê×/ã„&q<î×ó…Ø¿O'NOáYpݽ€åßN&fÖB¿©ÌÜÇ º'IçÓK²Ü ZñÀ­‹Ê&Ëà¸S}Zƒ•oìÈ;å«dl×&£ôAï58:&vt³šEª³¡KOìíÆ-Ͼ3Ýr"ûÅÛœ:ã]ÎÍ8( ¨Ñ"·\Zæ²é»•Ö®¢—z²:@âžëí%ç‘ßè§ñ RôúšnB+ž[/Ө˪䭭,¹¤ÁûÙ[¹ðR³xƒ\,‚PÉ·X¿R¿yõf5·MªÌTä2)¡wü¸ýnæØ³Âœ¡)q½^ºB%ò8Œ#”ƒõqnà.">³=Àµ¢rÿBئ'Dò¥—ȇ¥l6f²Ì¡”oQWÎÇÆí½(4Ö°ž½ÁËà èð"Ó=§çHX+B‚2­]H7èŒyÆ$—é¥s»P;ϳò|üs- @ü›`«7¦YÑT0„aJ†ûüŒ‚›mIàRûg3ËIOâ,d &ÝP´‚ëeî¾ý/&^S‘€4ï=‡€}Y£ÜXìò»Ás”³5J¢à·¦d{¸äPÇÓ@œØ.?(§·àóÖ°üjey-ݑҳWĸ1ɪ{†âé#o¥r·:_šÇ¶ïMÏköÀö÷Xð÷óº×m"¨^žöÙŸê@δ Ü&õyë>ú£)KѺ%Ì,¥Õ! EiQ´àµÎ¨ïLY.N˜ˆ4©ÓsƸqŽÛ”ÏÞè$h¬B†;Òà"¼R™îRÄÿÒêG;ÀÚèR”ø”ÐQÑ]‡Jèx™2bä-@ó¼k ±ös¿ùÛµ™d¤bº¬¢¾MŽ¡mÆÍ¥ÀòÃl©îã¢2¨DÈ[`ÎmŸ 9£ol¨kO;7®ƒðÉñ§…Ðöï©ÝBq¡º—/*³~ c!AöUlmN::Z˜o0ópsúyÎòb‰påæÓ„k-[ 2GÌ]… ÿ¿Vöíš0¦qÿS$Ÿ´µ­§ùjRíñuéC(?7äx ©Ægz÷&G˜Üð°ènàCö: D ²Èr/{ŽÉ¿íß|;¹9L… §Þ«£…%ô ¹Í{˜Í&úBÐÖH,G=t¸=+¥ærd÷³©Æ¸%Þ~þMuwÂc&ö¯’—Ò‹µÃ)¶„rF$"  !ÏPòÀÇ1ÝÈ8¥h‹þàÄ!ýRƒS¨ãÀq»¢*Yµ· ácñ({£'¨–îO* A“ëA¼à\rµÊöɏЮ·Bí°×ÕW UôêAßÿYnwìjä§-ëØ”ÚTûd휭 Ùèë KˆÀ-E>ôÞÓxcê‚Ô½ónºƒl6³Ôš«H7Èbå5’BÜ;Še­ñ¼-Dlo ¢Nm?G.ðQ ØæqݦbÎQö®µ“bËÜ«=îœõ½-qâUÕxÓ£E‚âìÎ%ä¡à\¿„0a䣠­ Ùš{é Ð ¬ÝÄÑ.5çËI ºE²¥Zñ¸žã¹ÏeÈ-1ÿhÉ‚õ'Åk…­ S‹×¼å Ï‘^™LeÉjSêP2¤Ü㿬êßêTÞ>H›cSGÞ›ÜoìõAžøì€w¾ÔA-]FdFÕ”5©)|ÂØÈ8ÇÒ;+TÖ®› ‡7ÈY9Ðÿ¯ÆAŒ±k%èÁìr\Z3O;gW_®A^F3h¡Ü !q¿n,â ÍîçEÙÛô+î ¿iŒÂòÔxær´ž¦:Ï[÷âÏ–3Yÿó)ýõ¤dpG7—?Æ~;óõ[Ìü<e¥GÖàcCZ©õ,Ÿ$vˆÁ殼0ò"c@ND^ø˜6ïLMÄ5ØthA±MíÔ—i:~ k;Í[_Õ–‹¦h×"ÛHÿø­µ[Ýt?&Ušä vÓl±ÛøÔ+ôß1ï¾é¹š |æºNøÌ¢ç–mK.åDAýKmÉÿRíø1¼àŸðlÌÍ\¸ãëÔ’>TWW =×>¿Ñ»©a9ˆÚþø«o¨™ìDÌžô =ûô£SUÂ(›ö,ÊÓ|Pq,‘ÆùæQÀ#h¨|Ñv 8˜=•½{nÒ>ÆÅÌ ×Â!Ä[scN§ë¾‹F€îû|Ð4S¹'Z´k¯.µ lj²=ÑKç›åaG ‹Ô‹&b¶¶xsà‰)¾ !¯ÚÈZLÚW·µ°[hÑõ/d–UV(‰[›QG!ÙznQ¼˜þþ2yÕraDÍ{uÓÝè]äÀ։ɗÁªö-å*@Ð~ ˆÒRã'm àÔ`‰OHú´òý.ô‹kОõ°ªôóŠAúØÙ­ä‹ëœú¨2É'ð9?o)‡Â´~ÙîÒe¢.‡*Üüzš€È&m3IÒùTíwDTaR˜•{°V©¾ð ;à3 àqIñˆ•Þx[1Zv<òH¥{(åZL4¾ß¡”}ƒo'Ñ…î~%Õ%Ë#C0Ãb°Ûîà_ÒLgrLz•ÞB×¢Ÿ v;$)ò_dzsÞ |4³X<]¾/·Âc®Ã¸ÉÂX'£;KDî5U ,¸–^„}!§Dõvf×#Ÿíã|Ú/’̤ż@³þ~é`ÅTû¬oô8?Ú8·"ÎÖMí|œ¹YePˆG¯ó$6œ<3£q°Ð0Q ÛÎbÙå~ÙB IŠP2”½Àd”8{’}¯9"xVŒY"-S”7* ”½Îb$S›#žƒÖ$¦)+ϵò¶,)ggåÝïßR8'›Ž”æ0„Íá‚ëv~ž8ÈGKÈàÓ¦˜á7 ãî ä¯5ŸJŒlAµÒNåžFºÅlŠ{Y06¸v_ž%Û¸$·LsÌy0Àóþ5í Ž,mYž!yxá/z¨ÕÑ6Ià%æå§7,RqÅFT‡‘ˆ|:“c]Âf/Õ!G +ògñ_!ÖÿÃÎ H²ÝÝ9âçûS}²Ât¦ÃÀ`qÇ–Ö|l¡¥ ÷]v¢ÇIfzçêÚ´ãk*gE€¡Àù‚µîÓ” cÆÎ]Ã9Û$Vȉ‚ê(õ³²QÌJ,WbKÇ› UÆBW_Þ ¾ùþf!¢çÎA=ñ5Ðý]x©‡ŒpчãJ”gE»¸1Irj³¢(´ìÕ4QRžQ,B=.˜f{fÛ£ ð«$v.Lj%6nÿÿ†p·ã0`·¢ÁÚˆ;&¶—Œuƒ¤SáïšÅE&žaöðsb$ÉàÀyàaµl@wzŽº\lå‚;9ùØñ‹Õãnt@»ïùé4ã¶r¯óCº”­*B9õ¹ý¼_ר<é‹È–ƒùÜrž/+8Z:Y`Óûš3ÓV9S‰RZm»²yhxŽñw”[@7%ÂÄ–Bä‚–žM†Á ïT >Ü Êÿ.’U†3b¯Å9»ÄÁ‚ŒYº¹‹Ó|,ÌaéOš¦=Öï­§43\©.ZË6æèQá£\Šø%U©ÔÍ¿ Ñ¿ý…¹ÙÖGƒK.§Ým˜‰DÔ#q·ëV¢‡;ìöŸƒ(÷'±·•@r6#`Ìaš€Á2± 3ŸEÝF¼·¤6‘?µÂÆ›ÕÐÆª@õÞïÙÏÊtE‚¡²ÅøXÍg'7 X¼áîu/å”Hº†n8+Sû}DÞÑG”õ,øxLAîí?¨ ¹MŠ»ìÈL›õµQo‹…Ä[\ï¡~å*üd©Àl£ TØ%;×[ÂÍuTÖ»šVy˜Ä÷bwêŽÚ^ò,‚q¶ŠB‰S]]P»5£éÊé¶zèñ·Áy_P}ºñiîvw· CÄHWÖPª«4MbÒJôl%o(]yK~J!^JŒ(}0-™Àÿ‘¸zårBb¥Od «Ã96v5õÔOãœ2¸ïb_•Çã̤÷ew.7ŒPÖ*›\ñƒ®O]ÓÏÖ¤n×/•ºÂÁ.þwÐŒZ¥+š/þòòbs­ô›ü«œƒVö‚; âþLN¦±ní"0–¬"¹Hpš6ÈJ¤ê%´ÂåmòÊXɂߠnÑÁõ£Sí ?‘—!ëOì¶ý"PUSI” _µ/3Ž-Áx‹âOþdÞ$X)çfMá÷Š·f¢îBî°ßv æªu/ZZQô:v­Ô×Ð÷ ²tÊ|`í Éø^Ë$ÿç|;»•£~ç6ï[Séá›±c¤ Ž˜.5ÂTÍ(ö/`Ün¸ ¤*!ºæ[%;Pá€; HãÄ„ÐÙj°}³{'±¶ ' éËún¡ëžT—VtænîÌ9îŽ „y°t×€Ê#‡â;ÅÐf¶À4Ì3 …æÚ„[F0ýßî‡Õ ;Ô˜Ýí ¼‹ÆM ’‚KôE3a pûËí¶M¯ùžÔqÛíÏ‘Ö4-}b¡¾qQ¨¡‘óЧnk^÷[Ú⣃yäµk~¸_Ès tmº¹%3 Èîå²"¯ÃSUýa²$åi­O.×Ç‘ç¥_M™±êv]M’µ-×b²¥_cÇ{L£™­ë‹…®ë‰ˆDQ{Ç ì¯}1íØ¥gø’võô<³eÈäÕ®1›×(¯õÍêÑÈt¹} g7˜àˆJÆ@­húNÜ‘…}í•P½Ÿj sÿßúxEIΫSá!möµÙûµ€ñ}Ö{ ¥"!d+¢¨sˇÝ"¢ÊCP^(c–®Gž¬»ÜÌ9H±œu®ÞËsǸgh8ÓþèJ‡1ô•¨š ˜x€ôØQ_gtÛãµÒÃÉL§¹8‰1‡`ü£+f’9á¨ö[ΪçsuÛ’=ô€œÑa–pb÷ZLÀ·­·ÛÓ*" ŸÀvûy~e‰-®Žra|‰é¥½Ûj·‹•¡N‘+¶‚»ÆÜ/bA¤î MAœú ó­IUv˜`¯£^ʽÖÓ í6àóeLéìL½ÿÉÑOÖײ3?øç€!7 jó1’}mz/;üK@’B*S³fq¤¦ÎŒõ5Øušc{‘[`Z«(QQ¤rư¾ŠYÇ z‘Z µ¦Å¿ŽgÚe3y7⠬eޏ”uxHP¼œ`­o޾"8×&7.Õçk'+WúÙkaÍ çÚÎJ ¸û~jÃî·ŸÐäi‹GBS:Gó»Ø*­¾C;CÔ,¼)¯GÅ7 vòcáÈúøÁØ<¶KÖVhÖîX®—F§›[RO&Z,ðÁóÿT¦BýB¡Ÿ´Ç•ó¯óª€V@ l¸ñB%n‡ƒoíaO§×¥Ü Ÿ‹ÀÙ{»#r`¦VÙ깜oÜÞk3¸ÕÐ}tí·É|‘šÂ hÌ@hËJáÅ^„ò›cïÄhU­S¥`ñÁâST$íMâ0Xëõ¢€ð ýâKÞÕ0Ó×~ñ<¿P°)ýÞ­W¤~éÖð˜ÕF êµ–þ²·^QƒÃÇ8¦|b"—`\ónÙˆÎÅžßÍg¿Mމ¼.i«ÇÛ¯ûfœíüÈmâPÒq‚Ÿ*_Oª‚ÿ!F2¯i=bnJÊVµÑ²‹§^ïñ—¶…Ä÷~Ì•ü™Ãª»ì†©$Np02’zZue-å­nÐlð|ÍÔ¥¬pø_Ï{óÆ÷2Șl¼í‚tQX šr÷¯»ÊÂg‘¤Í¢´±sM‚+7ò£¢l˜Ñ¨ñÔºG´[F÷”[YNeN§óáwH~Àä/ƒïtË #µÚY ´Ù8­iY\ˆÇêÌb|í&ã¹ÑÿGPd‰½b ¥ë[îAR e!Öi¥¨ÒýÛK3ã0È|åýÂËÔ0H£)Á똺Iì“êÙI\ýš¨ÚBMoÜt|7Nî3c÷B S+T|ö; =yGËÎT2?Ò|‘]‘ÍèÅ…JÏÆ¦(Iòc\xÀI”༠“)Äݪ!J˜ÐB¥Z"À¥¸ê¬ÀilÑCQµ¼•UbšÎ¬/q*? ¥£˜ —v÷;©Âßtºn <öuÛ¬!Z…Ll”)ÀR­¦ R¢(uªÀò¸Ñi 0‘S[E"T’ËëS{djj\¯›ß/ô¸¤¨{Œ¼‹ÛÕ°J¬?ÐCpu[ÕjLBg{]슀ÓaOÚüY~~Q ˜…FW#±c”EÀ¦žÇj¼Çê©&rÐ_®ið½ÀoO°þŽ&yvÿˆ¸±§q§Š°=wi»²}]ÙWo\ó™2ب ½5œa£èªw¦ðäÈѽƒ6L¬ø8/pi7чö&ÆŽlõ—èøç_­Rj’½ÙçŽçZl‚È4kÒÃÈl4^™Çp;b126*୞ɀ^×Q¹ã¡þÒž¸åÞGàªâ†/Oc îÀ±gCË ðg *çìÎÓ@ú!ã i™/¥Eðªoº›·%¸M‹Ÿ1J’êÅíJnë-Óˆ€Ì!£nž}›åïYÄr7GŒ¤ãáCw¬+b™¦¸1iú3%ç;aw‚Å;Ô˳'(ÇáÚ ™¯’ŒVGDÑk}½/q#@P­„›Ëþ(ë-œJ»<.Ü 3°“ßãaµaç¥Qÿ8½´#nR+¿ õp*Ë ³(§Fêºð&B9*9ÂÃi?¯Š©²t+Ž{ ö•[i¼€ Æ„±gèƒHö´´ìÚh9=Ÿj‡]x?`shQÁ³Ñ*þuέ̞ëùÞtË%¸ðèɬÏ¡õWZþ‚dR²VzÚIÄ(õŽ& —É| ׎m³ÛOžG/ñ¥Ïð÷Ê9Kƒ[ã±|iÓªòø8’¸ó)§‰ÊÐÜÍ“ˆUƾ›TQÄ",îZv>AÊjí Æ®Q;6°7‹¥ÝP$¼‚n&;À’ºF[+ò¯¥L÷¤úÍ©FxBJtd®e rÍÚR“”È àØÌû~õúxóá=ÒC›F'ïô·´(˜ªë¢Iwûýuî“΢n<Ù*áϲ:ûÚR9¨Š ÆœýÌÁ´Ð”Ö 81 4¢ ;€µÜû§º–}ht¤£s+¿,¥Ä.à퀫(Ješõ«Rk´c,LŒ6A6\cÃ9î뭘ͫ˜5Wø8¤›i_ÙÏzÅ¡f5mH.€Aì¶™¾skÊž ³:ä ÷\ºi:X¡H>³2-¡gå¾tÖOA­«#{%¾6¤@ág™"÷¸âE¨Ênqa uÎó9þKÖœ$³•1«‰²ZTÇQ?Ά· HäÄä ˆz  r "à±¢ÐÅšå®ïÁjf£æÛkË‚oôYÖi©TDÒ2Â~þJÖ™¡ó·¡9µK¸£+·‡cQ×ež0Tê»Á+åJÒ=æ÷G¯Iâ:¨eƒ W9mý0NYcdÕÚ¾^Ön¹‡¸ çºèŽÆkr§YÕ »ÒØkNµLƒ¸Qúi›;r𰿯¢†ïc“•òUÃr/“Øo`J-²ÑÃ×È“ /ê9O]–§Yó`råîqxwÖx(Š%ºÕ®œòn2i~;ýõj¨§§££tý—góõZaS0*Ü’uÕûa¬š~sKH0kˆÎzRäsEfúAW¼n‚Ü=­•88‡¢¼8v÷‹ æSoÓìyøàC.vÅtáÏ>b¶k—Ÿ1IÜ#mÖ);7¥bB»­+zCÙg¹¡&êUâ ˆoæ¦PZÝodçlßPBΚ ê€Ê÷±k¸D¡hë»}|0‰—N2©ûÎuÊ iæûþ >Q%«¤¬{d–ËÙHVxßý‡(ÒnSF#ö¹>CÇ ŠëBúLgùw!õ{žê&-˜oºÝ)U™­ê{2Y òð©ñ¾?t«Gɾœ$ó¯FCÏ–ž=â¶›U!!ù;ÄOey—´Öð§õÁC/’:<¿Ûî´;‘WN¿„;}U×-°°+,É #áÒúe-îúÑäëÇñ¸©ºÎT^Üì½X‘)C"ÓÏ©?Ÿwêã??šÐÄÄÆÛ8òû!Pó¾ÔÝ;50 SqšâŽÙR˜ÆÈWì öÒŒVãBi¡7ƒ²ýÓxT†ÆõƒRãSÔ°hq¡ âKF<׋nÛháwù=6îC|¸e©Ð iZ`®;}øÀsP9‘Çΰäšã>bí,G_Iü‰Ð¼Ö'š±YÌÝ 7ˆŠ¢žÒœ#ëXG–µûûÖ¤Øl™OŸ¬ù¾góI™7¢ê}äË”}cñ¾_‰` Nˆ5*æÈrdþkcFY@®¾vÿ¹,ÉØá.J©Ù,jéˆpžédn>ÌžÝ >ˆæT¸Bœ˜‰P–ü¾FMð`k¤U§„Wõá$ûVx„e9%ì–Ž¥ƒ'îŒùG<ó©TžG¨´ëyž·JÀŸ“z\†ø4j¯µi «y ÝSXf¾¶• Z¡H‚mŒè4·Þ¯›ž¦}G|º9Ù¹çÍ“Lïémüsžô¹ø&m‚Oê¡IðÞR+¬ÍºCªZkÕá‚t^…(l¬P4jz.Gɾ5¼Ä NÉ›Y6ó¯ê)±SOO¹+^j„íi*ÀÖMŠ­q8–·E˜9âø“ð±&ÝåÓž`y¦A™eWÄ…¹Ú‘ÛF!¸%‘ëô3 šÃ<°ÓÎl#ÞCcö$΃x‹+BÏR {µÿ}”ãTܳ´Ý¹8Uc]yá"^ܵ¹8ìYV¹²Ü¢+irs, ¨¾”7iâÄìâÌtmɬ ó÷Vx_¨£÷¿éf ÔÈ7uš#)‰(ܪô(û·ßÿ§fWttJO—èÕ‹RP}½JÐEÈgZ6•yÔÖ£Ä]ô çù”…ÙÓmú¹ ™Pu–PG]ƒ:Ðõÿ"Œÿ†¥Þêe79ûÈð÷zΪ`¡cû_S¤7]I Š€U}ñ Dõº_ÝS`"äûx…£úi9büÎûoWç\^I&ËBRP=öÜå\o^屸™c®}¡jè ïZ²ºë™ö˜]½ŠÈÄV•5oÅDÔ¬cU"«Í³x†eb—?K fV %á`ìùvÐïÙü-|ÁÙŒ3ÔýhÒ‰äH›îÒùA3-Z`ÖÛ$È8©´í7¨fÖô­ç æ#y#­|—«¬ŸmªKjL¹ñ³Úis°ñ½NÜÔ€,]&…Ãꉿéß5eŸ1é [П@{ítN¹¼Ü1³±£×!À½…‡‘C|zI'ãòEÞvßDÒVî³gÓüæ,F¿_žüPeøL¼cÕNÍ¿i¶ÌYü‘³:fÿU¹ª=f^“W[x†Ù›1«5×çö5û­o¿•."¸CŦ‡W¯w%Еÿ,$ =ûñ|ÜÜ|ÝY²ë E@B…§ÒŸš°/ÉO™˜Ÿ}µÑ'åF›E"ÄŒþP;ÞÔ—1!4‘q?Á²XÂÿµ–/E653 ®¥Oj†‡¡òž=YÖ;:ºí¢ç†¾‘)(›—ꊡêP¯D¾¾⤮Y©ú™Œ7hâ¢|ÊObéEâÈs½ìQoØÀ×#Ó¤äÇFÏT6aÃÔTŽ$-Ó`2U6µ¸ŽcœLúàÄæÂ¡‘¨ž¬Î9y%áÙå¼ApU{–Í–{-ßîP¶5£Ý¨Ô6àÔÅ`RÁ/ñ¼ `ÓÈ¥vQè½W¬ÝbíƒÆÙçWÒ[kkfºÜŒðTiSyzàÜ’Z£çŒäœõiiR<¤Ù§v”u‚}0g„¯7Kç,ò˜mVÅ&ø†û€2AcJMÒycƒÜèLôÀûOAtÎ8K Yæ¿´ó«o.+]§rãýýn]C’´+s'µGrÒm(¥{ à§Þ–ü¶ÅƒáoGˆ¹8߀“%²¢Æ@æ~Ï4ßÓ‡ØÒ›RbMI% ¸âd'/ÿ#k 7”’ªq<`õ7‘€z*óh­‰Œ“‹ÿQŽ#]wû¨—]îoÄ¢ÙtÝÕŒBfï{l8–ÂÃúë‰Óv :ÄftÁ{éè~ ÂõÌHtû "øpÈñ#í ;;f<òDf“rí3Tâ\E<+r²$ɳ)Èê¥u%yÎQÛižwÝ# 죉˨¾øM¸°{3Ýç¯ÉS¼ö&Æd@‹:“Í÷YAt<:ƒ„ÜÓÃLy76n˜0zÌ?usGJ #ÁåÛæ{Ÿýˆ6ЖǮ­û¡ÊŸÖ±´Šñ5ÃC~ ÑjU‡Ç´§dñ€Ò0„¯Uí¤²=ÞxÞ€YƒgëoöR³"b?XG¿‹důð$PºzrUL³Móìµ:õ*.RhÀ éíÛ›‡•o±uÛæÔb•¡Äý⑇*à18sŸ>çž*nžEa»wýÇËX)‘8tkiày:Ô¥35 œ@ØÄ¢)ù„ùjuÓ’»}Û¹c~VÝì dsV.Ò•ý¶m*xÔº> ¨ á]ívû†Á°ð•]Ì©z”óyH0©†m`žüìŽíMþ˜Dãi„“ã0wL6tͬ–Ï ·Wˆ¥÷ÝBy^4d¸Ë·` SÕj5[åö|R{ärL3÷} h༥CÃ'¿g©tj[ãÝÉ9Ú¤hjÖ3ªè†x»)6…!(€ô2>(ÁÆ ½atVd±I™Dûù~‘Ý oÑу(°Ål?îˆA`ÙŠ6K›‹kï±Yvÿ-ëTs±Ë£s™‚³l%ÐÅI+ƒPc\®Ïiát¬´ØóÖ£ >j¥8ï]RP€ZVSe³(O…R”ÄüÏ—ü׫¢H½?“¶£°’r§`^ ý4k,:"½öàL1)!Þ;íICü ¯ì:šíŸþßRbî€ÎJæN–U娻ò¥Ý3IõgÕé+¸©Ö]hÖÎ5Áã,i [Eò`gÀƒDó¤3Tëô¯®†mße„Ï´vUî¤~~®¾&LnSäàB¬=‘– ÓÔŒ‚Ô´Õ…q1œV·‰BƬ^™lã+[kòóyѵ MH§S ÆGŇÇÉP“[Œ·’p J` c^´ŠFB°»ÆÑoXˆøP5Ý2¿Ðzó 3…üÜ. žkÅF”âUVÆ~1°¢I!œ èlþAe1ÅQ®q«ú%"öPðš“I)'sWîú.KR%¦ ÃY-t²^D)¥3ï¼9ùâ¡»³„Cõ]ñ£Mõþá&:R)@Ûšò„„­;Coìóm³¤ u7ë*dš0‡}Ÿz?_ÉÄm¤¿ÆSÙ‰^SÜbMtWRYÉŸ2lüp:X”&&´]àE5ìâùøòa»ÜáHý3Aý}Š|UAhJ·%†‡U0ò qëÑOÓ2!Á$år-˜ Êt·„Ûò/1«Ü hù IÏa¼@m„7 Ž+ŠÎ_5ûYÙ¶›¹Š’d“o›Œ“ó®K¬^CuK6ͱ ˜㻤~aâañÎø`^u…p×SÉoŽô%/Ž¬Î»Í²Î ¯]Ríc²ù h­öÔnä”eé¸OV•0¬‰±ëƒ­ß òoõeýx…p&B©ýüï<@Ñ÷oò¹? jU‡s¬€kß …{Šñ‰žqãn%ÎQCà{«¨€FK*hrA¾È’`Á _D­#Û´AI=•@2_j¹z?K¯0e ðWòÕa éÞfõð¤döêçóå¥Jñ˜ªÌøIå(¤kañ ³yÜñYŠ'Y8cÁ¿ª€žn*]ÞŸ]A¨rµvº=c·(7[°‹•æRÕÑœ\[Úbþ‡ßtÌ‹"æçÔÖj¼…Ê~Áš±S}ý¼þ»6L«±i§Õö§¨¾FÃÚÇǸä[vµËr²á,âüªüÑãîÚS hƒ_f­W2q]d¢7Ìv”)i‘ÚtðQ1Q¡Tæ2yc¼QÊUP(¼¡fKJAñôUrM[0'³ŸËŠ%)Êteôûà«8,)P* ñ/á‡ÜlYÀ‰Ð“溭w"ŒY¡UxÃ~Ì@Â.›á$† ˆ ¸gæ"¢›°h 5 ›ZOŽFP[ü{γpßOòFÞ¥òkhçëèTäí~`6Ç*¸ºÔ—žqse1bv_$mF1.zZI>­ ‚MËö:†Š­£ºnÈ· Wž1‚ÿ†z»GI^§ë¨ê*…ö«> ˆ%A–%bT2çɰvGѱé´fÛ$Š›Y`»ú"*™ŒïCåüÒ 'ì‘‹”ÅŸ èK4 ëM¼Ôp5Õi@õ³PàŒSYæ7\“ÝÄVV’}0F§»˜ÈÍœ»—ïn¬©ÊaQíc’§ßcn:¿FHå 'Ýo¬Þqç ŠùîÅÆTÀNÅb.¡n┯ékwøCão^qø¿Øà;æìA.€uˆ\ˆ¦ÕG€ÈgËPé‰@ª|‰\[ÿ(:›ÕL“R#µaëJ>£ ²%ùOT‹í-™ñI$›†uE¬˜Šs«8ÛIßïŽXÃhŽÆJÞÛdnÞvfÛðn -D”ñvËJ¢?ù*±òo .ßŘ!ü1Ü5 ²t]²"à'>%Ì] ÅÊ¥ab@¹Üptù§°º€{ĈFß^öåÀ  ˜_é.BKØnŽ)Ma™wÔ ó“koYó®Eó%¾¡U‘ˆäA£[™I>ý·üéQñ})Þ5Æ÷šTÒëì@:§•,oÜ<¾8\Dq9”~è:û…ùœœÒµ®üÍqW»˜"·u᪈’8cŒÌ€üÝt¬ÈÜgWs‘*­™¢2&Œ´ éçÖxÚâ>‡½ž¦dXèô:ÏÓËWŸtg~ü–¸àXƒ,ÛùtÑ îá=ͱȻÍAÑ +ÿ—_ Œ{ñ#3úê‡jéÀ„Ñ#ͺ‰Õ"7£Žð­ËG°3A»¥r¯Ü\s ¨êùÞk+¼ƒäŠeƒ½mWïòªré;aÓT¢×¤Cµï0@E¥· Í4T ®òWë Cè8:-ƒf¨‹" 2¡ÂJY*æÄ «Óü^ç=°±!í©¯jÍpgiŸˆÚàYœÀ™… ·awÌUêË©+ïókm»}oj{,››¨Ñbxßi²!Ó·ta jS‘¸>t@ [é„í6Õ’q«!E!j¾WYÌ”ö°g§IAÉØ}K$Kª'kF$í`u^hºR ñ#Q€/7ÑžaIGž'«lmÀ«0š¿ŠU¶Ô±µ>9‹å•-ŽÙyrÇ€ècH22»Ôå·9O$&©_J|o:¿ Û£®;…Níu–£é¿tþÕ¨Gt²¯%$Ó[òfB¸¦B ¨˜?5Ìè`ˆÛ%0_p¦tÛ+í1fß2ž|Ç٪ǘ>Ÿ?—ðÌÇŽe3ÝUaÃ$tr!é<ò›‘ˆ›XIÈFÚSÐOÑ6^<ëÈ'%­Y¹DC!ëYÈXDBh¨ãÇÆŒ1ê,Kš“”Qðbš–y*#¥',¹ÑY«Ë°àw<91¸Yî$÷ª†ŸÒ@/e¦@©»tèð¨~Eo…¨ NóÞ|S”ýéaó8±Ì’ªé–µ¶1Æ}'˜a:on똶²š Á3@ë_Y6ÞO¼›)ý,®ÃÞÁ ëLá9ôƒ×$_Ö´áš`·§òE(Ö„¼; Õ ¹YòN×ÿ’Ÿæ›îìº ¿k©[M˜y8.J…Í÷Á”r¢Œ:<³<8îÒ­«Ç–·ÀKŸÛq Éݪ{ú-O} ÖųõyÙœ9~šµïFæHùi!{UÈ·!Ð3X·é¤hk…¶ÈyùµÉ¦Ë+aj­ö:¤ùǘ‚6í ~äœÏ°„ñ\ŒîW30g­MÑyjufœÙ;N¬Án~âBƾ® íY¤rªÆZÙÙAHpM¿À:ñÍéÖ‘a…¨,QäúÉÓÿe£øZWFƒ"æ4 ÌeLW‚I¯§ %~c¥"ÝAÚÁ/½§+UŠo…Ñò’ÜîwÜY†HÕ=CIj ž`ñiö“É˃øÏײ|Õ"DdcÁ³P´KÚÂ2äd»›_åÿs}È{‰¤Ž’q 0“bÎùphšô÷šX$êù7ƒoZòͺMgh¶sB€A¶ÎÞ‘ÄÍ}4)ëgÊSKÅÃù^A&Ì# ¬é6èg´Š©»/¤œ Ø¶[)_=€Ç²‘¼ß†Ëyny\Gùü;³Û¤­Ï®nZ°ÿ¼¡ Ç’ð$ûjl3vlc!QH• ã"µ&¼šK§ËÄw9ögȲc—(Ðë”æ©o›H¸ÚqO<- ¹¬£ñœ½ˆ=.Ù³ð5f,ÁŸö ÑZŽO¼–'؉Yó“]>…&.‰Üõ!.”-dáˆÑù(^Ôž3ÃisÂEÌ8­F-°9GâZ»3“8Ry]Ñt~rîòjŸ\(|~֢‡c ÒÞ4óMŒ!û"*_V¡Ý!c¬hgyžÂ5sÄ"ç·Ôe¹ÛSF[bº#m‰È¸œU3ÏO'Ùò 2Bwr3éÙ]ÀÇB‚„—æ|îu$ VL¯îmb·Î¶ÐÊuÌ@îæpÅ@à½1#Dâ°·ÑpeŒL™+|iìǬŠuûïÚ Dù]ÀúG ßâãЉYæ/ufðãZâ©ßCX>Çzt±x‰Ûåc­fFÙ6€ä=!û°¨ àþû¸òI×ö*;!Ò-m^Çí=e­Tð°ý—_ÆJ¥ƒÇ?ÆÈÏu°±;Å= Œ;#:€±Zš!àð™8†DP/.z«8ç-ì€1ÍH³µÙŒ”’R&ƒÁ²¾-Q5ŽýÛ³Øúˆ²/J+Á\Û&›ßäj´ö‘ŠËöO…Í4¨·‘uû:˜gÚGg‹7èqùØ“6àaÅ»Ñôìî…0@õ¿„¤QSð¡Ui®¶ù2âõ²ob¥´¸úÄÂÎæ!"hë1ú4 •jýÒZПÓFµ¼È*Pq¿ú[œz"u°=î ~Sr!î‡ ëšâé¨DÇNŒÍñŽ5̉4H~ºÈÇ‹U:eÛlëÿ³Ê è5ä|Ö‚c‹‰ZT§©®Ø'!5—û¢ñqo\ ظO²' ÍÜ)'¶Ox6ëÁc߇2 šd¨âjÿ¿N—Ôwžã-Ãã3¬GôÎ&š¢Ðk@KòC•‚û|Ìòb±êÌ…ÿ tûüŸß?~˜Ýõ7Õ* ÐÈÂâÏT‘ÅIžS³a EìZ¥ ³cŽ(Äã°AÑsÁƒ@ŠA-q•ýB“o…Ö?ÖB˜ÃzcJA_o$¤¤cÍäÒ&2,‚Ý…O-é!›«Ö½Éô'ú>æç,,zD+v$Ÿ±@ XZÍ[™p4F±Õ ]¿^Xé‘é÷[§™h'>r:ß 7axñ2½LÛ‡;^Q·(¤`ÐYÁÒÊ ô&:!Nœž×~5*ˆÔ_[^ÿïd‹0 PÒ±¤¤Œ„h›ÍIíÒ7Cö…ëq)(5a&@ö÷0ôÄ#òŸfˆ$õ¯¦:÷V×s»ÒSëˆ üfÝ÷ÕñÅ´·‰ÔÖ”h™BnJл' ¯Ä´Þ?4U‡a¡Éåiƒ™2£g´%Hˆ¶Ç»vúÕ3ÊjáÌô- Dœ @*¼5O–V‹¨Wʱ18ÜÅ.¼µ/K¡'/§7és `Uø þï‘Þ¬’û콇ùUɸÝÞ]|v0“Ž3¾UpÝ +„[v¸Pê}ù‡^}nZÝJø‰ë˜¸D=šºGôª\;ú¸"†9ÿqºÞ+@]¸k8s«¢’é¨FèÎ8ë±·üÚÁøàîœv®d+Ù1åŠíË-ÌŽÞCˆ=úiïä¥.;G¤Ž‚–šjxXõ„/l>6Fw˜«èagüwf•¶‘`‰Ë ï͸zê§ìœÆ¬’ åBµý¯)rS ?âqQíd‡ZŒ:Ò[É®8÷úß„éÆÙ‚½ †´Ôu†›À‘ý¢g)G²Ù˜¬É& ;dG(5Ÿ›U«ðÑþ“Åeå?Žïµ¬—A£ (v£¨„þ¸Nµæ+áO ‚¤I»r=O-< o8ºà¥ ú0…µc7J¤,dòuF‡”rŸÚxØrG‹¥Ú•l°Š¹db6LIúµÐò²|w0ÔÜ€FŽ žÎâ%‘Ð+¥Š³®\ýBÃÖ‡âÒ0bË_ñÞ·[ÊúŸàÄM‰Ï5k9£TW ý-?Êöý§©}´ =³:S&}ä]×Zÿ®¼>âÚNÒ*|Âý I5ˆ 8{* /d´hP¡V ´hºaw =¬ ÿ1é_ ÆŒ”t´íC~7ôC€vOez—B+"/ª£îháòÅ*ø¸(LÔï£Z@«æeÿ(†XÄ~¡PzrËšŽNŸCôv¬›²’ÿ¦q¹Ýxo÷Rʨ{ã˜ÖÏ]Ù½ I)ʉ­iÒ¾5éòüÎ&dÔö«¤T|(F™¢³ ÇÙ)˜Ý3C*€åðÂ[’Þ‡ÅT»˜ˆ±p¤ƒdò‰À5°”niz–K¯Zƒ¡Ï\‰ 7äÿ ;[eÿüê{}8„H¶ÕóòUÑÔ÷P|rݨçjL ¤Y]æÎË8ðR®˜eÿÁï©ájÖA2bIEbJëÂMØÑÅá½óusÀ<ÿ;…!faqã‘û µ†>‘ÀXÑPÇÕy¿è+w ÔÌ#ѲȗÆcŽÕWN¸ÙбPID ÇÓULãÝ´^›ÆÑüäW+ kƒèI¤·öüU"fÉt- ®¼1˜E­JH}"R˜¢$˜T—Y›§P™÷ ÷›f΋vœù:Ö4Yú°xû=ü s´'ó"ý,@ª±Q’¹ž´îŠ„Ê¦–€T]ùÑAYt~¡çl0!2 Kâ"j;Èò6kt~‹n*åí™ÑÕõ’;"ÐrÏÈ·áo;^GÖ¯±©ê¯8FUË ­òõ0ª­z±ó[Ô3Â86wGž+Ó¶ßâ/‹TBC;¹Ý]¤fXÇî!¶€Ì›'gMf9 ã$­”óuF°³å¼ÐËÿµçÞ³±ØwR0Vù‘ eS>`]A?çç gÜ¥^.×ÔÖ—†õœhCæ³®¨píaOòæƒVwÕ‰=41sÌS—ä!BOĉá„h®‰•Eî…Úñ—¦’K³øÍ{Ð6­ÐºâÞÈN s o,üj;Aâ¸j ábž%‡û²<ùæpt¢Î+fœü-+Ò]óö¡qöö>ÛVHH~§g]õ­UÐnä¡,±È=ÞªD[$ÂUC¶#ƒúùžö• 6eÅæEìŒhÖ™ ŒkܰNs·'K4qȈñŽ >OÌ ˆD–C òdèkÒÿ•#¤þ¼‰ªÏ¢~tŸB_±½M,DÆ„édzÙ°‹iº/»çäs÷šÀ1•Õ|Gvâ&äkG$òZàüÅjqM:î¦ófÙþ G®ÂgÞGî&mR4=œwlX/@RLÌÒö`‘úÔÞ/þÃ`í½ úùÿéÉk¼Ö!sú‚óN.Žó°ÆØ ñU,ˆ‰Ù¯hZ¬v»žñ$—™ŸÔ¡>ñ¨Å¢½ñ)ñÁ»,ÿFßÜÛ¶—ÑÒ¢ »q€%Ýà¦VºÃ‰º$m-ê™ß|&TH)šÉ‰™ÉA‡a¸ým&÷òX‚Ñ%"µGÌuádJ.uO¯Ø'%Ó8 ½Ë1f ðÝ À»žg–½æÝdº†7Á²NÛQ³y»ÕAûuEÉÇ î¦ßËøà7ÜÁú¥q|`S Éh.x‚:–| ÛÕš°po*¬šA„‚$ýø¬ ¬i¬ÿ0¶Cï¡L|òHo|~òøÔ”«ëJUfSHh„Ô&ÑzÀF/î œÜ¸Ñ>Õe`ñôŽVs,íg#]r¥U¬Ý •Xª+.+°äýæ8¤=Ï}[|¾IÝr)¶¿.ò f²›ÂÝfá50µi#6X¶EìFþâ¸Ù`îæY‡@’€²XÉ ¾mu1“ o¢²jÃ+·Ñçi¾lP‹xû2WÜ ¾ÆDæÙ3Ç3‹¡CjÁÒ/ª{Š]‡¹f… h*EG¿ø†w†§2‚w‰Ö‡ÀÐì{c5Fú”l®Ú6* rkõÜ1dR‹ÂÊO5k0‹’ÀCÜ‘Ê11TLüÀÄ]²—`ßÁ7œP 9˜‰ LÝÖ8mÐ_vŽØË3Wü¸g³ÌŒl„ÍéF˜ ·¿@j‘ !u ÈÛé!*…[±OúeCúTþÄ%šQ?bçÆ_í Ù¢ûËIÎK2Bð¦ç{Ï$Jd¡ëùsîV¡+ŠjD2 ˜Åй"’<߬ÎÒநăť—rØÔUÙò’(kau‹|ù Ío„ZNßMâ¹A2!6I]øÑYQlšÚr=àŠµˆÐÏS_£Œqµ:r€5#ª\8IcÕb௥âãoW/!’¢SÇQÊ®ó.}¿v¨Ðä1ììYØKáBÿ ç£‰Æ•ï^FÊö6Hb÷;®!¾E)ܘž ‰^µ©îTXešè3Å ®Üʈ|æ—M3Ô­ÍB#—å=s,e9 ll.fð#¥äTo*4`Vþ #îbm¥ÿÖ†uµ ˆ} ”GAèÁ+«? ¦Td÷à 0Ù|tßê¨ê˜þ×¼š{RB¹¢G’¸¿fªþrßzË~ˆ/¥¶‰ô \ºçÇyÈ. ¨÷«rò'þÞX,”öƒlhèåù-@s¨×0aÛ\4øcÈš´/Ô`%ôA͉ë”ñÊ¡œol„o¡ÚË€æó¤ŠâXšTtääè U„§{„.7]}•ª³xW8O_Ï™° 8 êÜÛb)['2cL<œÜ KìUƒßÊd'èi9ûÍiþ2Œ õäá±B¾ˆU¥(¢g%B¹nÎ\Šð0”Š ØhøÀ–Ø´HÎÉô4 ‚üþ‡×x¬…geBXóØ<%7‰À^6ɼ“¯%€g?QIM¯»iÛ6SH¯:›õʰKWÞ»6æËQ£>,~i÷ªSÛuŠeÞÛ´b´äž?+Á±.äF:^À½Ùs쟂0D%S¶W~z©;r`ŠÅ‡¨€üœɧP$¬Pu^1 9YÙ,Ï&­ >)?42üà³N±D¯Ð-æ,FóB1ÀôÓélWÅ@íá2¼ÿæTñËBj4 ’¿d»B=·’%so, A’ @î“SOì¢:¨È%¸Õ ž¢X­Ö°s½í@“P»ƒKú\ûì›ù—åXH(7è妑¦Û1²©Ã}˜ ‰&}ñ(õÂ2j s†ÿV¤šÔ³¯šÎþëˆÜ::Œ- ?,¨ÙôBmˆ¼IÏâÇsÂÝ6!t(Cge •íMè’ló9!(@È3v‡ƒØ'”7öò$÷¨‘~(v]ÒPÄÏ™®Y®¸íZ[â‚úËÂ¥ºÆh›Ú Iy-Õr”Í1b†œÉŸtØÃ]Ç4qšwêµxš“¥Ž8^ŸŠ\E*kªNëч&Ê–ÿÂ7¦ÜÒø­Ò8ù2X(ÙfF1Œ éå‹¥ ¿—du"y<„4‡ d®4f"wÈÝoÆÌ ã:éI>ñ™–«+nøzØV'Ú4ðÆû6z_ê‚bî™B ™™™–‚DY{XjáWS%ÿáAHx^Ygz/pv×ãL'ÍAèµÎþPó!ùâÃg2î¸h¾ÔÚØfŸTcv_#&ŽÔ•,ªgöpõ]DƒhpÏ5&…“5Ê ö¢L¤èIÌï©™Ù8`›j÷á{+sÈñty#¼6·¹s9óåKÐ|”lì :Ác2}ÞÔç´‹ò‚¶ÿ?æ±y6/ææ@Fg|9Ñ>mä«E..s·`HÈDƒ”ÚÕ· o»4è.à M¹Áè4V/uˆbfR—w_ŠOí7³oï$3däx®HÙüà=\¹fÝÑï%[ þ‰ ¸¸¤rúýª¥Ó–¹8gSiiUÝ¿öÿ|)ýÝéî+wl¬#÷eS’:E4c–bäÿÉëêÏ­àJ€VxåþN´QTY pŽ — sŸrº¡™Ó.}ñn[=Áñ§n\’ µT± ´-ž<ƒTB4F¯—fÖF©ß@ Éíå›fO6Óƒ/+ 1bGV…íAÐÜS"ßm¯U"¹7ñHÝ“=á˜zðpáA'IûDJØ)ùaÍz•h6”OƒYžò (-mÒžŠ åZž¢Olÿ¡) ˜õ\ÀÙ õþ18Z ¨*¸Ô²:JtÍ‘Çy›g-î² ø” ]wà… ¾Ñä¥éü=èŠ<ö·åÉ`ÉsáÛ:UsQ3ôJÍ ¼v‰Íª•‚†T ù²Û}»àÒØ× fCûÉ“9^$¤~H\ªi®œ¦ce=±&=M Ø"ôÝTõt½—¶úu$(ÉJg.q¾×ê–¥ÅA”­ÒŠ>Í<‡l"“T'²‰~°¿ÛwÜžÄß¾ÔbX$ËtRþç7´Ã2ÈÓ½òvö« “‰±[—ö–V…[ñeH¶>+è«yÔ¡¿/KØ6©¡J6ûÈËú_]Öø@‘ç5SJ‰²Û¡²ô {“^úƒË"ÚÔØãÍÇk G:8¢ãŠè8{S6ƒÎÎ9Á€Mƒj ÿŠl‡;y­µ±÷$Ò¼³„SÚð$*M Àk±Êž@WKܘ¤mÝr”øg'­½$™ÍU‘Û¾]4§û‘ßázçC$â;βáëGg ±¥±öŸ ÍJe‘À…ƒ,»¯Oß×”<ˆõýÖ'?—gø+­´ÇÌ™­zÈHMñ*€ä­£·ÜŠëÄ9‡š4Û‘çãŸIIYÞF*%ц¡Vºhß/¦Å¢‹LŠŽ‘úÄשnƒ‹Â»ºÍœ[.´DRæy§¿¥¨®ðM†ûe}+!Ù…ô ÆU³eR›füð•þü#õ‚Sc;ÄIÕLõp,¹uÙ z"o! ^ œ’ÂT«!Uêë*÷…‹þYž¹‘ óÔ“3B øÝ÷øC ãØPÐ2}-z ŵɷ¯golŸàeFéNRŸ@4Ù:Z° i̧âGAÐüwþÞÔ²Fég66+ )on¹6,éuåÙ2 µÀ¿ñRîW¸¼iÄ÷‚ž ÅÊÿæšÛÙ˜‰®â:ßQZê@êÛÓ•ZZâ–rÕè¥#µÊT?)J-¤·ò‚×7i;M4ÉïܨF9È®1E¶`Þð?­1/cÌi7݈$ÓŠdKKæ™-ØXµ?nYKäïfªmyéÞ“ÂåËÇhÒ[~²D<Ê"¨$E*’êùòãÆÀÄU¢1AJ%¹êEà¿M¹¾Ô-9í·‘ÆCmJ5õÅM4®Ó1{dF°ë˜’ë5û¨Àl(=#KÏ›ž’¡zÄìÐòr5PŸ„;CÇå$â·‡çƒUÈÃ4sñmÊL³ÕRDIº4ióšwl¤Ïr™s tôßÿ Æ“ïNËó3!ê‘®s¤Ð•&÷Ëôìç!äPî–¶ä|n5ÁaœâC"Á’¤Vç›QOØrÿÇ®Õ4îF9 î¤d[p<dž¬®¦bþ*l ÷CûŸËÉÒu&{WiquZÛÀ§*Iê6¼uk— 3Ä: ‹3sÒhŽÞìH£Ñ,zsdïzÞÓ ø¤Òì§pCÔ©·„_ÃŒïyœÎPSþà+^ëDï´:“SiýνÏ.û RèÎ64:–I ï9ð2ßð7Î2'êå–"[àlµ³HØ5fC-I×z­ù²ZŽÒEv $bi}Ï\«‘{ Ô<úT )UßdÚœ>®ldY³ëvÑŠÐýÊÒK±½\ :”¶Z‰‡ðÅIþ¡¬FYx 8ãòC5ë{`ØÃâ‰^ƒYi›·­­z“®ø‘/X¨(ûCè,vÊÐjç!£6 ÿTœ³'zïßÔ/¥#fÞýN&iØæÓ™HKµ´zsª®ù|0u}8  Ÿ°mf\¡Ã}~ö>vY­— V~k±¶mI‡ñÜW* šGdoƒOIº§qbÂ%§âaTVT\ÀÄÚëßÎD¶ÃxóŒúE”©%¶@=õMÖM™Íóâà0¢— øµÕŽ/)2àNX‹ôM¸ˆÏDñA2yŽ6ù\<)$à“_šµC¶^ðÔÒ_SI´ZÌÓq_¥¿ÿ0å  pñ¼+ijIEÚ½Àa,¼æâ*h‘áH‡À¸ÿã:¬‘Øëb¾¡RJ^Äľs —‡ÝÒää\VˆՌxÓUØÜ@.AŸ8ê+dã=3bÆåÓЙ0gçØç@¥lÓå»é#_+Ò®èƒ3TcºÑû(LÕzëCš`:Ûv Vûv…c¹3ŠÙ÷€ˆ’‚à7d ôˆvYSÓvri‹.D¹z²ÜS~5ðÛaˆ€æXù`@Äë}÷»éÖœ~Bp]—"œžN@?h;ɨ†̹1†l!QîhÍNh¬}6 '•Mv-ê ¢ ÉyÀT:Rñ7¶¢I]³´¡[îî”È 3‡€S*>˜a(Ї»©^<Ä9p¸'|V” Òd‰¨£ÑË¥j˜ð0xç“K?wtÎï5~ ¬c¥˜±ëbNO¯%h2^"çHÄi‚T[àI;µæ™»»ôӴ哇15z´»Vô_%±Ë"Ô‡ì1è“§éþµuþ‚Vò°„cRÕDÖÙ©8íŽd ñfR]EUa!Ø´¯óIÙsrØÀyóÌØ=ãi…Ì;Ï• áH¾bÞ”¾Á¶Îr\à 9?¤6Èßï¯Éâp/ʾª1Þ]P©µS%ê¨×á–È<øÌ<…“i£²ÿ[ |à9(TבyÞ/Ï“N‚ë/âÇÑ:,LzeÈe›øAeÐ ¶+ÿ™aVAOÐ-/>jû¸ºÂßÔŸU¶ gq«‹ÛÙÍ“£¶Â8Ÿ™vWNô 2ØÑ%¾Â³k¹dú¦É4Þ0Ÿ;`ĹŸÃ5eAª&xpíAbïJ´\0—Ò.A騂N¥Yí>nR$£ºd]%>Ëb.¼J(äÃÄs±iÓ„[ NA&ºÂ+%¾*<ÿÚ—wvÁã`j}‹?²‘ê>ý Æ`É3Û.ÚÛgÞÅçYrȲ^tÆGìþèj+Æ*dƒG»ÖçyÉ`R¶Ü.§bÇy`n´ùGþV1&Çãýi¹m¼ÞyC>ä*wãÌ f¡¼ƒ©Ác¸eæ±Ælƒ?®Ü-» 4ÝVcJ‰%>Dút0×Ý“õQ¥o|Ò°lž\ >ÄÕžÇ|3E"R“õXãŸTx‹`*i!é™.»Ô y;¦Ö™ïkè+]Î]¦ÐQ‰¨µUûo«k‘§A¡-¥ëÛ †1#Ï©C—Ò÷ó¦h>³!€¾oR Ëw¥6N¹Oý#qîÄ׈Âò¦w~—ì ¿<7~.eO³ éÌRyvôá©<ƒ•”I/ÐØ@¥6 û. Ë3§“Â~ëßë'Ãù&)€½¸Á¯&GJÀYh÷Ç­°î’Þ±øÔ[fЂµÏ?d<ã@BÂÍXKlixÔ$ý—™™Ê3XÞëùº ÖОPÕ,ã°¤µ WæH…ê‡ø¹/°Ð¥™¼–›<ï[ áckÅ1©ÄrÚà7%‹ü}&1$|R#«Ã:JùÉ„ãvzêo1—,‹ ‘ôoå¨;Pxy볘K¥–²nó-K9Ñdò¨ol¦ƒ¸‰‡`#Ë6ÀV‰‚›¤Pq¿Wi5÷">Oº“¡psêêd _6K²÷Ôè ™Ÿh²Xΰ#ncÑ•¢[lY‰R%å7ÐXâ;@ÄžÂÏc§ÇêÖÎ`6¥¨ hÌ(u‘g³È!Mĸ†d˜ƒ=БˆFP¨µT˜ŽGJK D•bè°ò'Qºí²9ôU«ðûVt¡.¢ ‰\Þ¶©ôRÌê¬à€ÃؼÃM¿AEÄ6òôòPSÖ8 Ž(üÔ§+ÝÏ £àºý¢?Wðûk] žóSK^šèOÕšöYjá|ø¸ál{cO·y_ìm$37ëÕ“ùž\2/ßþÅH^Єzp޾ý®‘ÜÉAC‹EÅÇ !F´CšE6œÓØïÖxÔ;z|ñàf÷=$g6°¤1‰{;r‘u)¬—Фö„Tu'„§„æ&Ê9ÓüMõ§‡Šh‰«G¦‚Cëî™ ¯Ä òøp£lÂQ0u{ƒÜ¹ 1Qg<·º¨§†÷Æ%0]Ù¤M9˜,IýÄÿLQ:Ns•PñB¾½&¶gà;ËÈ]iFÀ¦ »Áöé/²q·KëÖä Ú®k‘â8ô¢‚“@Ï G.“ånØ_$âV„™ˆ/kq­ü¨º:O÷Ÿß±Á°=âÚDD#>µV/¶V5êØåhÊwD§wÍ ²–\ﯫsý=8yݸÊp2ú×™#¯2»6«Ê 1¨cþFwy‚[ÍûŽƒÆhbœ KIuMýPŽõ‘µ#™§­bÁÇæì\ßR&ˆ1·P!•qö÷ '¬é_í’Út3¬™²¼Ç-ÑÑÂõ‰XŠÒu„Y­ÞN³¦‚H‰W2ûXZ6T ‡ ãÓ–q5s›Xͧ˜Æ² 1ß·L=Æ_•}m9›jº£»“^4SGÑøGö»ƒø-kYg’U3z›V,TÁ}š4z¾}‡ì2p©%îx-S—Mâ^HÃ9ØùÇmŽ ßœ¤To½ Òà’·ýµc’®¶[ÞµB$M©ÕTÒxwz¶}öyxÓ›_#F™Š–s&~ü`kfvù×èéá‘WÏè¦iÉ­,ÊÞ¢‚ïDK·%)Vͼ +¼ÇnÀï$¹qõ¾ô§xäâÿ¾JžË”àv‰•bZ„[€¿u(GSäe'噕¢a<Õ6ã€NôØZCc ÀK/§«€ûC ò~¼L»­V­•>:ÈÁná|B¨ÈOòj)×å:…—bIsÌOzžL ´& ¡ès¼¢£ì!óåÃE ]Â`£ˆ¾9!Ñ‹9™ÜÂbéb$Szä-;=ØÞöë8ãEÑU)cvÜÔs§Og^ŠG•9·óÈj'ü´E‘çbT‡¢ ¦]_,[ >w¼"ˆþ‚”Fž· jÆrÓ¦yŹÉ5¥® ¼å>…—ÌýÀ\ð:Ce»Ö´ÊˆŸ‡tÈ<Tl»Õ¾;ÍjèR)ù‘§ØíÖ×tžQ€;êÑÊÚâ$'жJ¤ ©i[ü±Ýñ¿w*Ch/4DŠ>'¸dE2–æAPÎć„Ëâ†Ý·ïywŽX•X¿–§-PîÞàgÌÌö3†?¤@ïën.7*ópü”M ¨¡{­þ\qÏIK…ÖÕ+Ϙª\‰ë©Ã ùó2µà²‰2¥Róû$ U™à‡âì‹“ÚòpST.î­'9"ý¤f¯•s®ÚþE×@ nBg\OBWP6ãèˈ•®p'~È7BK-"”ï¼'zÙÔóõ_UJ|Í…1Ƭ—»á>”rŽØxU—„}Y5°c)œØZ= ÏäÍýb7“šŽ {ß¼ìkººÞHlÀmL`PLtÅd°îƒLXªêúä†ÉK­vŒƒfrž*bé“©ÆÏty…‚"“Ln‰;¦PRPÒg1ªUúÄ~×ß$‰? øO.R°òl)’.˜¹°ãÑrd¤¾¤ æiyû`¬y[ヲ ‹ í"#EŒ°‹ç¦Pà.§Î¨%¶Ëh[Â2ê èqZ} è….g+¯éš?ˆîÆÍ Týý‚šø¥ñÙŽDb¼Yó0×·µAºßW+õ€­­&Á@H×ÐÑÄF%y?5 –¨ºŽ´+¤Ÿ{-`!¢®îLφýùŸ#_q⠲Ȍ׋šmR€ЮÐÓt…îÏ‘¢¿P3ÝŒ5ãd;fôÞ¥ëL lÃY¼ó”ò ìMDd/‰–Çe¥¿œ¦fw‘±”•#•÷ÜÏ­™­Ô>]Ô[°CÀ Ù‡gŽ÷+Ò%ÕPätÂeÜÑÅâ†3®ã Á´Å|aägy¼2$–9nùd¤3ñø‡ß¥Üèz¨SJ;‰ZØ«N°|]ÛqV`J~­áã(O¼tC·ÁWŒÍr\Ìn.ÇH‰'ÄÞ«€ëÒ}6™áˆ`÷Æ#ü,†T„°l´L ›ÍÁoÇ#·”ƒ“xŒ§Èó ÓgF<¨†“ädŽJwÚeê-.çûl¥9 {ånØõ_X¼¼z¨Û'L :¸Œ/œ#1@|טÿæüh¥Ýûþ-æYár·‚ÞU„;Rí÷í‚TÏò;Ä—Hw`wŒD$–w†Rp6 '5È|³5*øñ3<¡˜õç„¢d–`]t=m›:×Ãïi,|c³^m¬›fÃù’7K™¸–™œ·æ2m @mR s£›† ?ã­gƒƒÞ¡\Pa¥Z¢Ô=!vÊ=ùi7ü!’¼ÏfŠì´-޾ˆþ÷‘ 2éqò¡Ý³$ud‘bïÈf ‰Š7Í„õNPÊ3R; ºP?°Úk˜|§Š×ÖÕ±!Áèz]az»›€Ãj·åm(ø›4·—÷#„2rwL×ÏãXëvB3d9`³d3Yi=‹ŒL@_8_‡äQ›"ˆ¾Üp߃¥Úõ,Ü Þ·:âГí7n'µ±@v†¢Œ“pñÅ4€êò‹ XZÂBD­ÐX Ÿ2r×pVgnH…YRÁªÓœ¼³gj?¿¿O Q>: #ËØpîØºžÄŒk‘´þµÚºáÍ]]þ”ÒŽ%ƒÅ†P„‚Ëûšjw e3êgùZMÛÓ ›k@1'–‚¢Lª…?Ò´Hg€©'ݩڢ•I°ßñòH0-3Yüß6Ÿ4*‰3Ö8Nˆ„F}ÊäaK€Óµ†€V²çn$å¬&´õ›Dñ0^ùüð"JB:L\¥ZC”<©›¬0àŠ Båøp›º¿ý±E ¿£hA•sÔ’õA–ÂÖÖ('Ð)-Õ5ïCí”M E×J%1ŽêaÅvéòoJßËÖ™!£!¯ßËä§R«J ò‘K6‘®ELÄø–©B¬ Ñ ­ßg§}z«ä Æ “¢ *õ%5AK’Iïl\zº {d­\”ùNË™wÌ-u ýX1”èm 0±qC@.ÄéFw—Gb7¥¼ìY­ìn‡Ù4­p2¹çY¸hÕtÉZÙØãûŽß=1za €_Ë~´îa™µÐÒÅ7ŽF­U,™¨àÈ]îP¼0*Éi”cQ÷Ö)¤—^ʬÁÃ[_bR”:É›—jWCêœôž§é¦¾ð§¾‰»lCjªw26Néì1ñ»ä:+ W®ºáÍæÚ‚ÿi„PÂ>™Ny#åT—›è.€/êý}—ÀAGj“É+EM‘ˆ§yõ#u…&+©V…2£ yûî:ù©¿—>ZͧJÞ"ãd#SÇÀ<ì/xPF0Ç;2¦¦†—Í–ÞþZ}55eœÊ›ûš »Œ§T¯Ÿ×.29³8ï ± õ-ûà–â`êIñ¼t¾å™d¬À©rñŸ}ú÷ŽÆ›» Œo(¶)5˜YÛ[µ;Ös^{ÇÙÈÇózd¾ðØëú¹·¹±ݱ*ü°õw„D*3²81Ï*Õû{µ¥ UGª€\’ò±Óþ€¸mÔÖ6ÁȳàèýÄG¾J7qù_ ‘F5ÜÔ°.Öæ_¬åáëpÒ£dò²‹ŽMnÖ’šÇ÷ ÆÚ Q :+1§Þ{0ë7…už$Á6 ï<襰΃b„°€1Þ@¯žL¶Bõ@ãC‹ÁVf< m‹¥i9Ex˜ÌõÅ#K%R ÅR^‡ uØÛ[ì˜`â"‚X@I¹Ûh¬ó~T¿oŠ ›âØØû1òáƒÄz•ëJ3•þ¨˜/<°†‘ìÊ G»Zà28Q¯ÌG}D4P=Ž®“Þ!×ò.b¦Õ5WFîêÞ<Ë‘t«Îɹ`ðÀFbíÞëÍ }êÑY$Ší,ïñeK%r–› ºˆ´#NóXà†Y«š`#bLâÒ­¢[|µ*Z¤£^¦@îœ.\„p«svJÞ䈔~.Z¶‡y‰'²ÀpÛtP¡DÅÔHr:²2YÇ ¼]˜à3Ø4û84‘÷¤Ó5ˆ$%¦ë[i¥ Ó´L·-¥C|ƒI¤j ‰®l{ec+TLLÆn®; å6Ûø‚›Ð/jš^¢®\ޠΛfÓkÁ|Ä…×ÍàjéŸDrðû\g;“Ò~7­Ñ£N±‘ ©}Žœ£4°bþâu9pñÁ°¯º•d8ÿ·ôê`&b¤]ØÁòV°ßzp ‡¡ w|yŠÚè@Éô”?× MÛú2¢º+gV¨HȘ`R”0Ÿl¼ôÿ‹çÁ-­YXýñ·â:u0' ¹­‡Y;°*r•¶Uȯ½â­Ã ÙCÏfVïo½g«ÁÞ«9Ö]TÍÀ˜ß@î6sbÇcM÷¾&Âã›7>äVî°R×ÜûlSêö‡¿zþ1™ aþbGžô’FuLÒ¡‰/çÓŒPHhg‡¢û°ðHG/Tåe¢„©ƒ!^wû‡-)Y—L_œìo¼kÁ4BdEÖ1³¦Þ™ô¸i×ÔäƒLgoP$Dôz˜oåÊÆwS1Ü™åZsGŠ}Ê' 'ØQ¬tKQ6LlìÚm¨WmƈêWi3ɲH4¾Þá8ÂW×{=§2²‘‘6Ñiu¼Ä@Î2}”  ?¡©ÕبÈi£ +N;ñT¡\½˜z öç3Žà×®ÛV³1•d"Ðáç·nPù\÷9¶Áñ%ùƒÒS j’×”³÷J—IÝ;CS÷…ìdÁMä¹ku)a»'ˆÇK˜°e“Q5Ó©ª—_™/ ÌýL‡½@ ݾ¦ªiŸýt”(ª’ågÖ‡óíµ”@Ö2ó—eÑçNÚ’²8,óýÔŒ¤:¶Î_6ÒoôîêG÷3ÜÝš|ð¡ ù²´}¡_<ÈKE(Ÿö³BÈ¢8Ï!úCZ¤¦’¯“ÖŽ´»êoèç¾UíÇ= #õ9’Œ7¤fŠc8dñÜ??A+&ãf’¹Æä-+lÖÍ»àPSc´ AÄ3¦™Gž J¶ãÅ›ÑÔ&NèR{Þy´O@GŒð ¡ °0Kà¿z(P¯2" 2.{‡;D콇4ŽróèBO\>‹ °N•6™Z¡X§1ÑtÜÌ©²+¿3³Îu"^6¸`–~£µ°½ÔÀ” lG×ç¸õù}•ÿ12âZEb¡[©&öÙú r«X©‡D&Ĭ¶ŸÃ­t¾9†Ë—U¸[cên*%óäÙuoN3D›¤­ìýQÞåI!×S4Ù#nhI6aŽ=Ø=ð€¡Ñpnu§TRʆëÒÞÕö44rM¶ŹÂõ¶›©·ªÚ„Zˆ®+gˆùȱŸ'g1)Ø¢AoZQ³i<Âßûe­#bÁ³gB3—G`¦qÊLsS§ˆÄ”éª4k*l.A<£õ¥§<Ó[lL¼‰ÒxD§3¯A•|ŽøgSâ,ØêÀpÈó›X&¯¸®Øò¾×vcM$Øz=>Ù,„Š ònx ¬Ç£ÈÃÎØ‚ã÷¨„…ÔŠKϘ‡zÍ *Hnö]ÿ½”hdƒáá¶ep–ÄBîìÛ€ ¼=÷f7èºm%q¨ Ðk©š·Zðm¼¤Ó¸_w@Hê–¾†èÞ_È¥….‚Éœô0Î~ß'ՇǾJ›©ªëÚ•¹Öb³ä–¿H(ª[¼'òbGWs~“«Ñ^Ÿq*hX.¿;g¹%EKý°¼ ˜Žì¸_J£”­Ñ1ˆ=¸!*à{ø8Âì?ï5ÏÁ‡÷Õ,úƬÜ,ÐöÝÝÞgòŒ¥vÔ,†©€ÎÑ%ÒM%ÔÍh;ÕšÆ œÕ†–¯½ºÂÉÞšÅÇ ¡ÑAñ-÷ŒSÔRý4úG)†9¬ZZývrèO'WÝZχ MÙ¢¶}èK4{äkn?êþc‘|\QU1Çó-ñ9­ ?ëÆ90)ùó?ºêÜ)ÏÖYÛÝnG4˜än¾µc‹ÎÔy*$–²ÍA¹~5Úñ×Ö–(݆°Å‡WUMOЬM8õÀ–1xKD½Óeu² ¸ƒ‘•ZÐkç:6ÈG.!” [vª/89¤ÜL{Æš*â„Eê[©Ì¾·¸˜cbªiQú!ášïá3æ»ápjöw|¿ :%`8ÅdbwÌXYavúõŸ X5ŽÁ±Ûn±Äpm† s¾Æ’Ž;- ƒ¯äK&Õª$/üó¹=›’L™”n€pÒ¥ç|IM»ÏGfÂ4¯UŸõÏj†áÃØ²Îz‚õ@€ÐžH4yÄRÆ•0€€>;.¡Þóô¬IÑ#JWa9”‹œ€£rv‡’Û´¨”m×Íûðå;ζD>(Ë—âÉ"F­ülZÇ¡MÅäè_®j™í(nhœ†ÇÇ¡jº‰_õ,¿s®íP ÄtälU+ráÃÓμØÂð„ÊÜ㘰:b -ZÅ5‚¿ÂÁÒz 5®cqkp€"°ÊûyÝÖ=O±» ð!çœÆuC´»'¢é±_Õr¢«1™7 â†9øD¼ƒ„fû0ü‹l¸p‡è .ŠfAr;;VíðuG»¡\̳èwúý:ÑQº°_¹ªà ƼEX)â¼ S>O³QÍ=mo¨­–I¹00z×Ç‘Í:s2+Hé9ærœ7VêýTZžýÜÌBä%©háC¹ÂÒ?ñ³PåêZ{4ç!"Œ¾þà¡A-â~õ ´û¸C˜M TÄbËÖIglÅjh?Pta3ðC~­'ô„M ®”B(Üfò@OÞÇ’]àPl±=ë=¶`‹oâ…ó,Äc6Ù¯jN¹¯,Gšd™³Ä;Ë@94çÄËp%òÞ çÛ”Ia0ìš¾¥ÌádmFʺóD€/8éMû…!‘ÉíÓpãâ¤VÉt÷û¬’'3ÎFU—醉0¹“÷1šf{ß+i å´©&ÇÙ¬Có$åpFÖ„Y=êÈΓ ¾®ø6¯´‰ÇKÏ2ÎÚ¤j¢ ¶ôÐè ÁWøåÓ%„ƒ³"pnb‹ï%­õ–½-¾•»l™Ñäà°`#º²µÁê1öâ àYælI¿nc˜ ú*z¶ÝðP¹VbàoiË‚/æR‱\ÁA}†‡U1¹ñCÔOEÓX­«ÈÅxäUœ¸mNõ”çýwƒÉ6I²lýO«¾w;±¦" pkœuùÉ'á½ošE®9­Ã1˜%•¡z1¹3Ù]tæù³ïVQHð?RŠ0æf‰¦L7ëü%{ãª+Æw—¬' ”o˜ = “d9ê ›Ÿ!K¬Êût;´—^˲°‘™´ü€ºùß·»eÀ›lÞ*n£/ e¬#'ÞÕŽdŠâ¯è‹b^<› gÒþ£\>ŠUß²‘8' d \=–Òš8ñ½"èÓá ¯:®C' •X:~ä±>04w qrù Y™~#„.{¥–O¦´êZÖ‡øçQïk PѰ%Ëi­¾ÑH¸b*WŽ&U[Oén¿ÙŒh[8 ‡äÖçÈ©cn•¡†ž@§Æ‘X5A¦Cª?(z&$Û„ê®0;[3v9Pö?xÉ÷ï‰ i߆ðV2i²ÌÃgJaÁ«µ¯øT/‰õµþHûÒ6XŽ1m€ÀÈâF—Ù0þ–迆96Sâèxœ7Ü®¯;%†¿¢ÇÈ„FÅwŸ  îití¨æó°°7€§Yß™m†°'J¤üäÕj?}LU¬]5œWµý<’vÓN»ö»ñyÎ…ú7_4†! "^ ´Z4@ž<7õ åàŽ.o<¾9ÅíÒ@§)€©—(p„4¤|Ê6ÍÈj:ä&Ⳃ:–ãSŽ»ÚŠÅŸhŸ!Ã+1,»yUa©¨bnôîx’ÖÚ¬y³l]12wV˜½OÀœ4Aø¯ºW»u„jAÊ® ¿–t™Pìr¸Layÿ}©uS–cÖ¬ ³±9pT&P½—li$¾ º nh{°œXËêöÊeŠ7ʲ;šá!ʵ„È·’¢øR1Ý{x¬¢é[‚Ò"’ÑÛü·ÝÌ*ÄöñM|pAáUl}¡óÔ¤øëTF´\?B0¬0uåŸyizå]¦âw¤P^j0k¬ÚË¿…QæÛ"sš%2©‹Å9íCõ…BV‹”Ç­{næP¥/DJ¸«}G²Ó`ÀBý̰± .¹g—ãâÿèü´Ïì­¶ð5I<Ǭ4ðVFþ'ËÍâXÔàÐéðbŒï2}]bÐÄ•L°’?¢†’¾§1Ü{ÛÖ<µéH #ôz†,!¯#(ÂYÚF k"Ú¹Š½_cwq'ÚxßòŽX08ÍÍýy>ë/´4À‰™ÜÈZ„z€ŠCÇà*®-ÜiÍã¬z„1~ˆE=]Ö€Únãž!»çõº;¨$4h!TÇšq6©äîTÑÈìî•pÓÔR—óéQÌ0ó¬à-­’Væ0‰Ø:ìiÃQêCÞ…™·!þŒr›æ +!꥽ÐÁ¯6ÐÌn›íæî…2Ä…_«-¶9_%Ú ‘¸1ß½óÄЄòm8IìVÎéíí ŠÒl#}Ó-êpÄÃ~5ÝTîâ‰fÊxâyPæäWhv’7Z8æ XTE%ÀØME„ÊÝJ)# âÿ>/!eòš$ÎÉ0Î/XlƒïÂÃ}gñûêöK=ù§_µNŽÕ ã“hÔ:)R¢P›QÒŽù€ÁÅÎêP0þƒ $Ñ`ñ'Dc××ë‘«K0€..—¨‡ ôà ϊý´îÉO”láADagæ "¨­EmAošÂò¨nG…SCQË¥y…–ì‰×ÈÓMëÃ*Nßì*ªD –ÉîðïŸJf¼³ý*ÝSï¤Ý…žÿrÉhmOÒ¥_7ñÁ²7ÛzÐÒnJ?B… &2OŠ;¬ÑÔ^oàE|`t|Ť»Ëê—[·TbjaÒÏRÊåGúÀ3º3»½õ[È£Ðz¼lzÙú%Ï:LúPr£#’w¾ì«P“tðƒLhªêÑžŒÕG4ÖF/Úýñl‰–ðP츲½…Ø:£2™sÊ”¡?‘&%«Îtb3…ÛÚ×ÔœÚ /McoGj„Hõ¿bò¡ ¯û›Ñ¥#!—šLéN§4#l*!ã¹€?>e«oÛáPxB_ü_PmÍW­.0Ê„]«ÁLw# Öb}!¿8´£ƒ†«Ý¢KÓ¢éÁ]»Ûå¿è¦5í-£·ôyŠÈCmžÍ7ÙÀJPtä`äܒ̽ÀŸká·[¨`ðë±+Œ¡ãÃãú¼…ÇéÕÃu«*ù G¿ð;8—Om —ºC—¡è›:3 ¯™9œާD‘ÞÎsôá>]ѹöB2Ì÷ê+ÅÕº õz|ûsòú©Ð ÝòY²âUé_—âdCg<23åiua•qã}=FÏ qít%Ò°û ó£F'iзÀtUŒ<#÷yf/€ãkæÑn€þ YTH.e…_ªÌ´¼Þ0J©ÐìUÜÑžÜv@IúkÖ.?’š˜ §‹˜Røë£´¨õ“Ev‘õ|ÌÙ…8³½ À­Øq'’M(UÇšóL C }{³Úš9|=Û6¢.²W˜uи<¤¶|‘56º†ÑîB(N„‘S PE4ù™K í«j;!ÆÂ;RWYÓÐ4²6mǃì*ý…-Wj½€y'0În#¤rC¡1¶¯(%RÙY•êD•`7>MÝÛ$:ŠÚ—Œ s›o©»Î#¹Öˆ)3qØiT·œªs™@©Â¢¹‰Ü˜í ŒY†1<ßÂ!/¼~ ÕO i\A‘Ä)ü­Ô-Ç%¥]ÚÙY½ù;À ƒhéy˜¹ü3þÞvР¾$~Âð87¡æ;a-is’ V³Ïí#´§”0-ÕÄSµávܶ0ââyRq!›!–%ªk<çɶªµö•¥^Ô0g<ê“vÓøAõDYÆÍƒAÓ­PÈ|@%è?¦~ ù-.ú ‡âšì Žó”²Ób'SÕ¹ë:ü£Õà\ò¥FoèkÅú­Ö¹~h—N Éá¢ÕÐXÑb”·"˜ V¢Jü‘c–ûAêÿo'ñb”M©Þ¶Ã,»’\rÊÙ«¾ü`†öìVœašÀ£îuàüŠÐÇö5ã|É5õ`1B:m2 c³Ã«ˆhDüÍ’8Ü4¨¨à…Ê)tý>v£GœBÓÇšjþèV¦)î8ñ"½ØH86W×OAwž)­G9L¥ þÂÿ3öÔ™šîYS­§•…·LlsR9¯ëñ¸Ûo¿ÄŠSIcÐ 4t%Áe£°Î]ÞÜüøÝ€/¬ˆ-|ù_@MnœcH™^‚ʘ¼ü—Œc1´çJ+ÐÉ´“•µ½¶µNëå31ÔuÏóff¶˜f« n€,¿1á'ìÒ±­)žFÆ;€ÆÙ½šçNÜŸÐu™y¹Ä®cF eb÷Úã×í'22É(^®Úܪ.­Ý¯9ŨˆØDHÔUKI}ç-÷ž·ñ—‚§y8åË©¯L¬/Ú5gQÿfCqsY¤NH‡ÒoÎnØpȼ‘CpõéM”-ö“¿ƒÄ)—›5hþ§àŠ+Á4⟿uœ£â­¸Î Úî:sFr•æn ·ï™3§\ö#TF®™LX:Ýý÷¹É»?÷-€ÏÛäÏ©ÜÆ4ʧž µWxÜÔ>”bub†x1¢÷t·þë0ó+4H4-&r^âœVËkœþsx—óªPæ–pgMÄÀEË~÷58Öš¶å ™’,“èÌHa™ ÍCÛ9 €‘¸L:<§7 Ó GµáªðÕ*`ÒH0?’~²J¡Ë •Dá“Ë„‚ïäž÷â›kˆFG=ŽC«ŒO`ÙãoPK,\õÅ“‰/N„ù°ôVhŠœ†ªUqñü)’Úvå±÷]²î¦o O$« õÅ3_œÞoNò³¢Ü‚8ÏLÆ@UoV&ù n§!ÐÄxAûÈúø!͇‚Þv'#î ÄOŽ©ïYŒ—õ“Z7¯8ÖtìRpy…¥»@1`6”š`“öƒ˜û°fJDˆRç‡ÀÌ·#À ºØÓU†Í «œ ¿!PÞRñ $_×ÒF{ÅŒîevÖT?™I36€T«›óbmƒHf¹ìÕ¾¤š6G˜®hø®èV¢û6Ýá˜iÞ8jn*Rm8(ލ‹ü¯†Ê_ž€œ‰Ä1¬¹®åÞAàGW¸È•×_ð(»"‡hÁÁCúÖ©”(&ÞÕÆ#ËÚ0;‡ûr2©ÿ­Â‰¬L—Ìh÷¼ ˆ¦fP{–·ÖZð•×_È场!ºz0×-[Ýà©úE’Ú}<·ÝÜýúÀG«©Iè;რ;DØvoJ+b/û;Àî-Ÿa^ÅS&Ü!z¼ÝÈoܳ'`¦E? GØŒØ "£@Uíº—N¼r¿|ÙHº±½þŠhÞqr˜’²6q´1óñ„;f.Òø]—Ék!œ"”œž~Vôæm*ôXòFû̸„MÛ[Á™´ÜÈ!“í²ïºV¢CL^ä ¹JôŠwÔç7£Y7#\U—Ìðêö¿nzyѦ¶íu¼6ÈÃùÜkôù7Ò°•ÝD,úFð¢8  Ÿq†ëyû[<Šº¬ô:•G#”èú¹«Lðd]•rŠE2ßd/Ù†‰ð~ôàDÞP=ó´ æÊÆ´ñÞ@M<;MÙ[Ÿïá²ÔÊ-V×_V*jº°ÆMeÛ=¿¤·|–â€)FŽC`³|i¾ì&¾å £O<Ã¥ ÔTÎ@äÙ¦¾ßZÜ)<¬ÖÉh‘£VΩÿÚ÷„ÚO¶±ìnÏ,îÆzF[}øùC”ëï&<› ¾”Š:PÇÑ8Gáyu²*ãßyĦ›ž4áåBÇ®`J]>ûŠBþ@ äáàeç»sÌ÷K€+Ç>»¢ËÎߨ^e3õ§±¼«FèL=txT/Ñì )Î(ó¨$Õ_h÷ˆ2étÊA&ÿuÌO™àTnp.z #jCeãj­_£bY°s<àÝHåmô5 ~z°¿ˆ>_”s5çPòï³ýÉÏô‘ú ~ɑְ4¿ÈžÄvˆ¸}ñ[""1vZ .¢ržÆö’Ù·*aznk…×’/iQ‘O:ñ Í(ˆ6 Ú[rÛ>Íqc)iö#s{ÍPç>@ãaÜu§ sÏàÒ‚^ ÆÂ']W¹Ý[Y>µ›í<í±Ý› Øçî~Œ@ú0`ˆ2cFÛuÐ&*õ_qÔïœÇväºû~ý¥ð©·¬ò/“9$8—J›H(§6Žc%Ë&D>˜6[^³’ ðÑPF¾]×X4è+å¯ÇhÅó ²#åe! õa€Yº]æRK1xì A•ÄM ôIG#XiyúÕÌóʸ;>¿ÃK‘ySŒÔ}lýr£3›¨Õi4Ź0@^^½å„ AUIí/¸‡šëôžÐóC£ ô$ àÀ0·Ë¶ø4¿d”òH| ùêéð6+…2Ì 0ÖØ™ŠÊ…,M‚[ö€í’;¡<\¾#ѧvpòSbQùö-¦ôÎ×Skx„Oö*Þ«¶y¼ÜÁ8êŠoภªÖÿu[/ôxøìݘœ½kîÅeÙrh@+`yeË%31êC¦'l¶—&›/×%Q“ì·íbv±'ªÔ̽E‘ë*ž;ÓÅ›Q4‹.•$§™u6š»f†zÔß%Ì£uN û2ËÝ^|¥?õÀÓwÙñ`@;ELžù4ÖÉ5ÊšÈçÀRš]åmçw“µ!ØEg‹Ê`®ä8ïó."C¿mf‡š—çe^nGš«ÔîÕàq¦ÞöÚÌÍ9çBåìËü•>O"yÁ›®*áÔžÐsùšK&ÎNß§ÿÅŠ©äU¢”÷††ÆóI Sñ8Šf¸`¿2 ކsx6ê£Øêv]Ñh))÷ÌKd(=(ÓhšáY×Ý%yê÷Ô éˆšçT¾D  ~§gvU™ZT™S‚UËÙ¦¥ŠÍŠÚÃËq@2€Jƒâ¯€ŒN½þv—´?ßÍJb}§—gê¬Ü}XÌ4/\P"qeÖƒíèŠØ|ï·-n?0üùO<ýâdÇ„}îÁš@%¡ë½Nò~—ºÏ¦"‡êD–9©w9Ù‹ârðòJ• ÍDl„ß= ñ%á+ƒW<µßsKzï&T³Æ.§ØwƒÙ„…æê¤ÇNMWm·p$»”,$‰äL.(ëÙØ÷ërQ@Ò²-£â'ÊÑ‘£YùcâåuO2¿Öý_8n7.œSxîd ÃØ«k}FÁœH¥tB«tVJ—)¤¾tF’þÜAÑ8¹žT'¢ÙƒuÒÛåï'xßHí/éãÚ?=š ™·ºÅÈ€V¾ÆùäËýªé— ^~°·`8FN=%¿ÿ!•>frhÓÒx¤P–¨ºÍÇþÊC «G½¼¢ó§O¸¢î‹¢§cÆlµß ä@ÕÛÞ´_xº”ÔÈU‹2äëÙ Þå“tÂB.¸Ëä\„3X–ƒÁ‡ ýŽËÜš1DP¾Â1ÿ›¦\1¡äy€ôæ®F³«o¹ú&ø­]¥¨6dý‚>‚æ5Æ9¯Ã²U>鸘[D¯¯JªRçÞ×Ùºï=­3?`“ú½)ÕRüÖó?°˜ÌÒA¯.©<³øŠ¸(?(èÌÕÚ–‡h'÷¦èƒzû%QàjS¿"Óý÷ƒB‘¶G}M鹑êBáó Í¿A.!»·È¢|5™/IÜ´|#ßÂúI[mj®:Ý!ßhÄýmò¡ìò¯ŸÕW’3dš**ïA0›£^…G §‚;ß§ñ´’ö dòΚîK•,„3@Ë­Q!h¶/ϾÀÈÕ«‡XK*)K&¾ƒàSêÈ^ÃL¬-£û²°48a…Š®Î°Å×Ýÿ™…EÁïPÞ¨ñl®‘¢œB¬‡O$îCƒ¨ìúäÛëåT¥<œ¶ò„Æ»«ý‰®±ØÂ'¦®LÐøÔ.l2ù8 ë–îl.³1zP0¿.7nîDÙíïV¤PX^Çú,%* H~L‚îUN°VL ü÷ªÕIãèÇ‘±”Ï(Hñ\"`èÎ{,BJCãË’é–EöÊBFÉ G®úÙx–[l™&àÈŒæ]m«}r\9}sz¥ÀxOö>G`ÎÍ[ˆ!Kýæ­M<2ØË¥ÿÕafØÇ}Ä÷œÆò^` ¿Š·^k?C›è @yN­'}OV ™gòbÏæ+_Ŭ¯¥ôZé¾Gœ*ƒ]ÒKÕkY­l¸8 å÷¯ívʇx¾Ä+ÝnÈD{úç¸Ò-æÒ·"„à@òn‚Êy?+ó'3Ûÿ|û«;sf‹mϽŒÁ—Õ‹ðF)_åÌM<‹umGÏí_’¡ú,ô2LâõÄklÛÝxâW½ êSú ˆCyà)<6¨«º>ÏmäÌGž+ÏMPÆ©‘ ‚UlM˧W3¡Å¬zœ'o‰¹¹'®²òÙûö”n”j øÍWÒ%õ½Ñ9>Äì {¸ ,,<üñ¥mY¤v\Áj%mÒ¹ÀèRÎu\Ô`ud2ÜÑN‘Gótκã,?ùU%_¿•L--öª¨€IWl¿_ebŸ§>ª¿«ù~;tS\ª§+ñtp3‘fC×-éˆÌÞ FÍÜŠ×(Ò4¥‡ÖÈ3¦ÑeåyTÀ Waþunî!UƒG¼™˜_¾ST‡³à»Çín½ÆhBb‡(ʾ¡oJGLŠ;)Ü)‘Í,¥ uõˆ_ðÃÁ2i` èó RBtÛn9„ìÊôN~•Ð× ò€…WïÇu-Y Ĉ”oBØÃSŸZm”v®2™r{k¥K'ojÞžÙ–`#[w•¯dÛìQQ†2f6åM|ïPÝÿ¯hB䕜Õ[—žG."†Ž!òàò·l…ê£TIˆH6…Ãõ„èZJéÕB~E€ÆÅ&SÅ"Ò}úKã"­£—f ÝÝo×!zž w„ÕY»Ê8õœ­`þ—„aoLú’/7¾y‚ù;É8ÝTh‹,å§êlrŒ\/Ö(ħ׽ ¼ýÈ õÊÆåQÀá'qÑAÒ:I ©XJê6§ ƒd}" ˜ñsA© Üoâd¹éW´öBЇß¬å2Iëàìõºu‘E5Lï:ªw¦ÜÛ›ä:Ö4 Ï!~\¾Ž©á•Äh¼þ!Q ¦vå.à L93‘ ýäæê›a:®ã/K›š6#¹`–`ÝêöZͨøÈ‚91HÍûB ÇïÔͺvÂ,X‚ =é)þŽoüÓ`žÉöIc¤–`î© +Ë;(ε˜’a@Í2™ßTêýGÁèR^©GQãã£w}«Ø¦Þ5Ø_¹“êŒ%&|»¶«ÐâQÖ:kÛãø£k1QÂ^p«¯"æÑå–Žj ï¸ë2‚k*ÆE@Âö°ø×?á\é7ã=C $Ú0Ñ.1W‘{ HIc»`HÈ£éȉG壶ˆ˜Ñ7žrxØúŒ™´g¶zêvµþb]sví"òHÆÎ¯øµŒe*| !¬k< Üdt| mì±ÔýžÛ!^nuC–ü໸å{âv£¹bq}Õ°ú“‰jÆÜ`DÔíGneœJ©ÙðIu~p„÷Õy¶T>šL›B«âÄïì3Z/ƒX÷¯ãÅÆhÛäµm³«pø¼$å9h|óXɳÑÙÿ1Ö  ~£Pà–$ç”Á‡DŸH‰yB\]kpbD–( 9r=ã>zVT“U¾öî³Óg¢¢úkê•1“êÔ¼ÌL‰Á傉´ø63:T–Ó”w\/¡ÜÝÀP½Œ­ÌÝ×hßFu&½EcuÜb ^¡ùvÒRñŽpó”±X@ÜȲݳ+Q0ÿªò.á¥|>ÏO£ {`1Nê»ñ€`2ÐöÈ_•¯ä²¦uè†Ù©Û¹HR§þ„NàŽÈgø%“<šelÊÔÃÝ!÷]ÏU…ÏÃêÕ y›Ô¢Ð¥|-“–¡ÆsºáGò' ¶¼Š3nÓ`dK(ÎÿœBî7m¶Ž9¹!Ü´ø¶ï¢ÃW’‚òm9“d_Ž™›:X`wäÌ}´íÓ_[á™r„¶©8©`¹Ëǽ¤¨…Ѷñÿm úcAÉàÏBŸ·ƒÁ%ó£Ð§ @¼ˆFÉݪ‘'9IÄ M\/¬#sD ©÷% üÎÍ[“](¸åu¡×xñ`ð\&š`•|oöV)b"÷ò“Œ÷ôm…õ)8xÒ¾¾;œ›wñ!q uaMù<(ؼ±ßÍ^<ÐEYM¢¤šþ#íè÷C]³3­‚ ñFƒ¨‰j¬ÞJ&ÃXU/óîóÉFlJ,꺙’YJdãN»ÏIv—…ÃÚÔuä$ \øÅè?8ºE7¨°cAºxaŽÀ©*Õaû¥6[—¥‰ñVŸ—Çmù΋ŽÅtÃOª(µRj`ÆãiØGÙP.|e9aé›7YסiÇ©;¾ÄTkn–‘Ÿ¾&È¡ÄÛĘLOÂÉëøÌ4ëhEFÈëN¨JÆp“Sîò`çæ°êà¤ìpKãŠ;§¨ f¶ ‡²ÌÈåm¼‰æZ»ðšm Ƙº±¿Ë0Ø=7'0{ãÅFg±Ô³2hiÍŒoo~”:FwB9Âëf¬-ü¿êØ›²"¥e«»Ô§ü héb(ãC‘Ô§)›-%+TD€?ÿü¥·„–4çåÎBkŠé+tåV…?ÛUÈÇe&éÿTYVÖÎ ÎÇ?â;hn>'ɽ´—‘>I^AO'fU¸PZâxD8k¸^¯°éëäD&rŠ—ž^$Äp™—›ewòŸ‹nha2}Vè1be©¹ÄîÐÚM©›Éö¡YqÁcŸÙ† ‹´ Ëi…iîŠIéùQ´‹p’ºˆ-ÌpŽvK0îÉøÆÊw Ö¡„÷¡ËbkÕcð‡eȬ;ÐO¨Þ«¾ZOFÏBP%ÖünH¯ü>/¦+yÿγ|p=/Ä&Íïpí¸¢4ã£=f“-M¤ÀHEмÿo@ >¤vüÑvÝ$mu芴úäþ< €‘ǯ쳿M¾TëÔ×3‘'^®õvqš*ÅÑ{)q“2yéd‘(IDË“}” B9ê‰W–‡ÁL&]‹±À #ãÒ!F{P£®™ ðºl¶Ó2<Ïäyy»Ñ¢iYì•繋˙N[HVÍK"‚J"í2µ1Ô¤èdOÀ½èÆ1ƒ˜²õÉ!;ÔL¾»¤`R[«šQçКÁcº:éÿ©3Ö~ÐÉø¢Uý`EòQ®¢}ÇôŸ¬Å˜’­œüÔl‡‘@b{ ÙËYϘçåÉ9j S³–’7"JGèÂH˳}ÆÌkd½±ƒ¹6B-å€òeHb'ëÛ²^•¥|>–&§¤¶ñ™2Ê7¥aº1½ÇÒpêxrI\?B80­œ#¸à'à†§c¬;Åki޾Žm"¾õ?/ª s ÊÚ2ðj`jÀ<¼«Dž‹Å˜y·Ï ?ÄÉXøèM”ì¨û4‡çÖQˆÓ í›§yPM èB×ΰF\Y¸È_ÓŸ§î9A‹H[‰]¬6ú ÌÎ3Ã_`¼®Þr`›Þ1]ê:8 ¶Z|¢ZR‹ 9–ï3YWñ*ÇÒ>÷‡õŽo`_±rÏ„›%æK¾5%%;QDHñ6Sá!ǯÍ0±m¢|ANc:¹Y†Át/¡÷ô7{1=¥§"-ó X<‹mE„AíówÓh,Æâ¶ë½I ·µáZ ºP‹X‰?iøúëÒï–ŽÏyÐ}rÝz•{‘ «XÎо8õìº(© Yžù—ë>3}Ç€ 䬪&vªÉé3¼B*JŒe“\Ù|/Ô(é2lä‘ùÀÍàKøîÌÚÕ‹0‰(> ôYìV¤4å ˆ7š¶Îð–Yµ „ô·/ šƒ âŸuÝ35<²ߦK4èìÀ÷ÈàH`ÏO~˜ù ÎLcß3âÈT`1Fÿ¢eèo/鮟Zºüiâ üˆÙhSœÐkÙÕ /s×-‘¨hð}*d¸„Ë­[¨oÙŒ>·ý¶Ú™˜~W´9ÇÑöCÆ'¾6.É)©C£hÆI©‘«Ú(þQHä‰úW+ˆ×¬‘úmz=í5€÷@Ú{bÞ¦ÇO89×±¿§B UYÉwc ãc¨ŧŠWಅ#_W%CD¶Ø|[ÃæÍN’DJ‚dŠ›ûS(óOTÅÇÏSÓ8ìåÓ<˜$Þ©E÷'['åàѦp‘ç|¬2NÒõëc”ǯætår,Ó~ûaGðx¢éÄy/m*Ï*â9m§™Þ†>Žò›¯´…¶¯ý#"sAƒâ32UÖjÙ[r,¿ß…œ`ò.2¨;¤†ðç~ 5,aµÔø|£ò:ïíàL1躇Y‰mÈÿØjñºWÙ/Ñ™Wwý-fѳÂa/ÔÂî DhõÕàïvNÑòæ?ŠM¥ï9ð|.9ºgܵ8ÏÂhlbò61^±ör+œ9ű#…¾#OçÈž ùaö§·ÂéÃ'8~ }¡’E 4!¬Ÿ½øéMù}ñ‚:N¡?ñýŒR‡ ‰B‰ª’Wùަ¸°ªöu”²‚©öƒ\ÈÑï‘$ÊOHXòV¤þ¢öé»Y>å³®®ñÙµ*ev¸€bN¨…(.b€'èžk‚á‰a,÷×ÓbT ›Å†Y¶ƒ¾÷Ö°›6z1?K!s8Yæ¦(r£{-Å£"sb0ëö–±Ä>˜·pˆ~"µËÉÊ&ÈU9¨û ¾jøn^p~ŒÕÕó¹cõL™²Ë ZìîŒè›/ÐUSP±Ó ®¯óäŸQ†<|ð}³2”¬o¥<-„»w)—!Pa,û’¢)@©Uê/¼Az‹@oh‹'ã÷Pb³òo]:¤¤@…d»”Æ[à znìÏÖÁfkWugæ— nÿ:šÐÄ®­H#£Âtp ZÈÆÓÍè.-k̼æï8sèŽûº?Ü-FÝ—mÒgv¬âx¿‘Œ¼ƒª;èàሥ³y§ø´Ë)è>m$*fÒk^O\>õÊQxD¥™V–Ñ’ú ó¡€UÅú7‡ŒÎÏ“öntø'Z¹›Âx¹mï &êcpEñžŒ|ðUg5y…tBÚŒÛå%Âz Ÿâ¤'uo êÃäéæ.õ|؃yÉÇòÎóHšh:-gxƒ:ŸQi”ù‰~ý:ÀmHÑÎÿ4R4²¸—^VUÁF6¿¾àEöMV…d}š;³¯Ÿ“û¿æGÈs®U” luªòÐ-2ý:å|Ïl Q¤—3[Uª‡x+j®OºIÁ·pO™ü4LœýN'‘ð5áé4jìÛ‘8:Í4tH`ø;+kÞ}^½A,tOãImþAÁU– ½,âZNnnè¾½”·¦ëô™u±°.¿^Y™i3.Ö˜Òs “ÃÖÂäg@Õ˜j¿AÂf)u¤‚ò¿zuä×Àcb"4\ƒÎ_„Ù†ÞþÄ¢œ;߀¸n©„ß‚†Lš‰ zØò¦éRå–qýå}`GW̃\$ÓJè.ºŸ<Û¿›E`ë°²„oÿ#×ÃçÎ~Q.´Ëïêæ, !U –hn ß— æ­¬"ãж_îÞ‘Ó,ËcÁ<Ü)§V8Éåà…Û„®Ñ=Æä™]9ÐÎñ놘ÐÓK×U]y(ZA‹Ü 6Ì`ã‘.« í wü@ñ ­ª:ÏDÊòCõVÔÒs¯QÊî] Z½€9 çÞ`Jhiƒúl‹¤ x›ÌRž¿6)ÕzUäù8Ã1ÑMëY燊A ©ž¬`ˆÉ!ÕßúJêòÓn\TE¸°’5ÒKuméYæ½&Mî´xµò~ÒÔyò‚ßÙµVvCÄÅZ`ð·ë=€P}—– \r?ºIQ.–ŽOöÚ¦Óî`߈·èü­M Üܘó½ÖJ8=éŽxh‘-|@W z§=c ê¿¹6»¾¾ú?ïÌÖñ¿h•òñ\¶ñ ®Ô®D¸›§0âÓÞN8ÍSHyü±éìŠém%¢ï¤;Œ;šx,Ÿ7ÁÍÙ‹þ½C”Þè¾ K9Ì´‚ˆ3ɆÞz—ÕdE £Øj^+Pú¥ŽaS>z$uÍ ­̪·¢M«Ð“²·T¹{Æ+z­ð==UüäÎÕ)ƸÊÞÜWÕpi¨«9;}^³(Ú8[rÿÜY*ìŽÄ“|Cx]ÁÓ,6Ov‹Í‰˜¡þ¾ÝèæG¦3d—ÑEÔ×ÑëÆ»«Ûœ´Dgks†ÀЛ™;µ,>‡5éÈDÙ Ÿ…”Éÿç=O4et ¨`׫wùž!á YK›œŠÕª¸¶N<0Ë(0éb¤×âJ®ß¨s¾ëWÝâ±æ€>†= …‡öÝ|ÉÝòÕÃ"æ ñ+fÚ>ÀõzEËiA¨ôà3怲çöò»tÈTšËÖ@ï,mV¹˜­‰oîôïO†9yÅ3¸uD…É— Í‘`…èT.^ÆÎ²\8r®þuÕ XýÀÃÊæ?oÃ^u›™t[Ä »sãã›SX=fj«ôŇlvRc¦_χ[nÕxžñ7ýr8Ë ç¿(½"^ Ö›[òÕ­Ü5é"á]mÅ7÷EëÚ.SÖå.Þ€µ¦JÓý´œOy^ÉÕ.2ê2eâ¦Iý<„«×n‹Ýï‰2ÐZ4 ©ß[Õ‹pÄL¾ASžÌ1A‹áÉî>* %$<ƒ€}4^! xö¤^¡6WšªN)Ìáúôçn ¥Öíˆ+£¼&–KH¦­‚˜olÛœ©IhH¸YþI¹–´6HCùÂÒ·Yê¥'±?Š„|˜ üK‡Õú Ê2l³Ê™*‘­¢ÿP­5+}î´—È¢[Õ~W@ª«‰Â~­­B•³çUWt–û[W§úéÊŸá†nË÷6¯ÿÊ0óRé\sGIŸ¾•Ä¿#1;½2¼¹bò•<®u<ËÛBB:¦:ŽËCÖÆ?>í¶vô‰Îã2)Ž~ŸmVò×+ÜF (_èQ kDíˆ_Ö4À-µ ‘Ì«bBT†‡é $æ”fã *þѬ6ð-4½0,Ch Eúgdl“+¦hã[:5ëb-¯˜\Â8Äö5ís)^+òCu~Ûz¾·BLÀýyÒ`ÖÄ[ÃàÓzY”uÒ µûƒ v!,ÆŠª¤ÏÉÁjER ?ç™üuYy¸0jL¿&C¨‡‹W-h–àÈV˜ "”è ÚdN-·âiÉGt¿Ù—|Vm•ÒUPqyh¸@Áž°jêó··ÌǵÀD¤Gz+L®Õ@ŽÒ¥_‘¢ çrLøDÌ.eªÊIÊüƒÅ5±âÔ·ë] BDr9©÷Î_#g“Øjó¸DàâíÍýžÄ#¿!VK~+yÁÒLÃÐV%ØW¢¼ÿ¶†bw$ãVZCévHgÚAß„êìýÚžgta¨×¿%Ù˜([Áoð䔓 PÉ¿Z8ì—“·"1ð™‹áñß>佑'å5çôOî$ï0ÚÅoÕ ”¿Q£P,×dÑíÉG]¬os[BßË¿ÝÕ(fÌ{~'Jp|eËÈMÒ¢¾C‚–µ¿·õóóâ‚DW0ºwùk£E²k`ÙWÕYVTe:@‚;ϦÄÊu‹3YÍåV S1–cTæO~¶-ƒ„N[Ïá"UÀ¶ó—ŸÅI}ÛßÞ•½%îQn>@»aâ¥DßöÐxé¤Ý8˜]ÄñWNŒdD¿q˜í†œµg±/ÿ/G2]¶®C`\‹¬šæª¢¿ßÜJ›è«, CxùªˆQ ÎêAH¹ÈEºñ›MH côXDVé¢-É!PLj™Ûx_è¯g ¯×`bdÈ€A†c)oÈq ¦8…ŽH‘ïu¡<NDù`L=ß]ƒ\hõ¯¤?Zís·Þ€‡’@ù‹>Étãï²8½øÉ ˆóƒÅº³6©Wœ,WÕ[¬lI£ü˜¤KíBòG‹E ÎÆ©%x>MWYÏìW!=•£àèÆH¶y6Ü@#÷W„à@ ¦Ø‰mû)˜lj¹¶zSûz†W—Q:=Ìß\æOæé¢ܾÁ„?ÎNõ=XYóbZ@õqXì»ñR®+9e¼)3„;z!¶ðl˜Xe»'Îï´ýÉxK|ö­±Y`##9€YéÊ»m̾?]3½A= «¥W™Gškl0SˆI‰øE-yk?x«»G«:áó¢IaŸüT,+ º…‡³œ„=·´«Ãµ‚<0Þ.S mÅÚÖJlÆq-ŠÞcF‰SYÉ9³ºõ¬×).E€ÙùzVì5\R$Ù#©s\oÚ1[8Ù½ô÷×~36Tœ"ëh_ɰþ§±tÐŶƕ¾»L¢uiqSgÌhj ³™È‹Ø7¿{oùB½æ±Š ¶8P،A…·È"@G_Ò¬«­ašå·¬Ÿs*%`w~/›¼¦í@\Û<¡¿fõrGÅx 0öÔŸ€ük]ÂÑ.-—ˆýýZlWvW¾³¡ÊJD Ý@äñ€ šÅ5²òDü$õŒ`œ Lª9¥0ÂÁ<¸¢Š’ý=7xè£r´TÀ>KMûµôj÷Pž—´« ¿ùþx¥W›«g]¿ŽÏ¸ÿÁއC81 tM¾v4 zõi ®„®eÓ¡/,XÀ¥0bW ™m×C¸µ’d@>lY<×õè# .'†„úsMíËžŽ¡0ùõdß3ïˆ0{ Yü(}* @äû[ÝèØ2O»Óä Ú† Òiç°À]¶ð5—ê•ÑnS©< òd'Èð#P”¦à h4$u Ù¦ho$‡”v‚P‚|€ g½ÏˆQ±Ég¤õL„÷þ²M- )¤ñJp#Šg˹ÖÏ7 Lr¦©C=Å…Ó³ºÆP&IðéF;h«ágç*ÕpšäpÛС6ŽÁɸ¶Y¾r¡{ð"9ÌTÆÞõ·žÏ“ÌXT(œ|ùÅÞõ¶è°Sdž3%¦Àã­VyvžOáïXsZª?Ã\¦Q|ë dÌk*uyæz³ÝðWßw‚ &/9¡Q;qW,`S9½ðvÂÓ†éy‘Ä@Ò›„uÕÓ«{î!É‹n;vq··PÆÀ‰DjòéâMÎõüÊÕfãJõÂ%ÁO„{NJX ™| CK#ð¬H‚ô¯jšô”ž:{M›år3Üc"&ØŽ“¶ âö\  \¨ÐmŠiŠÓ Iù'WÌa+èI¦Šsül”.$ÓÕEßVî—A*s§f7uÅ¥xzš¿v—š^36Á‘º±wx;T1Ýwà.”»`ʼnP&ÉãÐ̳fEd˜Âg I &Æ-Õ^õh^®ôá0‘_öäU¦¼uª½Áƒ\d©sœÔ°‚FT´–ÝÝ ¬$’#uD“RÜ3Ê\ÊPv„ÀØIÂU·ëì ˜–Q€+ß”“2´kg¦Å×¶k÷—H¬“õ«š“ÐPØÊê"H,çŸ2CN¡‚YÙ™ÛäFìÈ×FŽ2Òp[ò´N›( õq ¢ƒþXÚ•S¶ S;v"] 0?ß„S× çS‡ÞYºì!ÃÒ—|Ŧ àöV¹<ÇP&gë ËÙ]¿ ³ Ô“vcøF{#†J Å›£° 0R[ºR–6Ä#ÒXït¾‰Ï[õëû•f(]ϱ¸åQ"+^ri/ó~hæDÖ-f¾M°Äùõºçv6Æ0V‘Ù¯ä]dm™ð˜Q²TÊ”,E8Ë©¥Éª¶yÙˆuÛÛ|bî Ð-û_r` ¢·®3I$9Oâ:öËQ`^P û„|4½žC¶OæH[8Äï*qý.·<öHl ZÓá§å¬•.ý]Ù÷1Gt:÷ÖO¬|ÿBKE†WoQ±þÁ®äsÛ;(~Ö±£5n5•?L{RÎVWFGý¬ã³Ò¦;æÛ²:ÜPì9éí‘´[@ïû´5ÕWîêµ'B~3`B$îîu!Ähù[SFŠ,rˆ|1``•8>™›·lsºB8KГoK>îd–MŽÂˇÊÌòØúa:‡{J\y‰"SôW< «ìѬ%Xk5qgë’ÿ„êÈÌØ%¹Ùî,™†—&¤yÛ]ûjÌL¤½sâY´GÅÔrp_ùiÝ32“ö"?®6hÏ£‰B¹~À•½èÉùyD:`Ÿ,x*ŒRb­ÛJÌ›o×H ìŒ6Ö\õÀðØ4Üžúrœ›‡Xà9PcÝäŠUûí ÁSÚÛ’«œí7™CܽK›· œñïÔ4®nz5±VŠ`®Óµæšk&Pý¯œ•;B߬½þ)î)ÔèÔÞ<ð[;‹±Ç[”/È…x2/%zCc¤AÝn¥Y=0 WõŸÎaùgÃ…öv…÷e7‹„»¼›ôÎbÁÎüÚôÀg6ÕÒr?5T›/À¡¹’’Ù'Fð'yþá óID‹nK—2dN”=ä‚„5åwp¨SÊ%mdðÓ©?y~R5k݆áˆ_¬4²ôŒÔÄÁ¼¿P™Ó!={õ‘q8ŒP1öÓaùÛÜ✛ªz hÙ¢5‹GªI]*e°Ê(ï`Þ»™ }¾BTÀ@щúÜ«ˆ²ûqÚ}vøêc%ì+êVî> ]¬ ÆÜNºø³‚]­ÝMŠß íÊ\ËM©§?©á®Ëy†¥ŸÑê£*^GË7òÚ|ºƒÖè‡CË6˜nð©bC=W¡K¤Ë –îÎP*=ÔÈ™>Iñ·tãLŠE~a]ûñqXbŒ€lq:Zãý29q/~œß'<ôoüE«<•êAB{%5MS?÷0»À’_ud .µžÖÚ*Þ7Ä+ixèLØ%Þ¤©žßÆ__ )WÊ –”%+Öêš=TV(.3WõŒ=&ݸÅà,%¿ÞÒ›Sø3ìo¯#}¬,…}ÜÍÚönE‰¦t¬É_Åú‚°Pmû;‘`ãÛðfúHçõ 0¸‚P?3úŠ F˜ÝÑp»&Tc ufƒ¹°¬W™ ÅØf¢ä×½ó·tafkÙ‹wa”õŸJÛ“Ëx ñ`­Õ Õ‘2£8uÆ´ÇUŸ9©«F¹2VLRàI¤À¢°HQN¯1K_¥”Ÿí»Ò^ˆ-ƒ=˜Liõ{Áñp-±æ;Ï2l>üÀâEжV7#I§%&ÛøŸ.u8Ú WÑ>%ã:nWs 7ðØÞ‰¥¢÷¼Ky‰ÑmL0ɘG=[û¬r£5Oo`+ï½Ñ¶u›ìS<ó¦+?£‰DiíÄkŸ:åî<õg„$+†~6àï稼¿|¿È@[[h‘¸b)I(šàKÄQZ484ø1Ù¡dØ¢}¦j|gSRI"šY·9*£Ô×½Ç(0œ;œ·rÇè”ïµËDšèí1 úçÓl{Á…ìöC V lkªð£ÖWnÁ±w¡VZEüù}z»n3`ã²}ÈâÒoñðËG‡ä%z•Ëš;¬ep{Û)}røeT|4™ðï•y&"Ýð`ôÀ‰mw®É²R‹³xŒÝJ¬ûó>­ßKÇCù ¯®ˆå|žµTUmfitÉ·Q˦ú°g§º«oq±•G^ï⦃ô”7I(ð¯ïX_Ë[5ï·á–2¦ÎÓ5V_ƒ”…;f°ö·ásRŒSM!è±Ý–n©„¸ŠWî†mô¾íñraß Ä{zÒÝb¨ÀÆ›ð–ý€_•K¯¾("-{r67ù,ë¦Çj¥ÑœCpV¯ð°®je9m«Á†PÊ÷ô–;/£‘„n×U¹ÎË@ÉTšš½ðF†¥1ÿ1éÿൄ0ÓD„}NÖ1På˜[wð(Ÿz„¼Yf¨áÀ‰Go+Œþ‡pL=èäî¦$ð#öûÐWÀ!Œ‡3û#£RZ}À|¶µ`©oTét… "Ò\˜±Û,<§Ÿ\ûã.Ûþ¸Òx®4v]Àª—µ0Æ$–†²Œfœ‰ÕÔ3o”J¿ `Ë×R…E‡ý{Fy·~rÊ;tŠ©"U)N×< ¿ˆñ6} fàqZÂb!®%f…DM@%zÝì—M©·êC*®hBÀ °‰j7í'\@úàD‹üVâë=2SVq2“¤ë˜ÔQj·®ï›m.lú ES/¿gÄùCÌ ZÊ/¼YJ q¹ºÝ¾ÂÒÃμáu¢R’1%ˆžräÕ Ä`8šÊÖόΣý¦…tÊ7XïðÊ<ð“Ê˃ Æ?ˆ™ãû;¿)Ûº‰‰òE¾KÙí>*0%DòIÊ ô $¬6£q¦ =ùž‡¥k"šœ1ðÚ y¿QžŠ /öïQ¤fxŸ<ÊÙÚ˜ †h/ºÐˆ« —)u¾ˆ¿?¥Zm6 ‘‰»è hhyóqÎ,é&p¥Ñ„š-UqÃúÞ7Ĥfo{(¢v»Í¥ŠÐQ—y­/µÌ‰ÛÁÕØe!`t¼ÞAûÚüI׆ÀØqÛvôSƒÔéjÃÈ»ž»8¢®H¨hñ¯,®Õ?âT1Ø›w‚w/< µ,:’~ÈJm/ÁÌs–*Cz1åh£ªk6;™Ù.#ãÐÒ UˆÞP7/±MÃĉ@×~Ïd·u­ª” ¹*j¹“?sÇ yg%?Ž\KÒ<Üæã¼…ˆ¼Ž_d.¼?ä ¶UÜÊ»™…iôÌeŸK5jÚ7½Ö¸é+ì÷ßü ìAô$墒šcFg­H3E¨ƒÛ¦Òª€yñz›¸®˜ û§’˜˜ßËä¶Og¹qÁ¤˜²Ñr:\%¡"ÛÞµ{nX/@º‰„¯,_^ôE¦=@!dÇ¥ýÉ7'dž8Tƒï Îà1BoåÀ§™û”’‘ÐÝ“íÜu÷{úÚI%·Xѫ̵J:öe~^A­´>¾‰ðAæmùãÓ©Ÿué AÂbá<ð‹Íœløê%º (XÜ L”ùÛ;¯Cù¶F=¶ö®ÎƒfÌ4 úP …´V,Æu„†ˆÝäÜ}o;xŽ•C­9PÔb«½oK@ûdöò÷rÔbÍy°è~œTq!õÌÌ9E7Û ¦’e_}­>·7·À*¯xŠÃrœ4å?Jð:P¿6EªÀë¤ …´ýêÀç;R€ôYæf7ïË©/á)ÑUÕë Ù¬íw×PN6©¥Õ˜BY[ó „c…³Î‚w¡§vàWhĶ~„Ìiv•ÍÒÁ¤'´m¸rÙv$Æ;Љ߀aQFø˜v9 sÆ'F”?¬TŽ  géÔýnW£™ü-õ÷LÞ•þ¶+‘Ä® Ó©è„<âÆLk±UX¨'`w Ò+nÈßó“ ï\‘¡›#‰2ØÈ¨ÿ_»þ(›ƒ`iŠˆkæW§°æOngæ¤õ'7@­Ê֯ߚ̗ÃMŽSèïÒéRì$Îe[Äí¯Uâ­/?Ôüä÷Q–wxOZCß÷@C(je_öã[GXIì§Ó(xɤº¶ˆZ¦lQz®¾øJ‘VÜþh­¹¿ Û£N°oêñO1²xAePM] ¹æËÊφª_œä“D˜'xš-¸ez|Û3[,§~¢heíŒ"CQë˜í%ŸØào[4¾|áFAø¤sWUÊÑº×ØìÐ…DÖ|‰/(˜1QÅÌÄ3 šcšdé#^i.Ü3£*+ì»Ú›,U‚™"j#6wÄ¡ÅcŽÃY@Vjá¹€ÚV⽸ÿŸM–7 ®V“¤x3+Xä”;” ÐÕN߆§ã^c(X­pjµb:jõë/á/Fк| †|ðWç/ƽ °!áLl”¤ýÃÉ]^ÌæÄÕ‹C}ÜJ,d[ºŠ%… yû‘+r ¾Ž €fo?$n÷‹ãÃlc£—¢Ž33¢ˆÕò_x_Aƒ:çŠlgªyÕûúÃàS_ï1]b˜ÇïÙ23ÎÓ¥©º¨ÖaWmÀ{f›Æ`ÒT9„žH™Þá# «A墱“£†ÞÕ¼–Cæ€ËQ®Ñf+ó ./øoÕÌš©¿’|²¶¾‚ù+ÕsÏ·¬¥7d\ÇÚA7­Q¸i–o™¤¤ÏA†€¹MÞ×€t~ Í1>,Ö66ã/ÒÓéÓËÆ@ñ¿W-XXˆJå’oī⽽Hïæ¢4>|çMl4ÔÒÓΩaìÐó °·ù©.òô/Ïe —Ö;,"à®ÆùšÎuØOHŸÃmÅ6’]‚I³âÙÕãn³èÞ;ñ|·³Þö³ °!¾—ò£ÝJŒŒÏ'—·À—W›’4éTB,á,îEMã¹Gü[ANê²ÝϘüs—¾}€ŠäS†j´±^DK Jë¥ý×"7fÄÏûh©œ÷¡œË/ïEQ«çå²Öbdœ„/â¢1¡Í)ö¨¸e«“^S¯»‰œuȵéÜ8¼‡i)‰‘šœ¨+¿ŽYI¯ç?!qÌÁbXS àGÑ­7âgÓ¬•¯Ç²Ij^>gŸ8׿¼Ný‚c³&í»n%÷Ö’ ÛKê5ÚoÃbÀ¦³1¥ @1̓ڱB ÿÌfx ^XÃ$Wt¶¬Ô$N´Ÿ½‚k!'F¨ ¢Ól×Ò÷‚ ¼nkçÔpÃÿxùHÅ}îœ#L ÁùFŸ2—7iílüÛ®Ç{ ¹jn¯Š>Ê뜾°Õ%uˆäVsé»—O¯}>ÍÿŽkÔi fiWA)BÏíÚ>›<êƒÅÊ ÌÐT:]åœó4êAm«À8„?†/4“d¿V¨Ø0+ZÞŠ‰¿§u#åAâG²tj­ä\ÃÉÛd“®­®°[¬l¹Écx׈gq tv¯ÁÈTóÇÍ kפÆ2œ$~¸Ejѧ¤ÃKS.ÞÎÓ'=Xýõ‰‰OJx¬]¼’^íӵц < À‘v -!Ó>îƒC‹¢qëãlÎFõW%$å-€––=ÈÓLuÞ¯yÎÝÿ”æj›»/Ãð…zˆÑP(b\:& ò|ê¢Eý©5‚›rml¤Ca=ð GHÙ «½ß^}#J‚FQë®#:BÚJWWwjHš0ŒQ°qwoÍ3á˜ð$ Ðê†RqYÔ€ÊØfuoω?íÝpÚݲ45¾¶çíèÏàüÿoиS‡ˆ#ƒË+0óéd„Ï ãÊ~g#cZM„c-¶NÎÀo m`ML8ŠÆIÍ—Zq;úsBƒ¬Má°Åkþ[I‡ØƒÕ1¤E0c¨4¤Ôäúc)òDÈâöÖß] ÃÙ0M|JXOHùT›çer¼OÚôýn,µt‹FðßW(°qòV¦³Eù¥.1‹õE@S ·?è:tžAѲ%…0Å+añF‚ Þdâ—‰ì&ovÔÀ¤´Z=èabÚ$wvÑŒF;©è Lʪs®fmÿ›%˜pn®À‚¥Ô±„%ï>ê`Ù›NF$¹ä÷Hº‹Ù7)W‹Áj¢Gýmý™C²âçˆxŒÿ.oe—½‘?òbQ¬l¤lT,Á1“ƒ&¾N[aËrä!«E}ãÜÿ?ÚÄQüIž––€DÕÍš|vÿp\í•>`á‘?â‘ !燬‘-oÆŽ'jE%|#Œ1èÓéóV÷ÛY³ÁA€ÀE+”ñÏÏÿ^Sé4Í¢«k… ÈFðdh­©FÙÛ $Ž;†»Ä«q)’'ý‹ò=^PÊ‚:‚|6*©·üÍJ‚| >APäË<—ÕC f¥?ôÚTaù&יᢥ©‚O"T‘¨õÌò7š‘æLò< J¶3¤æ8w/¹„œ½ÏÒòÒîzбÓB}´x?9¶zÑ:â©je1c'•=öÏÖÇEL>fßRåä®Ä€ÜŸ 9Eîž<ÞþT§ ñ²,ÃËC¬=ð+ù]¨ÃÉ'*¥¨É¬¬[®ZÏÃèÝÒ™pŸëX+ì–òñÜbÕAdov˜*Þ7Un$Cö°±Â 뼯v Û°aÇà¿e§}uDjrAõëwêDôåÑŒùvY=Z,ͼbbŽìŠðTƒòáÕ|ù‚¼ñÚðú¬ *iÂ’ô—pq›ÏŠQŸÈ4ÂîÒ¹o­*µÝÂ?æ¼Ì¢‰Ô·€É`ŽI:”Y3]GösiX²²%ߤ SÏHq«ÞïØh »ðq¸HwÒ'R=óßÚ=MáLl:oê›õäzé /užˆ<)P_ËHÖGŠŽP²[{¸2Ê9k"XSncm“ÿ¸ßSÙ>ÿ™Ì{º· zk4ÂúýÚÉæ †ä”h¡^—aUXÈwÔ¶H§’u\IÜk¸€‚ÎRrÚ²,Hã‘ÜÔrX¥מ2R»¶/ׄÊ3ønš¬Á ü¿å‘•+v«FÁ>ºézHg`Ùð wžcÄ–û{?6܈EŸ"/ð .c®IHlVV Ÿµùžü‘GY.Ì …´êq2Ø(tƲ½Ї£M¸–0Q¢l|-¨Ó/mB|¦Ú ñµj˜æÌRdÿûK·Bm+QÜ ˆd‘((<ÆiÌVgÉ>ùh£ÇæÿÙïnxQ•5þÅ%·‰93õóÞRW2 ËS* Á,I<óB}æÎŠGs7O(SY“†‘ŸJbj•¤Mt°‘ê¾^[™tòODCDRæ5^˜({ï+HžÌgî‡÷•À|ÎnϱT¦¨N¡‚M/¾ÁñØâ`{=D†wa[t³’Fý¥óµC4,v¤_Œä>LWÂüå7;8ò‡ìÕ2=£?³Í;Žn_ý¤!¿ÆçXu¥œQÙ2T|¿42KÚ²µè·M€Ãÿ—Á3,B«}!Å´…CCõœbyæwÚBÍ[¯ÂoÚ:ëgGG—_%twÕvúSü\¨’<éž »ÉÈ…‹ Ñ"9’Õ}º6Ôð‘ùçWȵ?ú—-ëWþ…Öa´#Må‹[NÈáLèžb§ìR—# hÞ,j—àaɃÈ&@¬®êºfZ›©P¤­X7ïšÙ§E›ktÈ¥….taRhŒ¸ý9‹¶m=J“%»d]BE‹×5ü ¢äÎY¾å¢×çC!èjYÙØ~ªl^ëmtje)ÏÏÌO èÈçrœ_ëIi’çŽVV}ãIS×|î¿]ÿMäÁZ&{1OÄ [OÍ•Ú&§®|o)?ºjߎu·i'¿Å‡Ïqj åçÄ´Òó©Y…õ«Óô Í ÏËwõ¥Öù¹lI“hÿ¿>• g©flô«1·d+K™šmJ]EB(ås×&xA¼½Æ^…„!o‚òí° íu@4|ÛëÂP™ŒŸ§u¤½µ“vEwMã±ØÅ¨j`°öÄ;ã,bñÛÌöŒôoåzt.¾7àÀ’ÒI²Ý n¦×­Våêq8¥rϘzçëé¯vGèêB/^µ_G)Æ0‹ó‡ &ÅÌÔ®²¸“‘=2ö@4U8üÕRŒDÞž÷]<›Eìï8bŽyÚg¦>©%S,éªDîÛßà£ôxàvÕ8¨Ÿ*…ß1ŽÄpS-zy!»pNeâÀ_Ï DFWéõ™ø6fGjèˆÌ-uÁ}#ŧ’m}Ë'¸•cd±©ð:ëë|¸Î¥ŽñýðHT!Ã2Ílì—“” ŠavÚåy÷KT0ªQLZ6aŸØ8Þ„­è&Ïpšû4®6(ɵ.êË=ÖWæ‘ýT#šËŸf| ÜÌÓá²PiÿÝNÙb&¡ ξÉ… ¹Óÿ€±ŠUý#¡µnž ïõà:®Œ}„A?|3EîÛZÎÅm}5ñ׿oÆ%à>¹ä&ÐÈ$dW|ÀBqzÙ¯xæÃ)ê‡*QÑ®"z¿V· RIièän=†Š›éwÃ~(Õv½ëºRz›{:H‚“â„s÷:´'ïéþ·¦Êv[¢Säè±-Òæ”¥ðÀd—i€[ø©Þ|€OdY¤¦´ŠŽEÉjJMuýçv¡8Õ‰—Žuj+½os\*]Ub`xâÆÕoú<žÃÐ ×vÍ><ñIó0âÒ¼h§D ‘V¢ËˆCóˆæy¹wû\¿F¢ÿ³×4ŸÃ0þ‰¢Ý@µfX·Gö–=í zì[TÇrÚhìë<©ZS^vâ :ü‰¨ž'W‡å†îqè«d‹- Ô¥°þJz .cÍÛ_´kä—‡Ä)÷œÿ¸h ðÑazPf§G*íŸ[ðVªüzHô—¦¤ð]=®³°ƒÛÝJÛMÓé v¢ålyzâW3C“@(ñ yÐÐ)V£4¯ýØZßp±¶¯Töp”cŸ˜½ånåÈ ’JŸ¦-<¹zæÌ¨5=è '͸Y l¯ƒ,šú?¤BL…,ü‡`œm‡Kx¶ž„l¦!ß>´’OŠôǾ£Üzäz²üä‚P`· ZD/øP»Þ;@ñƒé1Žs›E’â>èC1 uÊÖTHú=ç# l—}îÁâU2A½bU5\^n"ÿWÜÒЖ9q‹oÂfL"¨9ß&ÿB ã=ü ,XriÐ-_öhÀ‡ðÜóI$#ÒÔÎ=Ç!|›¾#ä'ˆ¿'ñ[4(ñ7‘ƈè*D0Twë’X|‰:ðã¿ l(ãå\_§¬ù–sÀõ¼V Z¹¿ÕÿŪúNÂ’Áƒ'ÂŒç]â1K«]®£˜Õ½Š¹K²0ãö¥ü2µÃKµh ºF{ªÜG®Z¼z<³Úfå€iwj.™ÒÊ…2 =sZr_I…"ýá ‰s¿¾…å‹m3Ï,÷ÃÇ düÞÅ炨øù‘OEÆÿì8×õ±n5·Ì$iJVeÓ…PÚx`81P%[s7|€Šè ͯ=É]¦ÌÒjGN>L‹úÿj:m(½F²y#õÁ²Ûªzús¼û9ø‚SâNUäoriA ÃéäãìŠñÖZߢžJ¼k¯À˜\CœÃÃl~_Ѥ¦ª/°9Ñ—WJDÌûD˰BÄ?W†™ÍM3.‘òÑîB#¡Ù 1ïUÎäq·^6Ë”“ˆ”öBÝvÃ>,ŒËq<³¤êé'Úõànð]¨µ­yj¶¦žþ' éw “4‘¯²3¾6tÕά!{QטmôÉ=-Xü’@ë”EcºêOYÞ.ú‹lÂ|›Fާï€Ò?ÆrbúÀRD'Ó”i 2ÆíàŒIä—E):(DßG8M•AЛƒ–²á*WÿÙËÖnù¥Ö˜f'=Ë=¯åËyEn8€¯‘S¾ÉwÒÜù?W3Çsƒ…«Âqüöúe×®2|‹ÃT8رô6bÌÕàü´q¥rf‹âà#‚²‹¶60P²Èd•ó½34,7¾ž\¡eTò`‡È3ÿO?WÒxÛnâ} SkèJø./)¤3b÷0g«@àÈr½zwÞ$]bù‚š!·LjìgBêÎaa‚ö¢•¶MþÑ韋Wdo`!:Ö!³+Ü2Óv-ÚáÜÔ8æ¡ß2|+ý ¦ªQä}ÙnºÓ‹0ÒšÔbÞâµn#wí¨ÆþÛÛ.Á¦a¨hGùj`«@S¶7¶eFÕf~rûÃh™Æ^ïø%,‘)y-º¯ŒØ^ˆAÉ·Q»xÐm§Pø½;]QàºIøÄ°sýºtÂoGScý ŽCþz\o#ÕÈ~Œ]ä~ >-úi‹Ì£½k¬z¯V 2ZL˜!_dÿqf3¬¹Ô‰J´ÿ#xÞIQæâ„^ÐÆžt75ˆ]€±nçÝZ)/Q=hÚJäwT«Z`­Rƒë“Î)áæÏÛB¨¨žª »¶×ôô诤Êص‹!€ ˜2CíÔq—ÿŸX\óT¯qöWÂp‘4ʆþösånÎ2ŒÍwê¾Êð]%zç€ùy y":‘”é£ÞÓz?ü[¾êÙ³{fâûkPñMïv™1`{>ø0#‚¤U¾[~ðbpá±…ïî• ÊåAa𷤱­ãveïüÁ‡JŒ]gFÖÆ·H'ïr¹«ï?ÿX1„å<jLDtó{!‡üsžh\yv€07—Ú3烜SçùGz]shŒO)¯T×G,úzÎW ­U^ï f9nj:ѯbh3¥[À:ÉèHjCÊpÎM+¢MW Ù Zƒ_We¡•â#–ð¡7wå¥ZoSíi¯£¿ÎöhäsáfÿN/¦Õ÷7 •6Gqó0…;x…C.¤•«Oà¸ÒviÅÞš’ѯ6··§Kè(Ø0â%s}®w*Àu#I¨ê<È…b¨`@B}'…‡¥2GtÒ7Úá÷ÉÉ4&ÿûjœ‰=Þ5@ç×Ï5õ-–ä¶@·º¢VÜ]µ<UU”`TŸ% ‰”L†bŽž…,Yë+¹éOï`ýA¿D¡è=ÐlÀÑüy»9 àu€t/%pJ-W݃ÿíáH‚v“$쪢À"ã c=bÁmi3=(ÂcCy|Îáпz)"Hछ àâéFekP÷q H*ì\§µçe._¦Åð?ûûÌä—duWÖ¼ø„EªÎ³§QNû¢}9𿾧á2ˆ¡.ßÊ=6 âk‡fW½0~®á×k“ ÅÀ>ü[£«„áèidˆÝ¶Öüìn=ḊDà´Rùl"(äeLhv¾EfOn±ut„ÒCEÂ.‹.¶.ÚÛ€ƒ^:ÆÕÛ²Xú8wÕt§=éÙ@ä ŽFs¬v‹)ÏÉX*4•ï.ñ²Õ ò:äƒÈÐÚNò#ëyC³}ׯ±v!²y5³•šH(þ¼ÞS©‹eú`늘X2†Èø™T`Î8~mÖ3}¢kŸ ¬>!tÏõë?TÞ”ivn†§…˜n¶_ÿ1¸“À•äpUuºÛæ©ÉL³(FD¡z¨Ã™Tö½ÏʉWÂÎ&ª 9V÷öÙÞ“Ó,º'.ˆ`ˆ›¿p3ÊŽ8ñ%8<<Óª}ˆYw‰ä×ÈŒßr9…ÅMûÛó“t@“Íf ÀgÇ‚#œ¼ÌöÀºù=åDåœÛ"æ–36#¥KÍÚ0T¸\øÏn#‹öÊ«ùˆq c)ÖßzaDÅ& n©ìÃ˽¦!{wY —=²ÌÕë¶š9jã¦ñŸû޹Ùo=ÚèbõÞA±7D n¯Hɵ8«Ã@qvò&ÿ-%M½MK°×7ÜcãT?÷McVuL°â X3¯þˆv‘²Îwàž âi廼£9\ÄzÝòPLúšÂTþç”KPü´opÉG¥–/ks@å’ð½€ø°‘|°'w±Ga5DÛàØï—NEÚÖöy‘¸©MJ½ øÑ°±·‡të—6ª'yׄpdH|q¯\G²óçÜuÆá¤Û¹ü+>¡çnúÁÌ[Ó)K ºÒØU³B¸A¤¿)(mî"”.œûçžÿÿ÷›¯[صmf¾Î£:ÃB$Ë×,? ¨1F_—z@.üÚœ&ïç@ø¦´X$SÖ^¬ÊƒlïP&åZMZ EV.»îO“r6Çâ,­½/ÙðT\†|¾0cÆ öëŸ8¬1{ž›‰Óa‘P¿?”ƒT;0fm%Ö¸\co‰#Þt+ÚÆ3ƒE\»Õò+þ+gŸãUó²ÇDÔ³=.yžÓ2~rø:ë µ»ÞCeЈ²B1ê-Ê Wæ—|šn·ñOxI0Q¢ÞÀðé'þïqoz5OÔm³— $²TçU(;¶ìĤãq·i䦋8Ô/çÎÎ÷›'˜,ž.,"¶ã– ;Ÿ6Š·¸¼¡»,4 g². ùAç+àX8Äv¿_BB#Û´8–ÛÈKÍÊçŠCv¤ÍA-ÛÕ›aœ·"P‹AåœÏD¶·~{XޏÊô‘,ó±­aN™ º_˜=zíå9.†æ†˜ìÝ„zl­Ô±C½°¶Ð>»ë¡JÜÃÀp‰}¿peçñWqi’‚£[ª¯¡·àÈc§w[Uçæ9¶^i?—¶þ½0¢LYÏ`>¥Âqû%?ZÃ9¦W.T–äž+ev¼ž_ Ò>”.¬\¥[  —gɶã²[@Þª|¸ºu]¶4#/¶x¢ƒX«€%4$ôíÝzSÀO»\C9`­Ë”–µ¼¿®u†,;7²Õ%nY§ö¬ž•ÊÓµ4)‹_£VŸe0Eleùw›ˆ…D–zÚq…œ°%XòO…›p¼inݪ9%¸$T{ʵS'Š¥Øÿo­¹j0{Ȩb=mí;H¢¾ß«ú?p¦\‡”Ð\å?GÐnÙ²&üç®lÉ-Wæ ²µv KòÑ~z/ÅŽäî’Ü”ÊÈÚWÑÔrÝ4ÖÔ÷,e'Œ@\Ø8‰5ñÕÀB÷õÂ/FèQ-Š]ò顆€øúË9ŽºîšØJ6ŽüC“*©ðÑkô ÅŒ–ž&õ‚׋þÀócî ´þ””¦ÃäM&Ë ¶nÌŽ³Ÿ_Í2VÃqØÕ€Î+n L¥ý”¥¢³´È<槬èÌ4B.ðÁøI˺8Ôë•­À?T1kV}”ºñU©Oïz\ÑQ„zÇ=.ßÁìX±SÉŠ šûðÿ5Ë̹‘½G^ºfíÑ >1àlo]¤JY´sŒ„·šè³˜¦•¡ÁFÌ+ä´Kux¥W³ŸáE¼>¬Ày Ì«"J÷Oéþƒh4Öú‰÷³E¹uÙB™´¶°‘~b¡T{P|ÝkD½† ÷Ÿ¬Åç•¿kjìܰs©™Ý\{rGÜðoûÊp}³³¯TaçJòfdTÝØf€#‘œ&1'i‹G¼iîŒéЩgŽg@á¶ÿ ƒÜk‹¹ž“'ëÿZKBWj4)€ö,-F¾ÏwÞQ…/­ÐÈë _Å‹T»‡ZãŽn¨¯@†Â§šŠX*OMF[ÉM§Ì†c5R¹ÀŠ¡Tˆö2‘‰‡%óRÉ0LjÙP½Ñ&Z± ®\²þ—ý.gËD™{‹ßãÖ¯}È×R”îiÅÙ{Ûtø¾§_["GR",PÆlulš$±Ä›PªKVcŠ™/@{¥G¥Èè]5¼NmÏk2“[À|3ó›/2·Š\ŸŠ.±/roñª—{ú‡`¡Ò%&Áw¸½{Yo(â‹:AÐ+9É"½Óç÷X_OŽF©)·Lq[¹xž(ê|³Ó ú~Ê×h8P6¸)HC·KÉJBkëÇáÙÁà ƒ“·xEò—’¼©ó0ÈQŠÉ6õrv¹u¯Cý².ë¨üÕ]su¿ÿæ¹ÇYøcí`(¾ÂSe>dB՘ЃÍÊSõ¢pâÃîán6RM֨х…¯­œIÌUl(…j&§ÈsÀT¬œ~€ [xò0Œ 3ï¢ô©ÒiG”•ª¿%}' YÞ€jBêU²W=®u@H¿` ØN†{Kà@+¿d¯T‘9ɼ}æáö(# òÈ2&Wм³Á`½?0[+¬}†ž7‚‚ÀFk>'„²í–"t(ü‘uñE «¡œ/«²hDÇö_Q"mÎyS$’ÈÙ©r¶­…ã¤Í}k RJ¦VøM_ÄëÇÍ3›Í› „ù§hÞ"‰~T=Ô[÷|IøÄëäIFsü5Àñ%Z´þ½þ93kÝ^PšÀtáµ#– Li_Rx ö´²­±Yãúœ`ºÏãÏ^zJ²¯Ut]°ÑÒ¼ò\F[7³¶øyôÀ#‘Šà µÓ|ØÆ•J#ã³Ð¢©h¡ †gv°>?˜ÔÐÔ-‹-*Ÿ77Ü0Þå›$û n0ÐHÓoÎ•Äæsê€ëFJ²iɈIümþÈΛy¨‘d z‡KÚáwþŠuâ¡l3€ù_'ì÷ËK!{ ʮ ]AèLMê ˜‡;½Á=“ŸÀ,Xb¬ Õu«àü¸¬‘;dÿ‹ŠÎÃÎtJÝcFrv|*¦+Öáàü„ŸÔzŽô¨l.0úwæ]$gkõ‰ú£#2‰ 0¿êLœc ¡SŽ‹À3é¯U_HM%êúv°´@€y\3{æ{$.ÇfíÄ™àt­X(iØŒÛ0ë‹Y¶QUf‚öÁ¹®‹Ôq¥Iº/SŒCozÁ³nT§€ØáÎ6+Jºe¤QÆTBsÅЦ{hÖF}×Ä"˜·pk¿ÞývE¬¬Ê>ûžc66jWUxÿضµJš 9fتÔeU:Kæ%ÜÆ ÂUDŸpm{ö/³¢VS=uËjß§€¶Ü(sKnuÈ÷ AÉ(Û°r¯vWöÃG¥ùŸ»ÌIX3¦­F †à(b„'^¥gû*“B–¤10xí‹2TÖ“FcÐ'ã†ßh#Q#·„‚¤à9¢<|=ûQKÅ…Á´¦Ó„Ø'i6lWÿ `þ[)Ø @´õn(òx³¯Š5+š[‘ø6ì3Ä&zÂ9컟;’t®D’iŽbÂWßp¾Hv[êRëGŽÝ(c®”`â@ï›ß‹~€Õ¢^îÄ–ÆÓ²R[œoü]Z$Ö Ý.Á[döž¾’2&:ñæ¶ppù_Wu:ýÍoþ.™X^€sÔU¶­Ú# ɾ1À lwÍ­(àæÝ¨:Iè©g_žÁ±°zÔÔÏ0—\ÌãŸ¾Ì g4Â×âÑ?«L½ÖÂVÜž¨ó¢ëìä¯:ËY/5’JUÁÍYÊ\†ÉêP+°êè(bÅã‡&m%o½ˆW3½ÛÜ” ÿ9·Cy›ý;ÇÄö’í{^ΞðƒË8œ¢dˆ³n؇ÕÚâº~ËO3Áa¦"³í‚ÙEŠ+Å£…q­Ëì|qfµýÁº!tíuºOÖ/²¿ü´ò"n#'²  ZU•ÝçSnŸÐëz!r‹'p™Öíx³$ö‘bÍBÔžfx삾Ïçz0 )xTr謗æºpœ¸[fG5/¥Jä€Ý£Þü¨¢àsb ‘€©`° ã9N$ã\žä‘·"àxPQ+¹ýñ¦«–•*[–ðšj`itó<ôÁ’7nÒ±[ø e… õ2:¯ÝKaáËÒí½Êj6‚M ¬¡êf.8ßÿhä–r$߇;À2Ý!¶´Û±šƒ‘ãù‰=€]:i a'3a4DŽ/ÎËj÷Øÿs¦ú଎Ÿ‹Ö× ´ g .£«>3 ¯ > ˜tÓLÍŠõ€`]ß@Jh , ÊíÞäkÎà ͎e§ˆˆûl'ÆÒfbPúðç-€Kï¼ÒæF B'µÿ™Rñ%[¡ Ðóa]ÃÓÝ"ØûfZ…zUgGÇj¡r!¬/ŸŽÐ›Ílº¨C9ö·mò—üDöÈ|äB™Ð×¢GhÇŤ ãfýß/ƒõ¼¼T­''ÎÅÜ2ý͈¾¿X0ÜÁ‹ <6þ»–j×"¶Žº3Þ P$7Bí>|³ÊÀòÏS¸ò¢Ù*|8-ä¾Ãòë†Ài©äHÕU"ÁUº&ç/žåOyfó¹‘~1g$ÿø&÷7Æù‰* v³è—á¼9"T<3}.ù¨U›“`øûB{a)¹¡{±äN$?B0}Ù˜ñAž¥–XZ×°MÄY,8 fõ„bB¢mwydiêGKñ¤Î솫¿øBNåÇÄÔÈÝÃ/ƒ¡/êÓO#FÒm„kòdßú1–·¼{ôe­jæ(êЛy´È,(]^Æ•‚‚K*­lkûä}/–ú±íÝŽm%‹2MYöœD]뿈RsЛ[òÉ º‘ýÄHR|Ù0¾qD¡g>I<º¸ .h› ¬ï®QL¿º±<à³»F¼ä„Û÷♋çÑþ{]T"gjÓ{*Šwúá«ÅÍi9ÜXámàúÂŽÓïÏœ!ZA#l䦄MŒ€§÷,pï©c¶(œ‚¼ªè?ºÏm¯f±â§â_©’„ëî#gêÃ15³$‡ÔŽÑ£t€±á,ÚbºÕH4*ž6`5DZk¦æ$ùÙ+t¨óå½nÈ*«2ˆ™úy†(9Ÿ¸å§|ÇÅÔI|b_­D pæSÄ<ûäÙ×Tü! q±ÛàO :"—ÈhDÀ@‹ ’\ùCxº?¡ø@˜sÉs¢²§|Ü×ìs^Ç‚ÃpôuêÕ5ÄrG GSÞ”¡™:gmÿ¿ØÙBø;1ó^Ú%`2Å{¹aŽCQµÙíx;9ÍÕS Å¥•%ͽ~ÄáÁ-¼-„³¿ã_““kÞ0¶çœE&ËõŠt<’sïÕ;$/sA”ìôò¨üÌ^—¿- ªí˜ù\ömOT=ûH¡ B·P-ÐØÂí\Ûc¹¤ˆ4æ%{‹P»F÷çßÙ ¶MNžtµ<½ÙI"©RÁ&€¹:ͺ"!/gõæC-6ÒQºÊãÿdNlc(¡£§d(d ­ifSÇ_uÔéCç}ÅA^ÿ¢mV#„¬!ï3¤âÙÓ?>§¥t£èïZ9“R  b&‰l«Ï®h¾¦ê&Âßzêü»Ù5%Òë¶!+ĮSWüü¤¸ph§°ÛE]Û=ÕˆÚ0<¾%YwL¤«ýÛ\Ì}Zþ]îÏ3«ÐÂwÛ=M¦÷ŠoIK­šr4"¯ }Ý{V8ê8 â.åÐËáGq^ÏBdå 3›q¤¼ õfç(Ùÿjçœ[­‡–ZÑüˆp26^bc'²+u€t"›%n.Y?£@ ³a/Íe„·j_)#,«¬ÑÊÔ†ô Š'ºëG|é”Ï]Δa°!à<„®[;1aš¤ÝŽhîiª›íÿbì Øâ92³ü¸ÂóE·+ c&MÏȃ­VÍ*̳=•J1ö‰È^ #õª~"Ûd€”±b÷¹™SmvíæÑóBÛJ-„ Ô 2ÿWS&¬úk1éDíI‚]ý*.œn¶¢µ^Iú§‹þ£ÏûèáUšÊ ¨IÞgW%ŠM'óù&&Èb¾–s>…¥ îÉ)?¤’Dñ;ˆûv3rB„0-ÆŠ9@uøBÓU݃ÇŒA½4Ç’†Ú.WGukÈÍùÏÏïµ*ïÓQE¨ö0käñõšµ®8¸=– ˆ½ìàWø•™éÇ!8P¶'¶ ÇJ®–X¢@[òMGJˈGíýé çÜé1äJß"D@áâvŒÿk+¥ ½¦"K7ÙÍ6*÷Œ~ëé›ïu—HÉäã:ܺ·F-ªFmo‡…9>“Ž:gŠÍºŸ~FUòÈ¥Ñ× °@ Œ…>,~ÏJkü¾$°(n¢á·|N$–DÇ3å̳º<õÒó¼=’}ÝH’’Þip[ø›ËxÏÆxÿ)Â@ËÅ&ÁS—8Àjå´•’ð3¤ »¾€Ð%@:㱋’ywq„zâ‡ÕÄ çERætVÂÖ¿N­šŸËñ»r§ÔÉÑ’ö›„mGRåJ㿘c(“áÅ"éqv²Ê š?ã{HÖµÑJ­ÑxD‹ÃÆM—Ùl‘FUiÛòþ%(L5Ò‡‘Ö[º¸ØlN@¹ï‚"¸&æ÷»î"Ì2¢æ…¨«,ɸF1@ïŒÓÚcøÏª¸ªKÀe°"3^ަjáû2±ÜñØC=Ó»’•]IÁ®†¾¤š[1§™§ÆÄmiâle &ÐyI‘r‡N`Þ5ž:¼Éãõé³¾tÛì2W ðÂ’ ƒ¶œk›¤wDØcªÛ gE%™}ë=)1/´Z ‡žl^‘+rDv•ã™Ûû£½`ð…h<žÆ8Ÿ8wosB'«¼˜ mãö…š*˜¿ »Ëã6h|å¯w 45L» 4´ïtÁAN‚m”Seq\­ì 1ãV ~ÒV&ê²¶üÞÏù½©ó‹£8öøÔôCHRÎ÷æZ9ë6&Îéü¢=lþð–ð¬SV“æaoÚMÙQ³ Iìó3Œ0IâTGÉÓ\Eñö'½‹Ç ¼°—Â.r¨Ã ÞÎm>à‹>><³|!#é›ÐcvY™C{ݵ®²É(ZËéÝTZ„U\ÜŠ¤€†ËEòÞ†nñbÅÜz(E‘fä%¸{”{þF6Ó_!ÅG+†ÞcrA¹FbLµ²[1x˜/*{u„¢î·!vÝN¶E[û¨5™ÆÊqâ>A¹P%Á![k÷kêÑï’ñ@Ga•z®¨ò>3{€üƒZ†»øÞe3é %û/ˆ’÷ÁÉîèf†7š Ï+~$Îhãfd}BÇ28|M‡Îÿ}Ãw‘œzÄ£%ª‰Ëù¥äÄŠÈâ}"D.ðí¬QÛgd-(k,ýÍéT[•n²à ±ñXµ@eŠ nos›ëKa‰¼ ²¿ÍýÖzWÒ =aÿ€VEw9ì£n<6óÂfúœ'ðGñið›2Ò^Þ{0vÿ6S€55 ¡aÀõÁ‰Ùÿɼuæü« ’ÀùYÔêo¾[Q™iT:›ó\E»Bt-ç¾H fZTÓ¾Áßëî Ò‡VÌÏÓµå…l|îTx4-d¼–òÄl$ËT±…Óî\º@3`ÊÒ„–l™˜ ®å­#òï@³Û UÏRè=aKoÖùlšÁ•ÐÞ¾6Öm}'oEEHE§Š o||DVÅ@Ò#¥èÃn&³r¯!ááÉ@ps|Ï¡S@â9=±šÚIêß(ÞñH¿!þËq;!ª¡÷‹Ã•ÙÛ}çÄ­×È,|(êLÀ”ÔOi*ëÅ? 9ˆí¨Ø)^â¤ÿš„ uû|(ÓÌKu_A[—£øUìÞ­ÏÓb^؆6œ²ã¯Äm³wàAXxí NËU­#ô7˜Â-5àþÄü³ tiøžbyc¹àÚ&Ñèðº½ÇóÕÎ{6®CÐz•+ïisçdØÉ[?s-èrpºéiwí£.ßôO`ºrw°¬; ‰´ÕÅ;I{N‚"0¯]¢'}`—9ŸS„F9Í‘¿p€puÖ„Й D1‹àz_’P6á€ßmÝy*’ÓFÔ6¥'Öh#z*ƒhT9aÕg›ü‹?½_ý<ÓôÃmÜ~QpOª3VÉiaœµ\INò¿Õ”'‘ð ó‘…–ä*ø1ÛµèˆCAãÄ-õ^œ—Tîêÿ¾I¬Šþþ _µP ¨ÝWd¢Œú]ò8ïäJÑÜ:òÎä;ÔUÖŽä?z¯~ JTp^ˆ $×ìY '¤Ú<çÿ¾£Þ3±¸ Õ*ØöíÞI¤wÒEfqîÄ?2 ;ýÜ‚Ìþ´,2X䚊eÁå NþŸ¨2J;¨ gIQ6塎:SÒ!lÊ÷{Ç=€Š'zf¦PÞ[]|åfÜ´w€4-°XXŸ€.¢ÍýôIcåuïNfP„ö‚ÖÜ"Šižñ`^`Ë qQ(æŸlß)û¢š›åR¯}Œ<‡5{y‚™Œø$f¥î¶0Sæ(ÎDJ’kÀÐGB“TòÚð‹øb\Ūf¢ôûöW O‹C¸Ãµ²Üé˜ÇÍõÒã•ôÔÈ1&T[¼Ê‹R¢í@œÞÛ$ÍIùòb„T%Ù²©¿†qxrRc‚S5ÿUS o#ÙÚ¶þ-±I³Ô>~¬ò©R(8K'ÌX2À)gŽNCð]õ´ÚŒÇú¥ï)êÒRÇ”–HEîí0lEÃ=«ee›ÆÕïÜ>’<Ö‹ÃÖç†ã…øÜ Ð{þP…hÊ iæÆÔP-¤ó'—iÁ;T&U˜8 e ?é'êÒ'™Ú‚®Ô,‚Ô}>÷<Þ¢];XDWŸVðÐöëR'XF.cä¬%)à•IÇ÷uœÕÒÇÍd x†T–—')à\‹h¾eDM°§ˆ\åy4˜—lœP[ì“IѰ•ï9nÅRß]ÎÔ«~çÀ0à%«}>XÐã»}Ê6å®.T÷ÔÍúÍwµL˜üM¡fv6³·>ƒtÛ2šÀµÑbIÍ"%;b½¤³„È òà@XÔ…¥ª6@¿-(.´ Ì(DËG×%4ê`T¤³,´Ï¬Rx[ŸøÊ ¿;Wäñ ¾õ§Öë3B–N0Ñîç¼Aj¯‘‹– g4›¸ñ¿F6Rê†0_Ú]šBKÛM5yì&ù,â=¶¥ÉV¢ºŠÒÉÝ&ãªá ÇɶթÚ¶á1`µnhÜ’+S²>Õ·ì„ CØ*'(ò˜<ù㊨b˜Y&ã_ߤÒB= äZ«ûH#îÀoÇv4kÉ*–ñ>ÁyÐâÿ…õ5OQ”Í,çDO.ÓˆŠ6ñ/Ȫ1_¼SÉÈRw¿{jWÁ¸½#+}±JÒ,^6£‰%cw´›sì¡‹^é­[´m´–'Éѽ9\hÿYʦÄRºÖ”—y=»ÒMan£ÿíO=[OíG×n’šÇ»!â£è-#ŒfžÁYk:˜sVl-Â$ì›EþrMsÙËg‹Fu‡+äМV½°í³@ó2‰‰©h¯÷Q+¸‰ñ-Áa±ŠNŠS™{扟± p}ÅÓ”àd^Æi½æÁéO"¶ÚrÙyžB<û<”v2V]Gxȼ™dËGaÎxv:ßýHýñüQK‹€@µlBj å¸ù"÷0J”¹5£Q`¼,ñÜL#\t>ñßô¤Œ÷Kmª0{s‡—óhêŸ4u“u¶)‚jÒÝ«•àÐ"Œ`«ÔYqy×9 mýwd'¤3›Ú­¢C gߟ{7³n.H >·Í0(DR‚Å ¾*Î ¤Ÿþ-çxÑ´cDg"žºàqQ€G¶¡Î]ɆžÍÍÕ}(3 ²á_E?5÷Þñ9ÿfJ‚.^…-ëÌ/)ßn`É ùóG÷™Pµ‡Ä2ܹCñ\è^^WÈëCFÞ]åÂXE;‰|ZÞ“i9%Ëãp¶…þ°ïZžÇäóh<©~(…úüüPé5W ß›÷¤<­R`úëÜÜaW~ݼàm8J÷b2µE•T¦ÇÔVPjÏq{Lƒ(2>Tû«äfá^#Áñ¡"1¸§v{,_åÚ}/6Ž,ÕåF$‹³²–ÑÒfvò`Ñ™jFÞ˘®R' ~eõF°ï\¯G )Ê€VÉ«‰v“Ÿ‹Bˆ*AOC.Cÿ8õøÑ»M%(¦«3JèIqÓ¹È8)ªi¨ß¼Á"ø'7«&½áÕ/wìo)†ýŽcsÅxøÂ ù”ñ]&U’‚K“ôè"Û¶<‹„APØü¶ÆæÒ7K8¦ßÕ–£1¬s’N^,æ—£)3]Þ«²…’‘OðF_wßQ¤RïÉ,òSdÃÒªØìÐU„_1 q‡™…¶ÖË{KÈ}ŒçÛ¡%ÑŸ8Îú¯„Âá<:"ì‰l~òç³:ÏO ¨¼³·™ãÀ™~žyaLX»ø>X…$.Õı”IAEyª¾Û3˜z¯ùAòßì¢Hƒ0¸€ôĺ?ÓÕ]#§Áé\”Õ¤il/©­"82²H&͹–À ‚¯ZÃ' "ioR_`׎óaŒ±t?‡Ú1–Ê<­³óhtÔT×Ü3Xóœ„x.WP³Õ1¶,@ôU]‚•fú3½Oµ1fÙc†o§Ïà Œ‘‡mB*%¸²x펻æŒÁtÛŸÍÁ»!üºCäÁ×ôÝÔ°4ÜO §hˆ][î¼Tȹyb–Wë©"Çw“À{*ÅQL .N`Vþ#D-†T_cTòÌpÃ.c›:9ÎÐþ‡·&ô¤)šyüóvRk\q1°îÙQër…Þ%žÍÿäâ…ʤÙDzhA"¿áÝ3ÃsèwñQXXÈ>A@?­6+4„)åˆ8{i€ÇxƒÍ†+¤ýOZ$M–FN h·'!TÄWž›·XlÚ&OQxm-DÖ>ÃÌÖÌ–PQçç:dÍ­C k·IÐiL"‹™°:'7Â~L¿6"÷%Ó”RƼìÐ6²ÜÙö'Öd© €[@ü{ϪfkÜ¥‚^Kz›âèi·ë²À9%fÎÌUÆ9’äLŒÐ'”•þù"Õ¼dÇñÐ3¹–X*ÚÕ¿“aˆïW <tâv1”ùÁÑ‹Ì{Ûg 92 Èý~P˜d¿ræá1"×GPQi3‘n”£q\Ÿ#•ƒB;\ÆCãïõ³fúþ «¹äþ†1¡OœÐ‡¸%Z[Úì'sBpÝé²’Pùên/þ§õh»üîdZŠ[ È¢L¥õçªzøÖ‰þÕacÂ6SbŸ  œbae'§ŒðŠæÙ%ÍØÄÀMª”HlÆš j?Õ0ñ=Öì÷@³D@ÏæÈ¬¤LCMyÅëÔ~—F©ã( xP×È`\v¬˜c|wÿºõÒ®<Žüå-¡#¨Vœïùb'A°6Üh;ÀÌÓ`ne Yæ™ÑÄÎk2nÝͦÙæffõ“#ÑÂ’qÿ_ÃÎC¦>ƒ¨úñªw~ÄàY܉<«ÝX, wÆIÙù|ŸÑaÏ隷¶Íq¼ß¦JãR¹tå)Ë‘òèɎ׈”ß…ýö /iœžÏßÇýÍÉ\Î Oƒ9›øƒ{p }âÞÿÄ.;xõaûÉ´×zF'ÓGqŒé,ißÒS°üT·|{ðÓ ÀrL' \ÚcxH·+exäÄM]va@Ÿ¬­0%ÕAw¼IÂ3ØwûÐeíåÌ-ÞïÛX…›оÀ›4ÑüœqÕ2ZÑ€y(·š+l.½ÈHJœaßêXS{ñ§C?Ê`ì"ô{ÚXE÷˜í…Îâ’)JIJþßàV T6:©ÿS”誈ööˆ蹖öÞÈþ/Õ#6ž/­“éý–êZÕ‚Ü1'Ž™…k< ÜÀDÅq0Q‡GÝ‹FuÓp^göqv}³ÁЊâ:iF 7%ØE@wÀ…Ρf?ß{}òF#„ð³"ôu\,n¢+9žPÍ! QþU°¨ÀÄ¥;3¦Ö^é¨ëtOµX"þ“ª«L,'µüeluCe(¬~ˆžgZÃìѾï$›ÁÇ €…|ÅÝ·¯n2·š-°Ý<¿ÝÅŒ$"$âzÚæx†¿˜¤KÍY©å…IØaöeèÜ7;§ÕV,m•ŠÇ k¤û³.¹A‘”¦äW¯o›³ØŠ(ÃcÀýÜ”ïÜ13Éš yoX^ÚjÜIá3ÅÓ³< CXÊ ¨v°m'·F[­^YŒÈÞŠ®SJ£h ”´“ˆ%Œ¡í7†ãoÐçËÔ±cäðyXð¯¾)Œž¶¾güc8nŠ ¼YáÆ¿"™ílÁ ŒþV#¦•†œtkžXŸŠ;Û“`̺þ.Ÿ>3™Ìƒš8P‘2ë›jW .ãÍþ°ÊË{ÊJÿÿNáO 5Çö LX¡rjÞÀƒôµ=½!a8úw4§©„ÓH„K(¾ÔÔÝHU…»™™Ò¨µ-ÕGO_ coðœn*ÿ'•CÐNål{½ :;x÷Y™¾Ì­‹2{q…ÎÖ!¸\…ÇÖ—6[,Uc­SLÒÚ¹vin«*ÝÁýF÷ ¿x8âF–ÐÛ3ü÷”%¾®‡!ìp¹3"}Ã\1Æw£{í±,_Ö«zIláYgºRü,»" ®öñ~Zgå$‘J8x t´ÖªßÍ3ã·æ}² ‚W¦Ù»µ“«„ï—ÉhÂ}‰…ä ·"”60VÒE­Éþ6¾{‘:'‹_MKP1œI††rÏ_>Ç1i3/¬ÏBT(gKH7)‚'’lêžRð|sL¥€àÜ)-'‹ú:MGüªµÉ˜,ÝöPL°ÉÇAîVí¶qˆnã~ôF/€ï`0ïú tááÅãÐB¨*MzÝç"ß°“°Ðƽ*(d+1|·1uMÇ™ýl…ðø›‘þå¿ÌÒA!ÔUÅÌß›þ,ríòö*ârúáS2dõ¾ÈŽ2ítE;ŒÝF ü;Nbôv¿c””{èÌìq‘ÔÁ­‚,èFô=îè^ËæOË ÕX¯ôzùÒ¼Â×3[ï†r„×ïàÁõI-!üå8>„”¥ ºëÝjXñ€ô¥ÔQ%ÜÙ‚©ðA›|[8‹O¨^ ½Õ`h¿Ò˜\¥¦ lo¶‘©ÃM8.Ôî}òÈ Œ–§SøA[Â|ü»•×TåÁ¾ë±$Q'ªz(ºú½›ÿˆö¯vµ”ÿ?P Ô$ûØï‡"ã"©CPhuVáü}ßJq5˜%Q4Q‚ò"‘ó´-ßÃ2Õo~0È83_àT_@òŸyS·BÚÏë~*ø‹ÁsŠ͘¸ï|ë]DUÇ[Y†tÿ&Zn}¤¡½æAÏ’ð6z~'›{1^gçÑøHn÷‚»Ð¥?mÛ”=faÉK“ ƆÉKn  ROÝW)ƒU²+üÍ]zÿgÝËš˜jŃÎÄüs;–KyZ@9™IŸmÜcMI¼˜~6KDµˆq§ %ŠjmæÙ‰ÒOqìŸü=²õñ¦Ä“÷”3ç‘q-"ðèÉPãÜK¤ñ3ŠëffÓa{”VÇ«_²\?Ûݲ"`<ו—cÕÀ.«p<ÿGk·ÄeJ³ÎŸ^#ôH$DÓªCƒZ·˜ÜdOÎ,¤àóñè9©×­ ÙȳÂ#3¢¹½%J~. ס’Vo‹P—rWÁéÉUãÏ­,}ÁgIK–Vá‡wîi]0ÁDRæ”Ïßpˆß¼‡À,ZâhÒЃ¤F|§X=“˜Æ _éT›‘sBÔ±^¸ïîS¨Ž £l¨Ž¼[ 3'´ô;åºÌàC­q¯xU֮ʴQæFq$[²psuðÚàC|ÑRó§§c½UÌë¥×sÂßLCvýi G½[¡êoJ®Äö£×ÌÇ?§ +)ªbAüžÐ= Àƒqaïÿ6¤ü9N-Q°Ú}#égäâwÐ$>³©ªë—h2FVãiò µì,ÓfiZ6ë†ñ¬[-t+:`N-Ò €³¦™"’pÐ Ò@c ޏ¤î×<ÜÀí/f0öÆœÇpp íT²ëqóûá07-\ˆËü’Í“a@ZfÓñ?ÄŠ+Vó~Dî¢W0ä1Ö`?ï'‹ ¢)A²áxá®Ð&ãÓŽ{D?89¢(ÿ6Œ{C#Y--[à]=ó~ñÛóøj—Ÿ.SoîsjLóRÇílG³‚º±Ðz*é[ ãmIcXÍ5Ê"ElûéW¦¼±ÃüœZ*N³Tw@Ì΢;üÁfKF !v`€·>¿À^¥BW]¹Kµ õˆ¿QgžN,¯UjruVîØ³1@›ÚÁ>å¾e›½‚/W«ç‘ ºM;£‰VÝôá@mñÞvêmIÂs€0f•Ö„¨ᕘ&à+NÏ wÄ/HaZ!C®¼£Äö¡\p²å©>ûˆñè€ì>þ\&ÆQçêᙌ´ýY™ÁH«Û(Æp¤ò}Ñ=d|F¥—ë­tÞâz7=4ÖsÅë™=Lîù·´›ã0+>Bs+Ê } ŸØ®tÕ<§jDÎÚ©DóaùB:óI…ºÒéÁæÃ…{Í#ë-fK~¹n­M'WÉÎ$roýÉŸÌ{ãJoÔ#ÿ*5K¤ñòoÏux‘Îiˆ½Aò ô÷Tþ8°r™Á?T²ns1ãÚ\m(æT§(§š"u%ut?|÷FŨ—öÃÇ Ýn„#ÍþÖzéX3õʸát«ÐDÓ#k]³άòݽÐ#ƒ âÁ|x,’V¥æNÁFÓˆà@|HˆH´[–Uï:Œê’æ…9AŠ9¯(·Ý÷9G©? ˜€ŠJ꺇[~,ÕfrƒúÆÁl ‡zQJÝHsˆDÜøLs2 ë{µ|ÞŸÞ> –õÇCŠùU=ð+Ô8ý–~jÊL´A½MfòE<õßä:ôÕümü¡q‹åhjHWIÞsÔ»ñ¡ƒç`Ñ/Vµ®NÒ KÝ2€Ðäo¤ƒäQ*K²ÌJƒ„-–4tãClTÝ·ëžU¸ oZÌcDoÖ~¡~ÿâsÏ7¨ MµŠ÷Î}561o>Ê©„›ö3ËG±á ŽEfumw\÷iÇsb#pvùyþô‹œu[ }òÓ/)Ɖ¦³ËÄ! ãγ}•ØÃ;Ü¡©d‡òŒ#°Jï€y7õ©¸|”i°™Žmž]5?sÓñ© ì¯|¢SqLEr ŠH[}:&?E·ã‚Eºhká ˆä-8 ØEáº=W¤}ÜܽiÐÖ`H5ƒ½ßÈsDô„¢°S• μ?$N%!”ÔvõÈ@Ü}br"ЭÎi‡œ:å[.„…q-aK õûÈI²–“µVÏP–ÖlLié8ãÐï©øZ/ü÷Øl&S-÷2OØ{Œêk{š‘rXOrÏ8l]‘Ï»¾¢ÑÏz÷bá"nKj6WàOln×ųY™Ì…Yn£„ÌYÈÓ5†W,E;b¢QÜ’Ò¿ï¾T#2ÙM>zMŸXÐ5þ#ñÝ3ýÙØVZc=ˬkó‹)’À0¹æIbÖë=Tsÿ37›®á\±’O ±z¼_Ò"”Ã`Âté=KÑKÒÍ1P%@}Ÿj­Rhò—‡±íDDkš1 Cï.b'áR(¢ËÄã’^òOx&ÁGõyìQ8-nu—*ežv¢ÜõíŸe8³Õ1–,•³ •áä¯å€L(köùe‚Ù*h¿\Ë>áÞ'žU1;É;«GöbÏê/)w„„{Y<â4!Ö˜¬&úòŸ›àóXåWù«ðw3ÔëùÊÏ÷éÔÐb"z1À9á몴á£föÇÊŽ±W¹ð¸á¾\ùÌ8‡ Ôt;Ô{ãê7¾žÑà9$` —Ûç /¸w7ÆðæÑrÊÄ©±À|*žlç_ƒÒcÓ}mþŠñበI#†ÌLœÅVVŸ•gdI¿.µÂDÁü%ªÖgÓÞ'_›Øcá?R~@ 98á}q¡9­DÃß=œÌh­œ[úYÌ=sŒžù& £\J8sß=µ™OzÉ£ FB6œîÄ^åwê&GNÕÀ=íã‚ê»;äñ²p½³Ñòjå1¨â0¢1qY˜…füÆ5BüÝ€§\ÍÔä>.¬i¼›¾;ð¨JAŒ³Ø/>Ö€°Êc‰‰óø;-y€N¿WQÉs3ɦރ·Ü6l W¹Ñ©N{®C>¦}ºO87Âé‘’G'$k/š}õ„±UD$T §¾g`ÎË0ÝÔŒ…cùGŽ«ñ4Ý‚îä`|Ñ?'[dÜniDÔh>\튇°RÑm.w %µ_v¸ÄvØTŒK9ÜW3(îÈý|#O1¼+ÀÐåöL´weÚ.(ßo/Üm'n-iø#®£ÅQô_|/¥P­ÅÂ} ʆ ?õ0dkÉàßQ­o©bij œ ‹á|Ãå½:æ:ŽŸRä=ßç (¯†Õ-¸Q|>Nѵ9xH’Ý›Á 1òÒy}qD"–«|–Žw#£úë÷@ì·>kRI„ ¨µ'‚/+½Cæðf#GíZàѾÁ_T*’Ÿl @Ÿ-P‡åŸé¦XnÑwÕ +–Ú@;h!4´pò3²Œè§g );ñƒ†ž1v€É-y¡öSÎwâYÁ|ô€Î«!V+øª(#ˆY"È8\ ïÙ#y2ïé§¹]%4³Õ…¥n\j²“yÕ¬>¤†ê’ Ø”äow|¥¥Ð$»Hêv›[oò¢â‚Ç#LV{ÒvèžC¶O` “f6,r›+ ­Å}".ôÉÓ5¦f¯–©YÚ M‹…á½Ø˜¸ÈIÅKú¡Rt"ª;·Œ™£D/‰W‹á;ØuØBj0 … &„_Zˆ¶~Y„ŠØP”„¶!êo ,ÁjsÑ ¿]Ï·T°{ŽÐÒ;Û°ÖUÁÀ´È%—í@»”’â>£6ý­ÒA£$åJ¨Úõ“mPà‚É T¬B©tD’#ö€kÐÜšâ£HqÄ"ºÝÿ}ÞOöNÁ£p2"¦[>Z¿ ‹ŽÄ™—¨íµøsÔÊÅI–7ZÑŽÖ3àßTõ Û_ÜÅTò3ßwK$’±í…9ÄS6̓³ŽßarìøO«²ÄX-ÃPûdŸé´M,ÞßjÄ?Åå*š¬Vµ…c°Ø:“Æ”ÔgMIðVí¨T¹°óþc[•~®2øXi±ŠM¦‘'¿Mvž*G» ‰Uøˆó_^Ÿ®Ýx|’»€:ÔÇœºNË«Wš[­eÚ¼Ùõ;9 ¦WIxKEj’è} í¯6ß9u3Ô¯¾I;ŪÏ(F pìö›æ¶ì2UþðEŸ7þ¡…z>¾).¬­žÞÇÑ8H¸n«c@= Œ•à¨ÔpÁƒnβU¦8{5Óòd]®Šý'_‰Šÿ€Àù0¥f-´Þë‚'î̪QÄa[Ô¯ÀoWªT÷$FuìIì§fr쯯ž: Á¼k‰(.4 çeRSKoÌÝ ÎÑmhaNWÅv7*§§-«»gݵ¹ô9ø4\°EC‡ßmk¹®àÒÓöävxú°³´VÍ…),Xÿñ4"‰â¡ÈÝŠàR4®lÕü–•4µ†KÑ! `-oD]饣þÕ0‚2NÄ×ÅÙš„l^Ëñò„`Õxy y¯ºÑÇ—ëêµòd;YvZ~•Ñ7dÿ§Ôc¯ïYã ©ò ¨C­dwÏÌ?EêŒúÜøË_Þe¿ÿ Ä‹œ´È­õÙÚä×çú-\ÑÎcóÞBë·p?î§45ÆÃä#äLâÆ²€‡±§ùX jµkM9u5±8þnœx€èý:·—ùÚ•Ôemú[ó5üqÙ ý¸ÙŸÇáuõo»„‚´ª½èè{Ý2¼Š~“$²(G§+þ"·a‹98Z[5ÚÄ7­ë%J+Ú¹PŸ´[Dz‚ÌìîÍRTõEyêÑ«önnN8ï,OTSþR~D]¼z|Ýüö†èòÖè.x›-äcŸŸápá®ü±èoD` ÷IMî$0Þ{äQj ’ÇÉeñc& /z*ž†ž’Ánœ[ðÑ®’¢þˆ1Š®ÅEc Û0Œ)vc=Ž÷¢ún–( —Ö¢4Ç{%êÞgÑÒ,²‘í•pAþ@èëÛ§¢B[m'A {a_H¸Ð.õ0¬A÷q¤Áë¥tô‘îÜØøwObEç´½î(ÛÒÔ˜£${¦Wêj§³žÕ`$‡‰o.µ»¾.,Û-IF­d\­úd[¼lÖYüò^*Æ~µ•›¶Î ÄdØ­`ïJ-ÛÇWCädô‡(¢ YÂ’j§9«^•FÔy…~HkÒ¯"œÃœÑ–ÐVÒ€h{3àq„-Úî Ì t<]fA`)õK2ˆï?—qAþOLo=ûh Úì+<†GŠT,í_l¤ü| ?.@›†dLù¦\—Η¥û¬—oÞµƒãµœ©©>ÝÎîÓ…{vCõÉn¯?h9ê…DJÙÊTzè~Á"Ûæ >S~‚ò;Ù È~¨VË*)áÄe·*SÀåÜc‰_»,‡Šç‘©AÉÊJÂÆæ÷¬­˜4ày¨‚.&¥¤&»”åGP'Ô¾-­(Ö¨àª}ƒ€¢:Uóæ´lm¶3­ÐÂmR_nQ<שH¦õ"•±(ÅäáyDe9vÄNiÙßb71¼'RÎd ¾.¡YþžŸ¼æPIçZþƵ˜T5Õ µ ·FLwJÈ- Z¦qÊ€ã·Dl©–uùɷײ¡àQn[Mh&?Á]oë£wÅà4‰ÃÔr¥Ì:#h(/–Fn¤‡ÐÏÎZÑôûŸ÷èzY cf“GµîØcÜ\/ü”yíÈ@SYg¯jŸ\4=^ âk5µÅNVs¹qYûc™¥/ ±ö^ÐúPùfæÃƒƒÉ«BX7ƒú åÉÕ[ AFµ¦éï;SôG .¶Ð›¸>LWuË{6|Ñ{î³!¬‘ÎV6IS¸{/:~?rA,ß±vÄä÷?L´ÌúçPdO´ÑkãoüÝ%´Š¢[}ÿ瘲¬WÛOÂ*Ÿs¡J)E8àø 7áíO x7nMSé΀ä±.Œ#’±RδLÙ JñZÒŽŒ³·þ‰Ÿ4p–Ìù¥×W‡%“½AôFð::ïßÄ­âvgCQú£ Ãq“nñHnöPc\ci*ëºK Î0'˜_àÒb&U‡;ç=.˜¨,N¥ˆ]®E( i,”¦••oÌâk°EŸ4þɯvþšáœo$aá¼+›ÏCsϧe¦Þ¬å ­€1Eè€Z`Jbp’VŸ¦Ý•Óú÷8K"ߊ£·¼HY±³’Ö+‘gźÚåQç\)ºÒ1’ûàLOü_!¶wƒ}FRŒL Íá µÈ¸JwòšeÙÆ™‘P 5§˜F €â¯ÿàd 0%T0¬Êrò_"ýeK“a–Ve>ÿž1KVйÄ9ïÕRÿLcܶ”³2" ÝA2y…×–o!. +dÒ^™'×Ëñc -NÆ+Ä_'¹V#ä…³ò] 5¥f ˆ>™wpJáŸX©ÿ¸ôR›¤Ã¡<+íý•2ášx,¸„_C‚p‰„á{Í»$¤>¡yÄ™€°[^j煮­P™bÖ6WbI&°÷yœØYñÅÑÎ+´<°þuET—À#óM]Cýóêª>ÍÌ;*¿’ï¸l©Pó=(#ùï#cVW õ=Bœw¨äÁnÛ¿Ï&·(Iö€æ8Šp]\èÉÕúj!˜¤[CeÕ£ž¬;=™ôa$¬Ø¾wpj¨¬â‘ `'Kc uË’aQüRÁ6Æ%Yc­yù8±ûGߪUm{Óˆ”±ð«£Ùðõ~úÒJ ÌôÈ/䢤;¨f©c0H¶™ýÕ©Õ QÎÃÙ¼ÅhHjVa2£ìÐHå’ÑëÕ ‚©Q™ÞX3 2—…W Ø®õ ˜KÓÝû§äÐ4úž@–>çþôœî…ûëeDÎ#‘„xTüQô-²´t•ÌÌ€s2H*/ƒ½!æÕy‘{´Ó¥H8ù%GÐvyÅUW„OÙ»^áÌá®;&jVdóÚÖ'ãУ4X­ïŽ`ç `©Œ4p¿ «A nXn’ï…Fô*B(¬â¨6| ½pA>}Fµ HyRs+€Ö½¡}Ø1JÊ ôBVj•LKÉ„I*:Ó8GqTÈ©²õ‘3ê|ˆaÚI¸!Ó%0O7Ííý1G]@‰³±X¼¥ÔÛêyˆ«’¼/‹&¨öÌ)ðg˜OéxPfèð»oÕT9ÒLF™Ma–‘tõ¾ÐcBž4üaçº?¬¦©‡ú6I«ÎÃMɲ==Ý [9€¾DÄ^oÃÃc»­‹nT'U¡'0W5ÝÐ"ä/µ £&"Äo,ÃRÔ]6–RX©îš¿wRR¾Ĥ§kˆ,Á66òcþˆ›Ž™tŒôXùÀ~C}Ëg²ž†¯»Ž%|B`ÈžNUˆsI‰ù”¿ÓºqswÆË\½wto&—ç\uåõVkÞ÷±Ò䂘Âz85¿ë'c(g]z$f'Z½IS)ªºBhV­n…r¨Z«c@Ô´ ÁA½Ì•PÀ+>€ÿeÙZPß¶?Èßšâ8‰‰ýiXë4.¸Àª|¾!ËÝ=\¦öÕ!%Vøzñ;qöЗŒTN¬[¿ôÂØ h„q3Ü32³×#–'¼+߀ã´Óü¸âØj2†ot·+ÐE¿ç%]ºÕºRXs¤™d>ÞĽÊùzä™â´Ÿ9Ø¥-ŸÄ,õÝö7eÅ/¸K@¹t*S²úã÷Zé]oâb£ÝD6Ã~|á=$ÓœóÀXL#‹#!Èëô.¹qFÏ/é%잃ÍéŽA*ßX(HI·îüÖÅÏ–µhT˜06W¹©M ¯RØ>ý~êŽeX³ï—Š&(Á,þ ”÷»nˆ$]þuÑUò±á×™q"& dip̼Ý”Rž°+q$\·y±ùutRm&†1ùÈ…58®2$7ß¶Bᮿ5ØÌlñü^­HþcàtFYPa)Ò>¼3À‹v'=ð*C˜¿‰qCiBŒê}awÚ¯}KBÎx 9µqpAáÝm4kí®1ùÄ0 Ú Ð (f3­"Ó‰âIßìß“[#/â´FœêíÑ­ÓèÐgÌŠµ¿„'‚¿©wæ43!µGh¶V§Ræ;….Ð Iò{ýŸŸ]KÊâûR£C]yj?xÉyïòX‚•çäÔÂô±”ÉÜžˆhÝ›ÑiXaWE/¾f`Ò±ŠKµºJòòsÅÿïhÆÓ¬)À×~[°´˜2í|å/ÿù4èÂÒš¾fq_{Û>×pDËѸeyÆÃeÝNóÿÿÿPo“…ÓÓd‰ÝEŽê$Ó|eå©õå‡Ö.E‚4˜ͤØöÞ€íê0štÓ  r=^—KÈÜýNwËz^F )WMƒ#€÷1Ísòm0¢G±¾mº[VöÚç‡?s¾2l!¯ás‹V&y/ÇJÏ3¨;V<°Õ‘wÈÏësGnºï ÕkÙ²Œ?‚$EEr÷/.Ͻ˜õ2ÄÕôÀójâ55Ó®_ˆ:Íg«Y]@C0j× ‡<†òBS¾«S *vØ€ÍýÉoŠn‘w¹°\Ðøá’oóln:uÝ} éêØøðä*‘áÝ{t¾ÞÌYþá"Ëó1m@(Œ^ ÒnÃKó~í@ne˜ªs­z ³{Ç|p ^éÕÃâ YÞƒ(¨<ÉÔt[ ®ik¥6ÏŠ¥Ûf¬˜AlŠ˜Âìj‘7,ö« ç°Aæwg#â=xP»Û4~ŽhaÀË&üÓhB\ @RŸ=Jo¯§‘´pK8ÛtÅU {1Jcb/õ|œ´°Rðð8 출팮Œ~€x™£SUÌN£Ÿ-¾øÙH¨Èý™÷*ó 3¡õZ{FVDá',…÷ º]NØð_xò©7ýŸÓ*ì$ÂÞ‚¬ãý²2¸ÙÈœ,©¯¸ÉêZ¦K Æ0¡ ÎÎuÇ~x´Š;iô âj8ý¨C"º<Èï†Ä¨6ôj@Hzú¤«e¢óíÁ4½ã. ïd·9Á¯«µ1zõ?çÏXãdhV²uû]ðëßïz¸½¹§2qS â!dá-Í:\ú›Šc‹˜ Cz¨ØÄŽR/û¿ð×îAawÛ`QÇ0¦’1½_U+njÂ>7LÓ ·}Oâ·µ÷B© |µJ9Ö³*¹©·­› š?Z:¯)±1PdN:+vl ThÈ™f·Û¼8ºqçÍO€ÏX“¥üiºžÔ7ìö0ãVâÓöÛ¢T¤Lõ‰"àhrÝQF¶¢«*ÿ&(Í|^|uúÿMÔ]è!ÉX' -H@èísÊ (wÿ˜.ß²`ã¤ÃSýÍ×›=ù´{÷¨•R~QZùSIUŽ®ŒöjöÅ]]8#N>Dg³YItµwÇæ`W¥HFŸ\Ãks ƃæ0ꫤ *èâ7¨ºèAhJ¦rIþà$$i^çÓæŸÉ›þd!YS]µbu׫Gß躭=îùÏ€_àÕØUuGRY[Û´ÇR,¯ì¾ˆ€Îœoêœç¨UMæ°Á••_x®§‰øßð¬$4ŸÚÐΫ›…Å[‹:ú9‘íWün4(m¾ç* ü‹ Ô­-ÚÇÉš¥-ïPÁê…â:±<*ñ6Õå=úü„z$ÐmDYqFŒìüè, š¸­¡¨Üä1ˆ ŒªÖÇâq˜¢•1.X^ÃÆkv"¾±…L®ãŒab~Œ\fiJ‡ùitzûÄ®À¸Sj3krˆ:ëpTaÿåH”.+°¶@‘lîÚ¯¬ÎIB]3ürÏfáÒi£(•“¶¥/"wÇøùSV–ÁAGn~½Çäщ´]Þ7,èùÊ·6„0)0hûRH’y èÅ›®ã¿»ÇYÁ:ûˆr§:³pqß,zoÛL±Ÿá­ÈïZûD¶—%g.Ëʩ/°ÆÈ ÉB.e'î±!Z `ß>…Uäì”8*¼5Ûpp¿ñÄ>u ²\ïd÷ëÌ1H•˜eø¡Fʈ=®™ªLŸùzîÌîâb]<¹«ýZ{g’ý’7õ²âd:¹žÌ@¨S•c°‡ÏpEl—ÕÈV§*,7ìÅHâ:€ž>œ’ã/HïÈ2êŸf¢®—°ûαmaœ^Öf¥:r=±é.%­æv½)ÉÜc²\’ÀÜ‚:aWW²ùÜÑ$✩'±pl¾‹{:ù·Ó¶HÓãÚ?H‹ÂàòñÊŠÒg.QL¾˜+4Yý^Ïq_ŸÄê“x,L׎±tÈi¤‡}õ?ö»üè0ø×qKlòqëˆ~4J„$S¦´´‹v±¦Ø ¼Œ§AvEçup_†ÂϵGÊþz#ÓÁ dAÿDÇý®ü“¯Äj–dLÆÆ­_RTö¿}]ôÓ²Ù¯?ÑdâpR ع½’߆ûŒTÝQtÈfAÚˆòÍ´¹•Õ]NgEAþN>¤ô…7.?©Ÿnu7nXr¾¾öÍÛ*ì×,5 |™&x©™Œk«t) ß/¥l;ÔŽ B”0ÇšÑ(‹¢S'£å%D´8LNvÞLÑU.*NuJ röÿM_b˜‹Ã5÷ñnÇS}¤@Ûˆ%øIqBÓ'VhÃYH•ïäxòA!±jßNÑŒ‹¸œô·%Çî5Núwr1„äv[àš×Šœ!ã&M©%F5ÉÈV3ŽIä @};h‹L"F˜ÈùqÀ/‹FÄfmªó“ÅÄ3M6“OwZÈŽûo£¼aAÆ@ºâ|eï@þ%ß V!zR\ר{n5ø“^¦òÛ.D?çí5, õü7gMõs±Ãó¥ÚŒØ¹m$îg‰zÑ—´à±Ç–k—)´']7:z5E¨Ð.ž ÏJE4—Ô´ìKælV8oÊQD´FMÕ÷}çú9Ç‚O‡?‘ „í’"}\ƒ&ûê¶9lŸS®§Å FÀâþùœªÈKß}¨¨*W« W´ïŠÑ^BQÕ²°%R¯\0N­Z ‹÷øüå¦L@I· ìøx¨WG:þJÉvŠ7zUj)ÁP{FëoéÂáå¦í7èáÃe&¯ÆΕùHØÎBËÒå'ÂGò?tâÞt2gL'©têExšSm2µ¹j0Oå^_VÈâ Ä¿&|öx8]Ê÷T]4ß4ÐûFä¤Ïv®û*ZgV”|BŠV—͵Ÿ²ÄžÕ©fpé j/ëP½ÁáÎdÄ{¢\N¡Œz#xÕH•™±HqSO™’Ýôg—{ìP)ÔvÞM{ÝÕŠRm8gm êþùénvÅRƒu P¼ü¶GíDa|SÌ’[µ!=ieÝt\.×7Œ€cŠd•áÊ>÷»l»:Èo³ØñõtÂddiÄ$í½Â €Út+Qõd5§¹±=êà€R/"õ‡êT ™žsWŠ`åë{O¯!ÒCÚOs_¯*5s­ZÂW£F¯4(´MÏy|KLùQ=‘ÐŒò²\·Éà6ü2_ÙSûÐŽV:Âë#Œçtœˆ ^…Do0µ‰±«ÇfÝuȲb:ÍÖ< Ñ ë•#[ÞåýÅ{'›AÕÿ¡xô¥§L{ÃÌšÞûS·­¡òéÐp®j`“'5‹iîʹœÌ迪TŒYÎæËƒG7qŒ£®K†ª—ÂzGCcrî£â`W€šMwé Ͷq—¹r¹5b  S#åkµ è+ǽžŸúõðÌù ºƒ•)³%©qì/'VŒª™am¡Òú>@¢\Zzj¢C¾ú­x.òàzJngÂŽ+ËÅïôÊ– H©èŒƒaœœMp®Ò‚Pw‘L62–¬\X—ÁœQOCy¤v@¬å.;°Æ7 Á©÷-þ  YªlDHëì#sÕÞ!vQ‘€M›bFvMºpÊÇ€? ¾*üv»d ÑÙ=Ƕ›3ßi,NÐØ¼˯" Ù\WžÎ7Ó©b”k:Ò6ïo u¤MWëp)L4¯ŸǨ°µîùeÒDZ¬ã"—¡ƒâÌ*å#H¶¾oßãfbdÁü¥qÌè ƒ€Zfè6.ŧҰöó Pyçb,ÀÀ \zU¨OÃQ°ûF ¹§L€8'xqº>0ºåïXØAs[qÁ©—²Î0z bª|—›Í2еI ñxS¦¥`¶ˆÀ0lêAÛ«teÄ ¶-,YêA€A[x™´Ø»¥§Ê3ê°«å'Õ# ˜ÀƒªM);â ¾a‡‚ŽQMèZiT¦>ùR¨WVbDgªÕ.Bd¿ø–´M“ê‚pLp -š—e÷Cý«£h×ZBtwd\òƒùë³#¢G”š-÷ô©èS©«§öûT•‚ømyÿ·ï䢚<ƒÒß1ÓíªÖfHÛX×¼¥@äý³gn%Ø6⨊=L)àf0cÒƱô¤N¢ç![]5$ÐîãbãÐðŸ£EñÄ¥7ú¥3L„—Ù<¼ü Y}†]£ ™¢¡¦R$Á-ìZ•òʸ¦9$ sö7`éÂsi4£§3{×P&@ˆÚäû—ÖIËq#îª"ð' ¶„ !ÌäUªLW¿(2½¬¡0Ì„[ófYËÖeŽ'¦±àA¢1÷ž’NUÁ«Ói o8¯PŒèð6±F ’!‰E.ü³IËù7ÅJ–c°}ÞÁ÷‡säÇm„fm@ò> |¶‹˜ yŽÓäfœ‰n¡Ê4U”¦ÚYXH ¿®ð‡Ôä CU<³õh¯•DÄ‚ÞÉÉ×MMrÁŸ>ćg˜swæ¦Ë™ >õ±µ`º°Å» µ³Ä7:bÜFgÈEͯ¿és”8dZ`å^ݸ׈¿…qùÂFª²læ¦>ö¶b7Fé€>w 6Õ‚$È{FüçÑ“°é(?º&ïZøý‰´pQpU¸AÚ´›¾ei¬¤ètBB¹oÌM`]Ž•21ŽåÞé…a@§æßƒ·ØæpÐo3È0ý-eä+4ƒjìeëÆí—w $‘(¤!?¢|Ÿx $E hŠ$±w (E“]X5·ôz¼´}MU|ÔQ"†¢}ÂÀ¾ “vššùïëb ¤„¾îx8 ™¼fϸ,Ž( ÇüôU$¿!çð²¡6Òf]p¿hظ–w°À0J—üÞ¤Eh½ÔZü¹ì[.’Ç—Ĩ$5çþ/g2ØI~YæqýðÚÑï|ä^дZbæüÓ²Ö+ÈuZYωÒ&¾T¶]BÉÁ/Ç+ÃNŠÙïÿšk–K§ÌþrÌ´YÁÏÛp±‰Ê©°EKbŠ;OO‚„(µTF!+` ‡-‚T g¬ J^6;²VÄú߯µÛêd2›Æ[œu×裓§¾¦'ý̽ê£8!YJXÂ;Òú{¾a m)ÂØØþ}ÇÒ$gå{.R¸–ʱ„\\•Ã*²³Px÷5.²;ÍŽ údß˺‘ÉiÔó΢Õ﫛Ȯ‡ÀkQu‹!„{WR˰5ÕÁt{~ǹ½ Þz=6pjÁõz°p:ýP ¤ ÆRÑCÊC饮š%£m_?³ào•å5—ÑìÏ­AAµ¨“f“^K<R?: Â&] JZ.dNXÇ®rÙMî+;á>xã]õËØHQ«uôÓ˜'ç§å“eñ¾å4 Ø& ßÖUÏdò—lŽÿXV·Û¹'³1ùׂä+¨  ð­G"Á8äéQ¡‘±-À3á[­¬ê®èh8TgÆ—sÈ4‘è,}(VC&f#7$9µ:a„ ã35|…)EÞÙë‹°²—6þ)•Œé1úž É¨„et87mïO¬þ[ïÈø`56æá¦ÜæÁY<¥aÏ Ï²Úu• £žÒØ0‹Áмˆ™â^ d)} Ã0?:ƒf óŸTYy¬%Sê“¡kucÊÂÄ’U¶šï+Ä[T;PåŒ3ðÑäŒÔIìOñê©Î¦G¤•4"8ÎÓà"÷Z»whD¸{èN¶JÖ"=07BüŽã N4‡&ùB›¥˜::¸ýg嚪»MÖÐnüjkªóàˆ!!NiÚÔdµì³î$_Bކ ÁhBoÓ–ƒeÚ `!h¡~g«í—±ð=0¹ï9ÃÌ÷¿½«Ó˜÷j$.`BŒ M°ñÍè ÎåñÙcЄã¤rkkñ’fâ£ã;é¸Ç½ lY‚qÊîÚp‰‘‚ˆV¼Ä !«?1䯥ÏD„v€Ó¬Nˆ×Ý3Ð(Aö¢™b,G(0H:ô[½ØHÛ­„–jh 1éßÑ65ãžU+÷w¿ó 1}|>½ªuÚÁ¢˜[œ¼§è¦4o²c#P¨º|¬ö‚££[™N™“$cÆû 1Œ’òe\>íÙ× Õ@Ð^×›¸^MÙ4(ŽºèTïn“v”Fwc}½R…[ó6⦔áRV™ßæ%¦<íÂ)v™žS÷$ñvX¼ ˆ3õŸ¨l2sÎbxgÌ7ÏÕzCÅr¾C‡²?˘i.M_½¤x3ꇴ¬µîk)¸;W£c¶ÎR=Æë$jµq‚®&-h¨5; Šð…° ƒc Ø€{KÞ”9g2O+¾D‰£³ülÔæØÑý!+G”$ùÞRn©Íù‡c=.é÷H Qð½báÄÄÖ(€GQ•ÈR#§xf³¶o½î+ÎÅ·@þóüµ\8òû YõrÙbú^¿z ˜‘µà¡ÞÅõ«bò¡»çúÁtúñLnÏ €ä3„‰õh4êÇŒ(u $Ž(4KGÅáÝ †Åwù8§#ð7ËdÅÁ#£ƒèåcx™µ—*Ÿ[ «±Lx.tëL?¦ÿääãHêF˜x®[Ý”£G¿1A¥5FðÏÿ¶yÝ­ƒ*MÀ¼VBã«”¯~+W{æÌG7.î2zNdnÞZ5av:«tj~é÷ëM Ë+¢ïOQr0|GûWî¹iNÈI¬–VTÎ e1¢æ‘V™{ðwQš‚›LÉ]EóÒÅÑŒM»vÉ{!J¥‰À­¬PGLö†¯Qr" ¯°ïÓ4 %6HÍffQ×®çð° zÛ_ÈÉÙ‡U¼•zk¥Å·tÎG>Ê 4:YU‡á÷|®¸í}kÏ£…¢!º¨vÆ¥,ñ¸Ìš+Öcy ×¶L >Uk©áoÉ<ÛˆNï‘íê‘~:âX$2f7ÇQdBÿ îT×)þêΆÞCÂQ‹/™Î€aRµ‰ ú~ü˜°ùìÖM—réû$#G2:ç¡õžóü(yDRÎŽÖ`îËx6êCi´yÒr ?²ç}Âëq4R¹ýËí–éŽñL©ßõ‰õ1.=plIsÀ~û»³9 .‹‘¾_4käSO—Œ_nDc<‡ïÕv–PiÐÕ¡PF\ô»ïy+4*¹H¼ÂŠKy‹·AÒ¡Ž0lþ_¾íÝGïV“)Èí³„i›)¿>§¬}Ì€ÆÀo¤ÝÐÿÇ 3çü]i£7$1< l!_Ý Þ*ûarîÝX¨DOæ\Rl#•lŒô<æâ¼ÂkçW I3׌:Õä$MR¢»’j¡(ƒ/}Šrfþ“á…@¯¨7™&ëŠä”÷a¬ßÖ@* §‹´9ñ&Ù…«Õæ¢(u”û›÷¼”.RWÄOX ¤`@RüŸ^¾ ;$¿†URÎcvM¶!ícy«ö(Ë[d L[âë™G& ç$ƿũ¸dF¸Z‘¶ò«ÅËB„ÎÙõ4Eñ8#a”š°–ï¯gZD©¢ YÌý-ë':‡H ³2~!µÉáL¨-÷D4êÊEœ1õ&ic½asˆ6hvO„Â?V(dË(Zya‘©»TÑìò½aÝÑ0÷aÐÁ‰½V'a’S[ŽËF08¨}.»SF”?êj¹ä£‹ d6ûÇÓÙµ‰R Órú]¿ !u:/%-|=/KB&לãˆS2dŠÙ aª‡´)c1½~ »y<޲›Ùž±rVc Ä6&gó£kàµI5"ˆ‡ôÞ‡èYm,æáî{GeŽb¬"1ÅG„Ûy’;n/ýg0¢µÇC]5·2~¼mÅOÈ9‡(%ÚF%@ßÇṇh@ý'Ý;KþÊÌ¡ ÊQ÷¥RÅÏeAÊɸ|†£¡ù£ð3¶u{u×@?ú†DæÊÌüÞ^0ºìÃ_AëaDõã[‚˜ñ…ëfŠ|{ÈG)û[©«N+¹æHyÎážÿó˜ã„ŒQ‰†Œ×æžüB¹Ñˆéû-_ ï6¡ìNð·iÚ²’y ™¸1œYÓV¥•ceÆàØ[?½¤á~‰™Õ9†RŽv•èþ½t´ž¤5=×+Ï5çk1ôz3M~jðÝŠú15r¶ƒ×•jŠ+LŠXê Db!dtAyÁo±#ƒ:ílgærCµÆ“W‚áÎÕPüRë^¹Õ@qÒ»²N¬|ÿ'¢ êJà‹å5PÎ_*­ëä¢g ·> ŒÛFm4‚Ü&¥Tåÿ{…Ø^ù5ëVDŸà‹7@w|D½B Ýß&Û¾0GUCðä@û˜óffYãÒU\Nøúç ƒS9å¡Ú:ÁåWí<•Wú˜â%Åë¼cù©‘4£Î x!—±Ÿ“3—í²=Ú˜Ž¡?>=¿ŸÞ’"Ë€MœÂdvh!šÀ±Ü¡X™.Óß· pi@¯jé qŒwCT»T}²íù¢#FÆ^½ÊP«}æÅk«\UG‡Ý+™$RÜžòYú̾ï¦=EÓ ´í»†a´Í+y DOûkø;E¿”,FYl·Mç¿'1v ô&G˜Ÿ ×<ø- Yc1~ tê5(ù³ÜÜÓú:CÆÝ#°¤gÃhõÄP‘ºiXÂy+`‚Ô…n[‹|ÁüÃO“aº ÔûæL½rªÊ8€ãиÐ@X©ü&ƒ¾™eÒ›LSïK7í«5 ­Tá§£6|)ÁFÈ÷‚ŃzèäšTË{»Q#K­Q$²ÏíǶ4˜|QW¼¥5§bB•!ÓÓý Œåêíÿ^5Fêž™¢?Ë;N\srÅ0ø0¦Ud·ËTr„µ‰¶çî]ÙÒ«VÌÇâÐìǵ@h÷ô«~Wx¡‡ÍÑý¬kè,¬Æw¢ÁÃ3KdÕõâ…‹¡GÓže£Äe‚—0Äž•ëC1RóâÇçiv ÷¸3©‹?#µÀð\à3ç,T¢ÿ¢Z~«Þ»À-“ ’¬NÄ—ÇaePƒšÜåïDZ¥;î‹iij[¼¹eØbïhÍ9ß¼w–©s(Ì>í˜`b V¹t×ë“ZK¸K~H(:~-G#6&€ýcÌ| ¯ñª/EÄú3]˜s†ŠöÖ©ˆí¯B§¦ùhºêçì’3á}â^ƒâ›Ín[q—ÅÛ‡¦. ;‹X;öQñ…ÖhKÞ\¬ço=ðºÝ­Ò‘÷$G˜ÿ—KþéB”bØ?ïЬh‰ÊnqÔV{º£Hƒ‡–S`SËò^ʉ µ`&¸$F…ý_RöýDjËþ\ =ФiàÃxh@'ìP‘¹ƒ‡%è,¼õ¬ÔDŠS„UÚ¡€º ÜÇ®_zCH’£[c!# ëDuuV%“Û•æ¨Àt Ñx“ '°á>Á¢¯¶’Õ/IN>16˜c>Ž®|{¯˜0IkÊ^J}þ4{¶Œ+ŸwÒi‹(r÷‡ˆÃ­ÞD×v:@;<Úø‰Ï ¢Á¯Â? ¯Ù Äº]Ì;ÿÝé{,ŸF*…Rë0¶Tèñ Éøz¯] ÀŒ#J{4m™CÝ-¶ÁÇÓ!{ªÇꕚ~+& ŸûÝÁU‰0·†ž'@Z¡Ï´_Ї¡+à2F¿ü‡wR¥Æ¾BbË$ ô[ƒÞ†d˜P¢#^©ò„ÎŽXÌu'rtf<£jÅŠ6ô9h«V#!ö´?^ÿõá^W7¼¸´nQ¥¡’„›6©"pÿ*¼@é÷Uèí¿KU§x¸*s¶Çýj‡éWÜøÅó˜?:-‚/Ú6…A­)· g\nßiÈ%_×ÛæŸÀY¯ÇûñŽñÚºœS» 3Z®Â˜§cä¥ÓbtçXÜÓ@·6³»9±[ã ¢E°X롼¡(R@Øq*ž¡ÈrN†<«Ù”/E¤«=”fª^k§6Wò“ZfÕ<ǃŒˆÛìaÄDÏ>Ï“Op G¸Ë¿wÊ0ý†ß ‹¨ÞËÞ´#Fø<{Àp¨ @ò¬¯ãrêÚ›;ª bqÁP—ƒ¦>NûˆüøLäÍZù§Š•É:Õgëî¶a÷~Ä×ÄBîà? ØŠê6¯†¥æ &…W8Éô%¶+ wNû¼4q½ÎT">ÃcNE“¥W» JòãÍVe@+'_¶ÖãæSˆ X¨¿Gnî`údxžnHPž,\4ýHž kMžè©¥¯QVÝÀäå¬Ìž¼Y@Ñ„S]Òk2Âä NâÐ~::Ø:öˆ)Iü­ë5פGPŒëzÅeKÙåúP%–dµ8:<ôqvAòïÖù{´ñ`‚N'MÆÀP—êFNWÚ?Ù¢¶ƒ[F–,纙#”sE롟*àóftySRè†áà9ŠËåú¿û=Äå\ñ”7C_yÅÈø³Œå8åº.¥e X¶”Ä®yëßuÀ!lÓx§«êI½p[vÆ•Ý/Õbyø6îlý€9ê¾èBò·–$” á;¤ÉgW³ e'¡£¼k L†whD§ Êdï5Þϼ®DT¡-½„.λæE'Ôú”‚ÐîzAÒ¨ûþ¼×¢Z-dŒTv I¨z=À‘ð½s¢sW ;ÿ+9=> ×ý•ûi +ØVðÇÏ;MuŠ›°õ-è¯á>b°µzš$S?û–! ZêƒÅÓáÿÒ&ßx/k®„G¯±1¾ŠÿGä_ÐH$v˜qªägŽB€ñ*Ñà{¡®HB ¬K³“¨–ûœõñSÁݵ@zônï…±L× ÿ¦÷S~²ÿ^~N÷ðdR–µÅþ—žc¨ÂÀ±Ú:þ³Þ<+·nj·$Þ‰˜OÀÐ¥T`éc¯´’›V67õ¹ß#ÒrýdzÕ)ŹNÔùƒýµ“v¥û@Z|¿‡~Ü;ÖÕ%dª0R‚¶¨æƒïµGÂ$=çº6zÞEq¼ÿQýÉÊ’/é[çŸ'V5€ÄÁ.a #/9Uú·Âù§X>åšû¢éCᩚl= ×6—a W«Î}CJW‰‡ƒÅ‘å•aNÏޯ㪒»_¾_Kð8ÿîMÔFˆ?ÍO¡ƒaðSp píid‹&“PMŽ‹ˆÇ†®¹5NÀü4:Ø¿v_Ç0‰E`ª lzŠî•œžDŒ=–ÅiLyÏk»ÂõÛR a.ÃP X]ây'wÑ0M ÂÚù댑å:íëA¢²M£(r`欸Ìõš„R¥¨ây±ÏÜ·`rMMªg„VªŸJ™ã`ˆ/Ú µÁ&ص'ÃÚ,KNæñøÕU^cWPø Dßp-=úÊ;§ö%g®½Ÿ#ÏÊÂà=;­L½Œ`¯dœöÀ{ɇöµ­}+3Ë…«ä»ï±^ ¡2 'úûu¬²-Ý<8¬»<€DD<£ö¸  ê‡Å®<@>ØùéeÅR/ñÏ>¾ÊƒÉÓ-Ϩu¾º­c†ÊÕÉÍné¤^Õ/€©¸Çí@KO¶šãåÿ× )_¼›€¶€Ð@&GwË?Y“-Q2¡opþ &õ0W Åì¥õ´Û‰a#±R“2aª¬·v+è)†ˆ¯ÞEò]EÏ …4ýS3¶Hœí¾ËjÑ| ›cF.BlºÁ„T@Vƒ¦.2jTÈ‹£éüØœÀ7Â])ºê˜É·p–«†ÓÄ@:z„18¼Ÿ–i°ý"­Ø4zÆ0Op«ƒWjïãWŸ@Láîø:[ºÝU$0ÌÛšnù”™~‰ÌÉçì*GÐØ…µ¡ë6‡\jÊ Ò®„9Î=rݪìVe€19l´´ãa¿jŸ ~,‡Œ¯|LÙ7ºâ%DÆG\"S°qÔve`Í8´M Óå3«ö’Š]¥y0îˆ#–(-ú:{± ¾Å¦êÅc+ìJv¤ £åD½êÔ8b´¥uźNc¥2ÙvGsu(i Èk„åÎ ó¥¼…"dnxNa-@Á È*Åà¸ÌEã•ê®/J$\ñocãâ¥_> Ïå“ÏÆA½^!Ýñë'24T<‹|_jÁŸ˜RâÂöwÀÞ— ¸¡Œ¡uIß?¶´s&^8A…ã Û‚Ç|"¶ÐLçU`ÔGãªE¹™Ž3 b?ˆõsZu3V¦øUT¬$Ù±®(Û]Eø¥>™¢3÷ c˜Ã&GËÏu«°ÃàP-Ûuy%X5‘ãcm…Çô$ š§®Â|V$“Í×nà€¦¿šø€ês¡!Î4!—ÏpJý}–䜚#°„¥H®ãËý~êº"Àðµ¦øXÍS—ò%õJ˜Ù³RkY¤»1#œ&¬ø¥8-þô_áWMNÊÄ—6 ˆ"¦¦²ós(ñ`iÞóBÇ‚9žû]Ïw[a|Õ­p‹k¾4^XR,}ž’yí9¹ª§™þ·ä3b¢Qø¹iîÔvÛ¤¤õ^ݯPù ˜\®±ü‚ø`´z¾w £ Á&è „C©ð üèV[:|xÞú6«’N¯qÝøï-‹<1­ËÓ1#Ò/Ýà¡*ôŽ÷õ¸[#=5Ù8fö×¶xÐÍÅìÞ·9ÙWc_4í ¶Q§C~cݵ=„[f¥ZcÝå´yéN„üèÙéÇé\˜rwm¬.)õ#*÷xÓ×ÞRGjÓôcñã5@¹éÓ¦&áìûç¶±„݉’äp*ƒ¥å0§ QHrPùÃògÄͬÁí²U.#·ÑC¤â X`Í×ÝŒ¬0ø? öcÛž»ÜØsÊ“ÆûÈÏ*6/@ ±…þ›7.eƾ“JÃrw÷óa")ÌÊíE?JÏ@$c»PØñFILWm7U²J¬C-ìã¬ôY[Êæù{‡' Á„º`ÜÄ>c)”æC$㊅‘¹èÝAt㋎=Š8<º:£ªžª®-‘7ÏÑÑ]û G¼÷ÁsrÁ¾j]ÞÍ>#Ï!{¨_*Àlþ÷}â}äÓ æ¹·j;ã;0ê]È–ˆ µ|Ôççßî—Ø—¨æ-Ù~Î3#k=¹æ½Ž`{SuòYMˆ(wÌgš ¶Œ~*ä»ê©ØUˆ°¦>'9Stùwë®Ö`» Àdž¸šch†è% Τ•d~*üv›£ß·ôÁ»TB(ýÊEoèGorz(æ§{7›[ê¿#'ÔÔùŸ‡0HIpü±–¸Ù¶D äÇßì¤ãè‚4œ6GmÇ‘/þ™¿ qïr7£¤l°ÛMóe¸ A4¦´¯ó)¤ÌCOZøRãÀ¿ ßäá—†·wD!£æ>L€¶ß;«¾§·òh9}u^@*yÉ ÑÖöɈèÅã– .¸O%2>/4ÙíÌKÁ.-‰ œllj•z%I_ÍÁëo>T5ò™§ù •³8Y¼³výã'²ÆöÛaž‹àžÌŠÌ9Øs?Ÿ»2ó1âÊ3 µµiIDÉÅt~áTñC‚  RÏl"1VeRóJäg ȗΚ©¹Òf^ïu—Vr^¹§q$¹Z0¸gâÿ–È:­ ¡“*H˜:¤Ú ð|_-Dtª-%Ãws·] Àt8¯HºúUkð×!~ Ú9ØZ ÷<ߟßró±/¬‡²S¬wx+`$hÍ¿Î˶°¼ÆåØÍ6;K” ½ÄèIÓ9>ÿÞÂàȧmMèÞ“F¢›~ôcR™SbÌÏ-,_hpòœ¦ÿà@ÿ¸Þ8ÖŽ;{ŸBŸcTê]dï:‰@9™ ­ß‡‚ÉÉ?fÞOQj))+ã;Ä'ö¡Ñ<öÝÝ„~..ßÌÐìLÛo*Õ"?‹ƒ¯´+Jc<ƒÄ_áûfûZ†’"h´Ç¸+®‹¬“.lþSgàïóÌž“²-üq§ƒô€Ëån~Ò†¯öÐHä,»KŽçÒF}æ«ô¶Ž ±Oxt<ówç/ù™M¨é_ÄW¶ë‡Zÿ. »U,ckÃÄÁk&øt‚}O³ þ’³Š+À\¤“·”G¶Ñ¬B‰³4n¶å”u¶¹k¤•@ÑùïsñÇ«VYiÂOOÔaœ-°+ʲ Û¯©s¸‰Â9 9Ó$¢÷“$Ôûð‚/ê;T‚üÖ¸ü¤4"85€Ìn¨ ?àárf“tÙO¿ÎIO­ŒkÜM—ÅyÿºõÒGl¹›V÷ÎÐ5ëƒô}êƒþíˆ_xkF‰ÂÃÛlÛ1íÔÑØ¬¬àî/²’À' sBI&Â… kºz‚~AKïÆl¿<Æ$Ø,zæ¡D½\†‹³KÇqû¶Þ­&eh™÷j¤¼µµ úÑÉ ]Üíæ´@ÿû’ér%Ë0ÙëìkâìÑÙ«ï=Ù5TÛ›¼N+ ÞLibºÖ’n–޹]t•‡_jâ4¤þD Ãdˆ²Â ”M…%…‡ž¤Ãuf³ Ø¹ ¥ü…g‰dawzÿøûO àÇÖõnòÇû^—À8_#1º×ñ?${†ŽÒ…n“¥Ä)ØGe ï¥p"^Ì'H¡¡¸i'ß({9Côsk{fáÞX˜²Câ" ¯/õXŠ££ŒÓÞk&¤:×ðÿBJ$ßL¬£[™õ~ÒÁðˆ)1Ð Ms(™§ñ×ÜFüíŸFàËÐdOþ_£) àÝëå© Y`³Ö„ãÒ׉UH¥ù×\"µd›Î˜Fì/ FÑï ù¢7{æľ áÁ,ÏÆe¨ú´é_ލ3Õ€t3e!ºýœ¤ø.Ôé\]ô¨ï°aÀŠ‘¥[\ãrè^ôÌxª^ßI=¯Bà ðOî5‹´®dœJªŒòÀe°ëÎ]æJ jçlðhðÂ<úÌÿásh˜;?óØå[Çœ¨Ùq1÷#eeÒUnÍ—úFÊáÏ©xÈñpb#DëL¼æw¡›.yŽ„ … ‹;u«SØü QõQ)ŽÑ®ÃìK ^g`¬A,&%N áìðK×é)×pÏðžÜ*g𓶉N<Ø‹[úcâ}ìöâÎÐ…0bo‚+¾…"–˜z/O Ê•zMc\§”ôgYòÆN] +à€+iúùC:²ðšn‰Ü×íp_è0Þ+x›Û ß#2àv½ïÏ)ûÀ'P‘2šò9Á§Ð2…ë‰ÝCJÇõ\(Áb9þÇúÆ>ظH#˜½E)è–ˆ~¹—AÏ—Ó}®ª¬†C?ù˜"‹iÙò ] îE|B?uyˆ ˜¶Æ/„Sò ôiOÜ‹(ï¢a»ŸÍùé¡vá/:Ò3<‹ð%Ïv~lCô³ ï@àë;ï-éVe~Þf‰T[ªõ4dážïÊ¡eŠù*LÄ5:ôB±¼ Éé˜ZB¤kÍ/®ý¶Š¥7UqMî6;»•ýf˜=eý!_¨ýo—ÎG¥ „=÷|ߪGGO9¼±Ù°Œ¨É¼_^²™•F¯„í\·?ðôÆ®üJyÖA_ÓÓ¾¼Ãב° SHžQeóí[”æáÓ}uQŒ‰óh±:]O‘sEü,!>Âs]Œ=÷âd«Ér»ž Á]t„zÐùÊü’E0GgŸæS[ꥮíµR$ÊúЙ=‹3‰½å p©v&“ƒu¬÷¼×ÚSv Ó‘…N718þÂè$ç9ØúÄ1lÓ øäºËg Š<Ç# º'!±k¯s9äR¢nl(Ïj% ä¦u{)"~¥?ŽEæy‡:må³QÐHZ2q&~e‡(w*rY°²¾ÈZ{¥ªÃË2ØŸü£ f]bia»®m*2*`ßGã‚"ž<ƒåòHïñxŠbê1¿\I†–?LÓÒ¯—ß­=¦¬O8‚¯÷€¥°æ7yÞ›Jdzd¥ `‹©·ØJBGª³áüòªHç'B²l«ÿV­ ]¢ÁRk£vÝAׂàÄ™óØoEÙ¦ÿ‚(øÇ™`<òmɼž„‡–›ƒ¢µêÒŒbJó®nË'"”1T¥%Ð]5v.yÃY«¨}Ua9;7BdUÊ"X<îï\¶c0œyó$ªS¾A‹2M ¢@Öho·çÓ>çk W~­ßÚxÒ±ÔüŽIšFÊ ®‚ Éò§C¨HTqѹ.Èû²?½ö…Kjì(ÛR=(ÏX× ÜéGú ¦sa)e#Õ÷ÇcÜÕçÐ\¾tP„ü»{3qÏ)ªOÆàÁ(””¥Ò”8é³½^Ç¡Ó øÑo%1:Ñ•«5`/ºf|—ÁEC:—×¾ ób©çÕ=9¼)µ‚ÐT©‡°¡¬l“ÏŸÏG–£ßK£ŽbÚXëkr‚‚:ÃDÚcg•ÇZ¹ÌsÃKDOØzÏUÓ!†ø&œùݯZvª•{>ßì}ñSʽ9é-F¿ÕŒ­qs‚¾W'aØeÆg›²ŸžÝ—Ïa”è‰ö¸æÈ \¼ËSÕÔJv窜8ž íÀJª²bΨV³q·û²÷"çLë¨^Á#ð²†>¤Pre¿¾j).]§”í3]Wœ§*~p9œ*—ž©£N¶dÌ|UPi'ÚVØõ^áh°ÊÄÆM@ìÆc~`£ÅóC*¶åÚ8ÎÛ©ËßñÇÄIPñ=úg²mVü^äž‹êì€ÍóCKýÉ÷¤3Eê™ȸ_[J6j-ù¸¶t'ºí¢N¥a¹$‡óÜ[ù„º7¤+5ö?W©:ÖÉz «Tƒj“‹*ùŠi,¶/)#çݾ3=ª~~3®¥±b/¸%~‰g[¢ç÷a@•Ë3û>?4 9-ÈÑ€ãÙ¡.zBŒ£a3æ<¬TøXó¶è¢ˆ‡šáOó›¡Ê¯\™K?¡&ë¤ä¸²ÝkîzhLÉîx•¥BŸ;cy¼ñ QtŠîÜVB²”¿±¶Œ]ÜÅÙâ^ç!y“V 'Á¿Õ¤«Ap»tù€e‘l„èyNw\ücì®y+=þªó)VœïÔiÌwm¹9¤· Z¡\H¾B°N$ÍY„Ö~½>âQ[&¶Cÿ¥9ŽœÂÏÒ_ ³½ÊòûÍ-µj"–½Ý¼R¨EÌŠt~—xìZÁŸw@fkŠÒ ¡ø~"î@’?Ú éº´yB½\÷¤q @Åò²nÁxÏ6‡“—ŸüI¨ûÍ8´‡_«Wz§D ûgÔqaï±Îù'Í;?Ô›pÑ~3ï¬úÚEÄlÏÓ!›ˆW€h3ìóófÕÿ.íÛòØA*Ÿ+ðÂ<‚2fS±hI{G#1䀚´€ƒÄÚ4þ?úVu.ÃÊhÆ¿.ú4u¯›šˆÇêß8³qöF²Úú].Vï Ü ÐÓ„þÀú¹H…¸b ’s3èÛìÚHbw}k5¬ÚPê¹`„F7/ÙëùÀû‰zİкBæ¥BÉ•¿æß瓨˜- 0Ö±¢H ^÷Å£ËåÐ&ØMy75ú!Ži²¢ƒ˜Çƒ6Kñu(2jkOª=p3•–ICõ…H^ˆ|\x3kÜ#jìC_ªæÅ¡`qÚ— ¥¾iÙÅhC%ɨn èšÂ /‡ÉŽmžœëþÝúN•˜ÒÃT”[âJèð#ZÎÅB¯ºb)%*è¹ ;T[÷Öo…ìíÄp]ÎÌ‚)÷æ©7jÏ÷á^z>CW~TKÆÂàu<ǺÿA2Àˆ33¶Q(©¥À”õå0%xÕ á¤eWÜTÇ¿LA¯PÈÝ›¯z&Ñ-œqƒG[/âÑÃ?fyÄÓ¨“iH–÷røÒÕq ZÈ27Jª¯gIC΄0~T,cÔ4ÌM´õÌ'•ï«e4êbÑ¡ßz%lÂÂ%L^ö&1òfºc°;¦RѲ-G\þhêq)nƄ禆(È ØÌ'Ù#N͆ÿÝÉsGŒ¼îŸ¨ö1)Ûþša5úµ»ÉùëGеïoˆžm6+¤½ž% Ç€}XñŸ›KìÙtÂMN`íCl^.Îsð¤miäSåØ8«RN¦éâ¹×1ìèZÛÎ&vÂøE¨ýi‹ä¥«vF‡‚"ÒOW°&­åxÕBµï«¸"÷˜mh”؃1Ꟊ*Pšù,¬ú~£“·‡ðu†¶]b£Ft•30Â9„`ØUÿMçeɃÏÝíÜäÃvyjÑ:ì{¶›•¼ÊRa0ø]žë'9šã(Ò'ªeXŽÎÐLPÎÅw±êæ·9Bµ‘Û,P6À)Ž0£¿aÒ({8T"ýÕ¸0Ç‹v—s÷Úä§’ž’!|÷p„(¶Js!é!§¨ü©—;ì5Pêsx/QǸï€ÕkÖc@ Œ.óžmaó—c[ðhÛ0 ¿d¢) Þi+Ƈ0ØÓJeï óHãÍKlÍœ;@¢ØRŕ˄xowÁóý¼2töá¡‚Æg6ŒXétAÙì3£ãD Ó›ZThêèBËÀ i¨8 nTt<ÿ€¹ªÕÐI¯ŽÏy‹³ />ý ,Çe2忝ðý ©U­—ùaG.ýl ×ÄèšJäèž­á!\ÐižïZnÙ!¥Mð˜+VÁmá3u«œÄkMóD¶ºPâÜ<ÊlÁ8øÑŸ;]˜iù5AÕ3ß]´RgE+ NÝ«æÝJ ÈPžù½¶œP9=k@4]ÉWÉQ¨àð°¥}¥k›<yòƤpoH”/æ0­t¥ë¬,Jöˆ¾‚JzãœxìÅ:®µŸÝT¿/¨K¦ãŒëRæ@#¨·¿y¤ôƒ}üÏaÍm‚=f8©õ³À1¼‘59³Ì]»sRç¥lÔËø9Jì}¦Q]/H‚DšëÎIç03š’‡ï­#“ú-¿ë’”MÞ|^åã!evµ‰.9d¯nrœoêéM ÔõFqè•䶘·jŸm h©P¡^ð“Vš+x‰J*ñÁ¶{|à†òu¤‘¯VœÊÄëNŠwYë…¨IŸ",PTfcAÅ—/Z"2`É[ DcT´/u Kâ¸B'.®Y€ÞÚ{”‘×W=r?.ñ‡°¨é,Cc4¯4A¸[ N,ŸGÝ.:EÃɲžvA};·•ãÞQ¦²è  bN?kÿV¥J>°®Ü«ýÐr–ôvDŠC ÷õ2³ª#FáüØÐç6 "×-Wfl§~@¹`¥‰ÞÆÓ¤¸Á\Z¤z@ϖЀ‰Ž™'"òô«ÂÞ“ z.”K= î»D›„ï0Aì^—æžOz"¤§al~OÇo…×qÜÖ ææCɃ’HÊØcûcCé "|Õƒ-x¾Z|_N @2ˆmšqrÞ'†(ÖÿÐ¥oìº`ã^Æ)`ŽÆ‹_ÔÂ![¾dXQÚš†£9Ó# R1v’Þ~õÃa¥O(ò¸áßê…~ã2³ä£¤RçÕ”H§¦¾¦âŽó悾ÜÁuQßv¡š°±dF3Jã’_ÀÍtUtMÈ®<ìF;ñÆYð¶×R4t¾ gÕ­Æù®Ö‰û"9ô®u[}|eã› ™{šv÷hÖ±=k§¡ý p¬Fd-±d+;•ïˆ@³ùÕPñ\)!Fÿ"E(’v^-çDëБëö'âÔ‰™öe:ԧלk×ô¾—mUq4ÕÁ;¯mYw½ôÝÿFcÑ7¶˜}Œë¾°D4W£’LŸ_ÒkÜÍÐÐz N˜ig¸Ê÷£“ôŒÍ-bÍ3á7 º>j›½jJðÑš±?wƒyÖÂÍêS÷ïnq?“àv;p)v ¨ÛúôƼ4.«i=áošÊxt{è¼ÌOãâ4,pÀrâ÷Ì€üÉ¥;–» •³E;²6’r!ïE†|ZGU½Â¬‘Ìaä<”¾ŸA.4#B»‰såŸP€@CfßÔëeJ^<+ !²ùÊ÷»}>ˆõû±Qm ñ¤Æ0â3ÛlÛš¯½æß¾˜“Cªq“'_Ÿ‡ñyg µÆM‚[&ø?Ž_¡ôÓËÝÉü¨øó¾ŽrŽ9Škùô¼\Þœ|\a £79#<)kñc²*„RœÝ†Y³#Sz3ÿþ ÞUõpB…©ŽÁ|áš(—ú0'V¨™MÎùZ¹ûÜU~€×Íkà ÄMÈÏâY®¾ Q ¡[«ŠÚ2À¯Îf«†â -_þE—Ò|ÐøŸ-I˼þ:/Ó¶u…G‡[;P²Ev‡\œ'{f3 u«0Kõiúl2fÒ.;fÐ?+QÔÀñÃÛ#v²ç1%ÉoçrPÅ—ozÁ¨ûø¢e3¦,‰ý”ÛXð(Ť;Öˆÿìd`yHv|®6™Ì¹kÅQ~3‹ÐʾS9tG»ó–Cðü2º Ü#k_“¹4S%¥Ïƨ´Ç›Û6#º˜+®¹`YåUŽjä€ݻԾaDœžžCñÝæwKtÿ÷O„ Ók4@Ö‹ŒÎ°Ügа:ýPÐMPu¥OÙ‰Ú×sý+5˜vž7¼½xRÖM‚î´²ûŽÇ-µNôÚ¼žÁ=ìx­N‚RžÅ¾S`”‡¦.víX£‡=¦nË‹ä£%°;'×°-âñÝx„W¼ZuY<Êá–SílWNêïørDÁ×nf öékÉI™ÙixxO64žøªª7޹'xõ3k÷A›¸3ütþP݈VK?Á+¿XÔ>Ö„ü»Nñ­Aª¬Ó4„7î5Qüƒ"¼ä ˆ÷âJ4Vœ­ü“µK9¹Ú€7a -°µXVÏ;þΟ.Õ†¿8M­ó7àÖ]ô¤ü wtíi ‹*!PÉ]|ÕyF9%|¬æHýO_¸²~Ô4͇tRùÄŠ¶Ô¥1‰Ô攃ØÜl,·_#q£½çJÔ@2׉¿¨–¹9€P?«V–Šm˜8[”™ax°ÃÝÒ¹#!"¿µ™Á»÷>Û´›LÆì«U(—élL)>²Éæý8E©8ig +î•[ä×J@UºŠg}¶+2¢3ËfƤÎ7ÏX̤SµI ut«•¿(k‹?‘¾ènò”nn^މ>¤0*)•EÁõ2áBú"­öè=͉ZbJ)âºÕÁ[« ‚|БöŠqxm àÂ9¶½·T&~½ þSezô<~èïïÔnØ“y@°Ë…¸–Š7Ðþ‰TÈñýKˆÖœÃ¾Ÿ‡¤´»»¸ÉcÚ Ù‡E²Ä·…*­êœeqÈD#{ü?~fOÉÄs%7ÊÐj¢°f¨…YBzŠÆ°Lº&t|…Ó{l+¿rV§e) /E¡Ô³¹®!jˆV|¢›î–€¶øÞô¯­d¼ÙQUw¡Œù5bøe¢û¾M+×üã«y„Päm'þÜwÕì÷¡Ä€Šœ>3«…¯Wy¹.E í¤?ãæj¯¨Êt²Áëß™î~ä÷\âäØ?MŸ¸û8/€ÇŽcÉ~ß¾'îq õ¦²Z±5áy!“ê&0­Tw.›»ï´qù#Œö0½»oõž<`K³E´?B·‘Ç™³&}“Ë×à.•‰ ¹4B$¼Ý ñ!Gè’ˆAí*^í1éñëð3”;}ŒŽ^ •dïQ%ABƒ8¡o£ Nê©*]14wï”Y¼³v×ðHVÖZa PÂÐ<ÿ•(„*ûç4Ô—ØN~[‘/Š´¯ùMȋ¸xõ¦íÛ.ž[´ë!ÂÎýdR Åðñ–ìɹ‘MƒVý«é—Eż8Æ£TT ŒŸ·ØStÆ CDØÉý¼ýo3rcte1£19VMT]°0 “Îüßô͉Q°f.Lø*>>¸*MÛ ¶§ÏøÿMBÈĶ)ÕöH6™ùÑ=Ñsé3ò(|#Ò§™¢ÙˆYB+ײtWý” °kä¨h‹¸ôœå- îÇUŠ5&-}<Ì"âÑDögžâ ëze ma,ã e®¹ÔN Ð+å…oÓÁþÜ2m?>†KMIÆi˜Å•Cذ¨SÞïI¤—2ë§îéLT­E›¦D»‡ë`”šùU®¬‹(‘ͧ*>Ê“²È"å/å DÉÜ\kï«Ð2àÂôI® lVŒÙö5à{)ÌûÒ=À@€_…-,ˆ£\£´=³¡O?—þnk3åûÓTÞ÷K×JŸ;ë%wëWbíbø½õ—t ýϴѶœö`ŒÆ±§ þZ °@{êºiúãìl›FŽ~©Øy^+¼L—ÙVëöl¾k»J·ÑJw-ldQFþƒõOtàžíš#5ìíˆþ“£¦À*±AÚô?,{Aè½E9WKÉ¥-:z·D؉éñ²úôãWy¨âníÇ·à 8u,qq DV:\8¶N2à'~¡b!’ó“ÎÖw¦Äj«I˜+úž¬F('ß_Á‚€& ¶àDvI£µ?4‹ |ioh_Q’ïc|¡G]¨ÿÉquÚLaÓí`§ˆEÍ,$3^dz¦`£Pmf°eò"\cšlT̃„“Ðç"¦€BèÏwè)}dóruì~‡¦=‡‹$¨zÐÄ<#Ã:lt;ȼ’L¶ëîBgîðÚõ³£€"œ¦n«ggPÞÓÀBËâgv[ø¶›§kº£¨ºÃ8}IáÉytHW±uÖ‹$&‰8ªRïÉ&¹Èób¦öéKðÏljc!#йwpJw\äåK4*?ãçOh,a‹çåO¡¼*‚þبråß™Åyl©ÁtKÌ!”S¾’×4 ò ᛄ.2¤*YÖÅVS½ Àñð #À_„>ª òÎá$Ó3Š7CroTŽ”c–ŠÐißrlβ½4 Ú;Ä`ÀSw åoÒ†¬}"ô09l\ W˜„¾¹RPÈwéxÂT„صg@*kÔaºQÖW:K³á¥+2v&Ì¡P96¶†$¥fçÚP°¹¯Vªÿ8ù@_0îq,;­ùlWßÙŒÈÈÿ˜¸E-t0ï⣞—ûKX,jÉŸ££»´¥g·<,úæækmæ¥Ý–ƒd}¹í:Vž²â,—· Àïî_óQ$!Y8Žþ†Ò·'ß´•u‡öøí9´´ ä[ïA‘§ySyæeÕiŽªF=€Ô¨°&ëýo{̲$›ýñYǟƬPü†PÌZ‹ï(ÓaÏØ ( - Eˆà3AEý{ÔÁPè'yÈˆÄ ßu*öñ)oh}?ò” óW[hnYT²Mr½­)ؼ‡Õ?©š/Ù$¨W=Vù¯i7OfZXDznD‰S‘^1ˆ4Y’Ð&Ç·8aˆÉÕ´-‘åbÚþ ãíN›…`m•` ãq0ÖìÇçtéˆtÞXPšÂ*j^†¿u¯!ð½X1/‚iÑ…ëAŠûö,Ù»“šÂžÐsÓÜJet‰;ÝoÓÅê¶| cÀ UFw¤’-ÌZÉ‹.Ý4cU¹è+Ù£ëÓA[x7¸ïáþL¹¾¼ò,…=ÇyÆ¡ûé_ML7‡e!’µª»z̤ž_CoÞF¾dm’ßVY:cMkdù§Áz×eÐBŽ™µ•t’ïÂ$i(YR `Ìsm©ñ‡ï æ´+q†P0òrœ´r’LÆ0°¯¶0Ro"J²ûb|¯4”M_ËKÅÁZ“úé~!°oØýƒ ¦_+Ý|}Lêù[D e[ë·#cW!GüáÁd0Vá_ržŠÞ½Ÿ \OT©ÃBô‹óƒTjÉ•%sßöåÆŠíJÇ‚TM ðÄiÛ=üÂoL¥7_Ëum¸þírêñQ ¼t™Ù¼Bjm»È¯!¢¾w»uœ$ü‰…‰?²ò[ì„]³#öÖ¿5ú¢Ó Ìß"èùÞ,ù=•Í‹†Ÿñ.™DÌ#Å©"h‘@/ÏÀ‰Ã˜„Π%™ó×ÝZÖõÔJƒÙÕÜìXZÄcNñM]¶¤×B®^垇F‰!`Cá²Ë"t@~¤–3§a P¯Ûßɸ4i•Ø¢pA Æ!é“#XƒNØ™jΔíJ0ˆ9ôsú—‘5GcÚ_Þ@K’9yÞë¨ÑÔÈÆôÓV9îíê!NhÀ›H³I¬® . u¾'¸í„’Hr¦a­–¿h)`‹,—™:¼#“¥Û•ìUj¬–MÖ*7†åu†T­±±H¾|¬æã j6û±1Bì’rFðBª¡”t¶eXkѼ!‹v“ù`Ñ*Z êS™ÞŒÖMM4ºC-Ç;>Žy-A ‚ ¯*#â ”cK²@÷™º÷ŽQÉ\{‹):ËÙ ÑiÉäÏ9Qò8zò9ÉįnvFkèg /Pò/î¼l%Ô‡  Lv4ü‡‘¡C”‰ÿ«?ÌA1G*iÞÜ܇ú@pv4ÝÞê¤NÌÖŸxï0Γú=„”g±²ƒÐ$Tléƒò—äÁ@ó;h•,¾ÿí(Y廨 ǵ5ñÿ÷rk1hG£“íáÃxÇ4‚:ÆaQýBÊšÅ÷ŠD‚1Äâ¨óá¸Z7ºU{Í´·jÅN¥ØOŒ{mǯô¶ éTRÿ·˜ÕÜ5„ri|—6ЪŠO¦#g¦rû¹ŸÏmpPˆ“%ŠsÊ÷oõн¼®RòføÕ0 qDHÎ:†ÓÄÑu |žqœ{ ËxL8;NfýüQ~Øä-_¨©O†=Ö®¾¬Tl€bZÎLi†3eUgCÿ «,\V›/~é—{Â.ÀÜqõDËÕ\öÎd7EØy¨›V®BY·N*¼‰Å£1V~䡲.þnâ‘Ö¤™Ô9|u–=Ü¿ñ‡£'Ÿz«ÿYS`™€' ÝÝàð›ÔHîôkrYƒ‰ËÅS«7àÂp!Òè!ØJ¬0‹ÖÎ~´«Ò\è!÷;„Ú}T°ö¯²Í ½iǤ‹X—ÿ€ZHK…®ŸžòõËT4£`û“µ4˜aÛ{÷Û¨ûü|üD­«in]bhIû19k†,hñRêzþ»éøøº¯J ®QV Cb¯o¡Õìƒ'®âåÇe™ IŽ" 8Þ­r§Ew*9‹ÂøGL²þœdêÓ|“›VÒkr¡Ìm%ìþªèL97vR¾2¶DѰ×qš‰Éu'xE¡#Ì×ê“äM®â&€þï‘á´…,i¼ÝìíÌŸI£-cÙ„Êx¾ E‡ Àzù;m VXnP^ù"…Æ}ãñÇýɲ¥£oF÷ðV'*öƒñ€<Íí{,J‹´tÎ;ŠÄxŽøpàÇ •[Þ1ƒ„',ùBbºÅ×v¹!—nH6|efÆÌtG”è?Û´ô acIÑõû)#YP 郖ÏjT$›};Å͸Dˆ{bゲ±AÁ„KXž*”enV¿‘æál?ÞÀQ˜¬ï<ó"ª‡u/Y$wÜÞE™ÖÕöuzD‚§Îæë/dDdsÎ/=~§ö]øíÁ«{ÜGyÇ(#½ö¨Wñ|$ß^ïøù#’hŸU©3¨Ô@yóX¾È„óžvUÍkÄÆ§~“9]»ÅfQþ„ZÕæ\QMSªå:p`²¶uÊì¯Wb½ÑY7º^}-©fÒ/,F˜ë²ÞãqâÌöÑpÀ‹Fó‹Jp3{mV Õ£œíöõ¶éÝÅj ùž_QÅ´„¦h>f“†·‚mèÏ@çxä£B¶¬aÈÁý¡N‚—r³•ÄéÛ7A .üÿ–0ÝmVðÊ~cS³›KAR:s×:Þ½E™Cð?rLFUÃŒé4ÑC3â¸]-š¸G¬ëÜb; øf=Oæù¾á^Î}9ÂU˜~Ìí…'”æ[ÊþÆ5 AàeÂAžÂÅD²Oel„Ç `עɹÀ¨á™**Úšƒ~´?;€Žµ,R¥[[>x‰”fÉæYA,AyÅ4B¶GêPùÑ€‘4³Â ޱà\Iã!.`V½Û!"Þ©&îÏOÂÈOÁ™ön"e«tôjTFªˆA‚5Û—¦jù+¬üx\wó÷“nùAø<7„ö-T»@õ™£ÇÊÁÌ:+š˜ºüo&<ÓÉ-|¢G ÛFß[é¯ »3v0HÛÜ7'Ôò¢^NæÔ²ÜñF(;« ånê×$ÅõôÆmHik¦l(õölŒ€èŠX9låÚ¶¡ “ò€“Á¸©<ÞV?X2iðw ;0’VäôQ æ6¡8QÉŽ¦XMõ ájaˆd›ÂQæ·¹l»¬BÍÂÏEmÌ€©N=Ý©n¦  μÝ1Ÿ]v†©f$ŽØH¨./´sÞpV÷¢ð8wt–õS3²sÆ´üH›ÞüuÒYx)JÄ,yïíN¤¨›99D“4ôoTø*ìÈ.pßÈv¯¡*­Xœ±jƒm‹kýùØñäoý8èvoåjå"€QœPîÐ ùŠí•«?\ûñÞ Poª\´)œd*’x1jÛ×aÆ;áËh2åöe`õNªr}CöqÛUë®F÷«vÝ’ eˆ0æ©pqF^ŒíÔÇ„àWpMMæå—à¼33AÇféu‰ïbíÊz0"l©NΟ_šd²ññÆš#=Ui;Ýž*ÔáRÇwVwºiò*#’›!ÀÁ‚[H±äJ:ÿ[ßÍ•¶‚Vµ¾ ñ™°rþyí`†å]! ™è´7oöŽ ×ê™~_A<˜9õ&…ݨ67¨ò;KÉî~ʍ1êóDaÓ¾g Õ€¼“ªÚ-ÞLXüô4èÏã3‡lÞÔšP€k6 åñtˆÞVÙ¦yÜõ¤[¬üÊ„G¬ð8øò¸¯†ÿ5‹Ýï™Å¼Ê<³xY8`Éì-ÞKï7t•±¦ØÕ°Éq…oôl¦(’ ÔÂØKßgÅNÙ_`ÎÖš6ºîÒLƒ¾dж Z¿Ï¦Ÿg çLúoÙ\Òn4ÏGIQöY‡ìºö5 æl!Ã%\, d’.“ûÐ #¾<¼Ì9°á(<¡¨]Ö24C„øuMÛ^uÕ`ÿ"Ý|[/Ýf·*°e5Tû W4’邽·׺ñÚ“á‘<ØÎ¸²Nª»ÏŠå~ôÇ<€G‰5­½]Æ­žÿã„o”|3 ÅŸžAeüÏ÷"-æEVc¡ª—rbÜß {ëFKDSXÁÏ›Mªx6ªØÃ[¿ôg’€oö‰æÂÇ]‚ ùÑPퟳV}ÎÁ$(Ä„ˆ J'E‚ÅÄ뼜 ¯f…«ÝN”^$"Ì.%ýõãcÅB_Š A]ªQðǘݭ©3ØéÓÃC\ròH…»;ˆ¼‰ž4f]Sô[ ÊÄfî\3(,©¾#r<;FQ0Ðmý׿Ïr•$0U¦qšé%üâFºÆŸMG}‡¼¶„èEäwl»·=ß¶(âöeÐ %gÐÚ’û¤ÀTQ øWeç† ä{EÍ®7±2¤eOF£[Ë1%;\ØËsV“ºìª ÃŽ¬Oñš%ÐJ þ¼§{ÒUœ¨PÚ+Æ4ê°ñB‚ï„›ãN¼d[%ëûcž^—é:,¿Å¯Þ½™(¦ÓRU?¾Ó4ˆÖG–lÙB2¹ ¸‹—Ì4ªjå¦=uf®ÉWÃÞ•ð@k|óûe†žÁuºÍÁʱmüÑñü7Êè;IŸ59ì ¾þ;QÖ–¬ )”LÎL…äÖ_<}z×ëÓ]ýhÄ[uïeþtùT•YlA‹‚Â¥uF«—•°!†/­<ï&ËО*–aÊÜ*wó< Âr+µåŠkO¤š&:d-ïBöÅb€½%o^3FÈ0Õډܧº £Ð 4Œ>÷?Pw$¤Ã§èþf€]Òcr÷pލîj½ †$Õ´?e‘áéKÿ¼7ÚÀZÕäf,ŒÑ½ŠôBã¶dšŸLÄ•[DÚ­Gú.?T·´K;,¤u ¨v\©!Óq|Þ¥h= µ­¾yŠGä-Ÿôt]¨±¿—0)dg ÓÝ&Ù¶: :ÀÈB3VuzK¬ H‚¨;,oŽÅ¡æX|¦ía ,¹b×ô|úû?Æ!ýû«ÜôéeÂúN¹Et…ƒ/(¨­–zþ,÷Õâ´Þ4¨D Z¬ÜâÌ‹±AÚ ÓUj!¼$J'­/ÄÅ °ÚMú ,€RñhôþÒËKò¬ˆ"ûQóÏWVí (Z˜oÕ&¬„ÛXªƒ· ËÐǼ¸s"ÑÒÇévÛ•ê^XƉÒÛ¡ÅŽ"LÜCß’n¡‡?_öÀá¾É”>H ³fÿ ›ŸCT¦˜‹E»¬Ñ÷Œw÷°’bÉ”Æj›†@ áZâN¹ÜtR û4büS…B¿eÃj7üíÌ”kˆÆõšž<::ùM,‚ˆÍÑ ø§Ø´êÉVQ~›N8O\$¬•h¼œwµ;ªÇÇü­Õ1 cŸƒê’s¤‚Åè â›J)²>8ùJêÔ{9xþsê>ÇÖ½ç„n¿‡FÆD€cü<4?H™'ûÙÄ$—k<Iè4?b»‹ýÁåÓ¯yåa¢:Ø€ +ïjƒ[@\é”Söž(šŒ†¸8>¡wFÊ/gp w~Žíèf£•è¾¾=zk$þ¢yˆÈG‰kÐîÜÅÿ:OU‘”7VîÝ—"bZét† Æ’ÉüÀ±ÓEO<•/FßÁíogž}ü8‡Œ€˜Áe"Ÿ5Í„iæMW;1 C”G¼ì󋌠&s)ßš0wžð"–šJ:)ÄQF  ü‘ZfvÓmåĨIVͪßI‚ï3›¡æ‘¾jJkSð))l顨IwÅd8ì@MU‡óò¦ÿYôÚÀÌ⤰^™¨É†¯1âÔr”°¥L\dZÞgq%&Å« ˜¼Ù£B±fNhÃÖ[d*HÉ— çJ÷0Dj›@Ä+z„Tòìݲ?¸oÏv3ü¤¹Ój§_}šêšÖ›"@>¡å²†ÏÆ;û*P.Zèx¤JSlùIB#°ÇØ»€Ä[4“k|„£*7Vè¼NM\¢ÀâLVôKH/1R§®p~ý×µ(R‰y—Y}½w ´ð‚pzÎÍŠ ŒòºÊ` Ùœº-]-!Iž ÛÛP;¨»ùÜA÷R  ׄ*À÷Š:] ù§¢Æ4:ç’;¯Œ6ÇxÍ"ûN‰öx¡=a‡éªš ›àX\Ô¦«cÖGêò©ö‰;Køùß XßÜhAPù3äqeg4î8¡'‡‘µ˜ÿ_!ܶ²çõ³Á¾Û'K×úÄè¬Wñ¿5ÖE^Û[P~· –É}Œ»Bj‰k¼mg5*ȉ(^´?q­©¸GýdÑ}šßÑ™f€j&G¥µÛjX¹ÄÆÊ1 ª ÀaÓ)||éп J¹Sa°€ˆÈ™zå;–ÎÙ*û3:t±m©‹ÏnhÚófõ½•^ñ\Õu`6&¿a/ E—qi%‘U)B1y2—#Oaã%°òΧIÊ”Ei\ívÏ£—ó·rvqdv‡É¼Ð:ªÆMrœ›˜AlÇDÝÈBWÉ3î넬®Zšâuê9’+wãç¡ wG(9ÔFª?% ¹­ž7Ë<8«¡û™çjêž!ã‚Ø×®E\¿òF6êè¨nŸãê¡ñƒ‡{jŽïF xc€‚"ŸÒ€ÇÜ+„޼®U­g›<Ø—bÐKµ(LÆLT@t¬*{c¬˜ ·†MWpwå>0ÔqÌÁæˆue³ u·CÀ ¢ÖgZüxH¿Æè¼¼GÉ¢ñulggð7eó[^9RÈÿÝ6ª‰cä_µ Ho?2€ÐÍ ?Ÿ’Ç>‚ò Í:ž¶Wçã¼™ùoXäh;+X(kS––½3ë~¯óðaᛊpûü)ýD‹I¬k¤›xÏõVäÇÙk¥’BOÓbuoLƒÞåAÛH6µÔ̷ѽi8ý!Ý.fš¬Ý¹ül‘oS´hH‡Û6|—miW|cÁD%iÊý×mŸ¡ý°]ôŒ˜¼@­A“â;óð¬«o±ìodJ5upk?²‰g}6;Øœ—Ö¾çªbªÌzpƒ”´Z‘•7– ´a Õ¥ÆÍ½!£­,“šWUŒà'Bn´b¶\Šê—7­–¯ÓôF \±Eȸö~‰ÐèðÞå8§DÎàÇäo_–«îXU§Ä¥Ë—’3é³àœÉD’wB#ƒ¶Àd„î ˜7Šç ~“F]œpZ¸UŒ‰Æ|¯Ô]/v”¯P¼áhÅÁKMà8 i¬W^ã‘xÙß_Ð°ÕÆ- s^›ªGļ½Rz/çýuŒ&ŸQÿiÐ_(çc‚‘§3Â"ˆ›¼ê~îÜ„¸¨…²é72(µÅQ³ëÇÛ&/gø yÈ+5Õ ŽtW¿ŠI\Ž©Fà£CòŸ×±?¢•u QÀ}[  ‚M]3@·ÐÛGSïI¤¢œÂ9'Qâ2³COÒjXdÅ?'žŽ„ö»óÕ¯CíKËYÜ´TÃ~iäã7ûÇbnÇÙ[ÇßµGÒÞÒ CÇ› ­}ö-ÆÐŒ½‹=E‘7åo"¬:-ªþ¡ä2öîªq¾Ô±Ý=DXÆ §]šÒ‚Ö ·.×ú®%Í+ÈRÏDú¥AŒÂ"SÂhö§²0ŸÿuÅ,ª›§6òQ’»É{µ†ö¤Ò˵õ÷ËÔ.˜“3—®I¯¸¤'ŽpÍqð‰Tá`áWÜ•rµå-Ó‡R·­&4oãX6d•Ù }hcÐ9²hYO†Õ¨IÌN¨ÙCõ­6ü0äeÉJ­˜áUíHÏ¿‹Rˆ­B¨š)—“H£Ekø?ÈŠ,œX$u³Sûu&ù¹«ïcupgd«ùt½ºPhòö?ŠC8]YëØ<›³êd0\ Ø·p׳uð\ïÁHŠØ S0¢ƒM$Ðé°ÊÜÆ ¶iÑÜ‘1üBŠ*_À@ÈB–9,Y,W¯3’§HY®Ø‘>Œ%ø§C§ŠÏbBë,Ý1€á-¸‘Msy •[î8êèÅ‹B`ªÎÙæHˆÞJÍ:ôÀeñ£P*­ÐN¤-A‹Ã»NÇŸ&ñ”äqWÑ®`ÿÏÜnš ƒ'ÕÆídD²p0²dáîÊ_k%¼æYnÁõ¯Ää‚a@ë:hЇÏÌAÙhc<ÞΛ¦ 0ÒFdR-qfQ§è»_€a–ך³Ø~]Ó„×…G^"(c=€°!ö'ö°/2*‰eÖbFuŸ ?swekÐ(@›öHý^uΉHWsSbРÐIèÊOç爲ßeïkÈTçê¹U˜æ! E¨Ú¶¥ê/7ÁØl€n÷S0|«ùÞ $•&ƒ+­Oß¹”Êl‹g¡Ì6+Ž‚Ìsè|"øãÔÛŽT¤[ +>VnÚVÈE4KqDøùQÈëyúЖ±¾èÿȤí²fB.ß™àðft–»Bªd£Õ‹„©íXB |äÁ¬Î™ø}޽ÎþæÏ]2¥³´àö«n4HڦŽ"Õ0¤–°”$šÍ‹$¶°§e]K/Äyô[¹â<Öõiw•ß°N|²AÉI7ãŒÉJm¹Ü&ÕèÔ,>8ýáQ‰Ö¢ékĆÂ>\‹ÞÙ­¸ÌpqKkYÿÁ×}%220gxëыϾlî;hØÌ‡¬é%ÓE¾B×hˆ:p‡%Ö9 ¢Å‡(–¼ê‡¸÷eQ- «u-«ónˆ_—«™¯˜fhýÆd| š‰ q`[ô·@ 6úœÒz VÀœ·˜{avxr6cŠŠáI·|nj€³B°Í3všŸÒç{r­¦tö6qž4=…DQ™})kMÕM Ýuƒ-y=uð7F£›†ûù<$>ØK¾ámEçxmtW¸•Ú Û‚}ŒÅS>ÉÊÜ/húÌÁHšM–_H™E®2(Ó…ÿ{g.!*;†s.zÀÔÇO¨r*I¾}·‰æá;ÜC|sUöµŽzkÛ×¼°éF,¤Ne;£ÓäÁˆÈ–&ÿ؂ѫ%¤ý ĉ›5&ã½–÷ð„¹¶ÇõÀ55óX”ÍwÔ.c§Ìq£~èúÅ—ðÆ:Méo0ôÁlê^Ì—íL½#§…k[;giL#]ËW è4‡p¬³æN%Ös£ø>íóñ¾CNË(Pô’Îišj¡ñUãU<8ý›GÄ-Z3‰X_\Œ« MUCnëíWU”†lë•"J_Î[û§HÁÍd&¸xr+ì6OxöàoËŸ5‹¦jÿá›^¤óò›aEÙJ2}Œ:0™5u™ÕO=­È­ h±í »öÒE »Ž k'5×6Ùjâýþcêÿ…Næ—~vSÈ„ tÚì•组Ù•:ŒÔ:Ò5Í×ëÿê¶«.>¿xQéÝ;]ñßø‹±(à¸ãXAŽÂ§ö•wmÕ» @Ä ‘ýÜÒJÓLǼ´HôÚµî¶þœ¨};°Ÿµ_…ÿ| F+o±•Â[Zœ'Aç¢KL;ú¨ü¾PIº ¨eÆ€K‘'Ep£”çRªæ2LÛ]3Ã'w¿‘”ê¡ëÑsä ö×=ß Ö({ó]w~?yÐÙ³D;¹`Q…¬ºÂF·‹9í& ÐÉ.Ï;c>ñ-yÍîþã CϨ« „O=:DÊoX¦ŽùîJÆ-$…eƒg€í€9ÜYŒ*>À¾Oà”6+O^Ä—rp¯øÆ")W³«‰Z%MWF%Gí˜ ’[j»‡òs‡ûoÖã«§†ÿŠ’úÊ|äZ6¨?š°õ ƒxW—Ö”*2Å¡«FãËÂ,–p)[(z‹ù T½ÅÅ‚¡|ˆGöÔxdã^ØqMæí SE©“ˆ÷O¼ôàjçßH£õAVºDQcá_«¾¾†¨—ž[¶1‹SÉ;nh9‹j:ƒ/1'ƤI—œºBÓ#`$õ¤â“Œ%…D…óŒK(ÿǧ¿±¤r y?£@° Z„ŒZm´Ã½w´0BL'bŽJâÙå{zˆ×Ô.jö)ÈV—ÙÛhQí¼dÈež!΃žûsYH4 A²}|™ d à„¸wŒX|Rƒò¸,m·ÊŠ«¿‹ƒõìô•J;Ç cº¼ÃD9 Ü ³.žUs1ÕÃ}ÙóÞÃRÐÑ“ó;tFù¡WSðƒáÿ-H×ÐQ²…þ™Œ?ùØ|Š+~È›ïÿüßß ÊêPà¿âdëBÆ ¿·QöÆòWµGy±¯üÕj"5Ä?lDT& IóKUovl­6¼,ÒoAúoÔÑ ]‘ŒfßÀSTõùÜ·×ó¼J€ÎI’ÛI¶CŽEÓÔ§c¾³¦3mýê!ž¨ýexš—tPšØæs–ü Ž4a솼¨O:¨ž^²Ë[Zµþ“Zˆ¯{ÓÅ×!òC6‘4±Ï£U}ÈôAXÅ·îyö~/6bÈYÓ†aä·,«˜ǽ}páо¯1‡5ØÞge×èP#ïH€±ˆûBÁ™}'»ÙukNâc÷eš—|ãH·¬N=ÏA§cµÖ2QÕ?äåÔÏÇ%K!¦½®˜Ž ÝÅs°!…7Ì·Ãÿ€/3Æ»^ЉÔʳª m`]r^(ƒòq1;Ò_ ’t·3­*ö©†ìðu$ülÜÛØ…0Å{ú•fmn$E¹º&Œ»ÊO_EZhÞ¹jNE0C%r÷Ѫܦx«ùG¹Š§=×-N½kÇ‹î»Jšh\Âz–™”ˆ]˜‘—þŒíñíŒ9§¦LÊëíÕUŠwY¦Úy”…ºó– ˆ:Õ±ue/­vÇö-ž³NºEn@bçco§F¶)‹šúØõ3ß³´ìÕw.°¤TÙ(‡gŸ YØÕ3=¾b@ÊlW_SôØOº*)ø‚V‘ /IÌça;N ƒ=;7´íÄàÂ_Z2¦ÂbãH¡“7RDq·f)ŒäýÄÿÌ@r‹V©G5<)ºÂ+ø&ß gv=G­GY<êÄZDT6 o$¢}cø8Zp S‡TÀ­æuBÇ?~GD'ÀhÝôðdA9Ü«h';8ÃܘbνÅÎsW”Í ;¿å€¸¼f{Ú–qqžØÚt6r÷NÎÔÝ•ÎEÀNs¹qÕå .1ÞX˜)Y€^R,ˆ…Êdù¹hXí•ë*·ª3¿Ð\̵Û? Ex É¿3òš:q~åž5àe Œ¥[ÑHdÔw~ª”xEÑãØ1”¶ä›”Â÷‡÷·…0ä^óÅ¿4&ll‹b´³ß¢È† IΣWaÿ¦9°¢öñ:‰ðt"HÿÖå¶Øé .KþÎnsz \d‘¿ûC²Ïh©RO|zŒt)&:É£„%}ÑV_œzѦEä¥8M^ØÉH3Æ…Pftchçfò³j‹;篑ø¬l„ ·¬h¯à='±…ÓÉÖ¡Êg¸C+ *æû÷3«ë_áÅÓzñk´Ï3ø¡I1L²€ûIÿ°€+^óÆ](j]ØýM•#þñY@ìgUvœGH.æ œß“†Ïëòè"ÇÓvjX{"-#¶€îRá¶Ì´tO ›®õ ÎyÄ̶Q£{íŽV"ЬáñûŒæ7e±êéh_ŽxŸÐÇ­3Í”7bR§Ç¼™‰Äâ€HlB¸lŒGèÌ d?š¬´ÑMa&…±_ÂñâaIÍÅÓλù«ÏÕš´—ŸåiÕ,¯ôòÚx²šP¿Ü¡€¤šØ0¢UÀíydÿ 'z’£* }'ŸµJÖå˾\oo•M1 1Ceó)\-Ô¿§vâ ü, ÀÝ=z´‚7à˜³Ž{ñÍm¶ •ÁAëg¢Ãq’mzSº>?L¨>É÷ ž›@î˜4aSâ£øjhvñ(î.pÔ¾ ÆÍóÙYði—òÄl 5œ+#aRR¯y¬9² 7é¯z‚þ0^DÑh¹Åð¹—XsSné÷R"¿Ç¤;Ø¥Õå˜D¤_t>Ïçr¦¤ìFdë•74,í—,a¥kµpÇÄÞe…ÆLD¹·Ì}IÏæsfU; ŽÔqžÆp맭Κ ÞMc½c–fÿsÐNÇÝb4³r+#k©½¡¹Á¡Êdƒ¾;¤‚wZsÒÿ K¸•òˆ¼ô“Á06Á41z¯ei1)ðíú[oS'xIfå®ÿBo/•ר4’RÇ—ô‚ýã‡NÑÆÈB—Á‰׎Eè‚w¼œQí4ã^^&iLœã¬õñ8Ñ‚Ëí+A^Ûê^}—v6¯.t_<ðŠyÙ”C:>Œm(iß…c»’BÈbÐèÌ% Ð8Y•Í¡QƒÊ2Ks“¯VÞGf±*Æœ彨³§æÁ1¡‚‘õ˜vê'c–µ. NÕ“õ7gñò)#îmašÁ£2øR`?ãâgiãQ®MßQÚÅ/KŸ„ýÛés]bp|žŽ–0¿c ÿ˃I«.‡¢ÒÑëÎK_i<¯…Ùèk¸Šˆ}ƒ›¶Ô'GâVeᮿØÙŸâKÞAð©syˆÈõ¦¹]ôíŽÝ½‹ë²9*š§¶“ ,>à$ÛwÑï1Ÿ«÷K<7ÇÚ} ëñ""0tAN›kÉ’å'¬Ò½Ó2k.G&šÆ}ë|DÃÎìjÑâ0á ¢Ø9ÜÚ•Mh15*«¾8–°³øÓ¸U~îçú*—¢mò×5tùÑ7ÜZdj·HG‡(c)Vvð× ¸Öσ·_ÙĪö(mš÷ÈP ¼)j¿Ù£ÞJØïHc¹ß¥‹­šH btUÞ`ŠSYæOV<ü’'%ÙdzªE 7IÑ‹²@p~ÀªÝ­…Ûíg¾IÎ`ÿ¿g±[‰Ÿ`Gb¯™ž­$®ZyÊŸæ£în§à„'E¯"$ä9mC“W­›‘£Ìó|+Àj¼Q¬àa'uº4ÿK¤*;»lNê­ÂJàÏg»_ !°T檅Â]Äñ–N6`v눖í6 _àyŽÑ/)Zí¢‡îœ¹}qŠP°ƒC仡u94å¶wh™éöÚ!¨á8ŸÓUhð*÷À³@í¾/9?$Òi áîø°Ö‹Nãy6ÉÈܪ»n¥a×\ÕEÄó }mDG¤WEÝT GMäu{²¾ò°Õ=úh…¿ÆÈ•ÙØH7ýPr×sD—¾¤£“ ¢0ÁCJ .pfzø9Z_ùV¨‚¨³Œˆ‰öô2’ØîÛŽuAIä\—*uŽìA›þ6¬(–‹óm&æm}åÝË ¥o ‡¥w!þÏÃJ{p ::Çg¥/¤7Ö—eÛÒQÔWB³p [†üv? zÒÕ ˜ÇÅÏÀðÕœ"¯|Bgÿž€G¢{©bÛpUSºÌZòFËáp©Â*±A/Cè °c­mŒuÌ2,×÷ùú˜šÑP#(à¸Ie'”]ã¯Õ1ˆ} E¼Gf“Ÿù?@À0v+£­ÈŽš‡:áPÂŽ3Xš)ÉR›á> tSÞ æ¾Ž)8Jz)‰=‡< g“×ãË›†QSú­¸WÏðq6ùÌiɶ*jï“–¸iµBaKŸ[Xm÷,!$G†µ¨H×l4%ÙL Þ)¼ÓC¹ì´œåévJK‹b“Ck:wrå/Ûkg¼Ý„Nm½¢–Ô›G±±Öº)FW4^=qlUÓØ…AÆX¾Hð˜çW»ƒOî´QâœÚ†0; Xå1ÛÜ~B’Âí˜)´gÁ«Á}-Vòq÷¦_“z)—m( ÀqÈî¼Äp6?0ˆÔñK qkÚBï7¹¡Òö8G;>ŒK¦]H§~½Æ³M¯õ3¤Öœ^‘A­É‘ñó@h³•$ ã5Y ›¹ØS‚u޹…O‰5jF¾9Ç÷h–¶ál„»gv®ŸN_+ Z¡,‡®}¸Û-¼ÆéYÊ\‰ž™¯ÖÆþÝz3là œl0W£¦¸êážËØ/vÕ QªË \¹Ÿ¦$KÉÛX¬ ÔÑ—w2œP]\cƒúî<”½†c¿]MZ½ó P™ç€ÍYgþ_h ¥_ð,dó”B:Yjb^ÑÚ•O>•ø c÷¼öŽMYûÆvRL9t¨8èáïáö@¼®g}X-­› “îª3¬„x’B%¤èœá!)ñ?HàNujØ£°Ð«Ž¬¼R %þ€7"Ε¨SDÖ%»Ó™R…ï-aS@òÚŽv,"5#î5«®ú]ï×¥¥²éyß!üèyò7@ÿG•Û¿Ï„£w>åÖ€F4TÝ+°q>[gˆPPÂx޼+íÒÓl[çÛ÷L…®YûQù9“ßϺØÓKò `k?vvölÓÏ_u!DEL¥¶Y)ŸUÎɬ+ÝŽ~º[)ü‹%Ðôz˜­1.£$n¹l…÷N„5ï{þ´LlÛrtWSçZ0¨›  *ûŽ£T ­?-.HëU^ Êb±VßbœFH¶ŒµÞx9A½˜N~´¹C¶..•%»Á0µ©Åú²t{æyŽ-ˆ¾HˆƒiŠÃ hf>ÝÏ_g]y6'ÈžüF(V},‹ó7ÇÔzÙŒ²7Ux cw×\ûv ‰ý—}w\Êæ'Òº0„þw<ð’´ßûTuÚ–dÍTÎY¨`첂0ÅIV3ápïoႲ>V$YšR•ÃøyÛÍËÐký€zT9F1˜_ˆôÕæ­³º«@¶ökÐ"ê*"Á³ê‡ d±èõZº¿nT¤¾í[‘. £ÅÔ^T‡F[GT%=¡æìÆ‚‰ž?욎ÇÖèž4¸8­’üDàÔ!øøpõ=n$‹§¦DJTb;ªÓÑÑ=°pQzðмàšFÕ¦b[£­íöâ)6Õu.š'}6zÖ-+¢’CM®ÐÇ3‹µœ‘@~@ä¬S̱à‘…sŒt÷ÜÎê^ál؈ć¿7]l •ù¼^,þLhü2H×¢H“,‡å¢þ}ì $¬‰Çsg1þV¸X»),Iù‡’kjºã@´g~´3JäíQ¿;8Þß`V&ÁZzGPïfÀ¢è  ˆ³»l ã!Pìù™±0Ø,=å…èåYs»¼QÛÑEn†ï¯¯:m «ÒõàþŒ™zç+Ε}ÃxÚG¨ ‹sh1»ŒÔÒ¸©N,W ,Q‰Nc f*8ÅØ8ð¾É~ê²6ófìåâÐ R3Í/Üæ¤G«×‡J_ÃFCA¦…JO˜g]›LÕA0ÇM(LÕÃë´î{ú€¬#û_Bƒ>æ[ùÆõw™†'S@R§SçɖϤZÁ…iÇÉÊþð£Þ?'žyíu–; éYK¹å¸@ Q õW °³q+u›¿œvÅ °ÒýyÓHˆvz9œ`5£ŠÍÚ>`§qî°oT èäü "ÑSsK[¦¦ïܻüÓn±Gš#b,^òt—”×D<‡¼xÌ캖ÄÜz ñ‰ÏÍ¢œƒl”pí.¾lû»¹¹O«a‹+êwÁ… å¬AS‘ÞgC´iuxè’÷¹^ªÃcÏnù)öãÁ9PN[H¬ô–P´Ya‚7xyµrî“ÈæV«Î]“ïnä#ÅÿŒ^EM"ÖÑaÑ7‘.+Sû¹Ö4æç=¿FûrŸÆÿæêÐN¹fÎ «õ B¬V$a¥_³iÕ6ca±h§°³„žh$–µeDÎÛQ"1Ü#Fê s_ê2 =ŽÆÑRÄLD‡è?vo>‚N¹~X§{UzeHT­+¶ÃnòO6õãë¬Õµ‡QÎ`:?_X K [B¢6¯¬”Ï•»;2Æš„ïñ|­dÂ@Þý‹t¨FÈ”å½p +šÛÚ“]š’" ’én¢š~‘hÚ§ñÃ7nVa¯±é#qw2é/TMàTnwézêÓ¾!ø¡ý»(“wT ®|ˆœ¦ì|à ôTË ÞTg–ð®½ðßÒx¸³.·äJ ô"ýÄõ´uxdÁ‘Ãâu  4’Cƒq‚-‰+t  ¦w?豤üŸX<ǨòÕNn øõ·ªZ1áÏ.BÝn|¤A'7'…Ç|(z,i"_›RøÉú(óòDówc7ðÙ|.…#$G.˜6Êá@nO$õ°+ç|ÍÐßaWßÒŽvõ…k"D¹¢icßgѤ1ÀÎé :ÙŽ¿íùM.Ox¦ÔÙ™C $ulìk(5d!Ãż‰{Ý0q¯ÿðT†:ð=vÁRo ªþž3סÒ<鵯T»è°ì¡à‡EÁœ¡èdÊ Œ.<¥©kÿ1Èžè£1âWešºùs/˜»/Lîä{J$5ž½ç|ŽñÅ`Bê›}•ËÔsÚ\~ÓÕc|øCà*»"˜ç92dÀA÷:¡[\nUªBB6€øŠ† ŒTß«VV³“YééœÆZ@fýMnZ/üÈ»Ò×àþyv“$Am¶ÞÑ›jB 6þ{™"1rÌ8 BÏ ÎȲºÙ­öE—53ೌ_ñW5¡âW}ÞŒe[8Œ pCž´ ‚^á†QÎçýô¢.y­¨¤~šñÚ3s,š+Íh;­ã%Ó:L !µ­1a¬ív0YXFà©r#p|®W¾’”±ó¹¸kÒo·—Xíõ¹Ë„†2Úª 7?÷:¶¾[vñ¿ùì× ÌÌP®Šü…Øý[´½,©³–Ãae~/aŸ…L?ÈŠt¸vûv‚’(aÊk?foE÷dÅã(,xEêö2ÒÎÐ.ãlãý¤ìö¤šƒ¬$„lŽ€¦h4ót[%ã¼Ãð3š6;Xüìõ†3ƒrúHÇdWðh¡{ðÈe(°¹¯Yña@ŽFì *aŠvœgɧð!#Š•9´ÕòÌé=‰ïây^[½Ã…¡{‡\|)ÿM¬Ñg¬U•S®)ÍÚ€YZÓÀ’$tèV{ñ¢ ’˜C>ÚŽ=è/Œ ¾LU*Õá#ÒÖ¦F&Ò ¹¤ÀÐI w’µí`†;<µ¹Ÿ:Ä:8Ræ~¢|b.¦Nš2Zqó]}Pjq‰Îé»ûIÏgzóò/[síT|S"ôAUiÈ8ɆÖ¡ñ¤‹ïI!Âú¿³Ñ“"po@B ᲂª5Ña\ŒÀä{}×ø¨ˆf™A<ù~Õ•T)ÃÙzPÂe^s¨Ã•c ù­†“hA+YŒÞ²ô©d ïž Ö×tY˜±´ >-!?àà&-<Á½ÆýÝ’‚ÇvŒÙ˜‰æàzCÓíh—´HbÁ¤Œ÷?‹e«O‘Éid±Z®- ÌÊo~$­iœs°t»£2/–.°Ä·•ÆeÜcT˜«E÷ëaòÆlÈýÐÅÈÇèë VàþêÊ(eÛ‰aW1cr~r Q›¡þBù@Ì-¤Ï§b骨vW>G•E HîG;TÐuhmŸ¾¾ÇÄZ #ï5´ÙCÃÄ(0• \ iû»“-¿²FÃ÷Ç”WWkÃU½ÉN”Q¿¦àd 9³qÔšhÛÒ-4ep8>e×sj»1ÞO-ÖßècB’çöÅãòæ.4RãÃ\*ê2­#s8ÊÝî}Z #‡ØÒÃ¸Òø8Ám%!MûÀ‘ 4`–2GZó/ GµþêzPMh½ì/©¾z¸_Ìs¸¬Ì“¬ D›êiYh;Œ}u³™‡ÔÔZ ˆ|šÁÚ,|…Ö*ÆĤ2ÏîýkF¤OuI°²–ZÇÕYÒQ }ð ðãâ§"òZfÓÌuùRêÑʪHõ:,Ý;ZЃýWŽWú„â„mãßðã¤IpÖª‰u3Æ”aQ[áða'|ƒ8ƒx¸À`¿—ïŸt².'UÍnÎY›W†)jN‹²Š’}m_5¶³¶¼þ2TÁVÞnÀ/¿üiψ–hY¹ {ËþX8þƒŸp k€O£®èÆ98-3âˆÝ(c•åÆ9ŒÒ *îš £žÜÉÔQ«É,ƵÍ4PžkÁw.˜;Ý6×øŒ€³©[i…f¶3"Rl)Dõ…ǵ÷Nú¨¤Žçв1á!ÚÏRs `˜•‡šÄ¨ p8¼¥€¾žù‘ØB®)$IÝ[¸Ë*4_4EÎiå»YÍ;AFÒ ¥ Ù{A·AzŸ©ð/mÞ òqÓOŒ­»Ò½öü™»rEæ?µƒ‰Ô°›.æÄ%ŸŽËiŸÙ pŠô6×€Z•²6¸ „‰>]äË?‰MiA^8WrÎv´H,` ½F&EûoÕ!{¤‹",Ót7ƒÊ3ô§‰¿‚²ƒ»äßs‹ŸË”¢˜6ðHD(XÛc—hú®ÉâÞOä4,$a]õuoÚkô†4“e‚ p‡ŒÔ´º±¥ÏF]&þŒô-d‡%øÁ­ÛŸ000KÓ«ó½Ä<¾ ¾iÄahu—N¯¡øæ ¿Úlµd~]µ•Pä3‰õÎáosç8¤–ØüŒE¬KˆŽ¶ª°÷e%¯àâìÚ—½¯¾é$ ‹ŒÝ¡QÖ†¢Yà4jü÷òTþÿ0Õ)±"¤ëS"JID¤ºšV âÿ„¤6»6y™ìè¡¿Eö5?°qÀ÷n£á/¤.üêD­‘YÖQô o0ÂXµÜÂñôùP†âaAÿ>ô±ìÜ@:Ôä Ð&5¦Õ臅‡ùUª>LÉG”öÕÄEËMxò H ƒO1Uþ›¤?KŒÐ.þÔJåÒ òÐÂÏî°‚J3ã¬5*²µ"_г+Æ®yÙ`J#oû% 8A–.¿T#nˆE)>öK€x`3sì ÓZy: ¾gä¢^g¢ø–âãÙWYo ô«åö­ÒoÀJæ—¡oGÊù4µÆEEŸô•Û¥Â4¤¼ µÆNË[ e?++‰À•>˜QØ2®[þ °¾ï-¡Ýï[!ìÜiãÆú¨­dl¼”‹((²Ç:_éÅN‰ž0¦?¡Þ¢æ¡Øù03»EãõwÅÛ ˜þ¥6€•£¨š™ªKÖ‹–àRég¡\„º‰ê/&Ë16€ › ÈO/Ö¼s1&b™L 0üŽªú¶6lQ¾÷£Û¡!‘CI©ŽÌ/ÔõãØr© QøÌŒMZµÁ&!TÉ=O£F·öÔòˆI{u€AÂ'ÍßUæE™æî³?à/A7W bõ¿ŸJß`N&Þº«Á€+$Ò~>ï-!ÓŸ¾,/ÑÉßsÄÅv}˜GgX ~_¿Àg{¢Ü×FQGÁ‰œH¿:>É¿¹múéʵwøèµ%áèbš¬}ü ¬ÌPµm/½*t é'›’ÐŽté:9ìÙ$­Öïÿ~Üm‚!»õÌØ}—jWý<âpºj•Õâ ö–åvÿ`ôÂ#”T¾MF¤ÍÔ’–ŒÄ¯û‚§Í–¨$Øg‰I”{'À–ÛD›ÕûGÆ ÐúgŒ2a—ÄPݳömtµÂþ£&xÔA}ø‚þK·Ã 7LJ¯CM ù¶²ÌË/âò•cÿl&jÚ{PßöµŒ‡ê61«­”bV‹’ã'p"HTǼߘ[W ­T,L”[º[™L-šñ÷”In¤Û®ÛªnàL\„í ]n‚(Ö#™BRðÒÏä+w”äD¯cxö˜‰Ö%nÊìZbÇ“&õ•‡úÞÀèÇËôˆ…¸ãý—ÄDêeLêx7!:ûÕyÍ 7¥©üù7SÛbKÈßÒæMÅw®5¢—ŠjAš2"üˆb£-í¬º âO ¥ºD9YIS˜…qëBê"¼{`ñxŒŸ’ôë,:ØKÈyqbò8*K¤/‚µ™QH¢#ÂÖäóJÇ .mš·Ÿ½bþÍ~9ñg(S9"17¨^ Ø—Ò=`…&ûÂÑ»Ó{£Ú¯ê§= Ð]ï®Ôƒ¹‡‡0CÏ?Ÿ™˜.`•n_*O 2…j ìŠD¥Ú ¨ýÒ½›2ÒR’þÔ˜¢?m/—ý0)³“|3%x¹ ©ÖÙÕÄxqNIáôfVÒmöJÚàp½ƒ¶üÎÄúYtcéZuâÆ<Õ½BÄ“ÌK²· d°žR=°ñ±}œÈ€±u!˜:•!ë¹;¿yô·Š5¶<1O‡wÎ iOóø«Kú2ÛœJFùªéã„Ô÷˜£¢a>¦Ç¦†óY ©„“Üý5´Äõ¼„b’†JÙ{Và¤LöI_½òDoÇ¥\ˆ+àP5B´X¿°m:Ú™m££ š•_ÇýV5¬`9nÒžï,ÀÜ–ƒš8j«_ao-E*‚ ÿqÑÉ!>ìôZh¤T9¤zÿaÃR4UO+·ê€¬ì‘þ,È&ãÊÈ馳Áû|­òéh­àš™ÕÀjޛŒI–/ÈQìá¬h+á1uÀ†§xC)™äño+ÕíͰüvm…V'¸Ó)¿£D;yNÄ“Éb؃g¯ó óЙ֋-,‡ Âoå~ëøñ‚U›EðúœêþNå[>,âpÛzºO©dÝ6›û'8\æEõYÍöyzgéeÇN²Þ6±ñT ÖÒ"5›Ì€.JÒAEî(aª õ&k‘|£ÎmðzШ.j2{IžtùƒÚèäòÕÈá½Aà Víµ©÷û– á!V':} ˜Ëé–ïmw~xÇ£E8š2Mp?^±°{($Í—ÛLÁ5X7¡ãÔCƒiN ÎýßiÆ%™ÚŽÎù‚yô:¢N/šÇuÐØ»\ÎW.ýÉ0Ê@VÀ;w°Œ2ЗŸ³7•òI? —¬>Üw®l©Áq#öJ<”š™(.tæ)íÿRµ¾¦{vß%ÄÜo¥åv ¥}¹øÜÐqÜ¥™Rãh¯þt&ª%ÐÔÅbhÉQ){_dÓxI.…RŒÒùèZ|¨¡í+ÌŠûQãlÒÏîÆâ¯2j^¯ß¹•-)?^7¿‡ 6Z\x»Ì@:ì¼³-¢*+’õDp4›¼}¯H-S˜Œbº:»¾Øv}£Ÿ˜'/×Íë8•–`QÜ‚õòyÖÛ'e±ÿÆz kéØ1æå%EC­Ù$¿þ Ë»¸¯Ä°=rCý µ ܺ´ ‹Y4]"Ú§ ŒªÍQp0ÎBÆ"…C>ÞĘ<Æ–ð%Ãhºšm¿ÏuæŒGð¨èòÄzœI6²õ+¿¨àxd±9¾íû«Ü³pnKöñh Í ¶þT´9YŽÀ©+:±µÿH _6î: q¡±”{úD$E‡«Îvå]a ²ÿfÈ÷§ífçåºçÌ]ª—5ùÿzA¹ÀC&¾ÞE-*ggáëÒYÿ<·Ùÿj%zøÙØ¡»ˆ„ÞgÌóò±ý§þV¬æ¯wi«èoZñO“RЂ7¼Ù}2Íkͪ©,ÈÓ­#{ˆÙŽmƒ9v/–r$Î Æö]ñ¢$þ4mÄFšÿ¿–bØóh‹N¹ÍÂìÍz%í¡\’˜¿¯.,;rð„iÓ^ +‘ú 4ÔiUÒ•tXòÕ|½Â z¦€IĶH‡¤«Å/:›œC,/À\¿ÕˆnÂÂ47hù2j¬d£ª¥´ â¿¿©`ìzðºuËd_°I¨ä%Ü£sÙ‰íâ9ÄÓÉG/óÿTP¼„[ðö c¦§i,ªpÂ6^8 îüó?dò}3^ñþGVl¶ìYtŸ² ù3`½g°‘½]PÞ‡$Z–¸+™‘{·¯¬yÿ Z¡5H üÛû›8‡¹Ö À $]cÙ*ˆ¶Jí@Ž,»}Öð-ÄO°;‰ÖRçuDk® NÉç‹ -ö<¨…öCš`¦°DsÕ0Ìýsþeºí|‚AÕb`ŸwØÈÖÙÇRg&M/¥ôq AÔß…@Èÿêkùhš6Qž3œ%Äv9ϰÔoxÿ_2Yì9îb fÝ’ZW›E_d†œŒ‘Å´«xò˧s;ø—¤a‚±åj,"¬=)ð\ͺØI#õg 'DÏoÜ2Ûzik~õˆP€^×èáóO­pþÉÉ‹uŠðS —!ÈvO}ë¶Ö;§fˆ^!d(ѤsŒT¯œþáËŸs¾‰SŽ¢va^2p‡‘˜@p¡,ßÉë1Xg°"†#r”<)©È›¾áßQ]" A–~Ô+ÅñÇ®!Àt}ËÍVg–rBåSmÔu+#›ôp“ NËtG¡Aa+”Ò£gD˜ØY—;ÌfïëÅ院âhƒ›üÏÝ×÷”Ýå1Öç°Ås;$š!¦O„KIš(–Û Jqì|KÎi½¬È`MyÈÃyc­jnׯmóè [ƒ‚Ž(MuYÓÁy‹܈Ѱfšr\Ù& v ÀÁð¡n\0, ÅoÔ¬oµüSà 3„âìW•Å >û««¾V»ûçŒÉsÇo‰æ;£*R†Ïßb8Ñ2§ñ`mm;ß÷ôP-‡¹œûwçm¹»ïjá›¶GØ÷;+ËÆõ˜¶ð’ܼ€C³áÓºlHâÅòÿ/DA¦ .Ò†è!2´_tâN±E*{Hð2ŸyUeòØKY—9 $AtD;ÝdÞ΂²Ë‚ô¢îDÿ¥›œ"Âý8 Àܤÿ û+Oš‹ÍÕ3€'l¥½*T½å&(Ãdî³ç­8é# gÐ Iý¯lOeý~Šù謅ØÖ i´õ3*þ¨ÉÃ~W5-Ët[oÁGè„x°X©;OÏ—àša*÷ãÀ®l_…¿"]ÁOÿa…½y}Zë[+°ŸTd÷^«?J»Ön¶VÚ9 d¾ízÎ’N@J”Pàhwš¡O:‹<»-YØ[;°¤¯û¾Æà-ëèG?Ž¡­9_•šÈÉ ÔnÅtµOˆÏäÏ4³ÜÚb>ëeó¢ äË/Úf5T“oÖ}ò±Û­}m…é­¤±*?[ˆ\žzPÁTPC*ÛÑ(.#ÿvÚs·ããÊùÆ;÷™ÅÙXØ8`Ú6'üM!Æ«û×éÂõœáŠ·îEŒ¯Þ™¹JŠ6³çòÍ&­µèA–ïr[rìüªÿ÷jóV>`3ô'+-xŠj$౨¥£Þ—'K|õ~+0°vcÁ‚2))ûv؉4G$I± *áa&sáôÛŽܰÚ7”jÔÍ“‘ƒf'´Jý”˜H®—dv6VëZ*IYÁi95NÄ‘‚ßl8a mB9ì¦;qAÖ0½ €aÓäÃÃ!ÇêΜ¦ÏxL´é-ÌéÃVGùáCéAi:–Yð=TA»?‰sº£üÞ$0Æc¢˜Û‡‘²ì‹ö“¥¡s&޼¶¯Oƒñï”â>¤€‡ÁÍNܽ: ›¡S dÌ\ºŒÙIÂ(íÊÙ{ºüd)JwW'Kf%yK_•ÛÕ:Òb2Zç®»’¢ï]Uàÿàæ—”®aMdè-$^80ZcN€ën¥a]@”›IÉ}Ô8hwJ_Ø*ö úÈ IJ)ÚLnÇäìÓÄA7÷‚Y©b¦‹vA)•KQ¡.Ø2j}$ÍŽ4é€[H±Ç{îæ cY‹A3ʯá9¾üÀýI°îp¢È`.¢v6 o®-ÊÃa!e ºá'ªuž¦½zb9 M·›E{ãT/°¢çm<Ñž¡©Å¹Cíÿ€ Ç«¾T³×j0½$DJ0Uš€ØÈ•ù¶ó÷¼Q±å:}¡ yo&2á%·³ðœ²¶„loi€¼lqbk‹„I¤Ôá'J¦±?Ô#«êÓß׃úµ_n@}W&éUÃ09Œ8†‚ ®§eÂ…ÝÇŠõÔÀsîx"Í-Ú™ÏHmèw8«RNP˜¶ÄAhDU³ëÑlq5ÓÆŒM­€ËÔâfì¯bDXÙó‰ckÙ4Ì©’Ñ… äé^:€¹ “Öÿc›öIxÎ{OeçT¢'ô7žx;'™õÈÁÿºµ&äK×À;¹O‰*Yv lT-°½žÔ­å\áÄnwèR¬ÐÎZOûjY¡YÇØð+®•ásèãØ;|º°³Â;MGjÑQ¬' ºP3§ãÜœöa œÇÊYÚ‘%éc4ö ¿WàºË[aì¥é%ÊJ4JÍxå«>Òê•€ÿü¬9…!΋³U_Eç^n+˜;y²êUÉY¹q®]”º¶|€ŠÒE£Qð;8]ªv?v&¨Žõœ¢÷匑–x|™ÊÀ܃?‡o!Óep±ÕÛ±r½¸!ñŠå`~CÓ(©z9)ýAÑx%oÚðª]ÐLßœ+ÕTkwàY/ã+_ñPjÿ¯[¯®û·'K^zVÐ…E£eÓñÕÈx9dÿOg9U3”TÄýg3¶ ‰kv¥³f[y¬Ì,­ÑÞ3p¯î¤½8Ÿ¹ÿ‚m²} &%mÔðÉíð[eßUêôK–· bÒ2ùn%ÎY—TT™êf¦ìŒ›(Ñ|”æÑ#.LÈ&æmæ›e©ÈRº»Á‹¡ó¡ÞEEª’Ÿ°WÀ|ÍÔH6ЧD¬œ"ÚÆ2þàm©ã;êZ»ìx«¡Ø‹®Ñ¬åÿ£Ï’êY%|‹Ѷ„4ÍÉÛ-N>²šæb>>2E`ò;h¨: •5ÚÖ¾•&Äž€Âöru²† õ02¢t•Çö~b³]ì¼'}ߟ–:‹¨\E/»¶ì}`:Í)ü²î[·wÌ?+“ø³–gåàK.Eÿx‘Aªÿelí!@°;IajNrÃÌýÓ ’ØBßË1F[x䘨¥F‰Ñ·j“FTìlêu+ùù|ù¾ä2™ÔÁK»T½ðñ ù!5¶^k?tÁÝ‘«ƒÌ%Ó'šâŸÜIPùpÙ7ƒK³‚¼>›ñ¬]~]‚  hXëxþ¨z² úËs$4!ÓYUká«·z‘Ü/å¾IÌS Ü žñýµZ#¨’ÃÄýÊç#æÐÃhû_Ư™ Ò¹ÚÍþo™Z}ÝßÎQ‡³©c¢oº©”Ó¹CÒK å•uŒ=,ük¥(Ú¯„þvñ\EkV@ÈØlgÍìJþš!®K¶i/‚íQ‡Î€]XºX’»Y£±ë¢}üÎÍ6üòÍ„9i¥7öE™w.½Pue °G˛ؑÁ±¦9 4¨S•]ŸCÀgbÚ­î­3:»sjôGŸ6ž¡t#ÍêÕŽe²fÜ=ùŽô X°7¢~SP-s<’£ì3]Ô¢Œ¬_Ò‚5"#‰#®žª³t‡ý);V®à§±ÉeòiÙ²Åì{i-~3'ÈÍ–Ý»M” ÷ÛG?¶8TñÁ(ðKµpü Èûؤr¼­§{Uh"Ø­¬u§Ð‚&Bf/·06eÎtw·RÏKz’?Ê?«“Å g1‘T˜6l˜fÓ"ma`ZÍ ||«~·ö†þnµñ¸hFen j#uç¬rf÷øè3e£¦¹i<çÈ—#ì9óÔ\Òðè:þðp^’k…Ñœ(G´_Ã]h ÌB÷ ÔǶ ~ŒSÿ…c#:o»wÒ€ªž=œü‘h8¹ZR䘘¯ÒóþåæDº ÃVÜXÚ[“Ž“ô7öƒ ÚŒ˜”ë=ÈNšBŠ7&;9 -Gäáî©(ðKTÒ°™`ÕM×5¿s+ üí ;”¬ô+t_Ñ ðmÞí`Í Zû¿ºL÷IcûÄ+P‘®[ÌÇ+” §MöW}ñÏYƒ\o­ÉÛëýJ €/ƒò¦å× îZ÷'íuCåD ©nؤTã6ªé‰Û¼´¾!…ÇC[* ÂF=âoý3§jƒQ£B¦t 4ÎÞ(Øó’X¥Öž5e¥W¶y?-kö:·.g§F×ï³S2#È$´ï(]9³9Ãæ”²jÿܘ>âühà™jÎ~ dù*y©|8üXÕýæ=•Iy?¾V‹ù×óø•Hcë4·H b)øz¶Â-XU‡¾¥Ð¢iH»Ò&¯Ì’[5¥còT{¯Y¶ï‘wP ¶è¶v‰OæØjBƒM28pg8\_iO³'h°¦Éˆ/oQ9-&?þǺÄzä*EæMEÞ Œíÿ±ÝŽýepµ9¡ƒ†ÕfÕBÆZwZî-)(kï¾?š ¶vÍþSzhøÙ‡,qaAp¡s²=F ‡‰¤—ýKúÄò ö¶q¶lEëá:‚|¹_ÑÖhtÁ‰¢v?8'è'p?dK×zæ÷l}§Œæâíió/o$0·µuäâÝsÕ> † ?nú{!åZÂ>âSµ?r|ÿÜ/g®3IeŠoï™1¥Œò73Ø“Š£@—÷÷a•Õzƒ }µKH±&M-Ò{ׯ•;ÇÐ1¦ØGLƒi ¸µ‘,=^ܳ!øbqLžÕ ¯,†yn<Ÿîmµ%#ÚÉÛZùè‡Üw [ð}?m5s9¥= 9sÉaJæ— Mè.`Ü>x^Ì|¢n m‡aêȶ@Üú Rz뙿ÏÛÌ›4íóË|‘÷©\«0‰do…¹q=sX˜Ðþ×öb–}{².+u–B…@BÓ¿}Àf~JïT„õÞÕÃÑ-¼%îEu:Û³‹ç5]¹ ¢ó–ä~qš3zû7>RBäuyTóœgû¡¼¯û7bA21çcï…vT»°žÁf‹£ŒË6çvóÌnõ¨ ¢K:ÑitõZQ¶ç_þýFè&­b&×_>îÝ­®P„´ Ô.Ÿ­@0O§±åHœœ¡DB¶‹ì™<¬öšùÈŒ…Á©ÚÍâ£C™¦Œ=‡4z‰™JÛ³÷iòŠÑxê› Ö’ý¨Û~]€ïÅ¿’%ØÓMºÀP-?×b¨]×Nfú8£´µ)–k=1¶åxÑÑÉÎ47kô#Öû“V=3èÈÄe‹|l–q¨› úGÒ/¬¦/pm„`ý€–0׫üÇd$„–¥ÀÎR…“~Ü=’¶9õØvam´»“¬ÀH;þx(ã…¹5ÏŒÁ…¢­/äØªl¨¶ØÊF¾¸,rLW4#™ö¿Å¢0I çãø°æGRäÄO\Nõî¯5îKÀcÞ+¡±q§÷^6á ëw?— ƒ;ãÞx /Ξ97ç·?S›yrÐO‹ žqùöî»Hb¾<òÞ,ò$¯ÜÅ£Œ}÷7®±ÉþÚ’÷m!x™šÔdÊØüR$画kU*Ã1\€Õh¨¬¿5BmG;trÊ©ÚÎf‚¶µ#ÝZÉ^Šœ$ ÍŸM›Ô|ÒÿˆºçãZ dQ 6?sxù€ý¸oç©îœ@÷iD 6'RƒîsIôl¿ðW¬ ‹=PN\¥#nÒ|ïº_Ó¹žŽÝèér–d˜Úì;qŸ€ ¦ÓìÊìØ\hrêïê ¿gòDso¥>´•Dó]:¼^{仨'%Ë‹©û2}yqM yfmo4B‚± jÁDK5xþŽ|/)shΧ]iP¬9Ù8êbaù¼FPmf”1‡yØy-Ö0Æ4ƒEd¢¾é¢þÚÇÁMÿF7~‰™e)hóÂðõ?‘Ý9Ï”&î5ËA0mùS&)}’ê‚Icæºé%]ÄgÖ¸Ø2ñÝÒõH¿ÝŒWîTy%ko—°ÊÃ*Ý\\˯Í4$Û# "ŽW¡¦Õz¸ÕýÄ’éÓ‹ÜéI(ùË]‚ú;Æoi–ðº«$ŽžS8W'WÏY:ì")V´3á]"ǵm9°Íî°ÀP¶à?TýʼKllìÄW$S—Š(Šò^³ÆÈ!Ô¹µ+„;,gØ€ÑL]ÖG*mËàø¿çüÜ”ÿC0Rûyqvtù^¢H怋ýÄ,´²á]‡¶Ý?×éUKŠ´à§‹}Ó³ýñ¶j=?+“(vß&2ß z˜¯C,‰øiÑYp÷”¾•YÈ¿þ®¤qËBl»ÚÙ¦GŽ,½—]ŠV/3LÔ¬4>nàì¨Ñ¡? ýnáÎüc¢ˆ÷wàÐï_\3â?ûÉ]'=h÷—©ÇôÚÄ BŸËåž>åaœ\ÃX*xüV‰î%;„}YNÑ—:Þ.ÞU»¹6™ (6oXNrŽ1+ËâS…ꛘ~Ðv ìà\îOc'GœÕÊÕöºç¢Ö‰:q¯wB^¤/²ÐÇu<6F$ËO3¹V"Dxþ m‰.v²%ˆ·=ä¤,dJ[nŒ…› 0©]š¿¬ËÑ`?EP¶U^i/²¡òEt6°þ³¼æçp¡#$ºS,‘®NþɆп;DzÀƒ ü þ§?£è­\ªÙ’ãUŠweì„sQVņtÒãad3–öíž± iàá.U•thã¶X¨Ó!!—S´ãVhºg’{˜#Q'mU`ýÇD¶#¢1]Ì¢×g­ñt‹—M‰¯ti3/Ó÷5a5~’!bh~9ð^I[¥³0‚EˆÓý]Mz0An6õò…1Z/Æ)–¾ÊWZ=l.€HÃ× P7 …b †ûÅŒ¸ZF1ºÂ&¥Fèö@Ù·ýQñø¢>XnW3VHº$ÔÔë9öɈ“U‰]¾4,/"7¦)`x‚=²Y š+Ñk6@¸)Ї1“w×cÜ‹ãÝ­Þˆ:„­åê_kîÊÒVu¼#L÷gÝç‹êùzªg›wÇé-ºrÞ}1Çz8˜\@ý\Øe4Tò·NLÉLËež¸ÌåÇÔdÃA×ÃC%¨Nl•Õ¨ê jÕ‹øòþaWÆì*›â=-^z6ûÔ­—2Õ:¬ã sÙ@¡žZ,‹—\ ÞKPé@PÛδl·ª-·‘)zk‹1GJ[ÙM僬_»t¼ëÔA¼_Sñ¼Þ#ân>é S( Š›ÒG …´//òlÞü%¤Ã=—”›€NçiŽ¿¸ [Ï[Úšîö»ºC˜ôWŽX½~¼ù‚r¢å:=Y¸J «õ¼ÚI{Cqg{/ÇLÜßõù*UͤçsSµÀнæUž!˜ßÚ­”^'{XÃçç¨dókîùÑ÷Ysmù»×¹BäžW£ âî-æµ” än6‰·iíHï蘭e³vâÐô¯¥›&±cÞ³²¼ë´°ØÊ«w]ØÑj® ;„á+ž’40ó»ùn]gÐ4AÜ9ÃÞƒûp(~õoŸÿ\òTGöêáÿ7š±·ÉþªP]uÕá6jÙåÖôZ†ªj^îDÝç‰R+¼HÛpƯ. ¼š÷át©¶ÑËk`¨M2œ‡ØŒÎQ&ÃIOŸ×¹JÉŠ¡¾!€F¨á÷ă`s­•¬«§ê,f‚¥¯•÷Ø~ +J ±¢ ªë†B³#Eäisy¡¦JÈ+¼ŽYc‡|ä°wø“—ÜÙ™›UšW¤—ôŸ*Ë€Ù0tièÝã]hªÆÔ ±â®ÍâOóÂd.¼tˆJÙ“b>%<#+DÂK©°Úg>ZŒ·Wu0…¾¦YSþYÊ–äúÅ Îçˆlå£Í<ÜdZ.5´eÁ)´[V(ëKåØÊ¥Yv=^K¡ñP‡%$‡NÃzü³"4ÆilÓœ,™•oÔ–‡é5mü d™çÆ)äTv§gŶg£ìH6q ‡ÜmÎ7²Nè Vø…©Ü³Ä*l¶Ãw Ÿ¿^TbãÔ÷­þ"ùÚŽ“¸;älŒ:-}ïÒ½ÖwÆXkþžqÃãÃ%¾²ŒÿDF-Ý”¹“W$: ¬Ì£—艭ù!|¥oœÅ±Ñsyêg¥4ÑwÿCºK 7SòlÃâ¸4íWñVrG/µö«Û‚ þµZ]¿Ð<ûÂûX‰•‹Ær›a7¥©îv.)ôꜙK ëþ¤Ónå’KŒO„‡w¿?èp¶ †˜NÈ?Á^ù€Ayv+µ#$Ä^cFÆÈ0xäðÏpNªqÖ­èûgçUT|å]ÖGÄ|‹‰Ê§]b 1–içÞÅxÑäÃÔZóP„JE²ÿdIû(TîÑŒÝ×2ÇU¯ê°ƒxø9$Óx¡G~™°ÍõH>-ÍbH;[å6íçkšª“3玘§Ù,faIÿ?ÿŠrŠCÀê«ÅÿWg›¦T;T‘êkÿGx„ä‡5.z¬û/ü '^©e1žÀctéØwðòÞÐ{ËŠ‹•V] â³v’Æ Ë²Žj¸‡é¶Ñ‡YÚ/´ÌN—¦-°\;ìÎmƒÎ1“€£À‡8•> ¨ÉcÞÚ*ª3w´X¤®¢?(€ðe5C-‚ óó"†‡‰Ñ]­•ÝõæåëG»:¸–¸ü9â˜ì=â/1]½Í(‚üØ€sˆHaÔA‹•Ñ蹚ü"”ÆØ­Dôoš£aÑàÓÐÞÁâwõºÌ±µÜ•¥#h8¡t¹eOìF?nj­±uFa‘º&»x/òlGO$–­ÎýFU,†¢Îå¸[,öù…$ý:žŸ¥<þkªªYÍ›~ZÈ*è¬ èª ÍÿME¾…â+ïÕ ¢#¶ð„R7aå1/ §N$ûÃÝž2‚ë¹M©Z8§Üíìë¤)óKüCåy.ÔR‡ÏjÆR+ª&E¾ì¼9—cÆøâ¯ûw¢{5+ó^«é¿H ~€)¹M¹šÂʬÚ2d®¥yª·ßènÇïœ4À¨òŸ|èvÙ¹aJÑYP Låï$%Y–Īã˜ïHVhã«—TŒlÒX²´•~‡çᛩ¢çbêaš`ÕÈâF°‹’Iz^€ÖνŒà ¨eI\ׂ7]íOÞ£œÒööç½ä,ŸA¬°2©H1´ùâŒÆjÒ tEÓï0$ÁHca½F°ãûq(*¬¯$QQ/ óÏâ÷{ÙˆnÇE•Ÿdh—¸Y’Rùª ±‹I Ú¡šn@Ñt$hg™t’¢=þ«ˆ{ GâÂóà¡glÌÙYªi¤ßÇ.÷P-C q7íÎ%¹¶„ .+<¼ôëYY/« >­ð(Àì(êË3K(ò5‘^â¶vR£~s¯¸Ò!-ÜHÞa^»nXeôÓ!0e§û"&4qÍŒó%¸ØïµfOÜuSŒüa-´U¦ùl–½~¦^†Üª¢aÉ56–¿­V›ó¤2K¤9%7WšjÓ›)×ÆŠŸÆGÍXª< /Ì’ýꤒöüóàÏbV)«Ñìì€öx’ëpŒòGˆBÙ¢E– ¶ý`ª¡|¿WÛÝú6+&ä€AH6Zº€‹º2]櫌¯‰<‚ÇŽòÞzFe^< @ŒR~ƒµæ9«ƒ²­dYg¸ ¥þ!7ƒV4]z‰½8.ŸŒ~—èpB*ô\P}ƒÎä~ã*EÐ^„WB+r2òv{%Õ·!ú¶8 ‚Xd{ã¥×DŸ³¸ Ôî9Í´KÃÿ 8Bx‡ãRN¬4–ý{fm:Þ ¼޽ 3#I*“Å;Sà³÷sVPÿx  Z£æQLœZÆÁÁš©*ïœÅy]»a’°Ò—6‡vù¨#M½5(êÝ&^ÖK‰.HtWaÀÕü¼dŸÈ¦DOÄÈK[íQHd@t*MiJC‘˜h×'ŧè\<)ž:ì×È'ºäûl,4(Õ<"[ÙwÔ …¬¤~´®¯#7 ïïf·Ço© dE#çÄAw¹FEËP©1Øý-Ið¤Ú‡ü–´M¾ee)¹½‡#܈˜«ÿ3ǹéƒH8ŠÞ"ÉÏ÷04óšóãw<‘ Ãúƒì_Øh!cnÝSyvA·#¢L~7cZ‚‹Z³«tLgÙi–²•¥‘"œ+¶ 8ë'HMG½a´ÏGfä¡Ê§ÀK»¼¹µ-.’0z ôÊ»{nåý͹¡r¹qÚ®E¼I&«[;ÒÛ(±±96hòJžµd‰ùfš>›¥##n–›!#°¸eßFF'É=œOyc§L½ó·º@ÏøÂJö–PMÎ'¯IÛÂ+úJâ Y¡Ò­Å|ò6êЙåGÄò/‹÷ˆT” ;ÍÉ:\eÝè'çUσ]ðkPI½{›¢ç/¢,cˆªJÊ4ã/5‡~üp€ÑÕYæJLTú‹7­Î¶¾¸*lgÄ•už}qŸñ ÁÎNÖ7›¨«–u²a¦]§×Ú±x‡l"ÓÆ´.­Ú¹h!eR|BÄcâ®»–X–e i Î:~D´ŽÂŠ;¶ÐÊ f¿µë9AšÚRàfæQÈí¢Vu¥HjôÑÓCW¸êòÜwÈ·€Óªz Fû"‰Ü5DèeŽ++,¡ëMKºhïçýiMŠjp ¤ÅñWPM!Ê Ï.ŸÄ.‚·×|ä?*%uè‚4#Ø3æÓog­§w cŠâ ™ÖÉE7Z`ž.ÉÜB$¤ž,Ž sýª ÷‚fÈUÈ÷õˆ0óXÔBÇôÝŒ%*t\cÌSúp”XµÒ½öžÎÁƽR¸ nò$îuÉ:qKb6Ç—ôM>þý&0ð¨¶|•ÚV ÜÕ‰ŽNÎ÷ÀxY®ÚË}äZÃŒø•Vw ŽˆFµ¡ycvöé{~©šFT3OÉ[Äa¾X%6€ôêršTiŒÑ¬Ê)°ùuµnýŠÚœÉL+­D’øtP—ftùÏ_ Zw~q0ÍË ºA2¢ÅJ–vbO4ßÛ¾_Q=Nû³·y½[t]œV ¯bŠpAÑZ™oe9ChHò) –hú6mæ"x¶Hë"(£È?ƒsç’š’ÓV›¶[Xažt»sëºþÏ7l6A1Ù-ÃÓÁ@”r’ç;ÜG6íqÍoèº7Ó/ñˆ–“¿UÕÐ_#„Í\ >ý`é…¦WFM…4U|œ%`ï2Í0’è G´ÏüÖaƒm) ŒŠT`ñŠÜ¶ #°¬>é\yC¼®Yç³.÷ÕLˆMüâ!ÑÏÑÿ5²/h%–ùl¨;Çzê°ÊãíiŽP=ŸSOÔ¯ë-qÒ£ÊJÍò»Nkc„ˆåü ° M ÎÑȆï\ÅC™&·?Tc`;VGÿô,Ýá‘,CòÞR'ú˜Ò@ór삪@¥<®éæ'zšN ­ó!ÞyOYôKÀû† ‘‡ÉòúTµ¹ +u ¸Fê#%ÐBO-²°jÊ-ÊøaáÄKãM\^ÏëïÏÀxñSKà´ËšqL[£(\#‚'´3>p,\º¾ãÁþ°h0žBl²È:ÏW_²|b¼R(…<¿Ac'†Ù©ŒPƒ¡tä7m ™çMîiñ±ÊoÎ ®ô"iÈ[””±,M®¢¿)ÐN6 xÙ ùg+éÛèÿÏ4u§ŽYH=fÙaqw‚d5“FN-/ÜkŸS¡µ‚¿kù›2ÚŒ30W@¦)õúNî$pHGõª`´õèå+ÌRöMá;0,è·¨À~ðÕN©’)Ñ£ªêÆÿ(º{ìO–G5IPKv¦LH/t8èB.Vimã‰N*J>ðŒÔŸFëuZIé$osvÚ"fÌ922cÂÝvðA°3¼(å‡ûIßjZ—ŠKtnyrÐÄgt236ß—Zþ÷6~)åÀ¡ãÐB@É1a¦Ëj‰íjäM­„ãOwåû=™®ÐûV´7úÇ‹P®ÖÎ6 µË£7ßÍéUqy8 ì Š(ûåKh˜›%ÙÓ¬qôèàqÈ÷@­ŽŒøCpâ=οE!ŸÕ¹Â~úµtÍÛ†ÒpwjïWf^æEò…’´–¸v)±¤;òe†_‹ñ¼ß»Æãé3i ‘€rüš0 ™Ö¦—Ò>TL1„ìÿÊ8v¥TãÌ-”÷KÊRŠ1땈)ò¡‘ÚòZCÝ“Mš•!#X¬¬ì5´z°¡}ÃëEZÈ>¨È°0\wâ£àqvˆ¾Ñƒ¬—n“ÅR$‚j~îX@G‡Rpw¨*轡º€©+t†ÖNþ^؈?ˆÌ´ó5/®‚9WûAù°˜ÄÀ퓉ºöé…G†Ç™u¨3"P´\¬¯6pýµò_21ÆA*ßl0¤0Ÿ&]Ö·Nl{“X|’ÉJ#éù³t—À<Ö/?‚üÆ $ÂÐöÎÓ)šÔÝ9o¦»Øš}rÄ*Æu—ŠûŒ¥rkhs²¿QŠ`ôÈ À¶O·dœÞ„̉?’P.t…±¯ã—×™ȃ—B uóu_¥Fæ`óm"~³Z7ܬ•]¶"E£eTô/ÄǨííQèJ&n"ªy§I5‡®)EŠÎBRe"#y$D·£i'ëh-g黇­üR/¥5p(:Ba¸•øa ºw¨bV®OH”ŒÊµÍ^îú[~‡¢þçUKˆí^½× ­ÂÈ÷ ¿@ ¤½“œãÀµªlãuT¤£º y70á?j”ô؉NæŽõÇk¶4Ìï”KDý@ÁñE©Bt› ”’[VajÉmÖXƒÐ €Ün¶’³ÆBÅ£w½Û@ý„Nj~zU/—‹RŸ•÷ùS·M›¦~Ó©Èý¾áh/*+~C¶,¼\GÁù²mã&GÿŸ•ThW¬+rãä/…‰v\Ái$äÏmÍ•…S%L˜ˆëjNá~Unüìe1GDØáº”GÈ4Ê£UhÝRû>NO¯|í>LŽ3ᅦ*úxtî°,ÉtŽ’…D€|!µÆü¾ýQzÒ¨º3ÖŽH÷(JN,¶u›#KQkÎÊÜ–l/&dý0¢2ûû  ú™¬y¿×Xé®ë™õ!‹ 0O¦hI äÐûù"İã$Ág³˜áð{LèdIýÁ÷nòè0$€ ˜,v§ ?dµ“ JÞÅààªâÊ5îkc£ÀÜBÚeëÛ›ý.É t™æž[æ¡Ç°Õ ùL [6¯J‚.‡¦%øßëD–BOÄA“ïriyƦËÔ"Ûõ§¥¸× ¤þˆïó=^8so¹"E€%˜ñ‹FØKj/;5…›ÅûVû×q¹TÜz½ò|Š%‡v^Õ"w`oÊSÀk)v¯ì¦8×HöïÝý ÕEé¿b¢Pr¸,ܲÄ„ò‹á7éâaKå4ï=Œî1Øk·†Îó ˜Jq¢èx~ºëmÑ®«yãè=Í8·?vìN¾v‘µÍµìO„wÚRfÙ–-²9ç;…_¡\ò¡so†²¯Ë5Ç­ J6M¥46?ÉI …ÅÇÛµÌÇJ{rèçFk¸mãuÇ ïÙúO”&ztá„æ–ÛK©»é˜;ðt¬¸FÓ7 õ¤ÒWy{”i¡%ØÅ¹¤ÍÅAL&ÈÅ c/`|JS¬/± m®_Š$hV:ÂòšåccºÙöÁF~á³8ÅW{GæÉgîi%‰kWO¬S¸\+e!H=$I†o*™–¹^ ]Ý÷{FÏ4îãdG­n;3 9A«õÓ¶¶Á\(«ìÃþý–¤]Ì”%D1•Å*ôX$¥ÞÁ42Ì©°âßqÁaŸ7Ì2÷T›µ’>i0z›0J¯aÔVΙõEîP(¸ò‰[:†QãŠ8¿ŒxSà¢+0’ü1>’ß"T`Øã—g@×áYp"ýTeXï«Ûq{„Y3Fº¥ì¬Žh^–ZÃÉ™¿ƒ7âPH¶ëóE“ýý)`G·Ø¼7CoõüÕ£Ò÷gꈣ—$ÃVªý˜R®ŠßVq¡¾šÜ„‚7'¯½é»ö(!”AC;Á5+ü.ß*¦/êèáýÍ(­H,|%Áõ_ŒÉ—þp­2õ=ͪš–9ÛµXß-0Ñ|Ÿã–(!‘+W”m[`Ãpƒ{j€kã0Ùç¡#7áÃqÆrStŽØM¾.#Ÿ@òqLf/û(mØ}jP""%hÌAŠãx›‡®ðkÃÓÞxƒðëG„Å­’],K.Š>Cƒ3 ‰Ð-W´™0½CìÏc2µE²hÎÚ‹ ¦3†K‰Ç—Á„U%ùÓ>—I6+—]°ô³‘¹±M”‚[ùx¥.Û ÚÄZÂYœ%é|<#Æñ"ê=Sø¤Îåö^ª‡fÀUâ"$CÌ÷@ã3?+g~W…`3Ô]3Éue¥Fpᱪ2ʃգ¡úù!öçZ=ç#Çl“_L.úˆæ$¾íVŽõ=ñ´ïiIm³{–îCÌFs¤šñ“eçªÇ": €¶’¦f˜ vwäïj2;P¾ Yô>ok¦šWê¢uMèWKxñ½E àzBdm •NF•§¿MâBl¸”/V¼­Ûó80òó¤¨èy ˜¢åxas-‰Áéž)¿~ƒǰDŽª“êãD9D–êÉ)™,†éåÔŽèd-æ@"ÈA–×Y“”Ö,Wc åÃÉ*ç:eZÝMGàÀ¤H…ô·à•²| 4ÄΟ’8Û¢6Mjуcqq$¡wÙ-vIÓ¾Õa:ölápHKº É /z-Íñ¦¨øhaÝ?KjVɰË5yåç½›AƒW ”hµãyåj4OŽ0Ãý'`cL¨éc¯›õþOGg•°_ ¦|ʇ-BÜk¼ñÑCôÑÌ’å krÖ”~ E8ûΙ$LÐ^Ác)QjYJ Ÿ Å[}CP®^2þ—p§}kåÖtûìýO•Ï‹Èʉô&xcD3“×µêøã·~Nן?wˆ¥Qo‘ŸßÐ{ØT4{öUb‰õœ8 ƒ¼ýÕ¦`LUÁF+;ZoIP¿õj0”Ð8Ê$¬°%§ÿ¾’h¨`=»a"+Ù©ØØ(J•± ã¬ÄÈÊbÅì­Lî¥ü®àS‘Òh)LS?8Ø7Ã\®ðð(„¾å,¥)G¯GjSJɳi#/Ù»¶”¸4òV%0‡ì›yÑï /é&#ÝÕFuØ)>2óu`å`hÝÌÑÚÚ!EÖ¹©š‘åK(‚““k~©1 æ‰ˆ5à}8 Ð/«Ùýd΋ZA$ Ô¡%’"ŸsJêžFF[›cüuhû0[ÇØo.ÁÁ®w­Ÿœ^03ÅŒ§¶)Ò[Z"ˆsÑ÷°~M»zùèwsÚoxO£ÎRMâîFóúŽjÆFíÊaÜ|iÝ9ìf*Ó:ôf¿]©žQ“ËêÿÊX]u2—sBNd!†äß}OÍ~Ÿæß-µ›[¾zÊWk ¸¢>ót™e(”2¯ Ûdç <º“ÉxúàÉ£?fªo «¢½ ò%ÖO¬hc ¥ãÊp´@,$$ðY<%‡äIóp{psŸe!fP:m‹FY‡)ê-™v(–þBщ-ÛÊàÆë6Á^._ápzà½V5X<}ìö+4Eé(=—Üs÷J¿ Ÿžÿˆÿ‹(¹¥Š nðD¢#®>–JÚ‘ç±hê6Œ^W}D†BR™¼¼ üdHñ™Æí§ï–6o:uŠ·Ê_vê6•½CóBJ Òj%ü ÀaY-´{Ö/¯G–i¶³~Å-Ñ—‹·ìKDöJÓ`à|R¶…¿«[Ôð”8Fèu<|HùôÌç»h›ŒVcÓÎ×ï_´¾ÍÁ É·&<:Ù‰˜q“ø+H ÔÊÇß”óüõ Q¿ôbR¸ÔM 5 Kòñ:¿÷¦Qi©ó„ ¾5¯ÏöÙ÷Á„î3ô·xUz…G)<(ÄÁ8D¦såÑ,k™ÈÎE€RQº(+c_^+í6r.Rg¨Îæs·Þ‡\ÙïlZàÊ äÕ$N(ÞÕÌl¡ÞnR0= —7a£(Àñ«íh¤Ju»Œ«mÀžOò]¥Éå¤/]DåÕ[ÖAfhd»xW³¨¬ ¬O'äÖ~0E)¥’‰RGyr;ðc%:ÍÏ<¨qˆ< Ì,í½Àù¤0–­ñ7ahÄaÆy¸‰*¢ÿd¡ h)¹Gù™ÖšdŠÜTó*mõ+{ûÕÞ¯(—ï õ&HenÃðÖ™Q1Ð×BU_QóOõÒ•-ëðó n¡e³MÙÄ«ùZM=µwèt3C¾+'i¡&—]Ë}o³Ïvž Äwž—æÄÈh©|§ ¼LRJƒÜµ‰ÔÁ¢‹ãr–ë`¾ÑÑî-¾dT[lIW€g`ÚÈ+OA®¢Žƒñœø¦•_Ñ[¼ô‰VÓüëã+Çâòàø =×pt%Q»ŒaV˜·B‘(,Äù2ᲕÍÈ’?K¼€úã–<У5¨‡ß$#Jö¸_¦2fHz¤Y\Û·Ukñ¤U6¹g]öµÂà¨KК\Ǹ‡ñL`ÚxØÎCÉ=èá×Ű€}º(r¤Â+»1 6» ?M.d½öœ$—BÞiJÚåêpµÉ4~=³Ñ1Ô.2ß.‡@« %_y¸hðŒ†„ÀD+ëÕCè7Á¼‡ ¬UÃUÙÞ 2Ÿë[Ó25]lÂþ–ëø5TÑb2iç*Ê.ˆn)Z«Ú]cÑê½ÊŽ_ÂÊB°7¸D6ÑêzâBÞû"yæ ‰nBÔsœ7ñVLQÀÝèzéúX&³æ_2ˆ8Çšèt•“ÚPJLlÕ¼cº ‹žèœ°§ê^Ž+.‘·c ß¹UœµA,fFŸnTâO,®JT)+fù`ø´^äc¬5)Ã(±שƒqMëmÿÊM¸FžÉH•Æ™­s€f3S!A€µ‡eƒØz½V‘óbC&¹—?ʵ›!bd Z0^L¿b»±+ªb<Õ‘f×o–QUÝ"‹åläp1ì"$žÏ—7–¾L&]úŽ ‡ÈÝ, TðR[rCÛ*^]ÓãŠCânäô­ÌG÷©|q† ô(Q9.nÕ¡î“*àsˆ Òw²üWR:]‘E®£‰ä;üÐ# ÁC’2|‡s•Q ñØ^O*qj…'ò~´1Ôˉ*niŽoïž}Õ»nìrQu†—§¢ U@ÉŒ Q3?¢Ÿ\\GïØVDl6áJ"?`€Ìü:®òÏ{ÁàŠ|åN,÷ã¨ß\¥úRÔè³'4=OÑKÖä¼(ãïØßÚª8«~†3º Š 1_‚ˆöwSÃJ’²ð9@Âb“o·­Æ}çöbûrSÈc/ÝÈHdEv³ïr[Æ™ü- K$Çã»ó¤ l^_À“TÞvþàÄÿ^ë(È“ 6Q~#Ú‘©þ—3˜ÊBΗ/ù„Ür»¹c9JõWYÚµ#å¨)^”á g?ùÂR¯ÊÒa$¢ËãPS²âÞtMvŽê¾èiêá6ÏÒ÷–ÁµPÌx÷~ÙÙÉì?]õªÍ²þÙ"±•EuÿÅ#“O…°6ì:˜nØM @ÄÛÅdV$3F¹†•¡Hd­¿E†Ae¿Ñ⫱Û_¦3ÜI ¾öoáxþ% Em7v¢Ÿ§fGS(=Íéú·ªÛJ;ÀÛ ",ƽ}2P6ß-â¡‘’“ç*!Ñ"¥^ËzÈÔVXª½_W¼‹gLHø9cä«íJ*6ƒƒ–ßׄÆÍö¢M ²"®ÎA»:í'x‰R²‰¥V‰Ò¢>¡®2”+ä²bo~‰WŠÌ¿ 2M^·BÁé>ÚsœãÔ‹´ :]$´ó"%vÔOª…x‹”žfL³)gž‹¡òU©°•¼¯aNóìHríEò™±ì(UbDØ 1n‹b09Ÿ_ÉOŽØS}¥61̰?Œ~v3ƦA ¶­{ß5ùœq’¡ òù¾j1çnKô .^ôEq쎿ëk…ÐwE&;Ü?ˆðBÑ{&Äm:9Cô/\¤Å2÷þ<ÔŸ¼uŠ3÷NáSÝ‚- ¨úÍP)H?I^ú#D¾Ö@×+r2®2Æe î\«‹"ÌTÐ9³þÜðžk¡Óî®=£Õô,4þ’T¢êž2ªV6ôÚÓŠ·”åó Û<Ìþ0 ­§r÷h:͈è#´í&%áÀ”ô“inUs3zOZÆ>0ÖW×¢+~a”·®Ð:‰ø½É—4] qÖ¼Äwûe0Ý–6#çeÀIÁÊ–Ó£ÚÊþâX®›&›ª`ÃXÏhC€Äú6"±KšDxÛþø^Ï=¡ùjÊìPGt¬R­†dýÑ4)äó‚*@®_|áÑo‹§aHzåi”4¿cøáOÌZ%øe±Çëâ˜ß’™££á%\eÙ±bäâîÁ[ºæ/³ƒÔ'5ü?mæö~æX ¯:jÍmI´±;ÓÎÁ`°‹çfŽ ø0ߜ늒D\eÌÁ’¤¨[ ŒÓͦî=)‹Þ$% 'µØýxñpÖ–Ž÷ªé¼÷]¡R¬ó¹Á8Ú~³yg’>±¬ãÕLΩ[öq.®‚»Cœ\^_ˆZ/³êóEE¤ñÚHN/ôxn2¯Šj¸È©¯caî°RúÔ@3>r*8súôñ+Íͬæ°°V ÃÏPüô(WÃÙQ“œi[P;Œ 9ÚÔ€ž­›Šùe/×¾þáüúwFæUte³P‘.Òí±Ðÿòäç÷q…œC ²È8Û¸¸VtP*Ä>‘g@‹_ü:È"㕨‚Õ~| Xÿ’¬Fšø12õ=ÉXÞö<é@\ÞI"‡qß°J½Š¹|huÄ<è›vÚ¹×üpMVGÕîZ8þ–£´çÅÁ¶~v8“Ó¤Vd*¹¼¢ýº-¯ÑÚra‹sÇ <of”ލ÷"îó{'Àô‰mZúÈÄiVzóug,݇y¬sD|(Ïä˜vÑZ³’ŽvWÙ*sk+¤³èºÞ ã`‚¤ûÕK ½ð/ÿæÀELìGèïaƒ168F+[ 8½\³˜ër],†Ff§*aèõàפ¥ŽAók‰0üpìS©Nœ §NžºÐÑh6È!ïèþ47:®|Ò¹žµ½"…EP3Ê¡ëFý¨2µPBW5—#à†>’÷An|®°¶úô”?ÔÉí-ˆ÷?©‰ÊÒ¶%sü66CÑÄ=Ù™»0æA‚8Cø²‰KKò§êä‰V|0wÝ5à}CÕo.œsy,¢xó­‡ì£_øôø êaè£î¶êX›NÞ§ÐZÓKrCÀÒ¦J„ „±HMÎ_Eeõg¶çî‘çÿ žæ¯e›2NuÑÉÀе­(0P2‘@ßóóò­šÚƒ¿Ú¸ylLÍÑ~Ë;Ñt›#ë±Ußõfßl`ʔҵ…?³Õƒ=ýYË÷(9xÇk=2è6µ·ZÖ/ž¿]üvuO˜ÉSŠA€K³ézÔ‹ÄQ û^çq=kVµÖ©Ñéü6ODÛÖ*dC7­î>ê ”5ñÅFäÌ{×M,¦=öú–Ûþ2yz}ìÜx“ÙSÓðlÑQ”'ó0a–ó;×–NÆø§±^Ü;M;3‡^ø+ vÈÍYuè[X$ä 'y‚æ œ:ñ .òÅèÙMü*¹é‹·G$œäFD%Jǃ˜É®JxþŸeÑ“-«!°GŒlÒ=óŽzµs`´‹òØ9«§WÂÐn7 pÐý-È'Í Øk-pÝM“€QÔŸäÕ$ÌzÚÉO—±†=ïûÖA‹¾‚*—¤ìó «PÅê¤[Öˆ êE/BÒö=J6K‘‡,¨~’·¸Ñ¹R‰(®§Ï’ƒM’ä]“nã™9_£³£"›:Œp|™OŠðõ_ ßàÊe¤µ¶ë¢hјü¤¹¸$åQ­}Za3ÉÓ¦ä;‘8³â3­Ø•”Ok‘(}c!–ïêh¬X®Ci(ˆCÔ‹ŽÁ~(N5¦iQ’¦ #:Q÷u\P$ˆŒã.uÒ6<‘Ígݺ¯'#è: 4¨Hk(Äy¾{ÛJj›ÎËzõsU‹QqLGb‰08ÇgtdŸ/@0ñ ÈÆËÜZ*ª§º»5OH“NÉ>WZ†,XÅ:våÎ÷F¥wï4åt!CÑëìʾO]¹²û yG! øñD?¥Ê30tå‡J<ÍXôÛ$ˆû¤Ælíçm«U(ÚË]‹tpd{c@‹¨‹O1[W}4JsøœHBMWe_Rsm/ŒUßæ¾f¾å²²9ãéêwEK'€%"¥VdʽãuÞ³¯`n,B3W¢ÉxQsóíHû«˜ÿûJE¡dtëQLÕ ˜L0‹üŒõ?ºîªÏÄ›~_,­Áã3MËOº ­JœöEñ÷´EVUÆjdÖÉ?¹ «´-j­~Ôl—Í60ÆQÕ„Q®ß«œ,Àu—¾ÖWüôv·F›¶€'°n „ò?IL=´hN.ÁõÇ4&ÑUþkÒÃpn²úüX’Î¥1\€*fÐe>ƒ¢«CøŠ;Û=´(Û“ƒ = o3@Ö8;±Ïvφçn¡íš\õ9>£¸¿X€}STꨑœÏü 4tBQº…€K/…t9dD€–$­¢ô 1jŒq²Û›#; ”xsÐã¼jQ?Êà·È0¿n¤ÏÀÉj,1•h—™oÅFt"Fí#8ô[›5˜r… ”ÕÞˆØTdHÕ7º]&/'Väá\Ÿ7µ5Ô»˜æ¿ÏøÁçÜi©a!BÒ@Îd.X VVÀê¼k[;3ÊáíªuM.¥CZ´öÖÕ±WÁ#daÍ8yÿÙ ¤,a1ªeóØ”kúŠd>âYÏ$[Á tÌîeŸ&üØJº5~¬.ŠýjÉj £ïôŸËü”fÕôîw1a"@¬|g¼k-ë×@.YšsðA!ægqæè^ãÆkˆÍu-çw#cJ—ÒQ¢þ›)äWø1`3Dœàö<ìóðûq¾¢_óܤ)1έȻ£×úheÔ²0ë<\Éf«FlRWBmdñv•Á ™™Ô˜§‚ ‡î˜^Íýb­¦ŠÖg\êø^œ>K¶7öõRP6…ò·Y2fX9*£‡Â8:ÙØ¦âÒ <»cËÄRŬç³Aº³ äz9'„„€R˜Žß”3ó™}ÿèû4UÜn è'WgÀñˆM=–oÅUÌP\4­›Gõ¡9˜:þº¶TÉøb7¤oôfiv]ÜH^ž0JØ–ÎÓâ¼vÂûnƒ¥Æún¦N5ã«€ ¡­E¤Ó6°œø{Ex™)£_2÷°]:‘„wžTÚ“ûÐ>‚b»‡=Hpe/®µ‡ÑÎï˜ï+qÆ·u(•ˆD|\ ‚Ã… A‡O¿­Àr1°xõçÍKd-Ÿ¾OA|æ}ؼ‚î;þíõ`6RPª#;®’ÄŽÕ£Ådµb¶jˆ,*KM’ê‹JBè­XIW:v Ó+%—!:º£ÃêóÖgÌ4•>Ò2jŽÜ[p SƒC~¸ ‡Î¬b…„¹ºg±—R„0ãD RˆDb[µQ®âa»5Ik ’c ³‰òNILÿ›¿ëm$êÏÕDh8¾rHb£RO™ËÒY¥r¼¯˜)(œßðv®‹Åé&0A¶8ª4Â3bø„ˆ¾C> ^½ôÕ½ /UÛàçitÜ^a˜ùin\"kGÙrüi&¼üDῼB$^v­ÌΗo²5ûTÊ„“Éò»))·ŽÁ4#XbïR¯f(oUŽÿAzøºõ–4@föul,ú&{|sø½†z$ƒ†÷)-3™­€jjèd )³IØÌNHÙ‹À,ù™7BmÞœà’2¿ñ)[>бî«‘@ p3Aêž:=HM«.×ñ ·+ßè¸Â!÷˜ì—çCQ°\¬<ôz’¾üê~LP=†‘tzAMa‚™^¦8î``%‰ rD¹aǺŽJ$ÞKöÊ¡aUÞ `Mw1BhfÒ¤‰!ƒg[¥ÝÔ”™éf7”ª*ùp¸iˆå*×Ñqþí >l -’L¹ÙƒcÓ”üw´õΑÕåEy<Î?<2̳ðùõÙâ k*•Û‡ª;tÅ~󚿇$§½ßÖJŒŽ_ã˺á´ÊÍ”^®åÿúÿ­Í™³ŠÑ ªÜjægЬfæÆ}ë+d{iÜ®2gâMR÷;_’)­¢Ù Ó&0¥ò¥ðWO"¢p- Rü©®¹C";±³ Š`²’¹4…rƒ(S$Ø¢ilUi¼p+Ø‚Å×ZšÐ;Êk˜Ëÿ¾8ë!VýÔ½‰¶‡^­în±wÛMB+Œ:…t¢»­(Ã!së]è_îëªÜ­‹qM³wcÐx’VççÆçÐZoIuz¦ÞûÂoî¡É"roÑJLºžÂP8ž¬yŸªN„~¤âã0D¼?±©û¶¢Kcf‡‹ªo¬쬮¾²R9×öÈģঌ_TŽçÀr¨ j-O[ï7I£=°3r5òPiÎ~ÂL>ª˜Ç·”a~·´f‹ŠÐ9 ,£¥ÃÊãx û,$Í >v “ô@\ˆµ½²Iˆ£ÇUƒ}X.ÚÚs¨Iì­R‹peªa¸JtÓÞH#dÍÂ9¥0ÙNr3›µ—œútSpUm'V Ýö©çhLnû¨)ªM ø½Ï]¿*€›‘lQ# q‡BvÖ¾‰&¤Ô›Eƒ¹…!j?²|*ÔhOV©Ù©75t)c Càƒd#—EJïTµô¬|>•|à¥@Ê@Ü1(&A³÷û2[Š‹IUÏØ=Ï¥±N°š¿ï¯6ì‰^BV6•×9´L®ÉP'>)èÂ-uX~mÊ`‹1(WMx Á—Rˆñ?Œw+Ç:¤ÉöXxý9±œpz'ñ)— hß_Í$!kyQ¬Ó“v`Ü€ñ9¿Ô.¾Ý(ƼÂcŽ¢M}{ )–xBbÞµ)$Æ2~‚{7§q« ÈlÔÖfx H†Ó@1¬`æ£÷0ìY‡ #ÍióQñLŠWÖá‡@i±H$û `³îÔ*=ò!ÉpèKö6ï2’ wLÝ$±×š‘êšg¯Úuêøç‚Cd¸Ü²]Að»§Îý“JAI¥£ƒq4¾Ç½C8¦™;!Q$h´MWëök¾Q»`!ٶ˦Xŧ‹¹µ?„ŽÞu£öÔc%®ìE_q ñèæî×Û^ìÄH_ëv¼fÚ ; uÞ8àTô_b°qy €_‡”o]—H¹s“ø6¡÷à"„¿Ÿp#ÄÕFÎg/>#8N«W Ä£½·§µg÷êÇð<¿70-¿ñ—éÝÖÙjëÀûýÃ6Hu Í·æ÷tv¦¢Yå:B Q\ÜIy TÒØ÷ £ÜF-xN3 ^ìíÉF¥Ys»¤€«/Î\/ùÚ–ba³§g1·â•ßX% My?ybè!“dQ…ÄHSÃÂ'uH³˜AŠî,;W(]¬+ƒR«sý“eŒL{ƒž_ô …êc‚Hz`Ü^Òûýhiõ$Ì«?îUåîQ>µ´¨‘£ Ž Z¯`·8îÓAYEsðP>¢>–|Ù››áŠæD>òÐeÅ]†+ƒäÆKß/7~£÷†”í«á1…äÙL>M ¹ìÞ;ðY&Þ¶[¨nº1·Hžä¨ZÔ"ãr‹¼ ¸ßŽäòZøÒ]Ê£Ž@Êæöì4è±+Ä_îA!Q]§ñg•(ÿ?µ+k1f瘘7àîWð¸ì)¯õ¢Ê“…b幯©ño7Œä52»‘GŸÒ‹ ½–ƒ^¾ø*¨Ü–`§é&†> Ùúæ4ƒ7mxˆpµ'r‰œÄ½ÚuE–ÅžŠœå¼8×SOô4ñüš:C5¼5>¼J#¬4X¨1êÐoÿÀ*âWAizâ-íâ(YÌ–2elM»ëd¹ê*êO…æTyù1¶<‹ ó™;p¯ŸÞŸ»µG‹Chw±3Þhôùüð˜SÂHâƒÍ¨ 1ï_t·H‹bA³¿}ÌŠÒ½sV³èåˆ?Ïô•†GL´„“_é]­VÈlõ\¯M‡?àfiìw““ùêŠ)vÍŒ=ª•_’­˜UÙ/ÝD1$í ¼ù”-n_—p·7Üq@7ß©ÛXÆËZν//±D·ô5Lá<))‘M‚RàÜqlÞM$I£¦«îo„æÌÒÞÕ¸ú‹ÙÜöŽN Õ"6 ý¶¶-ù6÷~Ú‹¥“&Æ-Àj""ð·c÷’jˆÙh#ÁŽÈ£ÞµF0`Ioˆüa?Ðú±ÀBïC 0ž.‰i±‰¼œ+d"µå‰¦XìÕ:¹ô:)ËÕ§•9ä­½PQ¼p1ÃV¾08í1±‚މ÷ÎÏ·0ÚÑ›™ÀßúÆéSA2u ŸÖ $w~ K×ÁúIFcÀt®nÎ݈*â¢9†oÕÞuÿO¥Øe>èáÇš“ì¶5àQcât‡¨ós«Á”êï:‚ööòñI«^ ÖE䭖˳•Áôý0ϰ¥§Ã<ÂÛ­Œß‘ûÐ@_Çþ`LÚ0>Ÿü\Äpõsó ÂÈnn]²ØáhþÊèFgyŽÇðd‘ÞKŠèozk^¼fÍ•X?°È12_A ÑØÏeBH-¯¬„YûʽƋ þaëÀ+ä” ›û²™„» ^$Š «†@=Nõ"øýßè ‡Ð0‚áíÅ™1;ËlòJ$ÂÚrŠÓCßÄQ¡ê†‰:¹êöK¶ø|½6ß"D¦õ¿¤ä´žÑæªq"J,¨½ûÛpð8µÉ^.je3LÛ°…es¦ èaU°Ü¦\­Ë¨VÅQI ' ­o‚N˜sñÓµ¿9l$BwJÓäÓÄáö:ÓhŽN¥…¾E¡ÿ»ô²Þ~%éCþ5ž¡w(ÿõH”Ù"d6eë˜Äh³IÉ“¸K¢8  ~æ¶7Õúw 5kþ(²èbÛá+Ö›´m£GG7>ÊÐ19(6$ ßK‘¿õ`Æú—“•=ôŸb•ä=,£‰ÛŽf ÔB¥l*²öðx]ècÅz½Ø1µG-*£ÞõB=N§UlïyW›§TÈÖ3zq´›L-<5\'ž–騵XfßõâœeQÉ([?cúì¿ÌlØî=|Ì·Ûa«ÞÛœ1sµ·m2¯~s«†S !PobщDzçqP_?Ö&ƒP#>1K:^¡qùúˆŒ N]+5_(ÎòR>îl“%492¸Ìh;þ|/ŠÊ^vfÊP”U.|ÅÝ* Á~!TÚÔ,UÈçÞÄ16©†2‚«P ¼M†!Út6&MåSÇTpŠ äà¨(*kæçèV’urõÁÍñì>Ã~Øx#kêNW“åúEHŸYÔÀ{‚"‹†Fû½v* ‹86)P·aµäóRÈp×UQøìıÌw'ÒÁ‚æIÐtè:æ›´o]ÿš„›'Ü m,=_þè^Ÿˆ&¯qiôŽ?âÍyâà„fZãÀ«?75Uå€búöÝÖšóJ&1½³@FÂn"`z†æl ¡¢•SS?%|Çì͈@^¼&ûl”fô~v¼¥F}²ßY›ïáù±™·K¿”ì.ý†>Ašµ—âíAÏ«dÎx Ɉ¤9ʵíZWÙš”B@ÞSÍÛè_ê=²½ÅÛߣjCWõœèH$c&¢[úI b•“\™J©V2ég"ánŠ=xùóF¦HÔqzŸd`V²é²]í*õQWg¢#Ɔͬ€ƒ›ðj©ú§ŸžnC¨ÌÇhz¿èæJË’y\ô“h«ëļ„[7`åãÌ9.ƒÕH>vŽ’8¹*%Š…Õâò¦‘éóeàAi"©Ïa„®Áû”XûÃ[…zŽce,:mO†6qdë¶ÅÜ:¤©ËÓÂlc1gøÁw¢URjWqóû·oëÏ×{ïò‡Ýབྷ¾ƒ$ f7@Ìp4ÕÌ8¤â€—Ù#•$þÊ_±Îò1YnµTà?íÊ Æ® Â)Ó$­(šüVÌŽÌíG>¢&é@èïGÇéX=7|t¤35©™píxqí×÷LqÓýÑö.q‘¿ÈŒ@ddZâ¤Ùñy·[%_i>ì­í‚þˆgÅ#˳¦w6xŸQ=lÃímkS6£™®]Á.¬i~í¦µ£Lèôê˜Ç’ > Ì­\ƺ桙¢sÍ‘–­p§ê¾,ô–ƒ~zÆ$ÅÜNäÃCËáZH‡Å«FžT6GÄO2 q8 Ü­¿ù˜Ý9Cœü8!ëÇ®aZVæ\/ßdi“:—û_Šˆ¦§¢ˆpyÒ †éÞù±™ê\*æ¸ñ`„ëɨj¿s Vxhs#^Ö}Ò üI¤.£–ŒnXîÁÈÛÆá»l¨©8²H…^|/ÉœjIœÌlZá§w›ºaYþmZ/ÛFVr¡\ö†ŽÛ3mI?*TDzGv®½>"è¹hgÂë%ú¡yéûh…¬ÓQhè ÖíC›ÈÇžÓÓEÈÛݼ‹µ ‚oäÕ¬´\lôõé˜ô‰7%A~Øù/ü<]4ÄÞ®ñ6w*zS;IŸ²Œôbn”ún æ&uND)|â(”O{{4LmWl)Á€óÍŠqK­RÇWkžúQmüIäDj›W ®?s©Œ žø„yrS]1tûW¸›.nn$]Q©zS6©ƒåt#z\„¬—ÙV@‘8cEW'¡?‘ñ¡í¨‚ä~N–4!-W=ß»sâüuòÙœ†R¥=~ü÷¸€u…¯ÕÁ$šÑð)Ä&Íyƒîcÿ“ ÀÈWCô]xĈ„üÁ#u,’(Å(EYÏ<±ÿ)Nï”åü5ðfØRš;Ž"‡)ì*(yb¹ƒ¼hÚ±óÃx»I¶gLóÔÊ…Âïe€üEîÑe«×€ÒY4˜·£cn“ÓwP ð7ºU¤rÞ2tFI'€Æ+‘,|n9¥ëF6¦Âÿ'÷0ˆ€·›Ã/”vai2`˯nõß}B Ùl¥Ýx4‡ŠrOÄo™g݃y³ó3·…¾®œºr¯°0_“B5¨JÃsƒŽ&źٴa+ÞÊ*ÄY|2¹…óÇÅžó]öðO¡ßÀ*L3dõ’Ñ[æ)㉉‡¥IKw¹ês‡ÙÉÒWs¯\ÒÓ¶æ§G‘Ë?S6*:#UT‰_³ÇjŒgʶD‡6º›~O@¸túœ#YN2È_îàjé´¿@‹/ßyH†4ã´¤˜%´¿.àa(£HWÐÌkrÆ=í¨€¤CBà™É‰ ãe„!…Ö0êbLkºîlRéQ>ã÷Cíw:ÖešYp³z‡DæáS{šãš>ÍñU‚Ρo¶Où›@ÚCŸÜÎÞÈ‚¦éŠ |?¤°(ìø œ–GÿÔÖö^e`A?áôÑ`Cñv€5ö›ÏðªC1|sâËÐTœõžöÔ=þEL|õ``—aâÙdØ›zÞpž\3HÌõ¢…ÉkôFë^j9‹ó[Pëß6ªå ¿*©ÜðHOB*Nëù"£Uÿ[jrÎbrB…Âþ;Ì|ùÔãO8J೜„ê„òT£âˆcÐôD> íãjìß‚¾ï᧨ôœÛØà‰ï…|¶–<˜+ŸkÈìóqM¼Í !Ç7ýžD:µüáN÷ØK­àÃ(ÜG^à™f,Ñ•S»‹ÑKä` *n)¦IA½æ»eõ,€¯‘ÀÒ_{û™ mr†°jpm™çÕš0¤Š‰u'ý•·ÙBŸ4÷3Y6S·òKupí@à%ðôðIá¾P&k1År½œïÐŒAYø‡ò¿E&½‚|ÿ-˜á¼»yfO؃Abœ²šòjlEÉ7M'íÂý¿ÂPWĦ”^ºý@¢³¯{Œ\Q£ôÙ&¥ù $æÁ†§yÏŽ·ày5‹@>?Hƒœìú"X*õR¿9cÁhNÇÿœ:$b¤ÚHŸ˜§µ |wÌÆ‘Ê»éÜû•åh~î"@b|2‘3ÜÍ­ºqŠIÅ8§âÊÂÌ6ÿ¿u'>÷[ŠR;`ŸÞþä{¢ïÝOµUð œÁ®ßCýÎ`\º§ò ÁjÝP‹C%l©ÎÁ<(ýØR¹ýÚHRt9´ýUkúøBï»Þ÷n+ò ;/WIœ’ßðlùtÜÒªí|Bÿ£LähB# RWBÉD¦å2M¾l»$4 ë• ÜFè@Ò“‘>±Õ@<`¥UðDÚ†‚C°svNT‹*ª¸þ$è¢eHˆb|â?W:`ÂQ„ÂÉÔi0 _¤Õì¾\ÚQ´¯5È=û`»”Y@~Õ©sk°YŸPb[ÃT|ª¥ÉªS‚Áj$9wVó'”Se Ur`+&•réq~ÉoÏßð„Ϲ7.lÓI¤ïá†ápÑ¢>Wc¿Šº*/Åo¾ÓaÚàê;{—â ¤ü¶lP€—¡â‘öø˜ßgéoLä2‘aÝ hºC|Ëw]+gG›ÜUÞ¦;yoÉ.9ÕýÍMÆrß9ª`À_€'²³ˆVµÜQôd<—V;Ê)䃛” ¸—¯êdg—´»½è5áÉì^°¼{˜½1O”>´±(^MGBó¢ ÿÄRâ*ÿS*?ãì\¦¤|dèÞkP»£H×jݛصr™ÉS-}?E°>Ü ÿ.ny;x­|¶SäÄeÃÃyZç##݃ iMƒ„qhE0‡ííò®ÃBϵ5à“o¸ÈÃs×R~]þDþm¹->€ÞUðzr"84±P¶8‘Ü@¯*t½é 3áîsÚÎÓ…î§DU Ð+{ð5ý7ùjO)^<è”'ŽÕ›“: ûäú×› Üi`­Û6i$?ûñ‰1˜.ÜŽ{þ´5iü/iY-¬é¶éÑÅÂZÁ+÷ÜÎýL‚çdñ8ã Þ:‰V0–ãùS]|Þº§»G%:•Œ^B^·“%ç¼ë4å¡ËlézŒKR? jô½Nè‡çp$rN#ØV¨Ó£1½Ð§l{ÀfÓÀ§| ¿iѧuò4”"}¤§PÝDz¬Ð¾ÞÌX2Óê8(ŽJž/E–wÿÃEj1•Õ§PàÆ©™7¿)ï´/¿×š>ò ›GÎämYÌ —Ô8‹ º¼©½¹ƒ²ôr¥Ó†ú?š”Ðu`ÔG„È$U¨·{‡ô€ /”#€|Ø8B¼d]n6›6m |z"?;çÎ;; ¾ÕÞ€§þÅ¥B}ª{WîBZäRµ¸°êˆüÁÆØ9üüÑ“l»[ß߀»üÏ{m±ÑL ùa© ¦ à÷¶ô ¢?`ÿÐÍ=>Š<Ùqÿ®ßÑÁ\¨–[­‘q…ËÿS ¨Íj‡’Q²Á©(Þ«ŠeÛভD³uI„­"B:¤ŠæSqÔÈ•ÔjyåÅN ”X"â´ƒÝMjRÇìxš¸‘íL ´vUŸ4—Ô¿¦-Nq­ÅŒ'«_¢R7³Í ‘çfX8OqöaÄøï 8|šOUFƒý; M–N†Òí‘S¦+¹´†`ÉyK£Œ’U¿îhü%òZÜx‰Þ‹9‹¤„å¸áfÛüf1X›ìŽt‰VÛQÝí©ˆl^ãH:ñÌ1ÞÝ×[9G×È$ЉÈqk£¿/QaæÀuÇ¢_P„—©Õd’o±âèpp] 4‰ºâ€ó#š¸gé ƒ‹#ìÅ9Gßg"~Žé‡dXŸ%0_fÍb&ó¢½SšDzÿ Ϫ*¨|5rΞˆÑ¦rçO{CEžª<Ûøéäêq¦Ç´I+×Ó­ƒ²xc ”ðº§KfÌ›ºÇÇ—ÄÍÕ-[õ{âÓs«Œ“i•p†Ô¤Æ"ÂêTD(3" e .3þŠ_t'»à˜’Â+|óí‡E¥®ÅS®=¯cFÃhF&ŽoâyOêô“mºe©„›e¹ËÅÛ|)¶÷«·ì¸æüJW².c¡ŸZ)fÖ óѰÒCÙ#Ù?v¨$EËÿÀ“Iõ¤zN…¶ƒ=®¢,ž‚ž±»M¬³Ñ½dÂ8Î6 2ð±pl3+½Q‚ÖÜõH Ýi§@û•t‚Ç4VÆ(ÀÕÍøˆKÓ”Ëí#ëï¹–ÉA‚?ð( ßÒJ°UðòÀþèçÚ´3:€ð;?øÏÛr+º.³ñ­ƒf]¾×ÓksUUY§;`4ô#\ŒJ”ŸV…1:Ì—3-Á²¾xĈ}qŒQ‹½ /Ê}pÑžá˧f¬B w¾_Àâ¡§¶wÉ‹‘Éf)‰hú6Š!F·$9·nôeŸ¶ã–Ùº„`jÝoã«•7ï3jGùÔü†ü·ŽGÍc†c8vˆWЙï_„¯Oï×~UÑ5n€cääøÇhKwW! „ñ|͈ÖêY8 ±WãÛðàë–)³‰l5á·ÍÕ5::SVK¯d+1e»­ËñÁ•“ïÎ%?v”ð‘€ ÛZ g\r±m³í—I¸I:ÐË á»DàäêJ÷–iíBƒ^CÚx@KX“'Ü‘% 0W­-¾.¥Q_SÖlx;ªéÈŠ´³Â€ôõý×é=ü‚‰j„d}±ã1ޝê3`d_rԟ˽´ít²^•×ú*è`*Q•H×=Ý£KËgáñ7âäݱîè+<ÿÏ Íáä2+Ì5Êð" ;ù”åh†‚oçÿ—‘Aši°×„JFmž'7ur£ˆ”uõ[O'£qöY‘Ž#ÿ×l=‚7MPûÚQšÃîã«æ#F û$ÑÇVðu¼ñ<ß!-YÝì³).úä ,ˆŽQÜñ]¡&"zS¹áNFÆ"ûÀòò×õ6ÈV²z³¯(‡-“×l4õæH|>bmöò_£Ê|7ٱ͘]oEt¼¨¬UDÒ{ ¡û^¦ŸcÑ Tá º6Hãe·½jÈ'ðŸp –§FÁ¤fy›×œò;rާG@}®ÄjG×tPE„·È¡D°aŒÖ—½\ûleº9úEŸqÕ\¤¹{¯ƒÀh%³¼ ;Ù.ëëý´íFE¹®ög$¾ó'Š¥bZéñ]!?¸ Б£>aPŒ¨UȽ ¯Ë —Ë×íüÿÙ­2J‹ŸÇl‰,¹~ø©¾äØ%SE  Ò]¤èÆ,BÊʾž†æXú ¨z$møŸ¨BÑä\t:­.À]Ùyí…x±-Òlå „ëàI–¶ƒ`ÛƒON¬³”Z0pÇž>hêòRÍ0Í ©Õöa ¾^ͱ ÀF6ofŠÿ³t‘W¶÷ 71ÕðH~WeÕåa^Ó=;Dz“sSÊ©?x<,Øî ¶8 ç53(ñUÝú°#±TÉX5Nÿ›s=À3wC9 CÓ°’ƒ§§Í™Ÿ9 +ï"J"%íΛtô²„¬ŠýWïTÝ¿.ŸPA9lï‚­ðßXM¬êQ---EþÍeM¨KìÎÛ`ø\û®šžÔ«Ã%bä! |õÏH‚D Ãzîïn­ãgr·‚2…-£ñA˜Xˆ!;â#]ÈG>pÀNV21í¥‰œïu¦æñv•LVˆúz‘Œ,e•ÅvH÷›YwßÓÖoº£MçòŒ²9¿‚a*3ž¼Ì–ËøÀ—F—"x>I©mSgæeÌ\]àz:€Ï®€ð9/gMÎ訋äŠ$…)1„»çÍvܶ5å4>°ç¢›®J>/ŸFY7+é–9žº£…„ ¸%·ZÏãO¹r—Päº]Ç^2åh¥¾´_þ3œHZ36¦b?O- >ž4lî6„I¶Œ?q¯ ÖÊ{Šq±)¿|¨l«!b½¡c=¦«/Þö•@WÛÉ t±è{ž}>“ €˜èVf¡í É\˜ç¯'Œ^c§=ìsUµfœ:÷¢ÇQ "2çì=ŒÊàWý›¤{§úYÚƒøžT•±~^ÄQ~l\VpM®÷ÊJ†•å·„Ö£'üâoÞH¦ø17[“¡†ÿ£¼ouiOŽcWå|¼hM4ÞhË÷¥ƒ`e¸À;ôîQÔZ(zõg¼´…²Ü,IJ4ûh5ã+ogb`aß¿«ûÙåDÔÐ\­ýnmd»\•-;¯ú˜ÂÙË$T –ä}<5<ŽsRïrÚÆòÚy6õ‰ìëd?»¿á±ÉugK¸”I:-еy˜˜Vº– ‡µ‚õ´N5-ÛÔ]/¬Ô€ULñ¸áMlÇäŽK…ðh^ôÒw¯\ãjÚþ†,pеµõ‚x²mÙ\Ñ/n¢h–ø[;Ý´¦G;ã“×­(0ý¡ºü‡gZ®$J«a?Á¯rä_šPbßöÔÜíëŒlb3õXiÕcóÄ BÙïpÈꚤ3=Æ2;ƒÓ¹<‰QÎ O‹EMòñ%’æ§ ê}#Q^Íð P“‹¾í{%O ›C_ªäíólÓoÂq^qŒ5$¶Þ1ù*çäª)¿%Óž£;˜°’Æá->|["j{2î'·”h£¨ 3ïÂJŒäÖkŒvŠâï“ÞÌæ£†pïøîµéChAêY4kîg“Ì<Õ:pA,ì;&öú|QÙÉ5õR’`k±X _ÚÞz‘Ê®ÕeZe~+‰®Î¯©úQ¬m¦•%P&(Ð)VcM9——qÏúâ@šä:DJðj”dßYûtE4Þ I¯8:Mß×Vä4 ßÀïüÎb¬<°œàÏûîo×c±%àžÌäX+{èîYbA ©ANÅ@»mµ ZÞç|mHˆÍ.naäï©ßJçÅÿÞìwBcñ)¤^^“%§tÍÏn"‚Ž|*TîŠ'׃´yÆünOOÄ‹À"wXx|¹XwÕ¤o\©æÐÅD=.%¨î'"L­â'5ŸWbЌئÈp!ùÄ8¬ÞYW[ê1²tµ¯MÏ2¦aH×qo}ó²7ñ½ Ÿ]hÇ,â.Œ[:+}‚¶Šp·tÔš0ºÍ€Œ¶¥©ŸËÅL uB¼ó¿CòFÌ:Psõu¡¢`cÝϘ9Ö—_{Úª0†O)bzŒ’Ð7ÖDí.>©Ðý燫˜i¥ÇÎÑ üŸkY“–jó@´HXªHf6”6¶áêù\ŸƒÇèÆª…²x<bbÏ X3ûJšï^8=~¬éÏà¾l!ôëjß]PÞF×ÁK/5®Ñÿ8þ Œ[¤°(\Ú¸ƒ]¯~#훦tYº”ÿ{°V™V¾‘:¶ þüàˆîƒëÃa_6rC¨¢Ñò˜>9àËJÞßz5ì]é^ùP§¿HägJ_¹f|½6þWuÞ­n™–v´÷dk¦>dui•‚¨ÎUäBWZe,aÏHh÷³o?Æ,Î_àb/Q0h"ü(Rx•øöm*¦=ËÏ,}ÄðAr$‡*r|&â²ÎaàÌ¥¼4z.uF èlyØ3³Ó9A߯wŠèT> mèq™@˜Ì«d–v`?ײ÷ïàÐFXàhTwp?NžÏ§ðP[.„côd½¤O €|Ÿ¹Vb/#ó›0Nc³Þâ>½zNM.Â5¿‡ss,7s§þUóö;`ÔÜwÄfµ– mUãàÓ…8 3H•ÆúT±&ZcžNœ†ØâI2†7¤:“»Éƒ“Á˜ˆŸÆÎ§·Ü•‚3ó¥TIÂÊ‘uGá¢6Ây¤FƒÝL÷{‹y¾€¢|Tî=/žZ"üU£òï¼$=`Ò‘ô³x¥rg±¤• Î÷WËŽµEc [¨â¢>áö7Cαy‘ˆ{³]1yUÿt® ÝæwŸ:2óàZ V¾IÊÈÇ+ÈéiX]e©jÙ¨(ùtÞQÆûdÿCìOf 3¾Ë£Y¨'73Zý´=1¨ªvè¢uçjxXIEc‡êq$/&6_T+˜­í¯©K÷Ãòmž„€-ŒÌµÒŸˆ0OuLЬ*ë•#à¬Ê=VAT_®½øø–ƒˆ_0Æ·éß2n­"W”Äöoºâ[ <¨ÖÍš¯ ÊÃÓ” žc8qYkÔÚîM@“Zþ:ÅõcaÌL>÷5PÐèÙ‡kØÉõÕ¦„sI‹ˆrUˆlVÀM{+¢ {5éø·Ê;¬¹%³31¡²)Ì{»ˆe ¹äЧ¿.3¥Jñö¼ÎØ¡îp©/ÂUƒv0Áßµk hŠipªäöZdTjÛe-äÓˆp°C9à„ú™ßK‡ŒûÿBpÆÐ#ÖçǤo¨ô4Ê'@¬ß%Aÿ0צ¦‰ŒHE%K ⪉ z–Ü:÷~§hJKÞG5„¡ó;…ië”ñáSë›AcúÄZgÝâí èPLæì#W«ö- îI Ãp[és&ïÔH¾ŽŠµ#áÒ¡ÞCÔã‘® GC¼ä`ÃnÜËÀWMxØbÎF:aé¼ÂÉQkÝô" ÙT,aF«QÓô",DH’¦‹®‰£Ê— Ecêa/%Ó{ß×ÚÇ>º}Ç÷v# ÖÈmJ›L½…¥ÀR‚×ÞÓb†·bã’åÈ®—u˜b ¡ûN^Ús6$Ý¥b"hÉr"ј^šcmæ)¯rbúþ¾Væ5QŠ +H \yaZÉ£Wc îا6‚d´ŽÞ,¾ž)Ç™ý…ÝM‹Ç²x—!_kêÌ8‰öàHÉÎß]f 7€"m• ¤KÆ'úÁØH˜Ë¡ŽF¹È‡3ÿú®º bYÔiä,øvä§Ð+>¹oQÚ¦W©«  æ±· Ïï÷² &«øO\_YÚ°]”{r>=®¡–Ñ"‚*‡o7:CÁ>„ ¤­ŸèªõÑ|ŠLXDúŠáî³eÇ-Žä©@§j€º¥“lûf•¹-”ÚÖ›ßnÆ {ÚuŸâ$P»· tKW«yaz¬mDKÛxYuɤäV¯º·¨£{&-öŽV=PSýx=¡^s£rÛ^„GÄ"Dac¤fùOç[B_RÖþÓ´ߤr)«B»?t¿Z“]%26(ž5(¦pC⹈¯ÊQKŽŸm¨nÿïᓾ‹rÏp,ŒD ÌîÝ*k–ô' è½­é¤Ù9U¤-HÑÒCšÿz\è½\Òå{ jê=©zŽ]×]–Ètò_^6Ò¿ª¡ºÃeHžÄL{±ýxìD‰å|aþ0 ‹Äh^¢‹ N¼oœ-rôÔ&‘ƒu,¦îœ(¢²vÿÍqމ*EŠcD5­?ˆ—à +ð5o4­Êò-ó_–JÂÄãâ•ÞÉÆ•ÕNÕV&ú@å‘ÿËìðqZÀ%Ü{rv÷)E¬F9òõ÷"<ÿÿ‹I¼4cq°Eñ3t_»ñ™]¤1„ËŠcc·zôßTÞ笃laã×Ï ‘w-åĤ t\H‘­ÛLv{Í¿7Àl¤¹ñÖ^ ¼¼¦+÷£°€us =‚žî^ÕWFE \äPJ³ 3ƒ^ÓOG Ä/vOù™ùN ^ѦÒ×’á² >Ù\S™žxÛ˜²m1i{±÷Çjv¾¤"U-VJÛ8V¿4õDhê ÞŽèÇþgÏÑý¼c½[ÿkž™áCÎ|J!OYryìF÷p;Çýôgl®q”ø°»‡ždÔ8²JÞt)*='ílp0¹ùN~µ~ã'Æ(';^P§Ó…ŧ^PžTÙ¶ÆgW:Às_úm·1’žik¨²„7&á™zÒ7-,^ö¼ j›©ã]c«+ÆÑœ1vCþ-ïŽ2¢æLñRéšµF74†âÑ÷ö$l=€E}¬fɆð¸Êš‡yÓ×N˜ÕÍY».°m`§öWÝK£AîpêñJ»¥Ä9pIžM¥*Z ¬5³E=)ØÇMVa"­»Ô\;dâk+¹Î†• ˆ„-u6Z¼j—Ê€€PáT¬ šg¢³´+µÂ’x§Ç•(ÁäF^&v€Ba‘1 5ï„é¿‘Q¢Dʲç"=Ç’Á z¨ ‰„?ËÕÉÛqÆ„)Jn©§ø‹åÒ¿6j`8鉧̇‹öb¡r,?àˆ¯¿P MØ…­dŒ¾ï ´öøEeñÎNƒs~iªÀ)Ô› EH‡¦Ö•Qwƒ}ó-8wŽ˜8¹mæö‹ñÉ-îZÐÞžñ#8Èwl[€¶Ç“bB?©åÊ#M^{8d½wí–™%p« ™çšo0xGñ"®6¸rÙÉñ•Í9rÔ˜*jˆ'°sLz"¤ÿ¬¬æt/,Éà o³.ƒ];h8k/v‡DÍ‚h_?·:ûL-?ÊbX‘0óæ£ðB5 ,lÍÇÛ]€ ÕwR¢uá±µ4Ô]û–Ÿ#t!ÃdÐ3óôÁ£8g–³zfu$ú¨®<¢šü«ŠŽçê°²«ª… ú´F]<ÄÙö½=çvéß„0Ì~­â¸N,ióA'ø€AXY&SòœÕ[ܱé~²ƒ„ÁÚúó„áûp"—ú^@n&t{r hÿã*Ö¿†©¤n1ÎãÒ ÑÑûFQŠjSE‚.å@$4ËX/‘›E_•q+ÈÔU u2þiåÐNd C„ À 1À+¡˜ÁÌs®N°°¹äyøpÆjѪLèec‰á]æSovÄ ®¾¹‡ÛÆ¿l3AÙP‚©µ6•kî¤é®†¼L†ºùšÈ3Üg’¥×Ì’êãrZ1]Rr¬jÍ`ºÄïÔ&Éįügxç‹ÐEçÈJ3ˆîwÙO!úðÏÐkõòn>ýg•xjSL>B¤øIß¹¶4ZÐ ò,7ž&’PüŠvUðÈ7²Lx{•ц‘/´\«wˆ˜¾ök€Át˜7Ì”ž%[¿¶×¹——P´Ka b$a<åƒOÓ*Èfø?}×)(2¬mÍ®M¾ˆ™&ãµiá7¦ÏÀý"Œ»PdU¹î·ÄƺÊó,¨ŠWÉ»ž:/ÚÔͶ\ûPÁ0luËåB?cnÓ-i9{ Æðyך·§I¨Øà4e)m_MóÈZ{=éð[Kž²š;àQìd±L§P½­l5÷NŠë>Uíø²ˆŒú"g šöï³Ï>ÐW×ÕNˆ†gèN‹]Ä^iFºE.ˆJ4\L0ö‹ah(¬á½"ºãš9ÔÀž`]}Z‚¦9ÕS1ä;è]¾#¨¢*ÚW3í‹»q“õ©€H ­ôç!ÞÅõ‹xA)ÞÓî0ÓŒcž#·¯òê>™Ãî&^…´ªø Þ³Mÿ'Ø5hÒ"’…+ú­¾Zûîf%6Sɺrͯ|;ì"{2½R9S²_Ûl2àIÇÚÒÔ¶ÿaÞ,’â=*©ºU< )GÚÄq›y>ÇçáÁ‹z½À#b’ÜÑB'}CXZ ëßH¬ÛóŽ ñ.7cgCO§PHÈXRm¢z:ç© ’…P߹Ŗvo™”eÓÈ"ã"x` <º·—•{8Eèð Ý`…¾aËÔ MÂ7¨7‚çdƒXõG7dß4Óì–ʇ|4~ZG¬ ¨ò3>öÁÇÓžÍðþGQ @#jæï–´ŒÈ|÷^lßM¥VYpäg¤?n,t$ˆ±!äÎi‰'¢kBjÿ„¬á6•›^î…ÂEpË™ûe¸¬º@á‘Dp„†Ô:’|-~íî0Hÿ[öHޞψóB¢¶(#¥D)5O‰Œ{Ã…Õkø’—¤)`îâÈ=X$`l÷ìùj5ÞÕ!®UJÞ•¾-îýx(t…CóPÀ‚Wƒ–jXNê…"¡Ý3Üã×)"ö¾¢¿ 7±ZßéÐM5‡šš•3\ª3íôÛ­:d‚á*bġߞ…¸¡ó¨®¬I¯Fb`FÅëÑž42ðÌÚÛ€wµ•+ >6[Im|±4æ6­¨©s~*x/¿‰;Ý–Ÿ¡¨sŸÛ6#k“pž@}½W}C‘‚5xª:{_Eèf‚/z1ŸÏA{§fö üÛ^ãeÉyú}`|ƒÚX]Ÿs–ÂÊф̇ſ^n^cÓ''|N®F²ufo-.êï-ËI½è{i‰Žá"-¸ü“¥R{¿/½˜UÅç@/Ç»ñ…×ëÈÒí ŠÅ ª×}tç=Ö v½Þ†±£ç$ʺƌyjHÞàÂPån˜…l–÷¢"¦)ó0GCèFäKaC¶°Wº_aýXäClh½Hk qþM%{¹‘7¸çò¤vmȘhÄ­êV¯6Yg>Ÿ]X Ò­<¸ ¡J2_¹pyÙwa˜"–cô£ŠÈ ¨7ƒÎXp¾Èû|ÔO±áÁ®–‘PÛ¤×Dp@‡¢-§%0ƒ2-à`%ÄÜð´˜’0£Ùž¼Q œж}IøcKe€‘ŽÝG›ÉmÊës?€ÖfüÃ'Öþ°¤aÀåÝ®´l˜A7Âd>§í›¬=c %yod£8×]™¥fñ¥æABñQUuô¿Ò­CðÓþ1mŸÅÑ<ë GÿñÒ­D¬Î_©10Y³ø1YÌ=”–'¢ï—uÜ®™ÒJ ï1y X³’Õ2‡†\ nJ ƒ³Þ¿]ö{ @ÑðxtMô#xÛ˜4!{ZƒXÚÔáT¸ôèoäÌN…¤i#Ò#•p;ĈÅ#Dwz¤Ôy› r¥›Åí]öŒИɾa“šŸ“³&"Miþ¸}—|Ü?C´(à?)èKŽæ#òÓ~üS‹È± ‚ˆ‚LcÅt¤vðÀÜüE\§OI{³nɦb^ˆØ@¶Ìê;!´ê dÆÔ‚ºœŸ÷‡2qHt,ïrü|ÿøðË\|§ä¿ë€×gâËèúBÐËõb@À„…7ætLAbeXÀú€Ç½0'Ï+­y¬LhúÁ—+©/DϬ#rVpœCA@C7Ÿ8 ©$ÄÂtÖ¤?i§w£Ø&ÂÑm<Ïjçç–¤?kÎøÐÃŤñ_ŒøF;l¤o½í ¤GÏó[9ùi„½ß‡°Ì‰ÊkµË½œ޽cÛO3”ZW+ìÝ”—Ròí¾ ð¡Ç”ˆƒ¯sg •»‹›DúÙ!‹ŒôvðY@éæ í­æm® IQ*w-ÝiýzWT+è²`¨äåP`¹„"[¦Á[ålP ü>Ù¢õæâ]ô4 ËŽ3O¢ìjeÇQ*bP—â0°WÚ•¿oügŠ˜æ;Åλ)%ÀCÈbÅ5yt Ja6,† $ØS"ì¹×D<845Õ3E÷I!½Ùc4ÈccE£x䮈TXMJ²‹¥G_÷#SÂí#ÛÉ^¬w2A‹……óÖ ÇÁ“¼ñ‹iØù‚d‘©ñ™ì·Mì´.MªInþ ý4#ò¡‘ôÁ/¨5`}Î (9{Õ~G‹•SŸ0&iv„šù}ž˜óÉÛƒúõOÿ•;òªè£\¸˜¬-¼@RŠèþnO's ÓOšãZ§1°sŸè5Å[ºnc.ØÍJGò„q·œVV^×!‹_6n¨]8Ôo GéÃVûˆö¤Àø @\®k €E³ùwêÉEK¼À}¶E‡ü©é}ø­&E}†$sؼ! &^3SØ œh%$Ÿøác·àÉ„T‘m§zÄÇ«üg  oõf%G4{x*T3ˆ “I.!xì“Dm'‹ž[ÐF†Þ !:Ù|ªçE"Ø -m›¹×)¼ª=>Ë~Œ„uÒ%7LÎE¸pVÇ¥ÆßÔŽ$GΚ¡ú¨gh=qöÞdc3ªIøÉUd 5섘ç¼xv_•<»Ñüoh'•ãéiÉè블ï¸â #ÞNóÍ©Vhò×û'f»Ö³cÌêrŠHÍIŽFn¾üäw‡ö­ ªŒæÅ;iº]ÀyvÂÜ6œ<ývŠ9d±¾ÜØÖÀßl.ÇEûL:ÏYÍN~¶\*Õ,nî–ºq3?$€rÿÁˆêM ºÁMßðŸ&ìóÒsžI#¦GáG¸ã"ý~Ui;ë8üxc:ª$Iô¶{œ]]?¦pËގᎅWÞYf×é]|J††%]}ë¤î¹¥:ýN*CT`¢¹{•œ ÿÈGatçÚ$m€›«÷òl‡Îiñk}œìêgìÂ4ô†wDäõWjÖ.›u¹ñ)Uè–°ßM¢y êe‰ ÒÈ*C7n?n|0ÜõA°y•h|BÅ•¶µü€"bósj"Ö½ŒÞ{¥—N¯«™JU¤t%¾ìBR4á%a;bàú?²K…_éËÌZ)¼6Òúæ·pì#­I­5ʚȿòr £â@ÅýHó¾g³kPÓ°^´ƒõ|N¯09RÀïFȘ?™ªK'›kÏpb•,¸{ÓºW ÆÅð*¾ñ×÷¾ó-°)Hc"*ß¶*^)Un„§Iï„y]—žÏmzƒ“Wqž|Óèíó³~2ÜÓ ú$©KÐ[@e8}6ªæÇ±-ߺÐOW•‚‰0?^Kç®#?Y¸‹ß˜.šòþ ”Uï²_˳!v(Mxhüôø­"ºN1b:1)¾Ú9H*:Û¨`˜ÞÚN ÜMhšº-7o»->>{Ò÷%œ"msÀðΑà¨x\^íÀ8І­²:§j¦`\és–<•úg«N5Ë0ê§@œ«+0ˆHCµ§3ËmÓ/Í¡µ'ÿC¾U=”;öKÜuá_µ¢ú ✪òÕÕð¡0–Ä€vŒ4À)º[A}BA“ÑÞ¾“Y {¹wåéúwê¦U|Æò¨¹ “ ;§Ï¶^”† û꾨“W⮨ôæÈ‚}óÄyt‹ãFΛ+·Ü”ìóT‡¼ð¥ o˜×¯ìA Ðê'òW‰™^y(–œè!ׄщ4z×»ySÊCãE¾ý—8°—¡D0L$H%^¨ô6ôGQ'fÌig^9$±§lÿÆG“¢ ÑRp<âKése%º\Aܨ;1܆•8÷02æÒ3«KŸBÆLÕ½ ¼C­ZW2ÇIÆ!æ…4wnàØ#XÅ_Yü'ÍŸÎ)n0Åäêp4¤%X­,£;Qtp†2««B¿P‰A_çŸ:|®H ¯y~wÓBw*Qñv7åsÈø½°— êäiV÷ÒEÛâñ"¾B°7¶,î äG;]7'‹ìwzJú˜A³=ó 2‡–I¢À>à”è†WðJ"{ÎãÙwv_Ï1¿Õ…ÊêýÍ ³H¨`ä&önØÎ' >m¡,æq.Ù„{6{Šs!RfE´æŸŠ†”(Öƒ\þ¿lBñ7JìcGˆVÃdX®&¤³÷ÔÕ±ÇáÜŒ€kB:#¯mƒÂ}¸ÚzÇÁùc&øÅo™ÛõÞ‚B3çöGJÄA^ßêÍA=o%4nÜzp§rë À)ŽÔS>|$HƒÁQ¶­k‚/ÌÛDI˜v…÷¦/ÃRÔ:¤FŸâ¹„l’±¬Øm~$_Žaû[.¢ „®Ö~y‡¡õâD¯Rñ=¶T*bt”–PÝuSÒƒ_ñàí&uÍ=d÷p§´ý‡v­°MK—ÈX½Ü¹•FÐo$Ìnƒ_Kcý"÷ 0©¯Ð¡ÿV1Íb6ÌÊ]¡w”ÞábEÚêGç,"ä6#ˆíTÎK…Òm 0Z"Tœ9»5 þDÔ¦‚ÈUˆËî•A5¦ðèÝ¿o]bå¬ô S§TrZÑêaåýle |ê ¼N g9¬ƒoF(ð+®Bú^¿?Ú‡·S2½Š1…´ód{a(ZölÀÃunÓ†kਗŸüïgjÖŠæWõTì }HIEZ\ˆ(¦¿dÕw ¢›þ§¾®û}…´6Ö°¤kÓ\‚.¨ð±M|X‰èYF«µq[ß;Τì¶&‰D‡eb¶ÿ<®)k?¯9ö‹ ü íI7”ˆœÐŒãÜE²øH¹åŸÎ.{†,ì°ÒçåîåK”ÇvOèÿsòð$šZ 8Í@K“×±éçh_SNÂÓ±N-ؾ`€€o8H„ñ%8¥_“Išô°HXµTß ´8IÀbDEZ ô¥GTÌ3.éQ®ÚäË›·‚î¬ ?Þ[Œä1–ô2õ^†—F„Å9Õ ]o9¦ÞŽ$¾±ú0Ú¹ð„ÑäÔÔó4¥ã?GÎ(k4¥¾/ ;G‹íò ±Öivª+Á5(0C[F »€ -~¦yÃ-.®wYÓ‚•A«â9©W@FV~Ÿ™­¦‘½î]¤…ì"­, \Ê®øÓ ¨ôÒ0Î¥Xñÿn@–»‰Z;š)3Ñ„n²6µ"§)/ãÈ̶r KawÉMõò(ˆäùÁ:(±Á Žûl*8ŸºÍ2’êš1n/Àûæ©ÕÓ&(dºw-âp-¾Â¶Lÿ/Â[£Ÿ“h¶6S€°S{§ÒD¬³¥²¨•žÐþ–Úõ¸ðøc’­ë§ü§N<ëî8Tæs)€5}R\¹A®n`l?ï¶`&é=3©¢`¿òl·"íôÛ-!~o¦¸±ží~ñ\sÕÛ÷ƒx‰3Ì­ÎMRV~ÎKu³M̃‡ßNý†é÷ôŒ4º(‘ÖºN§‰Õ¦SÜlÑiŸ^ÅàoLá‰BWUõz ¥ø Ào#Vfœg *ÆÊݨ÷¶’‹Wè߯tsÇ#¾%ïBÁAÝãçCársÉël4¨¾#ïÌW^á|»õŒÒÑnŽHSuhPö¤™*WEOºÅ—”³n}>62Cò¿V7©­Âµyë!¥~·MÝ$2¸m¼|>Á&l§¦Ãórò+•,+¤Z‹1²”4pî/îŸ"wщ*·ÌäT¶1£ÑüsFáTèßH ‡÷mdˆ?«UZx£™˜m²óª¼¼I“ñÑ'”•œò€ã„üm~á3ÙW“ã+h„gúŒAâë+ÍWÄ„²Ú}“ÉÜ“ööû .˜¬ÊÀG³¬ŽÆl |Ȧæï¸`@rà/Ð>zh†B é”ÓH5ÛàÌ'È›Q§LmY¶Tƒ‘.O-¾,›œÄ.¡¬~YÑÎŒx ¡;Ò¬ëB€ÔÝ–¹øAg¢cmܼ¹` /Qè5—ží»4• q:?ò»ìÌóPW„´ )@û#öNÕÑq=WÙ¾ Ùô®_öSÄÁe¸‰äa©ÆÇPFÕ=;š,v:³³Àó BÀP”ƒ»¤Ïiö‚Èé¼a‚=7K'œ%Õj¥" Œæð7óÖÍüîfA”š÷ñĨ(Çù„Bfáuù÷9€\{ŽuÝœq5=ˆ)s|õγ“U}Ÿ÷à{}¿Ö±ïé>pËEÝ}N?+ †8U­Ëx¯Š¬'Ž^”w !ÌÔóhÒ×tû¿/d(\mét\Ô²Çì“FƒZ§­ñ’p6¾ Dì©^êNS-_²ÄH™EléSïB~ŒýìûqÑ/KÌq‡ªMSV o˜ÐžÍ©œNu´fˆ‡#x§ãí>pëH2G9Ђ(+G² þÞÕ04é›ÈFx‡*+16ôÓL‘1HÎé ³èŽ7­2ì¶ÀVqü>,MÌĺ&u€™˜ˆùÊii‘%ŽZ÷>¸g•Ϲ&ÂйGÅ~íVñ=Ÿ°cÇŒBàr~Vù©ßV”AÓ¯*§<"Bíùœ§ìÈ&/™@:Ïëcnœ›È®²5I߃®y5PÒ® v+QÐð;P©}„ìû:Ð?þÇ¢fâäPg|çò¼výaÈW*)¾meMYB¦ìAõ2º”U³š¿'âY<õ¡nY ¬—/˜•]¿2æ¹#T 7‘Êè|E&xm’¶³Uv/xgÚñãT’A¥÷ý¸<-r Ĺ¹ËØ+æ6w5à_yÒûŒƒŸéâiT)E®Š.U'3y]4E ±Š}L£kˆÐêd—“Pâ‹‹Ph]@_ЄŒU+ka^ÇeÇYP`¸,”F~Jsû¾Ø<.„`jM7]¶‰Ä „ ¹<ª÷K¬‹üFk±š÷¢!t¨¶1mÜ77ajÎ6›˜°f¤ý »¥£Xºl#– ¾’¿šµW›7_dê³²âE‘nUikÌfèüamõ rB[$!µn›¹²Hz“'®ù”Áâ´Íþ¼(­`4©E5 cœßK©®þu¿öB>­óÄ  ß lBfú¶Í6ƒ lðÚ¡ò‹8ÍGÙ^E˜s´÷õMø’r† õnáÓyߊ³&ti,Je®Y× ¾$×Ò9'T8¸>ìÏjsl8P6‡ýß–H·å’g*Þ!ƒÍ%wðCn7“«ùêd8²/æbÁŸ›¬¨IÕ—ø«‘rœÌ½6h ÆlÍ«‚(ÄÌÏå)„,>¤ÃøÜ7›§¡Î¬•$‹´Fš~0H áz`±ï|X¨UÀÃc•F/Ìð0ÒKˆ'¶c|¢ï-ù Â×íúï]ä¢Bwª~*–îTÑ’äPóÈË1°ÚvþòÃç&,Ê÷Z— &¦‡¢!ø‡ìñþ´o¼áó´,…š˜,­à¦ç!sQåJŽËOZ%ã-ŠTe#÷=]ºˆærÃ3iô‚ð7ǧ£ ­¸Õ$¤s$81Ø3Ã¥àëò¼@6LU_J«M²KéÑÆA4iD9ýඬ^9ÖqŠ?P®¦»ºvGÐ —ñ¶ž¦ÿ’Y޹€i„:•â¿!ƿٵeÒgûºˆOäLJ…bô·(gÚíû8Ešeâ'PZ§ÝôáqÑ»}gbwÝY_—Žx¾TÊ,:mQ†OrH§3fÍ}^Þž¬1úW]ˆ™å8¼HÞo¢Ø¨¢@æj¢Åé8 ÖŨ/A¼ÀhÍ É¸{ â¡:{ˆ6^É7­¬z'Ïž¾›;˜™3µírX°$ÿ9Np0ú€!’‡Ê¡ …4š¸Ð…ëÚÅm9[“?`õ5Ú¥#ru‡ÔÈéˆ5³|ïøÌÅ/XÓ TõÓ¯æiY/=~~ªü-‡° TSOùL8Ç xhš°`YG ¾w(HÆßK¿atõ2™d¼–sˇþ-ÅB-Fb[Ïû›fGŸ ¤ÿÄF{µÔ˜xÔÆÅ¹óì¬Në¸8Nì\iöže?ì LA ·óS²el–ÃLStù«qªÝÐÑCäAf! h BÝDE/z¤ J:oÎr¨¬MÃ2çâ"îä¯UùÕ ôK'ûé¼ãÀgB…f[ø@Îs´ÀbœäÉ#ö¸è5l"(ß^§Lþq¶* $ò†õEB—!Ùž)ëVf¡y‘ôùoÍ#úß®ßþý_ {t†GTPõ ­©f{¸À”_sL)DöÞy›@»‡Íîë“<éŒ %„f°‹1Òæ‹6²QÓÛeî¡B0¦5ÿq™“ä£@ÜM†ÝçüùÖŒ.IúÌCB4)³Ük7àˆG,~, W'¾L”EƒÀÁв!WˆåíæNÐÑÀy³~˹=Ò˜è8t8œu,!t.^s6Ñ¡J¦ Û/¾û<wÿXé¯`8 T*274*O͛߶‹:HŒÆ£h×èl%Û^ ÇÒèš’ü–õ}Í‘ª3ªÔÓóÁòe ž**îJDt”.ƒã9´©ø>Œ7Å*Z tž‚QNþˆcé‡ Ó¦‹°ÝTT™0žŽE´œŠ 2RÈÓÈ{¾\¤1Š.o˜î‹cl§p7iñÖUÀ¢å¢Ç_ó>PÀÌô÷(‰þ¯'îJCƒÇê\LTÙ‚’Aœ‡Æ”<è$dŒ› þ¸up±ÑB¦H8y¹÷?›D 剺3–òdÙ4cÛ*ŸF²ÆHW̽N!=†´Ñii<šzESµÀNAed}û)ã9ï==ˆ—–·êKGówCzšØ“#ÆÝb½Yœ—®¦/BÁ³ÉÇÀ£¸Á-&zÙ 5»µ­:ÈÇD®Tçã<„œl q'Àø }­J‰jÎÖ¼íîÌfÖ@!ë.c{±þu˜0«´ðd¿&éWÚÛ…¬5GM¶j™ÏA‚æÛ¯hùR\B ܯÈW#cÔ5g'ºÔ8ŸKS-=¯|“‚Èæ^(mÓEˆf•®î2j»Pãóá’ý0ê„îƒÛ¼­\p>¢ŠuãÂ0Ì—÷C»Y;\å2\«-ì‹!]­ýáŸLJ„é£ æY¶ì ™çjì0¶¿lÍ<Å)_E5øØ[ÿ,Ê$,Ò”Vù)•éžÄ¶®‹E`QØ©1òÙ~Ôø¿sn¶ …ÈÍÏÕ8è*¼bCâÔ(Ÿro%%y8—<¯Ìw†:ߦµûR¬¥[CaÀô'jŒQ;ȰXt=Ó¡¦zÓ±Ñ>Ðäü¶B÷‘ÞsÆNÅs,ynÚ¦e,L €´`Ç¡tÀ½òŸÅe£Âê/gT]²Ä–|ñÉð ^/ßüd¥ù0LÖŽú`„ña3ö¾ËT_‚ÂjñkÉ`_ngφ½ lñÙÅ] ú›:޶ôX­ünN—qèx”xöŒãØ«nÈ–ˆYµÝ¦nV¶íÄ0 ±øÜ(M¡èë’ú]ïíz„3Œ,Ñ¥tÇcN†à—"qüï2_‚‹±‘t˜=â7áDÝHô²|œ?!¥Î×…yˆµmOâ—ÚR.OK ’‹\±¢G6¶.­»œ©ým£1}Ü"Ÿ+¦²¸Æ¹ÅÖ†èÞ=êZª‚á”2¤&ÉVذ4\€«Šùn_s·¿Ã½Aàã?7ÛÒ^Q+`â0ÅwŒÿØi PÍiè)µ8ÐÓ÷ ˆD3–Î9L•5õ$ÝÉååýNY-"„šì Üóþ>sV|á Câ¬,ˆ I’0k|™».#ê÷ÙH8=}ƃœ=H@Ÿî 9— IðÄ*Þ ¢½—§¼аÆ{_Ä0®¥ÚùâdTèÖôÊQæ¬ÍŒ«š‰d¢Æ¸+̪IÊôÁl|]‘›Çn™úYùµ%'mȬq¶€ÑŒø ÒæmÕBš9 \tr( ÌCy¨ÿªàçKùjHû†°)%o}zW(y2ø¦šx%) ó¾æ7.ÿˆ¢&Œü&+S­¨;wˆbš5s‹=÷Ei„–ùÖàhgëLî‹*Q=Ù£ËSê²@~êf¥ñ‰Ÿ;?ˆ©Ö4K÷QªÞ:‡'æK–œÉ¾#ÂÉ'Ø&é}lÅ90æpwYT9¶ý%JEæHv} ~n×FÂq_®Špåÿ’à¤^¨«®—͡俑¥çÐÎ ßE5ê:Në)Gä û½ßK¥µŠ+Ë $¹oúG`·…ð;æ°Zj&ìúP™¾hhí¦6âÌ^(ðâ&ð/Xÿhí)€½ãjIô8CñîCC,AQÑYÝø¦¨™•·I™RXú)XÄÄ%°¯qtUnèÆÂªƒ>œ‡”À[¨¼„Ëñ8ç ÕE} dâ¾ðíVÈü‰åm©ë4.Ȉ™+g4½ÈgÐ0ËÉùXÃÅ*ÓÒ,Ò,"=g#…gÁœhJ Z°µDtŽ¡™lVåéwŸœ¢Ú/ýÐjŵ>–Õp`$GL‰"ƒ¶W)Ã@sÕ[Œd²å˜až®,cÂcn°MAϺıª>Å3«ìûQÁN[9ôÿF­MœŽbÞXûŠ£]D÷Ôn†½Mî¢Ç²4IŸy;Š`üÖ­ó èÇ=âpvaC'hú–™¥÷Z­x£t[P_O‚ò6¿)Ú-¶ÄøŒq(zؼ'€+õš:;þÖŠj-ÿæu2pþIBÌw€±F`EÞ«#ç´Ð Ø'FDJúâÅAëö¢p½„+¶Í¼zÂJÑ5ñ|¢‘G…*jPrå‹[Lë!D¢Œ£î¼«Íà¥p¬ª±ï8ÖhSÖï=¨«@áãÚüV¡Þ#òÚëÇEÔx⊒R‘Ÿ÷/¡ ß! ˆë|g/Ä~o{2uæ*tË^͸Ò`ã:]Æ0ÃBeeSKjÏ"öY†Ü„–䯓ÏkÓí‡+Ⱥ wºU¥~’Þm  ¤döõÄmô7Ò§FÔ ÏQP^êûߣ‹ªª‰Â|ÞXœß̸Ð×OÞ*wÝv#Áú”Èݧ»Í8û×fÚ€c®”ˆ‹.³Ìú·?m훚ï csÇÑØ)2e€P©iJYš¢Äç±S0;=mÏ%ME·è¹W³A»³»À¥ð`}*Í«Ô ²%`c”\c8ö.Þ°9ò<«v¥dƒ2Y3@ã>õ»¤l‡¾² ™§týà›J€Ì…^&å`ïO=U`bz/WX6„Ú¯GòGsAuÆ&¦u Ò-ÉIý‰øA3«2!⳯²`2èY¶-Z;ûå}ðñ¿Z(DðC?#ìп›-+iUúËâ™ñ¡,2µéò¥Ê‡—‡Ä4—6@]ñËCž&=Tâk2¶Ë2/óAÉו™Yy·FéŒÿßQŠêw§0v'å²SÈ5—z¯˜O¬1 ‘=o²ö/é;Þ\0Ѳ?¸Xnfçº0ãÑ´Œáñ–!‹Ý?µêa©¡ƒ¨ßZ«Ù±Âµ ópÝehcY¹§³âÁVfï‚óû¢1‹8¼zß­¬Íë!)NtN¹Ëðú#Cº/dü«jú‰E¥îúˆ{yo[¶„çé9þf@Ý ÍÚõÏKzÞ |ɉ¶pg¹Ð ~›~ƒ^!Ô÷Á–urˆYE¼[r»…íf»PÉûųS…Í©%ss×Ùoý&ýhx®œRY¬>¥ù®$EtôÄ aÔEŒ4 S8ézAL1[©9·?¡£”*ã@nŸ¸.íGeõÜŽ#ר.—–TÏ:Þ¡ÃÞµµŠ™&žõwöËÇ¯ÑÆ”8ÖÉÝñ…Šq"a6ÓÛg÷Ðg‹TR†ÒRMSðÌ1.§‰Jòr¹+W³ÞpvEW'Zvæ”ùî»|D&Á!#62[E¨™N¾WʸlM®ž’»ÿô=…wàú `Çÿ{gÞ#o>ÙäñøÉÞiO­‰¶¾p½é=ÆÕ)IæsÕ @%8ÊD-îò9üÂ_q½)цíU»$·xˆ,Ì|c€k¼“ô¹,iÌ­øÈ 0j1ïWõÒ»Ë2¶ê-$]>õѳƒ<\à™h‹ó®^’Þ4±^-Ò¡7bF3ÊJÎö««µpÀ‘ލæ÷‘b+تSf 5›G íê‹-]êÂ#Þ͈ÿ`ÕOqþ³’‚4©{ç¾°çê3Ìê:ìÌÁp㘜æ¬gíNÆcAŒúÈe=¡L˳hLA/¶ãÞ?ëȹŒÕ‘ø¼ÑfïÞAW{“š~Ý‚w÷xj;x4Mb¿`>©)0¼Ñ/Ý6‹ùŸR>HñøóÍ>¢'7Æôžý'. f£/Ô[J³ L œüî. ;& fì÷œV•Õ½"Úþ7 ” ã(ƒåÿtâÒ5ð89KKß û—#—¨MŽçNníÝ` s[0Óùk«šNbŽ3Z5€o1êötª¸Cßl_,òÏÝnrS‘~™Áf\²ÌD¡$ÈèÄfϾf€K‰-» K¯($†&uÛû•Ú¤@Vb„²_~BWÍ] ¾ìÆŒ=¯¿‡UñnGç°k©›æ—†â U:[ p´uûÇX)½¿ë,B@‹tYÐÕ –ìqóîè®ÞtÏ]µß*¯C«¨®ë5&Ö¡àŸÝhmB‚¬b)Á — èàøåþ›O ¾ú%ÃGõ­[“pì´•®E”ãs¬(’ÉÓr•&Ý ËK™ÄdUb²Q„xQܵÆ3îM4l>ºy=a“þzÀ%íc¸ó”å¿,œ(Ô×R·“Ÿ·IÅ,B–yþê~mÜ…†L¹“ºƒEØ”¬ ÿ©Ji‚0ƒK®Žò™`r~–Z³éIÞ~·µûÔl)j Û±©²áØšìô›>¥7fäâ’ã»´’ʘ§ßöìø*ýÒ´& ²$íc:uí ÈàÆý^CÁ’â¹òÅúÌ=8 >ˆX}ºŒû<ÑUH¢ÿ³¯°{9oGükwO^.ª`{Qz´½YùÚá îG í~DZ D&.#[~üc²ˆ¶!2†’Zâ×±|y¬¨xUùm,±…qï‘w?‡[êš+¹ “½¿ü´ù½½xi/)e«BæH •JìÛ·†/T“¼Y‹Çh ¯ÁCô޲ê«7ƒäܬûk;&(NÚ㌥dò¨† ÆNáH·:ã²—‡:5,Kå!dÌ‚ª—hø“$~ªôZ.@šB[€P :ýË#ü0*[*|‰›wÇë0G­œpoÌu%úœª{U€^î÷h€D7Ý ’{`(í´_%V"}-ìZ[æ9÷–9"ýXq@&¿²/uÍ5¶EY½gôŸWAÿe¯äÄPbp½{ßå—…ïWéZ¹öHa†éë/%èckPh0ƒ—iÔ 9¶»<3ëjêt|ÎõŠbyBèvN²¤¸ÍÛ(1½ñ¸NÛ²•› ä¾c­ð¹[È€zB&î ëlŠùM¿Í³à•(õâpa´œ¹å¿Tÿ„Ö ŸŸü‡b 5)Ñ"qt°±ÿïu Rvnánñk"‰2y–*t¨ˆ9[ò÷”J ˆEòõt¬®tÅ_yÊÌ^R.dx§Ø7£"5âõxºÊ»Ò£‹£_˜YRm9°ñÒ§Qb*Ë©Ûø…à>é‚ šÂ ½Gô!w©ìÛ¸0ÛŒu¢Ð¯«Å |Gð;[Ö„ƒƒÃP¦~o1λÓdK:i/dµbéƒbezìÃÿu¤Ñ¹(Ù¾Ë7 ~ÑqMÙ‹ ‰i È8…žøl„ÙÉ4†>Or¼¯¶Ôx\¡r¶§™ÖáûÖþ4½Ïšœ·©N\'i¾g›ù‡ì3á·îó¬vNèK¸Œ@¯ùlv ¶M°!1"päa«;âõ˜Ñ_;QÀŒ•ÌU°S(ˇ»ã*/€Šƒžd+µ…\r²èæÏ¸¯Žç캇ØÅ¸æWΫ×RΠV,Ñë3Žñs„ˆ ,˜QæÛ zƒ‰ùE2YØ””è­)ZTÈ©}¦#Íøœnƒ(‹žÈ@C†hH ïS¿¢PqûÈžbsr¿ûRî¤f ¨~%[ÏÊ@Þj¼ ä|(¦Y˜,Åârøƒ›w„P‘?6äü[ ùYúÕ0ܺBYá¸Ð†åŠ=|=ÿ¹ç˜Ê»þÃPí—t Ô1N6è¾0 —Ú¯±»9ì¢ýÁ7Þ¶Ëá'66#«' VƒêÂW¶ªõ¾ÓF¦ÿLÈfÕ} øûBHÛ5ßëER§;µþYÕµòÓ«&ëŠŒÉ ì¾F©ù€ÓKîs]4 €‰ë–['g•“`AOØáâÜ–sø»øŸee»CN ¾ ¤fN±À_—Ú`¯rIF(ÑÂ\¨T¹+#†§kRò¼8Ξc†(NºfÐk«š¿Ñœ­-þ'ð"Øì%rÚ)ÁW¶Ÿ$¾£u<kcuÉ×É‹t<÷•Îd›$ÍßëzÎDS¶{¯µF¬ôM‹à¿zcÒ«Â'@‘Öv“Ž×¡\órˆã¤ÝMšºO_‰È%:îiE T .²liNþž™œ4sÆ«Sºe„Ì0Lo“uŽ4²¤y©'S#-Oî_}ͺF&¦Wî­ä ‘µO–è6è‰l©h{ y:}ò<1ÀðO¬\“!ßóðh^óRVŽŸ?+´òÒß¿MˆÅ¥ù $—ÎÃ÷03Ò'´N*uVᛜTÍ¤Û R¢•>ÊVAH/ +£J6týÛ7ùç„Ócåû¥Ÿ”v! sûœ\4D^à謯Kj¡£¡j…'0Ĉö‚z} ü_?£dPÌ™ñ VÈ:•.õ$QŒòàKfH˜oÔöãàýÙ°È+píç‡sl:¦ˆ>p ¯Ô1b¤îmÏò«˜Ü=cë݇ou’l6ЛÞù¹\¸gj€Ãú2ýª²üöÈ\?Ó=[£’t¿÷\·@õ÷$s¼'ìêâºëfp¸‘>ÇÇ­ATƉ.1£b£P8šbL¥G?veÈZCÜ6-Çc‡*ƒÒ ä>ÛnÆuÊ}Ø~µíaA– ì}-7ÚŸ»* ¤jî ×E.35Þ”‰eˆv¢›â–6,•{‡½QÁåš<”3Øÿð+ "‘Î 6„HÀDé'WqƆH|ˆö!ûMQ5Õ2ÔITÄBÈ5Õ«›œ;pÙ•Ù"™ƒc»äÏœE›} e¨´"é۱›HšÛNÉ$ÿ˜è5ËçûŸ ?³“B|•õ o–cäìo :ö°9dãžp­ç y1ά)”» n¢Ò£:a }÷8Œá $,œu=X^´¦âN°týãÿÇîCY(­¢0+z›NùK‰á¤ÚÎ[¯‚©6š ºï·`”[C8·4ؤÓ6þ‹Ç@´¬4òoÝ‹š‹8Á¹ß‰ ÝØü°]œ¶ÚûÊs.dÛBG)FèÕÿÉ Çjþl§ ýëüÎþÎšŠ½l€‘å¡2i¯xÕm¶çpÏ>®ò™_,jÇ4±fÒE\õF@æ(É4ƒ°3^$Ý. ÁêéWhXÂÆÓ8¤r(ò{i¸GZÁi . c 9’¡±W€^E9ÒVê‰/°fÕP¯†ÏÔäícô°M̹8hXÂ¥È$ö¾ÐvXeŽbs’³H"䈕ޭ)Ÿ '6Ñf|‰å®Ð#žkß¼É6i&¢[ʼn'ó½LU…‡N:ô@óá ÏšÈ!’¬M³ƒJ] °êÿ[F Z•ýHu'õ¥ÊU². tÓÇ’BòcÇ46¹ËO¿GŽÖ§€¨IƒÖ…SrĪª ±vX‹]îe°¬ÉËûV«v~­‡ÅÞ ¿š[7Ïì#ÏÚ­aIÛjœæ:(ÅD¿ØÑç4'?à©6ˆÂ¬‰1õ¥?…Æg\¸‡~\ÕìjÝ^‡`"Dt÷ñµwÑ‹PÜBºÀñ6 ªÍ¼Gç\¤=˜.r©†y÷™øF¤ð¨”BHU«Ã.J±&$Þ&LÊèèq}DÿJ£ñ!Q-¼!‚5æýÝÃÓˆKÌÜÎÖh4NŸûùÕ à™?xi² ¢7²~kXÕTD.¸ÔZ¦pò˜\LQÚãÈ•]ÝŒ¥dñU¿Þü>õ]þ×?AK÷Y…€UTéÓL‹i—Ýé¤Òe×(æ9T`¦ª;%‹|1ªdþ@Ô1}iYËž.m)[®ÙJŽ–5«æã3kª‡·ïX²ÇzžÖó£·CoB…ÁªLµ×}z³2ÂêÍz³•QæÞÅ([~ÿIÅzçÐõV~ZÕ2(|üŒu’¨XvlÜFÍœ:‘MEU=FðT¥Yq ¯ü„°þÒ-šQè‚É"ƒÙÓeƒT¡ˆ…O;âo|BÌ“=¤5÷þŽ‚­:bÞK"É…ašƒci•‘‡Ýq?ê )˜oÔ§óvá^£]i[h´Üuyåÿ­5ìd+Žs²òa=QQ_ù@åH#ËÑaÉ3…Q^ÍÍêi-²uËj5(;ËÌ\O’ÅdºõÄèÒ rq!ªì5ê ˜=žŸ|V®-Öš@öÝÅé;·lË(ÇI¿²éÆ9sɺ¥µlrÿY¥ÑdFÐ,‹\N‰âDŽ­Ùú&ÜÖ w%7ë²5˜öÙ–Û…·eöFRÕ¼º&wYùУ”#zÙŸÇ&u9G°¢T;ÌìdK /ÌÙIÁ ÅCì< [-Ý>­Âé³eÈBâ.èV\ÅrèH}ûkWÞ‹'Æë¢ýƒ™÷ŒòÀ.Hñvý¢%Á·J¥ZÅp(î§ÃÆŸ1Ur"ã †*‰x÷ŠstêMf–Þ‰œ !A¥Cf!Ç¿žçÊÔõ™`Ðú©\Æßkè85E¹É»¶9]yŒêó°`Ô (2œ­„ú§óŠECTö¼—Í!¿Ýüjü|ar>E¬z˜9«,Ó˜XöîôWè6PÜÔBé Ê« 0Û*OBEëžzÇBm<ËWϱ§¤—Åñ-,«iÚ&ÿu4:dÂX~¤G©ÔŠž«ãXÖÌãW\¬¢û“‚w[M西ۀ/sb­ òRR-ëôM.¶›Û½‡…òPAá¯UäÎñwAky¹îÿè•Èá´õØxûˆlYæ¼¼=!lÉYaðntv±yq›¤>sE?-wÆ£‰v 3(ó©•>ßZ’’7Û¨D ÉöÉÙ–üM+å­a@†™?bó©|ÇgùíUò‘MFïKXCÍ ½Îp÷¼i,|;š>Š 2lMÝùÐ@‹‹í9k¢•)´R&zá"ÕË®Ovžh7 µZ–(õya€ÍhðE[—0bv‘èBTcõÿ唬¹ÿnå"ͯBA—TûD=ˆdaç\d93Œ‘Yp,³ õ´ö§°¶êoÙTr4ù·ÂMÁ1ÄúàSvÔŸèîBɦâK\$OŸnªÝúr„K(›bÛ­ÜŒzŸ0øÉB¼yv1ˆL…•rÃJç8–uÀ¥o‘½##¤«Ï\éÊqûAq>¹óu/îžCWg_1Û¶Ç (ö°Ê_›Â¼I7{Ýa6wꌃ@ÿ„Ž¡Â G†q÷æã‚Ù^Ò€¶ø¸isåÝ_çîÝ$7¾™ó6d+¿Ã,%\<º~[z‡ÁÛ21ÊI Bœt¼Úh°ë+/—sÜ\]át4ì}6ÚšHdZ[>Hð •µf*ŠN$ô # ù9½9Íìå(–ê°t"~h?Nd~Ì»FÄÍ•px&3£ñ§Óý8t¶Ol g»œ:Ýù¿¤á@ÊÒ߯¨’JÇOPÛ6±û±à×úß¡¤rÚSms{ò»…Üò€0J‰í0™mQãŸÂÌJռ࣠fÚµO¬‘ê#ˆ5)àfde“,>Ólò6*âà=WCŽTÖ{ZŒg»™ÔùÌv=±w’¬.«E2N奃^¼f8€ÌœƒUÆáÓ÷$ ›MkWs9ÐCƒ+uÊ5Ÿ¹ò0'ÄŠ$Ãbˆ·f·0/ãv‚lWÇÒ/©}JZÄ$;Å­¶mnÎ7-r*Mçkøã‡ÒY‹ð÷\pȨWÿ`äæŸ¿Ÿ´溣±‘zפcÒ”ÛÝîDÀç­ÃF&1PKþ"…¢KYŽZÄ„T"ê¬{º„p&³kä3SMŽw`f%€B’ä|pуMÄ™5Q;b@êU¤¿vñcxrP“Ä|»ý¥Z…Î-c£sâ‰Ü˸óÕÈý9y% ŒñÐ:’ó7mY„G^LèZ6Bñ‰],+>A´É„Wd ,;G êM£êXÐ81v¨±½âßÊ'+³Z½ Çœ~Ò âM¡’róâH«äÏÑÇ’R°8¶åÕÌçìôÿÍÍ3®-\|ÂGVvö-®#™D<Ò@Ùh ûÀ? ðcçþm¬™6–Oô1‚‘aÅ%õêÍy³s×î–ÿy³Bõ|du¸è©ÅA¢¤:ìåô¹ U‚íûZ²³ÙôÄf_š…!ÂWòlaçÓa/¯ÑíFËWÌ’:o‰VÊudS<û½µ,Ô˜NäÇ0 R|ÍsHEH˜9H²* ÷nfÍ_B³eÃ9´9]É®jŽØ¸ÜÚù+" •Æ…(× vl-¸¢¬­ªýý0fáɇ9…b¨J¿ã€Ï–DË=‹—ä:÷•I¾>ccÆ¿2ÕBräç_¯«Z£‘ù©Ó½Ho(îbꥣ¤#5‘}®%0)“|níºÃ½ˆl,ZŒF1¢\]ŸCÀy‘^~I‘È/B…Nù<\ʹ£fîØ¹øjh\]és…ÞûÛ$1âÌøTD§œ³:= n~ßÌJá–Ždƒýá9¼ä!õ°š¶„C#¦ƒZ¼C•e08äÔÂé±ÈµçÕRP¹]§ ½¤¾±•¢‚ YFÒúÔ¼rímùvã!D"Ú1þ€¹¤Kr:å®ßL¦`ó_´ó]ZþkŒLp£oÂê²» d1Ž,–nŸ3O@Z;ßôŠ T`zâ%f‡ið3†¶JÚÏœÖƈ‹¢¬\5o™¡1Ù®¡&lmÖTú[jÀk`óà¼×´³j*o3i îçgQE¼GKe¹6ÿÀ¯ÞK,’™wZÐMañ&®|fú&· aK~Ï,„ê˜U"Ÿ#2„´ô¶3ÛrA²¯\&kÔ>•[ôË­ÓxPÀ~ÿ½iwŒzY)ÐW‰¼ìz¿Je/ob¿vôèÈ€\ó)r*BøL!×¢ ¯Z‡¹ÁºhbUÿ7}¯'Ld° ÅFÖ°-Q{ ó•‡kíú,¦¡šMÅ䃦ý56”ø«°„áD|#ÇYᑇk@ñ»èªJJÃH×~ä -RlÛÚY­ÃYÉ™|ýöÿwRøPŸ±(£ª¯"¹­«ØY¡"­YŒÊÖ‰v†WÑð¿v&¤ÿ+` Ÿ+}ñFÜ,CŸÓlDcÅtEn÷&Yòx ?ó/䄟4Ãÿ-ŽcØ‘²ãJ‚UJ }Ì¡·¹ÕvÝ»ä¿xˆl'ÑÛÍ&Åâ– DÖ¦Ê5äòÝŽ…CÕ9y.0<ÏœT`ùãTãv[pH)4ö®KÃ]:@Q€Q†ÛÞIm9~ªÂÛ4o‰kcȶ`gqTU ”_Â^?û=+y…Ñ=ËËVUð ñTóáöÖu<Æåw#ßÝ¢y¹Î3±7ÚÛê¶‹Ùo’òå’ÓHoÓD7ß2¡¿-BìröÉ4à kZ ­[iÕT„&Œšó7×öI¬æß³N .™qv`L‡: 2¥øý½h˜¿L7ÇíãaÒFù¿1™Ý+fî=€•©ï!³[OÿWÎ ^[‘CY se»‘¶Î{È'¶Äø4•Š‚ËÝaj‰]LׇÃYi" ZVhÐÆ6²[U°VÞí2Œð£- aVÃÉß âs fç–½0û\(¡ß¹Éïææ(ш”’æÜ-}1+бÖj‰½éô„«=5uZÄ#uÈ@ú·õ¦}k ÐØSÞÂU)ï¾óáI^©Ù $îLo H³s"Ÿ ƾõxºÜ`½|üŒò‹†´Û¾ÙE¶X»‰ò˜¾¨Äõ~¬ÿ_¾€…nÓ_0íÔ?É“ò`ÒœÊx®.ÁÔŠï`u¶éw*ÑÑï‹Î $«±®[Cÿ’Ì/{÷Ý#’æQv.ŒB«³~æƒÌ•æäMG1aÔRlŠ]iZgyæŒYÙ$h û)n9¿ãu}³Ói7UæŸhÎà»å„ò Ê„J)Ýç]ɲeùm'V‘ÓŠ0w-%«Ë–¥?‹ç¡pˆkzÌÀÑÜgðg!ߢskû/ »åur˜¦¡·<‰ã>\ÊoEƒäÃçýaJóv3XÚæ©òiƒ&  OJ¿ ­u Jü!›IcÛâvoË¢aëdÕg” aÎ;/:HlCøváÌ=.Ì|q`QIoM#?\ÿýI.á¸V±’ãPç)… ~ðÉ]˜IÝZÿåU¡<Õî#@x»ðAžDá÷ƒî„òØÿ_8àªRÏ×C Ní-¢ZîV!KE>ö|$Ÿ¸£Ù÷kV˜qPD |Gh€!û¾ì¥8`C’ˆ’Ï·€m6ªN–WËyäšk ráAÍéàÂb>ÔGZNZ:ØËzn4ÿܱnJ(Ñ\l©cÁTLöMw[bg´EÑBsuè߆Ð=cÙ€ñûžÏÃÒ;0ÏdŽIÍ×€«{=J5ÒZ¨ràŸ¦Ép “Ïqúv©CÉ]cþÁ” ÑZÏFî >Œi‘VR¢zFßUVðŒ7õó”1£—~ó§âþ¾¨ž=YsTzó%öã?|f×¶>kŸÃŒ¡å³°  Ð˜1Ný®R¯«] Yôׇ§ ?5.ì<>kî\Rn_¬¾l‡¬³x.ð›’Ü4÷7͹=¸SF¶'ÍÁjò—i5ª•>j'Ÿ³NʳÊ+¨OkVÕ1¼Ë{vËŒ™¡çà7¿«HC¸f¯§hëH¶èlˆ¤w™‰’~Y׫ß9›CHî«݉ùS—²ÐG(o3BVálS±Ë æÏTI¼±‚#Ãa ]’:è…:ô™=ÎëzÍW>Œ²y{ö[@ËØM™¯¾"<@Øt`!(çD’cÀ‹‡Aó_HÀÓÓSŒŠñ‡MÒÏÚÊ¥REÉÉ„R ŠŽ›~;”˜r¤:Ýdn¥S8¸Ûf/“™i2"ðR8'+µ‹ª14 "l¦òrwNàdω5©-`T$cæŠN²©u‘€áìÑÑ/„ÖÿSàFI˜pÓÉõ’[£³UÌ3ŠÑÐgb‚=ïzdé1Ä8Y§’wu`ñ±ÃH¦ãƒWdÝÀúÞ\Æ›ÎåêÀV(d"rÖ·°mËižÇ[p,ªŠ¼ßnc›_°éLƒMJmr ê¥ì’ª¿V Q°"ÎGy¢ã0=È`xŸÁ9©7œ×Ÿí…Ê£Ürp¦™6S÷¥ÇZ¤?¬ái¸‘C«VíE%¡2ƒgÄ6èÚ¢ºä‹†÷û?a£ÒÅÄIÈ0£Zã„Í|Å:Å!qƒ Pφ1F¬ôw‚¶=èCBżŠT•!žÑ´soPÏô¹…Ù±?ÀéyDxËvd !y"÷™½¬›ÃFò.¤îrzóší•ÿ»…IW‹" ×j„Ÿ?¤›¦*Aú@¿(HLˆéd;mh¸eæìš‰Åúj†ïƒ _©u’b‡‚™ªÆ÷þ R] ]e-–½»š‚%YˆÓ·.ô¤²ã­¼Iˆñ ­X•+uŽâ•¿ÛËuºvuZ|ƒu³ânò«r~èÔe©bâœûÕâ¤{ÆË´ç@½“š=­&O•{3ÎqÔðuU‚2õ(´¡ ¿•@yt¾z`¾°ïú²¦©µ(4usüx¬ híK¿ô°6À3¢Ð¢ö¢9>˜6Gd·Ô’˜ÉDû@ÀQ’Û½°RÜpÕ{œ¿žî¹ÿ2×Üõ˦?” ªf¥l &:†tñmªÌŒ¼uÞi')_BÛȆ|yµè¬ø|òpVÆüÆQð·jQtþNùŽ æA¾ÖÄÂÆ331›‰J’"F¢hjo¡*ÐóÚU¤ë£w¸nD†ÍÎ?íÐM´.ÖÊ×±G”xµÐšú¹AýÃ+ëW©má s¯7›¡ˆùÉ<ÈZ3îÙÒ^xÝÜ\æåÉðy…¦M0Ýa««4˜LY GˆÊé föy¯\K‘y²o5DuñËhM4úÁ 5³S¿4k4¯ª@IGx!Öè5lóê&é0çôÅŸ¼5¸ß»^ªÝOë)”#ÅæªvunhÑýn±ë#kó¯°‡Tôög=C÷=P&¢ÉEAÓ¦ü!%5©.k_”—¹Õ?5L"zD‰ féÀ<Ù£§‹|iiŒë&ÔpN ¥W¥í೉‹üà‡Rü/‹X†îa] ãXF\A¸Œ §V®,äZä¿j£¨®ûôˆâŒý9ÒA/,eé‰ (ؘ$èÁÙjû1ƒóÍ©íОûÂÅIêi ö D 3 9,m>Ø7”XRp\Æò Û•”,†¾€ÔUì­Z0Xß+Xk/ƒÊ^ÇÓH/¡Ì'ä€' Ì‹^ÔE…_Nùá®t¶¤ ×í)‡¥–¦õÙeß÷4‚PP¾Ùýã2}hcq%$¦lH]p-ê%lÓïx“Øéi[Ù›Á¶‘Ë£­3”ä¸ó»c›][©¯|®(>Gà2\ŸíT€ôIgƒp°#ç+¨t¤ö0n[¥©¦‰b¿½¶-ýÆ¥â…L±œlÑGÞOÜ¿Dƒò›‡¬š#ÚmÛ_µ.†d=a\B>qÊǹ¦çº9¡tâ} Û¹Dt÷ÃõÌäjna Û1‹¡ó9^_C.Šˆ˜á¶JN¿JÄzÏÑÞƒOˆŒÆ^¡"z[—HY·’©ïÅÐò¾wgƵšRAjÒUüèÔ”˜›øê¢h}£`-Á?tF",AÅ€@rGÙŠt6Œ…Uz“¥á¶¿nI·.ÜëJädÁ-¼~Î‹Ñ È:»@‚”7‚‡MŒÍ9²ö ’½*…À £úx1Ä1U¶Ê›÷]XvfÍ»5+ÄÓ˜?çvº'F›€ç„ÛëE•ò¯Ðu`SX=fÅó˜/³,¾f?j¬;âŸE=á¾ðlòžÍø &ÑTaȹ«÷W.¢·ìÎí¾©“ ˆ•UøÊ ýi·“LéÀ3H4K*<ÎþIwþ²ÃÁ'Öú—{x)i ã«¿!˜©‰5’Ó–©èñƒ˜íZ™…‡$î˜Êq„DOãKß_ ‹$ÿv‡Ik&ŒL‹IžŽ¡óð]•"MAÀ~á¤Dú£~^Ÿ˜­þò#¤íÏö0QÐWÿ›¸„KÅŽHi=fÈ÷Þ=h{ÀM¿•µ„Ëø+Uºq%˜„ŸKv?(Œ3£Ž\díoÕDŸ³„¿PÐd šçQ“ Z’fó ’йN¨P•‘{“µÞ›Ð8š‰¡‡G ‰€šõ¥”G%%)Oõ¯L­s6ÌÌGÜ-¯˜G$úøëS fÁú虆›ë IªV¤ö-ñhñ³ !’¼þ4ÐPÄž»Ñ uXv>/ ‡3—æÓm¡„†ZÌ)ÙŽe;íî(Ž×öTp¼-¾Â~3ȵþ’Ë f¤×û'õóÅ¿/ ~@w%ÊÚ§¡e›Êi@®ˆkzÄš•á Í‹Fr²s#½þ˜:i˜tª©d'iŒühƒûÿȱ¾5ƒ×x°Ã"×£0ÌÈ逈J`v‚[<"‹Š¼öEœ|éÄüí$Žwdן‡baæç?H<®$À÷Üó’GÏGnDr.ëïa"zÿn º“*¢‡Ï~Ã{è¯ùuÄïø à ‹oäãÓv«‘!|‘ei¢Š€&ÿÔ?;oÔèÍoºƒîÆÕîµ/2ÃV÷¼íwˆtâÈFã Þ¤¶ž°Ám t RÝ8v—§½´Ãð§×ÉkW0{ÝûŒº[¿ñ•&Þê:uë ¬þé ¿æç„¹öåôµÔ]Þc×uºh‡/Ãüs¬8z¨ê™Z Šv€&4jॣÕò]"º’[ùŒ,'T˜V®¥¡ èi¦µ¦–‚VÕWk½íœ«€ÿ¹B$}—(A²JxõŦ$€Õ7:IAa[¤Îg?Ó\ذÃúšëðõr_XaŠáþÿ'Ö°Rç'¼œ˜œ’ãNW›y}]pqoFw¿¢i­yySä­ñKi©mÝJ$)«ÔVŠ!§ ¨ÎÜ}aoœfÕQ•Îù6N‹·ÛÖ€¢ô'·ÖÃYÝÝÞ¹cbÄBdÇ;n;EðøqûöézÈ‘p—*<°ì–i[:qb¸z%~ê—án6M '‹ÍÞ(7¾#’=k©°y˜0ý¬Á×|ÛoÐüátàjŒ`ªŸ,Aì©ÇšR&¹’XÚóOÃ,?ø>²¸:©?û@g2ÌH8Söéã•#í–ýy¡‹ª"\/Z_ „*G¼à^9ÔûnÔüÓ*ü!Yû¾Î:ºŒú|ð B R[ízûú4«_<$Üzy•F@³ÜÈÆLZXRú~–ÄæÓ4Ƹ¯´Ö'D4±ŽfVaO‡±ŽÒiL޼ÜhÅNê \ŠÉ:ÔŽ‹BŸ Ìã”&šØTñ߬º¿ì2?³ëî¸}åˆÜ:K!ÃÊŸªº@œ»E6ÙÌŒo‡þF4¹|sì˜|‚®+ÿ}hUÁ„Å»œŽ]·ŠñˆV@#-$¸z5LòÞVŠÁHCïŽÛѳ»=79‹ü]ÕÏ®¢¢*4ËÔ }nÕ¢@ù¶ÒQ㪯=¼Š³cP¸àõ†Z?BßaÒ·¾Ë—>F_È:‡ðfYVÔƒ·*¤‘¶’Àî€]Ÿ 9`y²nTŠè6ràšõû÷ö8ЕåzÈŸh/V&ÉÏÇÂ.AÀÁQ ­æ¾wy‘iUðÓ0È„5L'anaí-€qŽeáͤ/”—ÖëJ¿UuÊV0y¦ÉnÞ\3ð?”*ªÅ H_óIqK»L¢[C•¶×îwlë}͘éMø.)Ñ>yŸ¨SGh‘d­Þ#+D0Éfq%0ÝÍLkõ OU–ª¿ÿÆ;” òW(FóÉð©øêßÀYUÛ(¦^6¶>Äp}M®ûáH^3o÷ñÌ1‘;¼^ݾ5C6”{,ù¢¯±ëݹ°UÂ ØØN Æ.£ nu%©0ÉK«Œ‰¢¿ih޲wbÐbæOëdO~qðN\ŠE>}Ϊ°Ên§ÖÖ ÕÏqòs'2¸ö05™5KpØç±ýo^ûœ¢'GÏ Kà°!:½£Ø¹ò°¯ù0‘W|—;G«GfÈ=4åqàECªWпóô|* qûªêå~NÈ~ 5uŒÈ¢Îæn»-»\O” Q–ÉY§ ¶&š’ìËîè(ÁÊÝk°¨Mq±rÄË3ý,•|É–Ùd*1oè" õì4ôüµ™˜›Šõ#»4,ÝP“uŠ·à_…ý[Ñ;´2"Ú>™íQnf ç/xÛh»oø¾º1lüOî6•+x÷! +žï „è&ÐÆ4û8Z| RËZ3‰ä)Sˆg¿óûœðí¡¼~Ç]#˜Ï=€ ƒô…&iÀöN‚±D¨4Ûªq©o"†JùË—\¥mÌÜ~ˆýÌ?uõ`Ñ1£K}ÛÓf-žT^j“’*‹^Qå©s¯’¡k‡UþPhàï—%}vǪcáë¸ÅŽïÅëhèöºˆÃóåÙ\°ôçÞ]C<8t‹®Ë!ÞûïÉx‰¾¼*¾B@‰½°7 73HÙ¹ÀYäÔÌKî©É´Dˆl ;…o“ J2ÊrzÄ^¸WI¼A¢‘}@ O*“y {TZž‡*~mDæ»NíGÄzðM,Ùå2IÞzy ûò¯m63’\&A ð O“Å#óLr{S“qÌ+âÎfè¹M8¾"‰Þeˆ¸X/²’f·I[ÌÜà™ûSÅ%†€™h˜ýOíÓäòÌ&Õš‰6›û”r¤äbA„ pÀëiT”N»pOþþGÌê©“¤(·o¢ûÁrÌ„Xix9FcâÑ.3X(ï9ôºÒ™D›ý„w?˜ß0<ÊAuGpæþѶiÞž4(Lõ†Ÿ¼Àÿ¸2D‡ â†Ìè£lãj¶»Yï®ÃÛ§:l¼§ÏÒ^8}ÍßúÁÎ:˜¹®ƒ±ÔÜó×v7Bœp42½eYb×ZgØbìË ¢ç¡ªR}PÑ §ÔÛMÂ]/§ê*„ëZhWC+]ŒÝÑ J¥ä±‚­#²ÇÓ,æJÆž7Y×÷ªóÆ­4/®“7›­ô3*“^îsl€V+ÛF.88é)'¼UóŠ3N«öŠ HiB˧JCBM¨b~A« Luu5"ýDÕUŽ‚ÒÃn‡á¥`ÙXV­¦lMü,øÙõÈv)›5çtêH„ˆÆ¬â`y çjšb©\û(¸@u&‚€8Y+À•²À©¨³ÉË/ЯGyÝP¦Bëðˆ”l¼NŒƒô/â^'bY»³}I¦U´Ü ‡°± jý@èn@ÐÖqv.Üûji/zÅ{ªgáM'[ñáM¤ÅŽáÔÝ*eJDgƒô°ó35’W º2ĨèÎö·<¬h¤‡=nÐá &ÕËè6°ð߬X'Y aLzLó·BÉ= TÄ @\&LJUÁ£ŒÏžî ʲ4x4!.m<8m¬@’0©6Øx>ÔýZƒËzOh1)Oˆ8)’úµ=n· a‚?é 7ÐHUѦkhž¢Súé±ë°Â*0¯¨ö× ·³åΉŠ|äSxŸcîç¿™³7*~ Õøè4>P~ËC®ÁŸ³“š÷øÐ›=î%$û¡ø% ˆjÇ6fë¢òÆ)aHã˜ùm‰8¼˜§@ß½’ÓMi‡œã[¾àL]<‚)›¤í¤¦?ºÈy{*ï¨ËÄ6é¯ ³óóµ?B¬á ¬Úâ÷€7ˆ"wèVP•{/ž¦ÔÞ+Ñ©·åú,ÜâØù˜ÜgÝ“„Ez{B­ÝÈ'gDwá9˯+% °1¿“¦Ä`À(›ÍŠìb„%§ ŸFÉgþOd)ÇËïZß“©÷G‚ì¾-ØÜóÉßy«1¶1ÑE'Ï|—ŸÇSí·0ñ˜ ¹^¿-dCD!UH;4¸/’loI6¡&Ã)!o\œ;’íXL™Æ¬íR‘G„n´íËz·³°ö´3Û6¼~ñiáqãœ*çj-NSD}¨,™u™>5Ï3>²ú(¸Á½Jë[‘Èâ“P6r5Ä$þÑGt¨Ýà¤Ó™úÄ’d¹1NlÈ¥,„ ‡¨œ}ÊC©Ð‡6jï^GY“&Ý©C¯6£ŠO‘ŸÐV$×§ 5æÀûu6žº:ÎpíZþ¶’L»zPƒ”4=-ñzO "; L¾à?¶¿æìYôŠÖ©¥9rkéÙ¥#KžÃº\¡L –ë9Áç"2… M¯‰•x:ię̀rÒ¶»‹Q³üâe ¼göÕü?ÀúŒq½©0Æ^Êø&¥ÔR¶ï¼çVÁ™HOžîN#V|øYœØHÖï ŽH¿Ïr—hñEÀŽœ×bÖ¥\ÄBV!\SÝçu2["DûñSï»: ÙkAg_r”-ð0`S.æ›_H‘å®MÌÑ"dÿ-k¡•äÄЖ7cá¾L™x:øTtl ë¥×]K4.‚k)’Ü»š¦ñ8Á±¥”9ûNPߤ6‹\EhåM˜†À3Ý›FÀË¡Dª¾knºÆ''ðØ-Dn€Í:µ'ŠÏ£2mÎIÀ•Ò夻qsrðuçod¸«¬«Y´z•Jq û±yô’A‰±&½É/9ËÊ×{nØþ­€nÝbH+Ë4Q9yƒŽêC!PM²zËX›2Šx¿æˆ1ã`zmS.pb)ó³@à¶‘8Ìe½¼Îxd´5>y~õ1;5w€îíu âô˜’œ’•àÏRéYIfþTï,,Ë"#]šÙõÙ_n*<Ž2,…}h“Á3jƒç¾t¤eX­]o üÐöÊÊÈë8ü°±9md^Â.»vXGòòO5ÚU}-‰ã»¦#ä䵉F.ŽU¤ìü‘!–K@Áú¿ŠW°*„’…œžÅ çO¨âû‹~ß2H]h2Mòð'¦_H¢Ó)33Åe’L#ØšÈÖÃH7µ-ä ‘‡Ì,ñz®î „@ø¥¶’kôÊ•©tÌ!ãøÔŤ9Þ½Å) ô)c z ÕÔ¡u<sH¥¼²ÒÝ41ÂDAȈÓ÷R:¶îu—ç„¥Ô„ÎÂv|cê@´iß!::}Œ`3NöZ¥ßš¶TrÆY눳oÑÔ-×|+CÊLö¦{o¹EÄ.WËîúu’€kh^U°¾WP—¨‹-¢]cÌ)YˆŽ°O¶²Z?ŸéÎGå`[ íÀÛW~Dê=¥&ø”Æl.ÛßÅΖÓÜêHŒàmd7Z$óÈÄϬó|ã(ÛUËtÕÝXü7-Í­2Éó[‰~±i¢nµºg1J”ù@ùÖ×ÏØ£ì{Ã\™ŠUÙE!8 Íš%pâGÕH ‰X&xŒßÔÈWyKû+Ìkì7ÈÔêÅ£xsܦž*ö?&<³%Šýìw’6Gß)ù«Y}¿‡ ©OWnPYWÑ›ˆ¿·aÝ¿Bû@q°’d4£èc~[ñW¶è)ÞËïuB-³»ASi,T(mæ 8…¼Áȯ¿Â*Ú˜›çËå)IàßS ͧû…Ë[Ø3ÅÆIj«®L©ï±aÝ÷¦åL ˜¸MgË#jN}ÁбvKÍžûø=™t`¸Í:¢nO'KÍkÃ$mGdœBÑ]8É}oüì»Lع5¸ÀO+ÞDm-âØ0¥™tó;^æ™ØBçÅ AŒ—¼¬ï^‚1k§Z½Ç$[‹'"™&˜_Jsþï: o¹”^y ª£Ôèøþ2•¾wRI¿Á ็øOÄxA/$¤‡(ÊÈÎö¯Ëeõ\ªqÞº,X-CgXqO&Õ]w¥éYf¡»â`'¹ÇQî¥>?ŒüüÖ+,K0Å¥®šè¹ÄG¼)OVk‡Õ¾>ab«Þü5†öŠ@$‚…d®|±¹°—TÅd–øÑCþžáÂÓî¼5ƒTËá4y ‰‘ :âˆúÑ؆Ón+JŒÖXì×ËÜ.u¹x=A} ( žG¸ž,'òxûtohÊÃïÉÃËï””kÒð´`÷èן$þW˜*˜ãô…R½Þö‡Ò¡û½J*¶è2~\@úNw€ç¦Å(¾ª<ž£E]q;¸ …`tüÁCÊFúÌÞº”ÌÁy ¸½©J ½WûW‹!/V¢’¹,[Ìï— Vý‹ µ‡ Ùcãœ<ç¿sÊGØ€S¤T½ŠƒõëÚ"´˜&þŸå8Xðšfë)¢÷éœË‰m÷Am/ÞտÞïC»Ÿ†i⃡S‰ÏuD"¡.;?^"²Ø³äÒ£sÆ&(ŸŽ %‡¡“*\z,… H§(f(W!=¿ß€q¸Pã¿Úi,Ù©ô AØÊ' ¡ºŒ®Li$9§ÝøßJР4®m¨ C­ Š0B—TáIç2U |:-XS NÎ •ñäR)œÈçdß›óå~& òù/ù ûGŽÔ$Ľº7ÜK?(ÖEÆùb…ÛœG^jxÝÒ…ïØ’Îª*ò\åÈN¹}T5qŸ—!¦£|ÆZú7YØ"M¸c ËÒгÛ1(9¨…•ЍíˆÊg\ê@:ùE§pJe¨Ó_å}¤ÀŽßšæl’‹v ÓÀÇϰôOSÆq“¢¥VàVT0²ÃŸE5æŒReŸ2Ÿu +“ü_q,16ÂÑûfé9hRT#¢[ ©ž<‰,, ×¹@±¯|Ö#šÝ&ÑZ£uÛa´Ïÿ”fZÊõe¡+¼ ŽÑKS9kZ¾…Ñ"ëOe±Ѕ뿜MÕÖIöL¼YwP.t€Q’µù»Î3H^L”VÓfÍ,£E+v™ò‘QÝdüƒoª†iþÊìQÌ|´ŠNý¹»Þ×n²2¢Y wcç‹,d-åÚúØÉýIÂö¿ÖpB쵦I> ŽÛnrØ•w1cc4¡`£ëU¢=.xÛ~—F7oŽ)·¥îÞdá^’ûY$æ}è‰ÕÕŠwëàà‚u^‹®Xj§Y1¶øhœÒÉó:À׌ äú܈DI3«éï›:oÈ­—D”žœÀ,‹]ÑË—Ô›ïî¾ '¬Z0ƒ[6Z@8jÑo©]Dlõ¡ š©DN"‰¦§Sñ™›ü–“õÕ•!j%æpÉ©ºÉÑCK¦9ãÿoÞÄõ€ÆŸ.w(¢áÿ6¬SÛLM¹xæ„ýñ6dæ¯ËW—·ë“‡9ÜÊÓKí×Gü'[†^&†6ÂUJ °ból"^e,Ž/&n{—u¡«:pX‘¶ºøà6ÑÎ×ì¸bq %hìy=áµ2 ª@Ëý5^X"CTÉ•Ug”ê´oàqøC¢‰üRP=ǃgŠñ´ª`Ë,^ò+PCrFNñ¥p˜è¿È¥NÝGSqùà{`§òƒœ2ä<ôW7;B÷Âàö‚ôÿ®:ƒ%; Ç„usνPŠ ìzÿû"ºâÐçî–¬rG… û+Àbr”äÃìò-†e-IZJDñÍf©uÄXò̫ͽ„×Û¬ßYg’šs[âÛ—Ùm'S> S" ÌwüêŸCJ#覇Í8Àéj•,ŽeµO/ͳ8¾Ðè†CÕ 2,w ^êlõ ‹3„ÖÐEÍw3ÿ0ªÔzÝú57zøӈƕâ±v—SÇ’mûr\¦~ÖŸ­‚—ÖíGÀ&ÑÍ×^£´ÝNôyˆ £²š„¥Jra"Ük¸çØ€V¿7€Š{N§GŒÜo ’Œ|ÁÔ6yü7•áó4»€ÏÏ”ðoòqy=S^-P·éªúØ´Ù,Òð¦Kûn6ߎ] Q(²ì‚Aÿ Fv¯×'q}WO ×€Íof_2¨ÑÎÂD‡pû…\¸%”jwºýiÔ „›\½×ì‡É¹Ÿ6áZêX¸·½ùù³ãÚÍK Š_"ꦡNá*ζW‡~š‚§¯š%÷e8ªëm؇LXÊÐOŒuÒƒstB˜VK·Ü„Ì£Z«À×.‰d¥þŒZ,òAV'Ávi .ôÕ¸îÆ“0(ÙR+lÕèÕAšã£9™Ý_ú ·ó°åô6×ù€z%ؽFeÕ7[œ%5e‡p¡Œ õÏ:G›Þ×uú2F B¬ê ?cœGÞ‡¬.‘Ö’ñB vX¤àý°¸ «e5áЃJžD¼Cm”ë!ú·¨GÂìs‡(јµ}Ø$kyXÏ>üÄà},™WÖZœ®âÛÔ ¾5ï+ºäšó-q€“x¦MÚþF‹öúŒÛ2nëý@ÈyXå(Z½Ðj*Ì­µÜéÓ"U”º~™^ ‘Nw}­VE†×†2J 2~¤Ä4–_M·½J@¥ÖÈ æ5.©¾izˆ†•ÿžº„²¶ˆ=6>¥ —ÝãJlTPªû,²NGÚY‘<¤Õ¿4‘$ðrˆà›šCt©ß—ç\NŠÊC±e —x?¶jxq•ÕCß¶ÄfAnˆ[¾oé÷ÒR­ŠRJ°ö®²ÚIl-6O”'4Æœ{ÌÑ*i$ H$ õäâ ©ô=Oå!ñ‹t Nêž—ÎÉ=°w|’׫»Ã1{èbe(ã˜:† & üœSî"×e„°F¹æõß…˜ëG˜ZÒlàR”Æÿy]„Ì^º.]‹)‰*Z JýïRŸ „'Žö{úŠT% $ÚI•-î­BºÄÿ1[õõÊ]ð\ÃW§Y·#ƒ2_±ß*A1¬—g%Ñò’ú_ÒÊ?Bw‡„ÚÞ‘¿Ô€¿_¾ö΂/0ÈÛË9Q…²‘i¹JOH½9Ú± hé4^ ðžâi—ÁÎo(± U=P‘Öp/àXδäì‰k £6LEPU]T{%¬t/“Bnã`6˧åÉÓ„{ DSþÔdHºÚQjýz u™;EnOÚ{d×öêR'iº?BREªÞü›hz! øÀïPˆüí:Dùí6ÚÀ#¢ < ˜pܱoã®yÒŒ$ÉN¤Ôv_YvóÎy…:)Q$G¥ ]AÔc!èåš§ è&ÏÙä4œæàìÐ=r#î%Ç–üN O¨;`¹÷Ü"¡8Œö*§¥Ô”¹ð±âhÝ,XÀfŽ‘»…<Ô½½9U{r“¹ý9D ©Œr¨„4Y!sá>}ð¦ž`,ZÁxî7?m×MGЭç,>ª ›·èpÒÇÁl@¥—þºÏ ·í›l¼\Ÿ~™>1¯óÀèßõãî-;w*“‘ÍC‡’Û>¬îæ´#8Ô|ïøbîQ£åÛ(dé¶FÛ]ßñ^ð.6¾x>!šêLÈÍÇ/År˜ˆå 7‡ÇÛVÊlW@Ëý¸¤w¢Š#Ö¸ˆöóyâ6ÔÌ|£¼oÝŠÓ³Ýâà¬mtŒ~œŠ¸Å€zU¸ ,Úåô€Œ2«Xå5¸™§ú‹Ë‚Úy¯þز±CrX´nJÏEÉ·´Æ‚†B6a©Ó—¿].®²|Ú¯92‹ù‘õ:«iÇiÃg¶ÙC‰õN—[[ðÅÜõýfЧBq‰â¥L¥Ìûôô—k6þ¬õbwqF[yTú©?£§g¾]{ÎÑÓ˜ÙI©¡§£ ö=ôF>¥¸pÏêIº±gæF:ï^ Ž­U—ÒÈ#xo´áoÉ'ˆ*³[´.þ YJád̈â6áÃe³wQ’zTØ×éÞ°¤½¶ä‹_›;åDñ†fö DdU|aÏmLDµDö¦³½_Z/j»qöƒ·`„üåp±9©/âÓwq7Oúö­•µ9›$Ñç7§v·ÑQiÆ rú€Ñü$ºÕÃ+•çÊÖMÕHÇ0ªáõîØ›jôݤ}ÔšlA²b¢1øO&;@¢åš1 lQÒ€Ù#ÐÔ‡Y ƒ×-UƒqÔ¢³}…8Q"<»Æ/@EÖÉÒ3”Û: .’ñ‘æÝxæ{­°›Ñß…_bÛF*@×tPÙp msŒ_*11ë“‹|/è-÷êµoV'iK›(ÖÈM¹‰î(X©*ç*I•ŠôJ.²$HØu°ê0éodTD_c7ù·‘} X ŽO‚>šUµ/™8iïÐ͸ù•„¬BRFä´zc‘¥q|̾PNn1\ß6gÍÜÊ˦ê’óÛ7Vè‹\2yС†‚ŽË+/ 諸ÒóÖøtܧ¥y·L1ÞšWäç©Ù8Ù€Pïã}%x;}­ACN*Õ=žM]Ò€l£zæv`‚AuÕM^¼Aì7¦_ï©Ìˆ/p:J-bRŒ÷*ÌHûz8*%ôVß.r‘VVV $Y0#gh69x–ÿý6jaá  Õk4ô.+žœ1(…V`K˜6H"]â}]ýÿ0†@.veö…ä_ j7yT,äÓ¿_U¨Ca†‹÷~R x¥f:³Bž¶À5HÃAqÎåÕôÄ9 73ÅÕŒ«hÙ øzÛÒ’€7wþ1_°ÓDµ!Wߊ',iëó»©SõN”‰µÂzô“kHÙèK+GÃVœVŸŒüuLOôcåg8Ebî|8ÊKE š©°à³Õè2?{% ššyMN™>X2øî[€ˆZ† ¹òC¹1[2fcc•ܾ¢ e=À—;×ÇÔvqd>²ü]àD„´ÈÆAè‰XÐ[gºÉñFÃp×R63~§9-JÐãË寇¹‰¹í_*wŒë5m†j»¯õoÁŠš+ œg¿ú.0³µ\@Ê)~ÚáÉlyú°D˜¯‡sK'ˆµØC ÂNállíL”`‡Ðÿh{À  ×ËK}?ª¤'T<"ËRe0=1"Ó{ýzxŠi39QÈE}¹Oey&d5€±ÀjôQåw97}öö—úTÏmÎ2ÏyÄd¼¹®Âÿ2 ¦~Ë^èkSzâJÂö_ ‡~G}C¹úä¬}G%fÞ.wwÑ[ÃÌoH­Ça 2éZà?v!̰¨ÿ~{À›zrêï%br;àüö0¨{ &×3=µ˜ªÊê”JÜò©§Àw€\ÉÆûWöÏöþo°©Ç'Þ—cåøÙ´°4O‰Ñ;úŸTΘ ·ì°-Ñ| ؽÀ«Î+zþŒj!7´ÁŸ§GíˆÜ…q¼ý=iþÏ€¶Kb‘ÔÃÔ9%™€ž,VD+ÎI>t©¯XI79ÆnM±ý¼Ó t¡6ª~[¤v¸Ïö¡Nø~D.EŠòYwȇmØüšÑ¸¦ÉiÁ%° í–†A #Þ«‚E]×dÖÄW˜ªb –GX~nq.æ°[®B~Igá´ë50™LMOôõFHÐÑTÖpQ,Ä…O(II~ÅA¯d°ÕŸt‡üþXÇ£GÀù¾>FÐ zÚßojoFùê»Ðñ6PcTkH.‡ëÕýÕr1±`,ÑÖÁYè@«^k$é˜Î`t¡é¥o[ÓtTi­O[R}ÄÊÁæÁ©#àôêÅç#ô,{:Úm=á(FuZžb8‡$+%7ÅC°EM»û*©Aè‚q:«4ÌŽÌz¤ûK¶(ØalùÎt$RU¹Š ê¿^<î¿* ŠÈË4œÛÁ €ÝÏSíªg#¦Dó7«ölPO'@‚=å¢{ãPrº™þÞž.F_Y’hšyØÏº t‰$×&³g7Ù/$ åÞ¢ëŒÇ¼ò¤úDe§•í˜,5wÄw4H¼›• -¦DfZ¡Ì Á0Ùì’„ŒÚYõñµDùdÿ£<8ïéˆà«—Ž¢X«íý(2àe›Îrã?z*KËqì5{Á[`œ>7V|×±¡gðqÛø=ü‰1ë%KB¯ù!W}M9ÚÉ.38Â]ƒÇ‹‡ ËSÔ¯W©•Ù^l©Î4ê4¦‹M5©3<¤{F†øLû]FáÉL„ì‰!urñ§o¨Š÷qñºÛJ4µ@4Çßš9Šm. ¸h¤“Ä¥UÆc66¿|7,”#ÂüI¼þ¦¦ŠEŽ!QVK©wr° ÷½{Ë4×ß@‰Ãp³»%™xÇ¡<:ÈRœÿ$êËßÛÍ<·¹Àï|DC­]d­„ †f] –t2Ζ¬´—¨–†to¸ÿaR\`¶?w4Ę‹r€$L)§1mõwaÖxJ‡|¶΢Ûã­c¨ìoÀvÀu(à®<)—5ãXµà¼Q-”æ8ÎÀÀ ü*i<ªë ÙV±J„ûƒ°áÍ!ò3›K-Þ>vS”~©y«Ÿñ²$=ó<ß;ÿÛD H8G¡gß8"jjçm3‘{– ÿŽ®È­tÞCžÞ€ü€zzù­’9P‘˜ÕÝ'qj³™*Þ®ìöc£í¾[Jòåe—/ôš(MWÏ]+e­Æ§a‰•¹Û¼@n‚Áú0LXèð+h†ÍÙ­[Ñã—6¡ßÝ=rk¤†!)uÌ r«ëÝF.<÷!Ç»&œÒÀp×5JX°n¹“”S§›ùÙ‰Fþþ^hs à<ƒè³¶YŒ4Ò}Ó‘G?’:þ^%Ÿ(P­,>æ *ÝbÁ˜=÷Z®òp¤Ä•¤&©2ÙèXŽÝšõD/` ©,Åÿ¯Åÿ)¢0‡£§|Uã+OÙò *eŒLƒ2%ü¿Ê\ÛLÔ–ªÊ§FHI‰Ä¥4… Zµ5©ìPBʉM ä—Þ& hQC§H^*$µXaü­Oß ¹CŒ¤ùω•}ˆ÷«´¬„˜ﻉ’aåBøX‚”A6ýéêÌÅóß^ôËcË}îr“› ¢ên+ØîOÔˆJxÝåcJ{ŒOÙv”ÝvsC°8Gˆ[/P#ó6iMcw@…'ò]KÏbS 2Ë9}úð¬äÇ[u9”}ˆ"dB¦¾ð²Cþ踅 Ï%*‚ ¦¿÷TJà oÖUyí0ŒO=’*Â?rÈôÑÕÖùbßc’Y·ÒÉñÙj\¶ûêØw.¿:úe¦0=—xÕÇã̪ÖîÝ¿(´‡Q\&ú~ùŠšd}Bª°EBQ‚}Þò·Ì18J÷³—#‡7ÚN€ å¡6r”§§`ÛåQæm/—ið#ºþhhAq%ˆWÞÜDYZ+ry VãgÆÌotÁ¶ÑóÎAÎasÈ,¿Î>4¬æ…÷¦ŸvE42ùuì‡ìÍrËDÔˆd³Å#N%¨O8…ˆÎ4^‡`i=}²À†_3–È‹"ª€¢÷SM m±všç±häðÜÅ]ê> #ä>‡M=jÿZñ?v£65t÷Ú[Ÿjìw ”aN«††:²ÇÁŸJHªqùñH}õ0bšr †Õ£°ÓVø§óü«Å·w‹_)ž¹¢‚žgfÒ$¤,¹"?ÞÉÕxý”X âŠýu‚´U‘59oiÖâ %J’çEyŸg“7ŸÀ½ l\ góô°“]º9¨·ô›ç×"(0Ř­ËÒàïj¸ã©¡ñ†ªêöŠ{çlJ¸üÿ_ˆÝ.]Èý®¹Zq¥(ÌLF™ˆg“,¸H<1\¬pÃîõY·[F!8_€³7&E¯iC‰úÄÐzh‡úVž ǸxRí›ý-YÈ'еÏîDÄ|sÝ$û ÔT}“_ü4Š:/ 0®Ç ´óÞÖ&AX¸Ï¯PJâÊ"Óø¬¤Ù}íºz2п“óºÍÙü¤_õBüjÛ 2¿·¼Í-‰gL"$1]åÇ xÖHHQÖÒw‹`\ãÂkr¬—wÆ]Ê5×B‰XÎÙ‚foFÊßžtëÄ-ŒëùµC?ÉlUä¢O‡—/àÃ>.â%˜N罚7Á„eMªwÐ01)NËØ‚ŽeÅót—žœ‘¿7xãAhå—ËêÃÛ@>\p ñt †a—¿î©…™öÆ,‰*]DÊœÏ㙲–Kœº‡c›ä2‡’vrëÝJ]Äë I:«äíPv”'L¦ê£Ñù¨•\E=­/6Q!Ê(/ƒ_@Ð]ÐI€æ7õkÖÌžÚüié 3oê"úÜ/É}´¨|n¢Ú·sõ\ wä6Š~‰¦dYä’ŸîANëþlLXvÓÐ& M•E®mýÖ@²©aᜌ361ãlÝQ8…mq¾×¢ÃöèhÕö$C¶ˆJ0ùÌåŠ`Ñn²=S5”`}©¸£j©.OÐbtVÕ‚lrá‡øm{•P<#{þót­ß7Ù¥Â8§½ÌWd›±ºè»ý·à±ûŠô/ziØ|1<ļ®×Ç4´8*"•¨?ôõé:œù@îäb¼¤ÎŽÎæm‘ÊìdhKu%¾qJÿ`@*Ôü&ùò"7vŸxd–êü€ ¢D›8îÆ €–€Ýí$^ŽÓA¤¶3:ïËXŸV wƒô‰}Œh»ÇbÐò$¦Ó;,§ë° œa¿tèÚAŠÓ<ôϽ¢üŸ½J9(•âë~HyßHЍepb"†T–«ñmXw)[¹*û{óÆBç 9õœQÂf–Ò8âû>1×p%Ü¿BéØÊøKÿFÌ“ƒ«X<•KŽr5­¹" ÉùÒ hv§õô‹¥#¤ôçMÛCURÅ’]6<¸Øvb4ŒV~V™ ©¢íû$9WF«ƒÊ?²6;› Ò5x~™j=ec:ÜNƒôÀ‹w ºv3þ7H5ÅÁ?gÌ] (¤jìjû¢K}Ý#§¤™vD¬Ë#ïð¦·J¼ ;È¡;Y8¼ó'²[Êu.@+t‚Uìûu9Ò9fÞˆ’¤ôd·EåÖÀ$°†7B„jDzªv„ ¤ÿÚ?Cd+û‹mwÒ-¤ÔìÀ­‰6ÜÂ>õ Uu¹£—OTŽ¡“Kg>8pNY´údñ_¾Ç¤’µfÃê’UД3A«däÕ2è 9d)SH.Á*;ëí«dIœ}–M ö="*_Ë3”1xà†¢kÇÓÙ ]±û1Œ·Ž\àßûÒðõµ¿ü_¶D­\2uéÚÚû߼ЅäÆËLmó¾]Z4;y$MÆ´fÖ•ÈÚºg»¦9ª@bõß³t…ïJêhö¾«Y;ÅA¸-‡÷’Î8¯ ¡ËT(=:AhëF•»æ©xU~ê‚mò£œ¬~Õ0.“’®ôd¡’k÷ ÀÁ,-Û6Esü+<:n¡™9 K@·ëÖ÷·>s»å{»ä`mu|ÕüÜ—&ß&ñv.àæ˜r5?,xÙª¼wÓ üèl¥°²W¹=ƒøi¾ÍîS #ýæÃ) /$‰Á$Mä&CªFþ%A¯r ‹½ôâÈ@)=\ù ã±ñU–Xóö‡6äCÿœš°ò· žRž*æ ÇàÁ,ÛSaáè.°&†Ö y]Q.°ì)t.!Ô'¼ŽÓª¢¨õN†íGCF- ÑhöA{4¿:sÜÝZd’ÖFœ€£†æ°Ç9¼JÐÓ¨˜3þÛè·ÍŠ%2 ?éÓß=ù)¨öÈOƒðĨÑlZ #âknGÉKh”OõÓ#Í%ÄðøW¶[’XÒ!Ñ¿ÖwE¸ýIÎlNÙ [;)“€û³güN½G=BcûøÐWÅ»Œ 4º\Í¥?€„'ä|h°`Cš6på0ÀOv¡^ÞØ” *%±š6nF{åÓÆ9XvuLøøUéj³’þ]øÇ¶G¡z£Aú0Ïcð4(ŒŠ^n˜¨ªwèÿgmð•ÒD¡7ëyP&ë"CÌçH$ nU‚þ<¬Ÿá¥¨ÆÉ¯*€Ç‹—¸ÇQ7  ÛFÍÝî½ðóîÆêÙ”'Ïÿ^Åc?ãöiJÖ V©ÔŸV‡+Î@b·÷´]1ë1ÊËp„•å¾ÍHµá½¬×®Ì„‹[V»f?ÙÁç‰å½GpÒ<ä¶_xL,Êùwë/|F.BAàÙQ ° ¼çΔ?¾î‹^h¹2£ÞX…^º1¨Fó8â“bVó0-s$ ºGrþm¯ãóévbK‡~¤v„GÈ ç꡾AH€æ^ÿˆªKÖ‡ö’‘Þ;q‡µƒÀu¾ÑÖa¼â]ÕÊ`Ö‹s+v¼>­•íójìÞ}óë"õ´Ã;‹%.5¤wx©Î<äÅ8Yq|¾_Û[jÁÆ³Þ Ps™°vßXL…A1¨CÉ>N9=1¶j¬;N{Ý+n…ä¡¿ŸLciô×m–òBr4ˆ¹´?Ó«¼e·o…¡e’:†rþäþ*^t®›ïŒÖ­,ÀÛþ­çêñNÚ‘·G_wPö‘l °ü ªWï/~'qõÐK ‰Ç‚§–>ûbV+níòæ^%9Ö`‹Œð9¹±#rû•Žà“æ°óŽ[ÎN^ﯧËë„…Ò=՞ݾEFÃ< ×mœ¬Á³ËÒ>s˜¬q[ûú#³'m!y’j´¦œàkbت³X7Vq‰Û 'ÊSŸŽöxêY?¶¥Úµi9GóELòÜÖ¢$þ™ÆÂDû®1µQ}@ÆTŸÃôœ‰¤Ž.|ø¦hLÛgúÉì¯ÙRÎ0VÌá¿ÊîÈ ½ÕâÜú¨Õ¿H§´"<í‹5g§÷IÀðÙÁ«™ë"Û¶¨ô zû¥ yBaŒ'Þù!XB€Lío_ßA“~ÅÉÛxó´ëž§’É}éóº5Ž»Þ)˜Uý~á@êX×@Ã_ÒÆ`È€Éú‚â<7;Z›ŸÒ S˜7Á{Ǿ Ú3-¦ó–ögKïÛˆh: ¥åIyHü>sµ;ý>tq$çn4æ¨LQ!BÛ7W8¤Y³ Ø<ÚÝeLeü¶„ÐnvpÝ D/íün1ìþë½±d!lLgøÂÌ#Ÿ“®! MG óGôÈ|°€¨7fH³‰Ñ—¾ ˜`IÛLe‰þXVß™}wôýÚl&9%½‡ù?/°çÄ ÄÖœNZ¥€:s!ã_ ¾uãsœHƲʶuðèÑXÖÈ›Q°—øˆùžvÇ×¾^ º¦ÒØ#oœ¼xAœäKÚ>ã“Ïr:‡m¹ð(‡òþaø–…K¢0’S`[„‚+â²Af]¢UéÓJ‹e‹_ÆV?IyMáñÝæä"—kœ³AS ‘–X|þÕ€ød2–‘ã™Tþkæ]ÐbbÇ8žqí"ýÕ4©ˆ{'ábÒ”ŒgîSxgég\³Kãù‡ðpž³²ýØ~r×;Ò¬j5ÿ¶ÁQôÂN÷¶ÕZþs—¬Æ~ÁÉq'ȽÎzþC·féª'Œcc‚ëGziðÄAÝÊ+À`$d}Ú%nuGå¦xõ<•Ëä¤;¹àè¿îC‘b^p$G—¬5ty$À&÷=ésd•LMuG³~.nƒJÕñ¿àÉŠ…«F} <¢±(ÆH:¨0‹ŒMÙ’ãByÕvÿî@¿z¸ÌgÈb•£ôØ43ž ½ðÓÀ+¹Åvu:íŒÒ©3—‰nFH Ư'­žÊ_ÚªpÞ°8Âç©k°Ã ‘½T½³°S;Öb™*[ƒD¥Û¡OÚm—› z¼qzÂ)ï½¹t{>N2ã¶áAØ]Tw…<*!Ž”Ð=éf‰‡ì?%`à½ÄI¾êé÷ûß>b„Ô|BKF4ÿ‘ÀW«?Nà‚L“<:¾Q ½Ü~½u`M–V(à]“>øÙ$TQ÷þ-çm#‰ÌÝîžµ1q?ï’ðæDz?º!ìùKì±µ„¡²Læ÷TBŠ”J:·Þ1^«…‘«¦ó•LÀaDç£$Ñ¢»nû{”­9ðý´wЫ•¶$H‘ uje›šµïÂå˜,Â~½R @q|™çÊæF_=UÚ¯°ç?äg”Cp ØÊ¬  =:«N·àÓÓ½¿Œ0d!á\ÚùYÂ8h>jÙ §hwt„ñ ]Ó4[ À£J¦ójÉÑuÚNweNÇ(? z'•Ï#(æª'Ü.H™ÉàÑ6X’-ú`鹃:&ÛÔÓÖÂŽ$#uU,W• ¾º0miyb^¸Ì/*”ïZžKÞ¢‰[yéUâøi’`~ñ_va ÁWYâv¡<#&c’ïlàQQ"özy4$,-oÌ·gH†­qR2D´ ÄŠ¼OQƒ¦f"-3€» Ê¤"û¬³|TǤÖÌôÎnËe‰–÷ß|µ`‰u¼óoW±qy÷åÝf.:¯üBlÉÀ Eëuœ ¾ (P{ó«[æ0£ÙµÙ"ˆŸOÔšö~-éü24©ÆÆæ…V£ðÌÎ.¦öã"ê_ %^~yA­Nd5w(>zwN Ýï9él+'„ßW40^½ÔœB9HWõˆïSRÚU7>oŸ‘ö‰÷fzbg[…\ºý5´;øç»;¨#+2¦¼ºçŸåpz¡ÝÖÓÚû†#7ê8Lïñ¸¾¢: PÎñ;òÿ‰<˜Üû>öÐK¬ƒÑ›³V.·wǫշŸDý•‹¡³÷oš7ίþÿz{Xù’ÚóJ bí](b-Ç_U!à,œÙ´Ñþaœ²î<9 =Íwæ{j»z"Öþ ý›Ϊ.ƒæÄ1€!H€êDp’¨p ¿µé‰×¾"âÂ}ó%©˜HSº -“£ãÛʔѵ¤˜gb8o“Ÿûÿ5«²JxT ÿ$Ü1;2Û2u¼¤aÄö6ûVØìîÜ—dz£´Œñšjt6ð•!w‰ÝO\Øñ(ºNÊRä£ÛoŲ·´6ŠÞê½'S¥ô–´¸‚vGƒQÁ¶ƒQŒ ¼m ®$x¢:ݧÝzÂ{¶{DÀÑrÄíSœ3y/ùÁzQÑkC±9 Óÿ)S[·K-*ÞT|f2º·W—ÛÍSÂ…cå^;ŸTjý=¢#íRœ½-Yä,M<õßOÝŸTÞ°.’¹™•¥°ÐɤvFý냔C¾x*PªåLßr RH ;sÂ$Ê¢XâsO(´( ‘ßfŒÜzÝO²ŽAðÉJÚ€¡þ)KÑUU3·\4°Àcä‡CÆ€˜^¾ÛdâqÆyNû·óƒ)8m#ØmÇõP9É1›Öì…ÎÏGeg…}.ÃK ÞÝžüü!ÏW¨–.çůðÎHê(ªT²×!àÜ‚6è þh¦Î¢£oM8%AëÂ_Ø)j¶œÓ‰Ì9iŸ6E3œ|f:Ú¼¦™¦± Çf©ÝüŒX~R:VNˆ»hN­£†O”6‚ß«Ï ió´TÒýÏVÃD:Îd Úy ´^îîÞb¡ì ð¶[(õ¥EïO#0qÖªÀC²³&©¹¬Ø.íû™â¿ 2¦Y3g5‰äÎ(*ŠüOp#Õ+“V8µ^©çâ/LíóìÓc(nf*ô£ªãlCÐìß#ßJÉ"õEG€f]YæçÇ4JèSÛ"2¸ì”þíE&M0óà`Ó+”íä žÒî·ƒ ú<>Ÿ(á±T¦ÝûœÔ¢u&«Éð1jv$9~†‰pnÁ—["†dX¼®)—º]vp´Ûd-ÁWðI(ÏüÔ®»fÒ”–äA¤k}Ç#ääv罯 uÝÃ1zGþJ\#’d;žV°{UijØeÎV †S¦ŽZ%ù©ËDþtwHADi8±³UÙ°®å¢¶’qŠaÃÏ›ÎXÇÊ›0Â%äxëªi»}5Ü6_& 2éìCm‘q‡ƒ'ØÀÇ›¾ZT‘M*:]:¬tO ¦³!næ Í1”½….RÀÆõd°r˜±üæ6¬÷_ Y¥>:“p¼9Bó»‹I¥u£¼ÊÚDÐõ ‡•¤¬ ºm/®´ $ËCpÞö®p õÕÿý+¨ä·¾M´FlÎz9ð¨jJLjÜy…( #S¸^£ .ð–;@Ð6:›“üHp:€^ò®¯‚/Š®.XÚg"4–(ÈßöSû?K &çÀ0lÈâá›d˜Š¡Ç‚ƒíú&Ò€!ˆËkö™?YMvû½áj„÷.@®›òÉRI¢Wuò!¤”­Ä`»Í©  „c¶¾³´áòód‚¿EH·c‹Ó&´•x ‹ûÀŠØ+³êivšŽðþ9¿çÙç%l{¸ŽH,GÓ“´x«¡ÏYÉ&gÛ¯ÿU õ©?žmáš*oÖ™ùÔ… Ï2Hu8—‡{ãAë7g6V$ñͼ)`ý¬(ÅZeîxŽm€Íq£r*",§>rÿ+®ÚZ®ï–ïljÔp“¨ÞìmM㺧Êë”ýÀ-º«PRÜõ@¹Ðʶ_-ÆmæT¦6¡z ˜þZòÛÒš<ˆócB)Ó]C­Q´.EFžwð#@øÛs¥çGñ,Uº˜Z¾\Ê#bëniusÖ"x£ó P¥¹7}û ðÖÐæ“_¶E &(ÜÒ$CdôIŒ·¿$ Ó@ÝN»iÿ†zƒ.°²â4瓟q.éÙ„=­îi|Œg¿5»×¾³¬èK2w#Wî­Ò+…°,¹cŒA?æÔˆÞóŒÑù/#Ã×Á(ô¬1/@­ ñIË_y2Árõ’Oœb ¼<—{®„E›Pã]†“þõTàV™[càvT¿ë"t9T¦”ҪĚf¤àIë¶gÒëH¿Ö¹=-d2jÍ[íÕžñ„ªP7Ek ¤ÆYñ²|nÑÑ%ÿÂÁ0Æ7n[zq9rä<ÿ¶(—‡ÄÑBÑÛÚ;•#½”ac0Üsb}6ÛÙˆ5ÇÕ€¥ÓöÆϧ~øÄUÇB›Š~^:¡Óss"¦½±î<êS¦´ mtrðWhš¨/ð]Ùèä‚”_I5Óë €uj^R_Lúéwl´5[ìb≮ÁLü*°ÿÖ}›1ÅÖl•#ÓÉ®A*·!S®çÆ´ãYªNz‰ ‹XŬNº} 6ùœLtKò k<-:úæØãn;v„½ÌÅ\þ1¹ñ’¥•.úÕŽRqy¨'´r|‚€d­ ¯åq‹–m4Td§9­Q6/<©”nÂø„lŽÛa§ÜÀ4Ã^ÕB+»+h¶o¶ xò×áï¦EÇ’u…·A†È.²<zpp?x·“ˆÄàòÃí²}C!_²nµ,äŒùô‘.Ùºü)‹¢bËÒ[?•T¼¹Ü°9–­T1\Ï'ºÀî}·[ Š_Ó€ k¡•C>SïX!”¨mHâenõp±&aÈ_þe‹«¸á³]I ¤ 5a¸Þ•öÓYžŸ«â×HŽ0^±H£_P)fãBʵ$³œkÞ0û+{üíù$Ý9 ÂLé¯Ò¶MŒêmºu}øCª®È¾ £>3%T^E&ÖavÖt¿Ã™ÝlÿˆmÊÄÛ«Ôcêý÷?æAu_²ÚºIoÛL…èí_vš·ö¾3œ<¦·ÚË)ÿ¨•ï7U=Ög¡6¶Œ#.“sh´i¿‚òø"±rÐë=$–úÊutTY*«ç#ê'Ø%º¬QGvè>мQ›%&mÃɸî¸à  ‘þU’vFOAqô·›Hümí/W»Œ´D(n­øÛÍ_Y سõe^â!_ü,ß¼*O…º>øHq¹@[dÕrì¡ò¦2º«Z‹rýþ'éÊŸt?+ÈÐÌPUjD¦,LlÜdc%Ç€£-«^T‚ü>76ÂïT0¥›LK@”>ÎÜ‚Ÿ!6d~!¥‹‹¢de¦>ë¢e©*ÊY@™Ðk¹LM:ëšõ:€¹zê¢5 ìãi6aUmw±“Ðû–•c=f>zFå+ÉÑeÉ­J ª§¦:߆myÖ}­׈­bÆø`Ë;ËERãýûÐþµ‹ñK2q†rŒÌŽïC_f£,‹¯UU¡îÙ/³Í6+Õ³ïèßÊÁש¶$lá"°Ž{Æe¸,nê‹_Tšõ]3$&Ú-/ˆËùjÇÈÛxi©Óù«Z547 ¹‘}+ *Ñ$ åÙ0B㛟ºÿ]¼¹X®[F5]á…Xo‰ yýé}ƒÖ7`RÂmjá#æzâ=©¨Ž´}=üm¦^¨@2Þjom+#*7)o»%V1š±ÿæü6çcݧÆKuuO@0¥„ª4©êÇZ+/Zõ!Ð+ÖŠeÒì0ʆ¶Pß ·=”©œOp@ÜÁp2wåYBIÇ0/–š9 ¶ÛiÓÕ?ø°a*€ÿûŽêsÐV®|v¢põ§Ñ]{ Tm…Òeæ«==™Z7K¦íG^Ðz;®ÝŠ?¥ÚÇ†ð¼ Æ.ǬG–R¡n“†%tIŒ¾B㶮ݎ¨ø Ȥé鯱4–÷·å_Éb¡‚¬I盈„ÏûÙáÛÏâsgdÉòÅìSyŸ,Q¡‘ñYÕ°°™Œ-xHÛ£ÿÚøúñ“jQí“EöÎCª¹}Сu"ÇC~wÍDËw®õíñK#6\ÉxÍc-H?½Ùø²Õ,[ÿX$j¶¾+vm½ßg‰\XmH½_1jù×™*ìä 6ˆŽoƒÂ†ü È_£|ÝÙìCOiZìÒñP†Ã+gÎ1`!}¶ªFÛOâñ„Ý‘¯FÙÊp/üÖq#S“¤E:±Uô€/RPn.)ç,5ñ Ÿ>î„–Å´6ÌZÜ#d¢h‚éh ‹²Ð-À@ü¹ë¨öjŒöº›¨%j3ï;ê ‹©6NÜšÌáå¼,­Šð­›Òó“Æ<€©G.Z ¬…4§’M ;»šƒ»RG˜ølªŠº´‹ûR8KØQ/V^ÿö©÷‡x% tq ÍìÅÇÎR =ϯN!yïÒ­e.ÿ&IᎇRc[yVxìõ,+Š*ów]/æÑM¯·.;б'ÊQºs½r:eãêÆÇ¢ÏEÓ0x"ìhùh³ ]a º“Î ÍØ:s·IåâÜ…ü‚œÆ›ÒstïÛÅÞÑ.áÁNºòîÉ ä£­Ä|ðfÈùuäDPYtCI²m¸¯ÆôRÜq.µ°Ò°ßß6–D<è¨QYád'8]ÌïKL9Ÿ[0XÈrÌ%:æ€à0W–JÞ. Ë{¡ËS‹è¾>ºOÔ„sÓRØ’f#ü; ïÃr¬ß‚ñSdË1#µÜýaHZ‚7p>GŸ_EÑÒ)ÄÔYu?+’é%³Úsï-Î¥¼¼AS›LèU…㌯å82¼3kÑ'¢ï˜û{2½ç”Í×KFWÜcø£m–âÞÝtB `Ùô`)F@sðÓ·Ãî·éÖ»ò©…íûÀF,YSÝÂbÂf)Æ«2›½â>àJk ˜×'†ÃºvÕm£Û/ ï1½j`¯#Êýp„æ³J‰8.à î:«ƒ6ݤÚÌv¼=iW;¿DÞ¦B­Àûg5 î…}rýzW;´Jİ5Ý 94TËDľMÆå?êg$PlÏi`EÌ‘›bä9{§½JŠIZ¸¤„([·ÍÈ`9¢ªID¢VÆ]!ÖS+kâŠÞ­Ÿ„j·‡€¸özyn»“žÿj; ÇèY†/"Œl+Ϊ/Î}Pö뀾‘HΤ.!\·Û½$n¦çò @Á*i¥ç‚Uÿeжt×}h–éAõõ&1‘ÿ†d†ó‡!P(1·D” ÷ijñ®¾¢Â!}éi6Åf`ËÝgð“w5ã³V#Ä{‡wsŽg®z1º€%3ÉY£¯uB’%_PÒžæÀpާ\rçÐÅóÝè_p€X!‰hÉœ&$ñÀ-xb#N»;“„g¢ã¡>ùH¨8‘£`M뺴YrgJÓ²ïot¨n˜§* ï€d¦O®«ýBÃqv¶æùã‰áéˆÑôD.ò« ¢žÞó½?xË+Ï #F¦4ïÝ;3ZŠjMó\xaÿµË_ûÒÆU_¤UÁmØŒ DUæoØCT 3°ÇFr—FåÎTB_¦N‘ÿfP'›%ß”®|¢ƒïë+þ;ú¡‚*ÙDO'+cЧK³§¿$'CUÿ ¯g3¥˜³™}. %¶Áïj}Mg{Zmá5±ƒR,Ý$\–åþ«½ÛÚoÃNvÑ,3Z°ùå8ó0 ¨ä„ð³lq)eWÔ©ºÇI´z¬LI™(úb@¹ªþÊ¢ªªnÔöm¬Ù”µáÒ©fÔ½8Ø«º­Aª6Aý8ß Ý#± ÈVB)ÌKÔ£jgÙ”F£Þ“è§t~£A)­N8ù½a6ŒJ0šË™N< Ð b¹MON… ©KÏj·R*qgéYÎD›ÆHYJxƒ"G‚1WŽŒ eoí¦ìAÿ‘&™¢HM´ó‹ið›ºiS:æÈiÉHËWÊŠ¥=«Ê¯ux|ãpÀŤ»#¿w( -FêÄÔAä ÕVÙN±ÞA&ÌOøq©Îxƒù5* v”!7Xûç7ÒE<ûwA¸ïL™N183à @Ö>ûª ÂKuc-©¨—›Ÿ¥a¾Y–¼t?üQ|IGv+:¯©Øÿ_ýL™äÏÇ;@#AþËå{0§Â„‘aÁ*ÒÿÄ/åBW·àI¶õwQ;àbvxp„ÉlÊ"ñãg¿¥5DYbÉÚ/¢­Æ1lžð²$ÁxMQaE»ï¿Úlõn#§„ù„|!dÿ ˜îÎàl}Äó&¯t´³Gs‰XÞîlNbYâDënÛBu,jâB¡)â&dÊlÉ?•”ž@? Â7qot$“Ä·“Þ™âQpÓFJ}6ÓÈð¾™ÀLÓ¿Ç+²TÝ´^¿RíX¢Z‰ ß-gx÷f-öažžå„¿Lh=±¦Å¾VŒWˆ²”Xg¤Ð<cfÏŠäìrR0ÝŸû0¯g¿Fe¶F†Zrtïcw{eÕ„Wý-‘ZÅexAdRš#0Cã K=AàÇ$¨Òg*ØR/ O[ËÑ .ô ŸF ™ßQ%*¤€¬÷P͈«%à¤Y»Ò•Ô¿mô–»ŒD߱š¥:ß-¥Ù¤‰4á#²Í…•œxGlÕ…|MÍ>ãt±rE7‚[‡bšŽä¤æ5ON ’:Ex^iúº(ý­|v}i÷ÃA íÔ¬´,µëWH!ÅXãktÜ*x»nA òå7\g™}KÇÊĺ™˜ûíus0 A)«‡„ d€Û[D'Sylq›Ã¬Øh“ë«üeq‡IÖ#ƒ]¾ÃØßã#/?›b¿ñV×Pl~ÔŸ\x…'-ȱQ>æÁqQRãâÐ Æ~Í7Ü˱ÑküzL ½ €÷§=Éq[ Ü3Z­ª¸Ýwûרé)ø Á}ìäÕbÑÉ›Ó…Ô " õ,NÏ{„³Š—1ñeCNwœ½a€EK\ðIË£J„ì[lüLH.áå¥=;Špä èù¸†(ú¼Z…¯0?ÎõIËSš‚jV¦6½Éœå4ˆ–;y6Èè5ü=e\Gë§ì>¼>CÍ“õ€‰qîI+‡Lõû’ßr™}™1¹Ÿ%ÿaðê ½_=†?"]`ÑUb¥7«Q“½dü4Ô*Üyðósìÿî-’·c²—Z|hùŸºJm·KªlMihg•7pÖþЃ±tAe­¥rm’²á´/A¢_eÁs' êm2~I P*zbGA&mÎ@`ôé© æH¿HþÀ>;ö©Ti v[¢Ð •SWGŠuà g>®1Á“‚LkG!H¶bÆÎr¼4/ëmŒö #‰|ÛázBª×ÅËæú@gÄï—8Ws¹ÍŸl”€¨FŽR6 —îN¯€·œ§k×müa8wl€ü´‡2gŠ0jK™ˆ$š¼™´‚C‹êaPWµëçW”øÜqÿ8úÿ«™|²ÕF )Á·e*¸ilrüs¬§øTôSålmƒBåÑ× 牌:9çû³W³)>î]=Ê9²Ÿ-vYWŽT¼œGßÓ×u åÓ׃6ðÅrL‰œ1žµ×³…¥l£â\õµµÿÞ` ñŠm®o”b=êÚÿÕÞ¶\žkrë†Zç|H†¯8¾S–fèÚèdNŸ9º–\ˆªå+ÀâÁ¿=õ#ÃcnÇÌÙ ßþÿ!@H‹/rP–$ÚBy€ÙkqÍíè¾/Ðú¸N_’ƒ$†4Ô¼å¿ .j^¢7݃¦Õå>«žHïžlý?-îùî³u‚(áŽ] …D§x"¢t&T…5´"s¤Ò­(ÜÑììæ—¤ÈÅkIü{Ñ¥3Ý]Vʃ ã GÕ´Íÿ?V3=rU.…Þ ïk?ù|î–°!½ E/@ã àLwRõÅæ—ój¹È”?·ôKz¡3g˺ÝFšubái.ÅòíûcòÖÚ ìbòãôŽ)4¦å”y¹,4èrp‚ˆ´ã%Eª2S€A¾¸ivïvWÝ¢6ùLý*¸‘ ¦x0µ®. FÈ´†>ŒÍݲÃÙÚ 8áÜ–uTÖs‘ïnÀ{bA“ÎCMé†þv¾Õ€\Î9Û^-ÐÔ?×ܼVF*Š„ñeQ4«G\ži^²ß:5ç[7 òßwi¾ i¾ì…>K„ ÿîdŒd<ü¬EkõA\~‚§¹û›'/ b–Ë»;ûˆ¶ ›'òê‹êó‘¨O‹›èsRáÎ%¶®‹bÕÅÎÊ Z;ÏæËTÂÈKQlßIx@gˆœ›8w-ŒµI—®E¦.[¢¯ª-u¬ ocl|©qgMèÞ$š“Z·»ûd¾êÑ`c™¿ëroTmŸË—Oc=–Çj–[XÛ¬Å-b¢o«]ëB4„äÀ;<ÀJ9&¯†:b q‹RFvvÒ†Ø' Œ21 U(°HÒÿ—G="„ÈÔVRõšë>äò‘9½ø¼Ç/­0.tÛ qµ cúwÿzõ/E9w÷ê:f¨p%°‰(»¼„¿&ójc¯ËBYðvrzO ]fº#ìkØ}W}´˜ÒOŒ*HƒýlqÙ%¹~=µ>®€U‰~DÓšè\"öèÕD‰0 jx»X¾‰H¹ÝÙOtŽÍã;Ýéh“;¶Wó‚ßÐ:ü§ûç9Wkýµ¸ã¨ûeŽ–m =Q}28ËûH"À-Ú~#ça&uLÕ‘®ÐÃflOT®)Iz%²$vÖp¹õ‰â‹>©1ŽvuRx^×bfÑ"k!€ô*2(k0mNjþÎV{© næÁßç†|Ѧ¤ˆSÍŠ9¾ÜÞœN‡4Gvséîƒ:³uJ‚0ŸÏˆ+Ø@׆óÍÞTW'Ò  ô̵ Kjäçv[IdßÕz½:¥‘Ë÷sˆÌùµ”„¿è2ç)K1f‘N Dfô4o½›mdMÄQGPGÒÀÀÂ6b³øêlŠf«¢K¢ÝH¶3C¦ÏÚ¬HS•¹ëãÖWu4( í9áSÜç[‚_^qttÔâÐgÙiÜZ/>s]®"E¡vZt ÊÆçiGjFG9*A,$¢·õa¼­©A„„1É©ª*NŒÖçù™å¢{:”Ô,Àg•zBI ?⣫\­$)æìžI&Qï==o«è¼Áy8´/ùÞ!꥖À|¢xüK¼,§ }ÿ¡Ö>DЫH÷é‹? #ɸ…6œ†×惈¢{Œ*ÚÛ FOVœp°8£%M€šO:åàÏÉQQé¼+ZX4ÂßöÉ—‘ÖuÞåú¦4ésàp’%ˆSÖŸ™-$!)j£w•Ÿ_µF'“\߃@´þ^ÉJF t]eåòM̯˜n“Ìc³ÈÂßv °«8™¬ÚÊ­OÊ çƒp¹@Æü¢VäÎV.Áõ÷Ë„5]N D¿»€A·¨Ò€eKv'[ªþ.v•²>ëtI»ý†s˜0^}. Dasùéû=dz%Dæs'Rfe17Ï ×fQZ°@ò}™HS§0E ,wD¥¬ÏÊn™ÁÖ¦óµ±­ŒgÃGi<ß^âO«C™~R¤îÖC´îFζFÎÚj‰&ÎYç#Èû‰›B¶°¿FkGï%xµÔ œˆµÈ¾ÀŽgÕUüw=ùNâzEý—¼Å}fVd ØMš6‚‘ÿN/ÊbKkwqR`m-±Ö¦…Uiðuä4U²…è‰{fÚÚã´$'»¹èÿ¬¦bë9|;]Eï)9O_tÌæqqÉj¡üÅqG ·ì’ÖvÞ‚³ÃgI3–˃1ÈôS!Ëxáê!”XƒÃw ºåÙD ” äVHêŽÀæî‘hù¿’ê`wÊyñÂ<ª×½R?ã‡Pe{ÂU~aëOøèO`µ)ý]ßg9ìVŽô÷?"žÅ‚mÕ”ÔCaì@¥f×E$v]pTŸßárÞÓ¤D怅]‹¼?(þ@S Ûª/9¥öcª†úºF

Ë9ˆ¸TÈY ñ+ó`H1nùàÅ&ùÒøû–Ug-­ž9^®Ùf_n…vÔ›ÿhDH1ØÞxyaVŹ9ËvÆ#¼nGICª6%>Ä”¦Lᄉ©ñ73UR= Ov#‘ötß»GSã\yªvîR¬òIøÔÒw4(#¹ÃÐI£í G¹×±é5B©a—‘ ã‚I^.ˆYp>>á¹ÿž&Î^1>Žš lÝ”4㹆~U;^ʆ÷J¼A­„šÒü™œâžûlô'˜CN¾·ëÓR%qæ‰ÌºžÒ X΄ßHP駋¸§Ãóç­©8,vOQV™}¹üƒßd)[g#6 ’3·þ¯àê8Ý„f^›u5|ØQh‡ecaHóµì7{ZüBóý Ø8)ýq¥—T@e’ ‡ÄB1Wï#lóeåzòêÂpÒÞ 'ÎúºÖ¥Àêò‘ÄÏi<äN—Dõ›¬HUè/‚Cÿf§ÞPÆ×ï€õPõµ®í’Þ®o/º«i—NIAÎý>hÕ_ Õgïî® _o•UZ¬@1†*=‡väQ¢Áð¹<Äu·Ñ­ÿüêV=d u¤¬f”ÃÍÝ%®îU±ùä^šì¼¢} Ðñëst Ã$!vì߉æeŠÜ†ÙªÏ¦5P2n#ÝÎÂCÑØ ‚åv5™É2t_†-V0…Xtƒ˜ÝùkޤíˆAÇEŽ ±;ÖGŸ"Áo7…óQëVõu./ÀXÐIFIþbÂâÎ%˸õÚ2†]šX„€>KÎ-¾AJ`å!˜'Ù·IŽúµ=~xƒèIîtr€L±[2™HÛì¯*YV±w'ˆ@ QÓÈgLIiIJ8GÚå'£d|5 Ú! r󨯳~?U ý•Ÿ é=Ç7J Úø\ Š5”ˆ¾*Iè_A)È¢|=¸šÅ¯ÀYÔÙ è½$1“þ®OMAë¼KÅk>Õ7)aˈ»ÉqYÞ¿fë@¸ Áç"\ؽÙ[ÍŸ6[²¬ç¬téð¥\õÕ¶)¥|Ôy͆—ûÀ"Ë,‚YçžÔ÷Žõ”w¯ÀW07ORò…ph¶4¸ý`]«Ë-F@„“ôûQ®@<¼xO„\>ÓHŸjýUýà0§;xFeCFáÍsžÒlgX¦€7Sž1-|>‰°¤€#„0¥(O†c^CS¿>“2K’f µ‹À©Ä›Z4 H%Æ•Sí«¬ì+ÆS[¼xN𹦷´¶ƒOÕ»¿1öÈpjŽ»j”ÎTެaúG!#ßjaµî!g <…˜Éƒ F#“ª0£j—ÄÌò­mšø•nÒèÏ·©kê¶‹^˜×I™5o¹ÄmTUõwŠ”*ÎFe±ùC{ÌF†ÄÿáôŸìÒOÒfü†Ž|G$‹O]þ‰u%h¤ ÂZÕŸpÑLÜ’Xm¥zñåLbuÏs•¬ò#bÝåº4«—ÌÔzïKïG•!ÎIŤ|éwøÀh`5Ðx²L§4Ã*^ôç4Ë¢ØvkìÜ{=cmRË¢!˜Sd>ó{Í’9ú1Xb¿jˆ¤Ezæô)&MºW x‘¶ôû(ÂHôvLu’Ìœö»=;ANI<™ý«Âú®Þ#=¶‡6­½üÛª …oæîÍeáúÝ„bs,øW½O°Á“CMy¦q ´ŽŽ‹Šxc¶®JsŒ˜F¼?1?l‹¼ƒì  t1~ ~¨AN*~f I â:É¢’ž,([8QH졬ÿÌ Jí5‰Œ¾¸ r) 9’ Éa’wù»³WÊ+žsSFw¼‰˜ì)J³BŸÃš¶ˆrÈÇn|q¦)ºÓeT*ÃJæ™HC[§(<η¯UŒìÂb5i#£%fàf—]$7ü“‹ÁË-r®‹—‡ !qåMÍô–™ÞŒ·–îikìâ ªÐjUÜEºýÕ ò/ O¬˜“¦¦r©~?ÞDr'—(5Ì-×TÏ+0Ìp£îrå'÷j«jУ3„«„¨ôKwXM!.Œ•±‹– 𠧯+ã&Œ®sÏBmlŒ™Æ”nÍEºiq!Q5å¢0L–á ßdÿÈFÄÂ, 4ùS&s’–ՠ󴾈§GUKœO z_çË}W饣»Øfòß<¹†hži»M1’›§ªMù%tÖD‹!%›ÀÄ´^¸e²,\Úu¯z¨Š}*,o  ¼N§žR¯Ù`‡oPÓðæc#ÅøÊŽ ÿ…k¶Fü 2gE†1¹ü¥`¨«iüÝò øGeëF‚s ØÜŒöwu"±gô±/;LذLè!æµÞ&å¹NÐúÈh—1~&q附û@º·´çIî!™&V KqCi® h5¿Æ*¡Ø ë^L5»¾ŒžÍÁ˜Ñ Œd ÂZ:¸ gôAÍ–·z#ë¨+ùrky­‹’ö¾ï£¢ãñ‡ª&ë§·ùö”i°§MQ¹zvNTÔ‡èJŠ€ìqñ(Ö¬Xá*ÄÚÒCl8.œ¨Të ò~Z ¥ß~7®oà6`Ä8Ï^7¤¹ß¤¯w@ 2’ˆÕ]PQ…½„ï@ý%è<꿊³žc„á¸ÇÈž^%—þ9rý›ÈÄÝàÆœïO…±‘òñ…ÌØTäÔqÑÿ±ÿp£>󃞲ÅL:õʇÆQ¿Ç«{žôd¥(')™F``8 3¾#ÁõÇp £æ|;Iyz{ðPeÙ®—Ùjg>6ªEe«RZ=Om¨Aðñ:g½ÔÑöí>.DÎamª'9[–¦ã®è’Æ ]vôÀ_f<ŸóL·Ëc&(ש uPØ‘Lçl‹9L´ 1àg%´Z”ìÍײ*ûµx2îÿl@3°•Ötà @ê=$Ue¬¶¦3¯Ù¾Ú‰“›)Ç-îÇ‹Q°—Ci·‡|³ÚÊûîg&·ô„8ÁtXÐü÷Z#Îݪ¯ou÷6v¦&×À^ú°1z 0ἺVﮨÊäú0¶ßÌ>“›“dtÝX]SôÀá)ËÛÔáfÏ  5ÉyÊS@(B߇aï¸&òÐ)à_ôGˆõh¨¹bLW£¶ï®vãí3e¤Ìe¤788²Œ¤¤D¾ÌCÛÎ-WOÁ²‹4N’ÔTÁ¢²ôc#GL&ƒµ PofÅý.ÆÿâüA-žGXE¨èª®ÏòKzO6Wù Ôé28-ï/KŽÖµ¿ "°Œ š ™l#ÝCêY9V88h›Ï&‚l~tɽI¿»Plç åV%ڵ扺œl­r®ÉwËÆf_pLö|𼻡|ÆEž1*F,ì‡è”Å8·‡ñ+W6kÂ\Î ÕG—ˆ©¡¹bxgh”(vŠ_XÒY#S §GÐÐdñò©HÉX ÎF…ìó»Ù!q¶ÁOn˜ŽH©Ô£Šl o6*Ø)€ðrÒ3%^æ•SϽÛåo±8rÛ€¦7¦“ûHs&Gí+ˆ ǓǛøq úûœ”{ïßGÃñ3è†Ýª}• fƒÚ0Û/âÂzü»Ç«ƒ‹à¾7&4þ» 2âuCujF»ðš¸ƒƒ1g˜Å±iîyùîJ–H½óÌލƒ²–ÊH6s !”bØ/ÒXëÙ˜¬ÜƒVF’iè-5ŒB89Çä§!:S•er!é¼d¨nV.£‚h©Bÿ»bà=â=ÑÀ‰…Ñù7nñì­_ar³àK!,®Iy‚M9èšÐ;²Ú•£0%û Mqp§÷ûÛ¤dôÎ:3ÚYfÛl鯞ø´Å#Án]Qk왵Éß)8ôŽòõþhâ öA.ú½Mç ò›ëÝ+ë$l¡ªÛ4išÊ¥äžtã‘§ÙÞojN­–cY•«W‚[=¯¼âÞŠÜ?¯°ñÆXÔííJ(¡9ÑfªÀ’êöŸç«RéÜ"93‚ Z ÓÉgA¥J/Ü¥dUP']f[#£PÆm‹@^P‰:È% "óQ_¡5&ý~ˆ8«÷²XãMRƒ /’Uâˆ?B¿™ þD3,ɼvÎÑ!ôŽ]eˆXôjÄRÍØºÂ¯9oÇV±¹ñRÖSvü? Âë±µð!çr ] ­` îl„ý†bôC–l9XŸÌgô·¡9&ÓPbšÞ)œ©—™õnÉB”ÒQUHΨÌó[œY~?ŸlÑ1glÐ}úàk³ù‚ô%åû ­e3’‡ƒˆÈïQ#úZY“x,§––”e95Q®òøŸ°3Jnâ?`±SÁ¥°Ô½H£¡Ð ¨¼Æ©ÂRæ‚_ä¸drEòµ3¤Ñ®\jäce­ðI5JŒ@dHNWe,u9_ÈìcÚI[p÷]1÷ý¼£o>üÖ¶•Þ\úuŸÂe\q|°| ¸ÂEVu–³ÇG¼¼co þípþ®dg¡¡ìçtͦ<¥n0G}{j Ik×P;M•e§äø-üÑ^¿ëb’q”yÜ¿%7Î~ÚHË&¤)~€@Î\Èzt~WgÓ×-¶>FþÕQ߃Dz–çävêüLÝ zŽÌ ¼z‰Åáz‰«^ö»_Y“:Ÿôd9Û Gºx ‡“zy({Á8V…=˜yé?ŠhJ´ì¤$slÑäIÔΠ”úæB²XMu“ô&gÙjÛ57¢Tt•?´çÉqV ßc¢×33ÎÅ û=’ŒS£”þræ3ýk»²³w;ÑTä-çDßT•ÈÅ!e3æPÄ*&D1B¾])Éó - IX³^š…ë ´3'Mè6™"ÆÈÚ‰@¹Âµáb=Tƒž$–*ð¯Yy'OME˜uB\Yë”[„Zê ‚¿8š_×õÌa‰²ø¹ŽKN¨Ø/T´FŒ "´f^0i‹¹'L“jßíª”)ÄÊð;OWÆ× Øõ²>9ÚÃþ á^|$ÕÉ9Ä|yF9ØoY/ 9wŸj€'ð¦ï5*†£#ü õiæüI 'ª üŽx|}Ë-æ,`IÞS¤ Ø%œ#;¨ÍÊÃH¾ú”·4ööEòus§ò&91˜`©¬¬¸õ0{ôС"+S,RêC “Yž– _"FÄôƒ–Çzµ3Y„ºrжB\AÒA4]@^ÂñŒˆ‰æ þž˜)¥ƒ ÷/®ƒµÈƒµ:ÈïùèEKŸ™¿Hò ½l‡U_n8+Ê?!·¡g<׆L"ó׸b†F¯‚ØŽ°ÓQdAM=ÉxÜXFMpv M®Ð«&kD%šÊŸ‡ß5q+Œ¿¾W„˘­Å`wÜÿyh¥¨+mÚôF9ÎËUÁ4Y9rè=¶ú$°±x«>I¡î‘ØÜm³9‚.Ó'ÛN–ÍY £«©*M.¾}Áñ7îj^-9Øh}=¸â]µ f±Gš³,À†;—_~è%ƒ¼Ýìö0ÛtFm)ùa%Ÿ€[mH¥ušÅ-N½tÃÜ.“hKU¤M¿wÌ¥eË™`äQøÇ¼ÖKÎRe`æ` ÆûDðöQ,Ó¥ýÚ´gÄý•,‘µV°Ö¡é4dËTX_‚iQ¸OŽkˆ ¼"ÎíBÔã/î ¬fÑx§í:øe&hý­Óh1„ÓVk•i*À]_+^'Õ¹KÉÈ™¶P‰oàSëò°DëÖ?ç +±Öá¯Gq£Õvøó.¾èO²9–Ü  ™Gôª‹'2œUÄT>óyXÉÕ¢Æz¼#¾Ë‰¸}&4î€h\óQÀˆ£˜¦n€ë™ZÉ¥ÌÐN£ªA°åMá³ö~+§é$¸qôœ !Șë/Óþ!h­ÆR1ɦÛi1öp»ý‚Zž§Êp‚c’€%^”Ë"“‹TŒ¿%Æçsv´–ÕÏÓÆÐ³Ê˯¡a–²Y£}É[©‡7Où<-f½sÔÖC&0úp¤°^—b˜¹ˆöLŒÄáU¢–PœÛôÕþï¬õ³[å9;y°&Õ¢ÿ@¿|DŽÌ3ŒÅeq^>ÿI |P¸­LVd¯]p âVg#Žúä9lê=ÈÃLlºah-ƒ;3l¼õ3?þb¡;S§=ëµbCç3L[„rìÉÃÌBù¢à¾È–>4*\•?ë7¦Ë# 26@Ä["C‡Ñ¶B¶ MÈÔÙ=FÁî!@•I!(…uåÿS²j7ð9§ôUËN§~;–=I6ëØ”‚½²öÍ)gÖ™‘%YÚŒßhâVfHã…'>¿ '¸@ƸÀñüå÷k€†ø}jÔ'x_tºfÕ7 ndŽ#làÏ€ªm7¨}}nDѬÁ=›…Nn9íÀsšÁl}6¿dÏ‚ ïb8*²÷<’µù}5k=?ìr›Üù/0 £%.Ês&k³ ƒy ìG%àþ¯ífQDÖ¶%å.#(Á‚œ™D‹oˆò=s(lb£±ç¿çd 22¸l–%Z•%sµÙÌF{,@(dzÀÎ:™á/§þ³<˜»f±È݃‘ÓÒÇjÚ†^¨ór£†såÉ †ÙrSÝJ¶‹0ØT ¦Óq0) .ÏSßoæN³¥ ½(§µ¾v ¸B¸7ž88V’’]ùÿY?§Jí1! ñˆz£çµêÿc’úÒ]0†Î5 ú&4¿ÍÍ”w«ÞÞ|Ýd;1!é÷ΈñäïàÊqAÅ£V€æüŒ¤]”0j¨˜ûcsÒ#‡ZKØÔ^,uo4_ÏÁ7¥|‘´ ì§ãUÑä»y_˱•:´·üÔŠ憸dÉ’D°Ñ2˜4}øsϵ’wb»ï;Oöƒ{?Å3‡@+Ô™9š{)bd]o“x¨ë_+ÇÓ;t‘jý¶ÛH÷+ÞA6¢å wèõ„%Iµõr ~ÕÄóŸÔ¼h÷¨ìg¾‰æ¹$WÛÀE䣊IŸ¿•!ï®ÕôP•CΫ£‚$tN÷¥õ4ݶØ5i§GÑüªsNU¼ØwsøþàC‰®… Æd%ŽOgš/ÅÎÄ>;þäÃ}·ú»¯%è5.TY{[q\åiØP”m›ºXäCU3¡ZA¼÷¾žt_¹hØ'o~(‘¦>‰V.üb¿ÀV+ì®|ÙÞÍ•þkQ™ \©¿Ëi!=}pô{Iå$piAài& &3^Ýye×5Q÷§«Ë6…j‰žyöÁlÕ0TP+¦0¬NwpàøòG’w¬«–”Uµh÷ ¹—Ÿ{á¾ò›C•#KÊ‘“”Žú$;¸ïÛm:¼Ê4é’û ýí6Wµ#·h6F ~n´S“¢KÖãmìÿï¬èø›*é ;æU¿¡/$?Žòß²¿«Ÿ„ÉÐ!ãÎ)‡uÞ•©T‰[Òý™UAk™än¡O2%;EËÖŸõü®”o”åÇg™6Ðæã mùœÏÌzœÉåG7¿lj ï«Ö—A`|vÑ‘Š)£ÔͼµôÝ’ÁˆÉèçè-YÊjÀ¦GëgJØ.ïÄQÓ÷î}¹7žéé®Þ`® Èúám/q$×ÊGù]¿ 0ÂQ›®z±dT°¥keG‹ìVŠƒHî–Ø«#Cžó:ÉÎÜfÔˆBÄñ2Þ¢4å•' ÚÊLÐ×Yp-kÝõ–bÎU@ùë^ߟsIÁ @Š—ä%Ñ(^‘‘Õ]Ôü62n³Ï`ý'+k>#?ÿ„T¢£+2ø¨I‡—3CC?¦4fUzª·Ñq+þѪ¯’wK½_Xb­mbw¤]rrG:÷ù î®ÊjôA[õžÆ”9u2³´ez‰‘/ Éþ‘Œ‚+ á§6øQÞ}Í î[K6³jb"“žoKƒµŸ˜¥ýeWLà·¡ s¦G´VE÷»cr~|êÅVŠFEJK€¡ÄÉs„¨ô¥·D'¬]ÌŠ®Ù‚y”ú{8yækñ(˜8àƒM4q¸"nÔ \˜"î¯òÛ$aêÅŠˆ1½„\·Éþ´æ'1Ñn@<•î²Ó䋲9ˆœÚô·~W«,1÷£ÚêÚAϽK÷G^AŒÙœ!i²H^Â4•ý@5ç•O«À'ëØ€ÕÕ—½c±ÿRàû™È*ÙVA|:D“\n‰ßg…õ:ÅlO÷wS·ËŒ~“HW^™ÂçV¤/¿ x¸å&U*|¨¢bYaæ¼O¡“5’(ØÊ}'¶KÝÖ¶§ã–ì–íPàB)2Tš&ûæ¡ YÇ@µ°G‘Ù/Ý¿PÅ9“dÑ}XÚ5íÄL!ÈŒO‹:•¡Q`'„Àm1XÅi<édA&xXH0&JhrúÒ“– &¥–&XMé|mýDÚO;Q§ WGÇÄ%-­¬ÎÓœ1– 9[€ŠaÇ'‡0Es¤3":›‹¶9q¸ìk'ÑU$|çòž©4dÓ‚š¨‘{Kè–¼3™ C¡êRœ$_ò L ¤ Öþ$ÆuGˆ÷mù†V¿mqW}÷èT…\í §8Έªî‡c_( Ûÿ™`{x…2"‡Õ<° ýž5a‰)¾·.‡r×}ßS•lu= X/ÎÉ»ŸK¦"øùâå>ï¢Tßaó j·Ó?yÓܤR$%ïv†ÞZíg·“SrC,³¦ú`RãS×Ã1Ôzã\´ß7Q:Ÿ»ÜQi-þ#}[túAÝȧ4X°,rR3ï°ö‰Û•Râ°ïƒHLL… ÃðþXȬgª¼~?£½¹Âú¿ÖèHV•E´æM…öôˆþÈ~x ®ÎD³Vý*œK4ŽAý¼Êf#´¥Nn¡j|@T3Æ&ÇBÜÇzYÅ7EÜ͹âo8Ö¤-x ¶cˆÜ6¶–:ÔxævòÀ½É 1ÞƒÑhÛ¸¸G؈^!x\L¹æ³uÁ/‚wóñ×LfŠ`øs‹i ³œÊ'튾{{ÇÂÙòR}ˆ³!é)ld^ã/ôÕ`ôD74õïöñ¤Õ¸Ýe²i癆MB~‚|]t8¾ëÀ‡N–¥q‘ŽkG^_®ü/L'Æ5W)Þ¬y3bÆrã åhqÚc<ÛÉÀ`Â$\” …³–+®Á>ÖÂcU÷vœ"ïN7±§*wËó|åf2úMà%|U±h¾ˆ¡ÊÃøÈ¯_¨©˜£¹ZH =€;”bÐ@ÀŒ[¸G—=ÍÅbt%…ûƒE›öæ9üLìÕ×"t‹fªqš8÷UUv_]—á°‹Úvï¿dˆM§>oÈù$ѽ2ÌæfNŒ·ØÕ !ƒ\1­¾Òc ?:#0ƒ”ùë@èd}0ò"#2!od­ L·4ùïÜëƒišPݸ3¯óË·ôaäù³\Æì«.Ù¸è"VÚ™œ#õGMË’Š¨J[¾4TP`(np.Br>¨nÒƒY‡:€ À×Qaåòðõ®ŸüñÓ¢{]2ÛZ—9paFïèi¡—1PIj_ÂO^Ò– »U­aZµN NQºñ«nô»¾4G˜>A' €Ú”Ä“=sÿÞ+ùópK_Ф&…Æ–[˜QñÜŠ4n—åÀr7’pFáLìCýž¢ÆyË*D¤†yò¸»mõ‰3ï&»&¾Á¬Ü\]"s÷¾ãpiv¼»¢ö%l±dË`¥«gx¨;T§äÊî6ùÑ€ØB8pb¶or´–œdRgçôWR=jCn|µɺ¼6(|¢xZkjZ%USÌ `ª9[$ô²!À*åÃЇƒ“”Ø…£×©“ÓbnÙ‡bÉûs´œÁÊO£ Àà·ÏÝêäIdÊ^ĉ×¹¿âÎyЍ•ØÍž;ÈÜê|ÜÙ+ÞÁ¿'$Oý3 Yö¼dÄ·—xZ¤ªÅ\f(G§éQÅ~ŠŠñïòZl6±ÀDß+¡,‹~ÑD°´ a9í¢2½´Ϧç é™þù±¢‚›æC!o¢*Aóf­dRJ =ª]öÚÏ=ኑ_BÈY =5ÍÙ»ü.Ó‚0ˆ0¼°’®Ó0A™´ÞE:Ókð΄®åû{Ù‚nyò”¢žÖ_vî.†Ú5sª4߇üÑJ[9Ùí¹\b7èÕ!³KÈ?c"þæÀ°¥O—N>ç¸GR(!€`ä,þã±7Ù4\A;I&ò£sPäüã¶ ÂJ ±ÖìK«Ê–¼‰óe$Ü(L1耋›>0`ÞŽ–„¶«ßrœy„ ç„€,x¯÷õûøŸÉ(žu­9ö‘´[»ÊÐDŠþ;¼ôãA)Im|]¡ÛÜCÐQ J‹ñ"²õ¯/ ¹—¹ÈxÏo(Uì·Œ}C–ú72¨RÛOk­í ®Îûa–T)ßÄÚðŠÈe˜Üò>qU»SË{Ëñ©´Þ&ý «ù6áŸœŽ«DŸål5ýŒŠF%?Án™îOXºbékRà ֟Dt"Û·:‘‡ &øéL™œ6ØYˆÕÎÅüÊ`åCÎc èÀ ÕqÂOêLrÁ'mjBáÇxჩµæ "±èwI×Ú‰˜Ó ÉÍÚ–Œð“«Ë=YšË$L@R;}§ÎS ¦bIñ~ÐÑ5)ϸF/Ã~B¼¸ˆÒV‹!â5µÉšcÞò‡äÞÿûá/fÑÁZrÂ\öRGà>?þ•º¢žÖzãn9Ÿa÷óÌ´@©ŽÃKÙû»v¨kSV[Š ã`ïbËî½u˜‚9ÅÀmP;§—½qÁõW—_€89¥}lÏ…ù®¢ ûÌv±% æjîëÒ¾|0#3;‰ààŽ^üöæ4:@Å©Ïc¹QêC®«•Aú˜Ä5™Q…5Ó¨FâgîŸ5wè¬e•óÝ6’x’ïé­,Cáö2Üldß V·0ÿò¢pê:Whý É‹¿ƒß€(ºwiy\Ðõž„ 4»;“_›ù (^E­A¨.{æ’ß%:·¯±Át[EC J¾˜CéS¨6‘SLAÚs>‡ØK+¼¼Ç6~Ò:¯ÞI7òG–ÿ訌ýès|µ¶´H^uç/«× ÷ uÚP‚‡u{5ùk/}دò×D-‚ßÉÏ—¢ë=fn¢·´ß$TÏâ±ÓK†;͔ţ zpî[†‡âÀ©Î3¦$’`T*K‘î\2­âwéK*Ê©<8`¬îý01+èl¦év0Be&c2£D&³ÓäAíÇÕÛQÍP„.U:“xà}ÿhã¯ZoU×?17}þÎ쩸Xï#—ªU} | eå#Í…ÎÉ/›Â_š‚QXŽw.õÅŒØ6IÛž,4-M• ž˜<0Å6`Äý Vã{Mæîv.óû&ÄQŽÚ¦áTIøÝU÷„{XùF„`ê¤Ù#&0R  :ÅŒÞÛ÷ ú 'dæôøäkX un…•É•VµýL°¨œ©³–Øü,Ï¿¼ŸÁëÑUª¿Þ^§â|¢¯¾æ0h6Y’ v~R2=ùÒ:Œ §ƒýÞÁ7 ï™GcbÄÎÍ>ɾ̫ÜP‹¼Ý‰mø×Ï+«°‡FA1³ÊâWÜKL–u>ðCsRÓû ²úôô7DdÍ;ÎŒ ‡ ­£1| ³•UG0 Ò(@àÄ—¨t³ÞÓœtªÂÁÙSŒ1JZ¹E#«ÉSè>ã,/•6?2J^«øóz«#O:Qð? ~2´' þïn׋Ý(̦…z«ÿ2¥âجæËÈSŠÂ]RžòÂãu-0oÿÁ¼§o<)ȲÀaÈ·~~Ó/·È#2›¢Ál*‰ãàŒtÌÉ—#C!w@“¨þƒmew(ÊÂí7ß-t«óJ‰oQÃký½Æï¾‚Ý*m±°î˜…t…®#CЄ‹µR~F® $±Ç“Í2˜CœNtzÅŸx‹[æýðÜS|uÍ?rI+‰Ô~sAóãÀ’HÔ:¹¸”³*î­ÊCPaø:0K*sQ|—ú\M¢êÎh³ðÀãðßRD>¹‡j‚ãÛóÞd6§‰Ñ[¥¡F‹€ò_ŠÔÆ)1%˜Tù«$_X×Î>ÔáÉ6¸c†ã-£ÃûÛ‰'}¿áµ˜¼LÞ~üíV¥öŸ"GW5Á«ïðµk¢@«Œˆ›ž‰|\ý©¡#Ú섾3”=.«tUûÏ•Mªé&é÷]å ÷[ûæÄF "±õ¯`Û“sÀv¼ÿŠŒ3…M]2dzš÷ÈÑI­ ¹¹Ö¢šöý›\(3ß“5¡øçÌÌÔPY¹§ƒ])ÅY¸Å0Eu ±ÀóÔRX ìà…Pk˸¯Ω|ë”.ƒþÀàþìEþ‡.æò:¸ËL<Ü/°¯ÄŠòÍ?Ù ˆo·þ‰7žh<ê ä}‘è©}œ*êG‚GõÃÏ)PHgO·Ç‰±U ç%’Ë ¿¼Í0^¾pkÜ>Œ1È(Ý¡cqbÁk =M½r©ÇÆÖXIwÒ‚}¥Ý½aô‘è — .%Ð25¯’dKnCÒj°d…(ÌæI²ØE¦qû> ²¨©2‹¶œ÷¼ÜÓýr%E3å×®}`hЦ¶À×^@ÞWضýàìAñîbP¹¨s„ÿn;í ýË”¦µvâ‚¡#v}¤ØÇen”µ 2hW¸²Ñ’ŒŒ;eÅÉçnª>|y§ŽaþŽJTj—´“Ýç “NR5=…1#÷|ì×^ DŽãä_“—é!C«û:î2p’Ö1˜Ì–ƒ·óV>‘BöWEEeF¯)¼àL2îH=­G¤rÊä–íKÉ'ÏOª]ËUS¤¾W Ï?ˆ˜X…2p’hg ñÖ¶&r%`rB qÌ ¿ ’N.].ÐhI3,RO<ÎÕþýØ~„û¬o»jzèí¤4o ŸF´nÃI%w½<­jv¹z'íÃ=Q¡J÷Wªà±\a™sPÛØŸQ|êõí@&—s—d»±à„it¼ŸéÃ÷Õ¦«›íPuP ñ;•‹>=27¶…³>€î¥BëˆY¯|ë JüÚ‘Ÿ%)ÈßÖŠ©Ã’µÓpÂðu¦œ4‚ .‚_Õ˜Ëæ;¤XåxB3êÿäo³AL^1üã#Š"xÙsZ¯™¤L½Ë@wU`³‘=&|V`QFàídê3Ç\ÑJ0<œE¿ Ѩå5‰~—6% ÇÔõGɦ €EÆÕ¹>¼1*À-&+á"Î BJè?¬È¼Xâ\ûÔýyðXerx’à»fù…K†ÅwS¾pêÀÿƒÆß´*=ïR/W¾U}§ê@‘h¢”à«æ¥C¡rv¶ï©‹'ÎLÃ.€_óN4Ý §fs†ÃÓ¦ÁÐa= ç÷ÚAGYóµ÷ =j®Zsž( UwÅû%;“HçjH!+×2¦À*<&õ–KJ0ÙË“¼ NW’;] òeÁhï¹7’Û:z`x!6dd«Ë¼Iÿë,6– =Qóޏx{j-[9>U8—-…å,SmcJQŽ_¡Z8ƒ“c;€ÇéW@èêãA’Z$+cu Ê}…ð˜v}¨»e. Q›¿¯ºgð"±î5° B>?Õ–Dwyçb¿„ju‹Hw%Œæ¤=¬:gÃÒCùƒÁû¥b  xÁ¸ µ>ÏÞ8IÔ™ÅR‘²o'z[à]=h ¿ÙЧðP¸CÞ'tc7 ;‡Œ[#1ރР®éiÅŸPjå½Y÷ù­ž´/yºáeC{Ç9ŸÀ8•»yƒvª°êmetÞ‹ M?¥ûœNªä¨ã—0¶'ê{ðr6LÀÖâH²,žQž!*â¶Ðô99 ¸îTŽ*u[ueü¤ÑçYÓ·Ð#åUÃLõÉ%>H Æf¤Ï'C‘XfnNX=mLÏq•é|w–U¼SI¸&aÜ›ÃÒÂ^|Ö9°áBhdg2¼ÛOÅsÍx¼6ÇÓÁî%‰0ÌY¡ÕØ&^¡C•R¯2OGMáx°«œª çü0›ÜÝi« Øn‹Y'#,Ž~DË&à ˜÷k¹Éæ³Brç×ðhµwE8 qÁ%0ÙúZR²Xž¨™mkñ‹@È6ÿZ±‚- Jc- 7õ–AJÃÐ@vŒbˆmQj]mX]s’¹Å•ç•»úeF¾ìŽ$¥ÿ³2ÞHVIÇ[æù°z ÆWeRÓ¬Â.’¯¶CƒØ”3åyëCslãû´-4æy¸U]ññ¸ ‡øbè±÷”%`óÞÇó%ÕƒƒThúE,9\î> Ö–³0@í“›<<%¦sÕ’¬ËÐYÆÑ®ÖMÛçà™ü#ŸÛ½=å¬JjŽ¢_;(f¨ ºÅKº »(ðEÏ}0nN€ÔÑç÷ÀGMåesZ®üùIµýÓ¶¥ÈÀfé⥠vˆdsAß3ÆðšôñòbTúiÃ(ñ.#<·t,¯—_PõDKQ ¬ôã‰^#WìK³¡œ¿Z® ñ÷öˆXÀ½,` ,Å®}†F<\ymÖÉÐ[²°¹[ðLt|*Z±úÚ¯†òWû’È tC: C2“¿Ì’„îgSã’à,‰è³N’œ„”ÄÛ´_Ï´ÿè«{òÎÑyFôÜû·›¶“UîÂ+å%CqˆžW«ÇÉ@D§ù‡o ”cÁ`å³!ÞbˆP`ùÕÆ»¬`M÷zKN—„8nY¾Û®ÈqüCZ´€Ê’ÉH$ØqR|4† ©¦îüñÅa ÇnJ×É3 XH‚\¢WLKÑ+ógýÁ 1 88>EF gFß /tîôÉiÉRzøzÌ`Û½E‚ÏAfj§jÝ-‘-æ ¶gx¸Vi0 ±ËþIJ¨=ã = °Tbq!ñ‡òºÈ–(X»9ßËFÅ® pùî—©Ú\÷¶\OO:Ä3ŸGˆ­ØþrÉ~Ðëî²dj¾ÌD=;×yhJŒ— ýµá­@(ÏO5ÜHû›3¾jÆOÈQ.'ãÌÀO옴ѡ^qžKQZ9¤CL*Ýoª£Š)q§Që¤õC£“´ºsÕ‚Ã,øJûXîýc2L÷ÀŽÇ­Å6>zÆj¤68²’(ÖÑ‹s0ìN›C£×_QQ”μ’aÜi¨ûÚN÷Xòˆ×±t)¸vÒÀÉE1÷&{R€ð–?òqºE&p§£JUf,÷‹[˜ùàM]mtÙJ <Ãn/å«]˜‘›#žá€;ÅTu2!h÷SÀ&&9ô½ß ^1öŽFé¡aëÆïaÛœc^X‘š)çúh<(Ò¯Ö†û3hzX ÑÞ‰ã¼nšô”³Þ¹‹Oñ¬:uƒ& ¢øU̱6Žþh1<6V<{&¦øD.©Ü¾Ò·Ïó:D˜ÚoÁ¯zX2†ÿÝÆ 1ߥ°/ Š:-1úæËäD"Q%# ÒȤé‚´²±›MT5<º´¹~ŽZsç§æ{ã½+5sÓ²ÝdB €…5êŸ8+艌A Ïü,ÔB/ô…ï~ÒJÏ~@&ŸäÁ †´`§µz…9ûìe¤&Õ…JÅÈÙqîé[|P%|¸éè(¯ UŒÜܨ81‰mßɨžún¯#æû’5DKƒZÇLâ‚mV%ãc™ßiä`#årþ`FÝ—^Ôj‘ûÛESõí)·AÜNÔ4}.¶Yé®òUìŒõE=µ䊱ƒrjÌJ‚¿<âl4GñPj‚å°Ñæö$,]÷w¼%z5w}®±‡Pv â¦.Eñkög$*Þc£¨TtcVp 6…‡~˜*ÇIìlå?S¸4˜ô²¾àb,+¸Ìý•š)ðNr\‹ÙÅK6Û–†æèy¢ZÏ4o~Õ C#Cþtü/ú%A˜%`ùrai¡01JÂyº"ƒê}Az;¥‚Žd‘°m ]£ÿs)#Þ³‰ðÑ»“ÒM˜®²bæÖ Cä—Zº°g½ºî3ÍGg§‘2ã&Ú«²ZL•Šm¼;þ¿bQH÷Cêaß·¢±Í.áz…}8iç_8}JçBTn,UcÝAVæÕnóØY˜pvâÅWó„õ¡Òº›9`ò¯kó7·©Æà@¢9¥# ÄŠÁÀþ%£xP9?t!Q…'=a—›º«’²ƒÒ¸è|uÈ¡Áqâ¬RíÝÎw œƒ&Ž=Ÿ:äÊ7SÃ{LÞh—ã;nçËfÑ!(©oËïKëæZ;Çò8(u'Ìw¿ÖLŠ"p•áúå^6k‚rlÔÌa& èX@:\¨³²µI="=ƒ‘iÕÖâi2¢æ3cl´`~ìør”ÄG’̹ôñmý%eRW#7WÙ8Õ À£í¨O³MáÒ<ÆBÑ'Õ)j®à¥x§Ó ¨çÈ¡PÏ„ž-¸UyŴ¸nB—a”_…½+íÍ»lBµÓàû?P·¢ÍV›˜1™Ë.Bð–8dµ_[ôÉZÎsŸ<ôì‰Hݧ¶ÆÉ5аqmÎk„Ü%J›3È¥ÈÖ«aÇa­¹e®¬¯$/-ôÎΚý\ïúaà¶Ë1 q7çî“ÔRqÆUd0—(`n`Ÿ¿t¼e–Qøj‡±àKà¶ßÇ9ú§zT/™ˆ­k#Ô™Ã8’©žæ@N1¼›Ôדf¸¦ðÙÝcÉûŠçùQáã9îKYɼïÚI9º*°æéÈx¨#¿ÜåQ¥qÍu¼4¼vhù‚à÷]I|iz¸„ÄïË­Äú¬€rF†·&¢¼Ni£aÑ '®¦ûﳉӡ·÷Ò?¥d§ÄnÐëB½Í†÷SŽ räý~••nØÈµ"º9X~ô< w†ñ%‰òêß•ú¦<88oeaXX3DÍœ à E¯>7t‡lËÃGŽ7QCá½CR cKÌ€ë0ó|¨«ßÊJb³>¸Í+žÞb"(üài¿Õ|AësŸ{_ŒQJÞ†hS– µ[CɆí"¥«{xưÉD°Æ *2AáÝ-(+þOW§Jf¥T°xÙp‚ú0ØŽ ¾,LŠÒ¿UØw÷¹Ãœƒ¸Ò„tOh”ýú¾¾kU' –É{Ì„ÿþí×sE¸žæ-ôÕ@à­ÁýÍ’Ñ H¥räEyjŒ]t¹Â²ã²·:ú)7qžíæÚ?gÀãf&¥Í¯Ý7p¯’%~³‚ý_ÕÆƒŸž¶-…Ò<:6È2¸[É‘ÎWúÙ£1‰0i«OM-Ááæ2Å)Ç™‘×ä3Ôë¼É€×Ð Àˆè+uVä»Çiž ê¬|à9óŽÈxÔ^>4ûÒË0[¹un>Õ4IÝX')B7ÄB-z©’xÙzgÒ[—–‰éBÞ6æ¯É)ƒ YŒÜ¾°Cª3¢õlêI4ûÝ—ºjèõ`að×±ÿ[c7&Ýk«îbžy© ²FЬÅW¦~Äâ 4rнXà ¨v‰®P†˜L¥—Ÿv«°VÀF©ð‘Ýh)Gp«Øá÷¨\ô.ˆÊ¢æ0F+.ã´­ÀÒ6ڛפ!.wÕÑ—©_,¡·Ââ*û³nA½ÎŨ'PCV³JE,dkBªîZ˜G~û¼¸CO+Ò¤W­üã cÄ$¼ 2ž¸º}o7kr•ý ÀI¦Ì^Y€NÆ}ÈÓ#vÙ¬ynÿÌÃÓb•µ·Þ.V‰R[ùì9ܽ5êÜD³±ñŒÕo$a–·ó18w+á†Þ¬[•Ür.:KJÝðgçŒO¬BÇè÷ñ’Én»ZÉzì¡h†ÀM^/!PC†²ÓyéÿìQE\KÄÏrÊ"Uˆ8c‘lÁÍ’1l%;y™²¿¦t7ê ô¢×ñ@ô€ÐVÚ÷§êU 8ʳå¬üà¢ø¯YZì.Ýq癥©‹¿U|[Šr팾íNÁcN]›I#9RÒpCêÍâõ!‹Þß«Z¡³þØ{:7ÙY¤ÂdöÐþ´x*÷áè‰2Q€Ü˜†‰ñrå|ÊÂ>.¾Ä^Ê!ëþ‚Œsšwöcàp…XŒÈÓÕêšN>£L?MDÒ›”ó‚‚@|M(³ ¬&‹9«ÈµlÚ‡©†EúbŒ¬*Öý쀱ëFê|¸È›Æ%ë$.|v·ÌaÑ®†Ç©JѱPV¯ T¥®î¨ùÃ]6\a7Ð8V@Vz3lÖš)ˆÑ’Ofyåœ6Ì- ô‹Þ Ïm=ö&‰þÚnŠxc,_n®+—bîo `óO«s”ìÄ}ä¦ÉÒÖqƌԘÉxx_Îq\‹I+º² Ðt˜w»Cl¾|Å–w%À0 •áBÿµ—«ÏY§‡bò{±ÄF5 ¿#ÔEz‘Õî§ ‘ HŸ¬Šx\·² *+ä|( Žy'SCëö¨-ž†á‡ “£É¼!_ã\j‚þîl®â!.uŸ´€‚18 mÚŸ#’äÃj`O0ƒ9WãëKfh;ƒõ4Ïûéz/ˆ®ú„ï7i¢\r¤»ƒZ3µ7ˆ;gK+«¹¦ß¾ˆiÚö¬¥;ð-9g:ؾ¥Þh¬ƒ°ÁAE5Ó®{ÝÄXfÀ¡Ö‡†Ø¨’$faÌAþ·ôxXqaj࣠½âìñˆcHüÚU¦¦«ß^Ö'&R»g!A8✩TxP› çœìò@µÇž,së7ØëCte»?µˆãÕ/ÊhŒ4ÅÜëµ#Ÿõ®u·Uœ]ˆaN«âéùõÏ2p ÖŽÃk…ÏœˆnŽ(£’d/é£T/Ssõ€±øCp’BÍHcöm4oÿºÜJÍ—'„=n¿ªiA½W¹÷`iÜlïùûZPZœ™Èæ-%ˆZö$w2RIŒÙÊÁHISK‹‰Lß6ç)ÝhAºø5ò<£DZ/©lÇ1§Ô¯î °Vt6GÀK¯R–@³$s/D´÷JQË\àGÔ¯†èüž{E8ìë_ýnKEî$¹±]çòa¤»ï0Nb…L!(ìXi$h»Xeô/OHtî¢SEöA¶Y úëµ÷p…1…cùôŠ£É-\N“éÛ™Z°©CÓ@ãÏo@ 棳I„“q(}ÒMòÒtµM°õZà$é2­¡vZ1#dôw¥í:ú­Jÿm£uéÁ7,v¡Íê:–ÎÙä¾ XæQòd°]ŠÒÍÔ^`K#*4ã®Û3·n..ØAªœ\mRg/¡‡åòB­­½/¤,\»—pˆxmäáÚÆŸõâv)ŒDÃ~ÐÃú)ÙŠöÕè[¸ýmíŠDmñÁn‘ºêc³gæƒñ;fSÁ^/@õ]­Å\q”µâå©Ê®MŠÊD>á¡ykqHK l­¶’*h^©H3ß[~¶€Ðº}²ÜI½Žsò¶Ò@)ÊÓ 9׿Ÿ"ìOGD !®›„@·º^8ÏÄù ©C‚a–X- {Èh%«tX}¶é¹ÊzW)lçB=*ª:–ÑàÎâêàw;Á®ä&ÁS£& Äç—ýûE7xÛƒìú/õ:*Lä[}5Þ£µ)Óùl°G¨]†Jt†Ó+üÊYPÐ`p•?gtmãš±¡¯ì~ùŽÔ\M|Ó$îÔˆ¢0!b²íæFtvå_e Ÿë¡btqÞîäƒß ^{V¦Ò¡!šk@ìÝÒ2…R¥B J¹¼ÅJCª®(ÁDº?ö¥n¾}zEºIs†_@Ÿo©9¥wÓèþ÷MÆ./HÍTæ Aœ\„ÛÒp?øû°нyÓå¢2ÍÛÂâp†ls^W‘õ—é'By¶6Á!)BL~¸J”²ì†¾ÂmRÀ8æà‚bW¼ãÁHuà™¸{žÞXê@g]ú£÷¥ˆYSîC^sRþùFœY¼Þ‘ÈÀuà¬ÿc,eLôM†Å)!DdÑê_ý:׋ K}Õ#X”å]búµ Å«eÓ­Px6¯Ä…ØDÀžS4ãÖ™oΞª/šKÖ:3–8Ä”àÊ”s[}Äëå<üC”¶WTåÎÎ BDA€W-– v¿@?´:ÆØÆ…\Y–¥@ ÜÙ·}¤ø­Žae1Ðt†‚H¬T}x Ùk LŬºÝ†}\¸áô2þf‰|˜L£¬`K;¤û D€Î2u1`UxœJÝJÊ8´a.IE)¿<ÄÕpq$“4®6¯Í?³FÊ4¯ EߦµUñaOõ¥UžÝö8àÓ!;½°íd·W†  ‹^vî6¼ T‰ êùB3,£Ê-yÁ­§®²”Zœï—ëcöÎóšK5D´jöÐæP݉öfÛÒ”c‚6Y“&³éÎZ2”àQ2M@UU£hˆk$N!Ƚ½cæFTé œ'‹jNÐëK¯>b~ÁéÚÞ¥ƒ¥ÞfÒ>m¹¡rŽiU_Yk€´éym%¿k†`_R$€´®†òixåhÑZú˜~ÁýfàYv¦‹ÄzÍÎÕan‰~êgP úd¨…\"z°·îÈÜÀ…¡™®`Á?¼‰_J±@ÊË8%E˜µ`ø;ÊôšÛ„)æ,@§>(åûÀfW ï­QèhVÓRÖÔ&~¥1´‘€ë‹•ÎýPRzŽ „³5ñÚ ßÒÀœ4ð\¬Þ|»±Ó~%Ò€x/i…®ørM­Ú„‹«A³­Å8mòw”ö!1·×º%ú• w.1 ×è,Á6²[Y»qŽÚ¶Ym¾©?èØÐ½w;däøÇ'¼˜~°n­3eµ²Å¸TÈÕ߬ÑR™¡X6óšRnp ÈÈk›(éÀÃ)ÀÊ«MQgzùv´ŠâT€}¾)NÖnYP:¾¸…¨¿²ü¥_ö¨®)ˆt7é^çËXœ:‘2€M­ÓÒÒá˜V 6‰¯§Ÿ^dèû§9`ÆÐ–½Ø—àÈ… ¯ÿùÀTø#òGw5-nqåÍÛV¼âaȨ N¿RíÐÕkž"ûX¸SëL`®‡M Ò(Ü'dC±»ýÂfÝù¼a&ϽôæþŸÏ(‘( äfú*qç] ö&•†"!ÍÏ_Jóoküp{–Ôî ñÐJvØ‚®Ô<…¼»~=Øä¹jmÉ%Ñá‚Sàöx Ë#š,âÒCªÌˆÊéúöwDvЗ±LWí·›CÄÆc>™ZS;¦=ó&¾¾bz4Û»<ž³»ªŠË< ’Eš+Ç‹tù3Y6°õ^£±D£Ü%®ÇÄv<éZo E‡á£ä–ái¬-Ü\tHy‚ÁÁ9úÀ« hiç3«rŠßLstâé€Û:ÉGíƒaçÆE V©áÇ4n¦Hê;HÒL—Ðêâkúéõ,¢ÈΩ•P§uºùBáðæïOr†V£ÙÀp‘ÏšˆîØÒ-©HæÄâÆqÊ/ _‹Vº»q¶/¶r”ؤK‰¿¢ðßqK*ñÓ±xï¾mØ€a °©­°·Æ»«:¯ºÿ6c‡²›³Pj;Üê)t;5§8Ѐ=võ«È=,â4gè}ß¿èCÃŒYŦÀ— eŠêHeªmüB#ÖT™â¢f­w‹O×Ó×Õ·Få Q¢ÍxpÅe±‡m’­wAë!àW.M–«ŠŽ©[mæX<QÌ.›¥…؆ÑD½WbPήŒ£–w1"*{iµÛÞÉ÷8‡~Ä ýa#ζ¬å”ô˜X.½Çê+0úL¤oNóµb‡{eh§úEÛ6pæ @a{Y2þÍÏUB»Õ8¸|yéÞÿ;Çq#uaû˜¯íÇ‹£ìÌWÕ&˜ú¿ jÝ|žÉIó}BwΧr…j²#ÐQ×Íâ¯ù üÞÀ$AF~„5;`†Âö“!iXcø«Q/T{4”z׆9vN4ÍÊ‘³¹ øÐîupň6\·Yé(÷ S {²³³»¦åòK³X‹vÏò½J,ºøÄtäèp­l£©Z“…p¾l!]Œt¦ˆ"4(?ÞŸë後–Ñmgœpw‘ýr{ÂÕÒÇœ³qbFñÇ€´²d¢E¨eW`ʆ*Ýc¢AÌÇ Mñ+ÓhÓ÷÷œ†, ¡”3pg´Òs™€zí—hõ~æTÁ¿ ý졹ÙWávG¿Cœ_ç®Ýžj|Ä–¸‹Öqê¢èÆk°¼Ûö‘HÖ(cP€ë¸)]娴³n«K_Eí&NòðIéABvé$¥³Løœ-!sÃ\[|Úõ2>#¦;Ð;Ó.|®^Ÿ¿êh‡$æK|”ó°š>³k;þ¶›‘ÅiÛW„ð-µbë¦C“Ct‡°2Ð1ÃÛÿ’ÃÀ=‹1O–lÖ‡¹±Æ,ëûYÂ-p ³ï6îð'ÌpÙÞÀ^c†ÌüÿÄáa52÷­jß?Mëy G#©&Çû Öò8n>¦T·õ<ªôÝu°1'9ð‹úéTrP|pbáïÐóP™?Tn©ö&BÉÑ\9]rÕS*MKÉ Ò¾ÙÐö±òõÖÿ%i½™D  •4nƒ˜ÔF»w½|Rv4À“Ä4õâ(+¢¡5Rl¦0cÝÇä·˕§Á¼ìÛЂ_ Û¬qд âƒZ0³‚W`Ÿµ:æÿ/$úÙ Sºì[C¹Ù“¾è –iÝaטàݪbtrŸ@v2^SZŠÜ§ 9—‰§ÃžnâgðÝ"×™Gx3<]§oL}Hwã~tõBµ+Ÿ¿”DdÌa„}#Ø/Òvî{xrî¬4»«Ã‡¥a¢<ÍÛý|=V1ð“áªü–Ö·Ûeë°ÜËGK’¦úuƒ¿juÙGD¦µ¡‡Æ"¦EØà5Ù8‹ÕƒÎÜo¦ YS… ÍjÆUå!¶çW«eÔ"/íº ~3`PCßqv vÎÎFr¨/Âz•³QßHy#ö‰Š(J MëH¬úÀ<. ã—µ“M¤*˜½ÈÍ–o´p-®³ FÉp-¥dl)V×!U¼¦ ¼D®4öùÛ¶„+¾Dó^“¿ÞLÃþ¤½¿õÔþ±Ø4e rð2(^…ÇK¿­C”h§°‰gæ¼oà[£…§±Þ¬^s7?dá Ü_’þÉïùÀ²£æ¹C®Sð´^Œè(L/½>Xµm<²9Ãç`+òx!ˆM刌,bgu‡ä㸉¼>>„eöþÖŵÓü"Õ>GZÏòtê}Ð,1wÈÈ ±oؽ¶¡Îï\<¹0Hi—â:رÜe.Üh¨9ïçµ ±½›U9éÌå5€˜°µ>%×ËG# fñ˜µZO’ Áö>B}¤É jÃÍÀ±Ô&*<,ÄÜkž2}ÖdLÖôd+žìÞS)¡fŸ§ÀIy½ìaî0!úwàŒ2+!ÃdsÍúÃ,ôà Iùô] ?ªdó|^xD^Ú5^¦-Jˆä_íG·ÊUÿˆˆ`-œ‚µÈÌÃÖS1%Ý€¥îÈx»5Ac†{õ\~¥b1É:› &¡ÌÄi;°UgŒ ì3=Ç::gaFéy¶Îeú²¹æ$>l§Õœ1h»J?«uŸ.¤G"âxÖöq¦øn޶9¡ÐQª<7t†¹Xfü€;q,¥„¥ò ¯ÛÌš¦† ’ãb½UÊ–ÐÈ"'?CšwCUø¸(l)?šå~l†ã(õÊfÙZp­@dTGTÒŒzÇÃ-£>EO´,rû<¿ÞùjMAÁûÉ)ÖnM%Uî?’“X´íÑü*¹ã¡°©ˆ¸öܵ­yäq¿–"µ®Šö¡¥¢,b¯ÆˆTƵQEøÂ !qä$_—}G‰ú&³Ñ)ŠÉ©a%¦€t~ú ä½*6$`âãY+mƒñΨö$!³À¢±òðä'Z¸á(`Yua·n ¿ÃÊÝ£ ²h¬Sgÿ²]ï”}ÁE¬”6¬óW¸Ä¥RMáò^dih¸Ó“ÄghòEÊö]G‡!Ý)É ªÉž­›ÆEV$í|ŸæÍáB u)vm®ZÁ{ i óÁÒíôCñ Üf/4sz…=ëé`Áwƒë…a@÷½-ÀnZï5ˆÊæ+±Ì03¯k~.Ø›Ü3=eK“´üêËvœë5_€Øy[ÛIÎhÞÓø’ݳK´8¥mæ~KÎZÅ;]ýÃT8AF‘µÐçmR_cÌS:‹²Q­ÙD·¾‘:&ÚwwÆqKÐÅ[Š‘:ȦÛÉæY’gP¬šQ¢W'kÄéNOXÑüÏÈõvÞP ÓùK–E“þÖ[M{^À9€T¹ôúő׊è»7Iª¡¤%ÔRsºzZùo·lž&’ƒg”:ÓWHb(‡™6¿ûWR¤£öñ uœ†c#ÖÍ{ëHÌÜÊvQÖ¼ÅàjЇõ{Äð.Ÿýë'A¸)îÓ æÜˆ¯°úÊë¹ÅE÷jxQ}OÎFu+g®›##ª*çšðèÎW¼hD©ÏéÝ0²¶¶l&»¡vHÈv“(q‹5EGŸ7ŽZÒ“žÜ2`UsøêjÉ5Èo¼•Ö;PXÞ¯>8}±{äó? ®DÇóg&:ÿú!Q1൙[û§£Û¸êS?®ì<§Qº±-#P¼Æœ)!gÉ&tG^I.ú¹â6šfÒÑ.¥;–[€&9·Pû1aVÓ:ãB²~è°æcõÛŠ†¥©äÁ”Á:ÔXt ãcq!†zh“ÂBþ›\ÐWêóù~eŒ>Î%ØÖ )M¨@1‡©Õ¹#r[ùÜܽþ[aû]ÐPyùä®Ç¯;>®1𹔄ÒFkÈh\ˆµ?ÙŽF__0|ôz݉þACÈÌÃkH£cì'X!Úª"+mìh:ú\Õ‹~­ç¯¤ø8¨øð¸ˆb€€&` E*yö°…Šò †–r.Î…B üÍáˆôð'¹[¼I¸yôy-j)žÍ¿×¿/ªr0fÒG×5=c+&üên²—kØQºñÞõR‚™áÐúp…+¬šzT`…`Ý™½J‹$ðrÐ5]cN«co q…š“Qyîɻ̘-—U ¨þ Å+û¨¬¬¼/¶K»24‘Àtx±Óx9ôš5X>_QJÀØB y?¹3hÌVì/ˆ'ì­|Õ¢™’àOÏr2óê½á”Pðz^w„¶‘Ù­4õºA2§ríìÊÁsÀi=_O'é€QÜ …ɤ÷}½"C„ûêz§Æd̦ó™æjðïep‰°%737§Hû)+ßÐåÈò=‹¬²d|©AÿІyäW¾ÛÅÛŽ("I0|y“gÎP¿›ñ¸!” º”'É:Ù&îqqýÉhY_êÅbN=U?DO:.î7YËá‚U?,ëónŒ°^L&5µÉ>¡Î‹È”_°"¸\oÓîß`2‰³0wbÕ°"ÿªê5ÿª–ë¿´vxu‘v‰›Î­µhï¹DKnV\d¬Ø´µuÃèu³O¡é“tìòÌôYY)àðÂÍaiW|*ˆGö¿”ïR¾«L9AÜÓ6ãÏ(`Aáß)œe”£Ÿ’(i"Èå‘—š1 ×Y†-–çÕ“œµ×r¸ÔjÃ9"OÙïûiGö+j¶xà‰õYsq„$×Û¨Ù¤ÜÞSœ'[ íˆ)H`÷¦¯¦P’Nò }ä4©˜S]ºYÒ¹g8™¼c“bÿ¬©y+Þ³Ž¶gjð&Þ{¥z5ˆ+SƒÖþ.-¾|îžAU»““ùDöE± ×¼qÞ;³5Àí‹ÛŒvë6ôÄÇ«·+ &`ój&®ø;(¡ó3ÅVŽôøV\ê>nÿa‰½T.¬Õþm=ÇÒÚDÖJO‘ŽzÂcµ–#˜˜(li¬u‰D{ײõ·É xŸ¸† ¹ìiâHa½¿|̽ r·’g8[â÷ª9¹ˆLÕ±„<ƒƒSë…:زoMê܆¤³j?¡9f¥ØÏøWK[ਸ਼%Ð>¾1̿͞GLYû#zÇ™;MS'ý1Õ¥$§$«üÒÕí¿1áíàYŸµ G´G´öÆS)œü~ò¿®8¸aˆ9'8œÀÃd÷?Á;6õ-¢H1*¦Ã°'ŠëÜXÍ‚ýÐb˜¦Îü€´Äàˆt+Ìg_XÄÉ¿ø[9j°†¦#<Õl1¾Aª÷çÜë¤T•¯¦Úi>º4»ï?_­‰âV‘÷üŒÕ]Œ=ÔY~£,ÛRjÒxơ뮷&Ã¥ÞI*K¸i„Óen4åöC~Ë'_‘¶<ØŸ¾ÞßÓ<©ÍK–4„ Í6mœ@CL ˆ‚€5à˜É&Ⱦ;´s}yWVÙÔ £¹ùa Ài^o¦Ý€ÀªcrPÚRܨˆ{´TùPpضr-)nK‰àƒCÖâÚË´ FCÒÏç¿÷ö$^Ň)ö™áÂíOƹ´jÞCÌ]qá¨ôgßð¼ÿ—×|ÁdÙl·3Í¨ÕæÃ´]þìå1¼É0ï IE$êøåúo×ø¡ã¹ýOÊÄÙN±j ëU,(ºú·é %Oì~;ÿÌRRâi¢3(¥Â”oÐ/ôv’èÙ1Qæ’¡1ŸLƒ'ïÌcf5HX-޼ú }Å÷ˆ¿@÷*¡¦„ñ?~…ŸŠ›À´nÕv8mG0ˆÅ·©ÄÄ‘[=P«Â¯!"Ã/oy™+̤ð~¢6roª8r$B|ÁcŽ€KãJ*¾¡ÛB <{µA#è08 ÄýDWä1KÿÆp øy KH6òóºÏ‰WP¢dsÏV‘aj’ºFõsðÙ÷¤|Xtpèaç ÚØŽ™íªK3Ììj*ÇL)[‰œçù5-ûqÐTÎ#~[£Üíýؾû®¸xÉAŸÛÛa¼UKR"óJtÝË—¾U6•˜Õ§¦ ‡_fk耯-J-ÀŽü‘‡ ’»‘çµ—3­ñ"s’!»"¶Ñžzò3ö D£šÍ€£9z’¢ãÄ’7`š9|Åœ‘3±p” h ù 0¯Ç8“çº ·OöªY $DDg¬X¾‡ñ½ò>NŸ§ Ñ[cµIc±L_,B·‡€X5qâL˨Qììh8ÙëTwìäçâÚ@Íxµ(|WˆšïRÁÉÐø…³X¾€¿[D5S(Ko:†„@‘Žßw¬÷ƒà.d*4°f¤0þ#  ¹M²ÇžºYW!¤Rp=_­V¹ +„ɤã›ÞóXоO†N¤“8Î'üZdxóù]v!ˆªªxÆ3DÇÌ@2§£÷OCPèÜhºnt’—[ÜÊev©Š…ò"Ò@¥m c+$Çl¸ÐðTacŠo/è\ _ž^ü‹,§ «K5‚ˆÅèþ“5@€ ¶6z´ÔôÊ{U§Ø[ V…nfOéö.lÂÌ'ea¡¥³C+ý|l,K¸cD³(ÁÑsde¢®$YürêC— ¨4¬°»‹Ã☡Ãs ´¬ ÄÁ”ÔE™ÖO v²!hÌ0•ÏJazË>íX‚‘2ÃwÓYñlœ æ±çF­ž:6:¿"sk{sy³™ƒVÑâ/·ì«@ÓŸ-%Ç’L“ƒÖu ÅKÝÔ¯cïNá¦&æ~°–Ûø w­TS•·{5ÓRá‘Ýs»L@Ô?!0ëïvùA^+ó0¾„‚’â¯*QŠÁ6 ³0}Ez-Ù.ÿ`É—eOšÉu®òÓÊÎXKè ‡†hõºó»H]¤ÆX-Ú>)‡Õp¨IúbŸ ^8ÑVâH‰(q Jò匹îèAÕÛBù3?À›êvL gÝ($K‘WQ¦ßa PË ; \G=¢­¯8€dÙ~`‘wÁ‰ŒI°÷+½`@w³ñ‘ qóÞùY].ø²_Äi~x}¯ dñ@ê„§QÓ¯ 3;¹Ioƒ…Λ’dp¤b§|(ºÝê¯Êèá±è1ßÑWtëAìHÙGd}ØæCÓwEz 7ù¯ßÏ‘{½Ý©›ÏØ\v4]šG ŒÅ%ãj ³ Q¢AÆ> wQŒ§HB÷–ÉMê|¤PÑp¬I»ó'¶»Cáß_Îÿö¬ï ¶›Oà%3² hN±}ŸiT2/AEzA¡4àå¿ÌµÐ#„ËpÅM…ò°ƒ ñ ;Îã"’‹jNÌ:R}W‚©‚À8ĸN2òán][Sßûø^oÜL+_6‡2¦ #û´Ø»úsó°Ñ2Ë+€Êg:øE¿cUv\ñšòÙ½êä¡ê9ùNpX¾#n«Ð@¾Ð·FÑÊ]Â¥Äè¤õm¨ä[¹´É$vù‚"f$R2Œ>†âéΡ/œ6íbs—ŽÆvú7狟ղjÙ.¾-§uN?wš¸¯úòhéœ/ø‹emѲWþ¯PæmLªæÍch÷…Ôùõÿ³()Í3J£ŒþºPGùä"_1ôš§›¾œ±™B)ª¤1r¯¬ÊÏÝ/YºÓ¯Þ¿“¿¤köXžEd-ß=N{÷ÜÈl†l =I êNßTeéð×ÐÊ,¤a,oÁœ–\ÚÀ ËÔ¸J)è_± ¯øùºÏ X´™Wâ%§aAÌ×¼ò’SeyÊz±üÉ î+kÄ“:Àšü`àa´¾•Ás „¨.,>âá„ËT;/Üϳë´^³„ñDA4oPל2Sr˜þ…¿–¹áÙæ¢¤Y¯Ð¥òÕó˜§gØ`+‡´Éh:r•‚`ÐV#¹ÞK“)?fýNªÏF¡¬o¦»ÛøT(2þ5Ü7W‘sÒÎp°ö^Uòv”§t "¹ÎÛîµ›,'IM ñøh8`}#cý¹F¬ùäbÂR ±·^›qûÇZ ݺµïBÛý#kJå¢U«`ó é5 ‘Šß#;îÒP"NÛï²ë‰¥÷ƒi#  «§~'°R.E󾁤$Ž¿îèÄ’{³,Ó‹ s¦G]÷†uþøͪ] •u_kû“#Šþa¯¶¹9;gôgõW³y¯Ù:l-€ò$Úte¾e³Ï! Wÿß&9 ‡QÝÕ³5,&‘ííÿƒ—y„™‚¨x”ö&²cÄÕE˜6#w(qåø@ÍÍh–H#àè 4G0€èÇh±nŒ<~¶³*çßéà ¹Ç>Õê3Ðú]÷+”¿ÇÒ-ùÁQøX¼˜‚ Aª ÅåÓŽÆ·À>YÔx¡ ãºrÖ…p|­ŒŠ>_¨3&G‰%ä×rÇTÂ1 ä “„dÞ˜Î/Æ]›åŒ¼Ê¯7¤yí£¸ÇŸr_Z/SŠÂZb:úƉÝËØ—T<Ö¾^~© 0k-¤£•ŠÃW§43:†Ó^*ضt“ËuïNÌ6&[–µá}¤ÍZm>°& ¿ÅåÉgQýΧ%y˜y½µœTvÑG‘šŒ°!ƒÁw=ú˜ì>–¢ò¤r‡ß$”F–ªµÁþþìž8ÚlQ… VU0ˆ̨<|T8/ѹ vQëNý 3|=‹IâDsqåå7ž ™3qÙTÈr¿AL³u¶uWµA˜øÄZ P&«eâxD·¬XeÜ*t(‘&å¬Ê`]Åž´7q?â?·Œ;rŃa“Ü—-[¤“*-|\S²¸æÙt–ýø=î0¼·ˆxåƒ-Q à‰+ŽsïDE‡ájàÐ’e€iÚ±þR²”ç{×h¤°]P^_Ómx×Bäg@²˜v|iêAa¢üQñ•#B[â™…LžEå`)zË(ßH9¶é釯p(Éêy_‡“+N¤¸ž{¬hÓ³ig]9Ò¸ÔŸ5—»J†^cêrGžÄ…Ð: ÞPqsP0*¥–¬”GP­FOáy#µ²ïÕhtTÞôïž ¢ãÉñÕÆÍ0㣑v×4–ƒ„ð¬M"€ˆ )›Èn {,L\LÿŒ¸GÓ‰=¹×É™R€³;Éö5dxf«Q5ÖèÖ$¥N“na 6ª¡öõÄÕ¹ ×ÛD¿_,ƒoF¹hÞËÎò[·K¢¶Ç!Â-·ã0éWæýN_þù%÷xžN肯B¾ª‚åüˆ‘áÏGL¤õ‰¡®lËX¤¬Ìž*šqý·ƒ×6ꇜnˆ¤´eÍ%ùå½pÎ}Œ±Û±Ên«U¤¾ÇÃQ¼HPŸ;a‹ëák“ÐôÀÑþ•·W8W§Õtqäœ-¹Ré”Hm®“ó@‘ ÙÎŬË+jÝ¢}1‚€YC`«×UÃŒàåÔsTËÎM÷áiÏCÔ¨°»?ûcpáº-ßz”}ºýḕýÜ­†å‰¡ÎDSwIâçh\ÛÁ¤ÝfSxMr<ÿϘt5òã5,̇}Oô;oa[etœ: ”ëØß uõ¤ßD­È ²MH—ß{„¸í` _N“dØàä@¢ àEËyÛ¤`¡©Ý: ýQûÀ5ÝEï?,´´_î¹Ò3€Æa^§ Üj”dÕN`ò ɦj¦·T]+ôõ<Œ· £‡ÎíÛ÷ó°T{›Y?ǤúRÅM¥ü¸uÓ&Z¯j—$?ÜÙÊ 7Ÿ@d†êD–h~sCÈ|4-5ŸÍwvØ¥ck2Á‹Q F$­´¡Ærg„¼™`õ€ŽQ TœŒ4LøÄØã&®D‹LŽS ¨g¹¥©ïîñ÷D…tÙÀ„Lï™g>V€Ÿg¾¦?,¾c|ãíÖøúw/övø†šàß­¼ þ/ÍãNÕ‡‚7Ú nñ NÑsìbeÂÚ œ· ž”*ÏEJb2Ö<.&^tò/v½KúOßCeJýÄqL2©Ò ˜ã$.¿Æg%ÝDäTeéR—®ýâh‘éö_®1á¹½‚‰ã¾éSà!Ô˜þlu/1ïQõ#ãhÚ˜’ AD¯›M˜®ÛK]²¬›+é) Òæë+0hbu${_v@˜GŒ?¶ëËÅòIæVªWŸ%ºû…’þïª 3Ðë«L@©­®Ž¡cÛ+Ê9•Qâ}¤¬µk÷1°¥€bF Ô}¼ äB[Ûãè%ý}r&ðFʽÂJÖ[¿2!+Óü$à iº;I™˜(KŒŸ½7Ú ŒC~Ú²2È^ÁCSÌÒcŠîçW{cˆ¡—•š¡{ãǨ({“)ؼ1qÄ/‚Ǖ⨃œ…ËÁIZ÷E¨ÁKI«¾×a¹øt6\oþ !(²xûf'Û“§îbQòŸ.ÉÂZ2|ýæ"^ˆBñ—gD’*„ˆ»ÑJÑ74|#€;xaÆVzfº=Dúñlÿp=¼AŠ:øz|‘Žm(ÇŠ{ÜûöÙq'ȹÁT ­)ö±¯®“û‚ð¿Ç¼9ÎtÌÓ#ÑEi´qEæ“§S•óû1o6ûž Œó`æß"‹ ’.6ž§"¢èa8ªdPKXñWÕ ·Õ¦{’@þ¡e0Z­OHªš.—/Axm~KиäòËÙ¹í[FÎOÎ yÍêÊ£[ôy¡ÃA»£4æð­³Ã1çÀz±À—ós:(x(çqßæÛøóä-ô€Ï-ùçA”ªáË;ìáµñ/Ï#û¢t &\(•c›³¯¶Ù—õÜ/¼'! “'/ƒÞ|ã¾€ÿO½u<’%¤PØ¥ÊùtÉ3åÕ’—jE·áæ§ÀÜPYÐù¼‚A.GˆŸ¦ÉDm `Ûé…ùܾŒI±$¯ÆU4–¨)†–%¾•10 Èu%šƒ‚õÇŠ<Ǹ°<˜¶ ]K|js°mÉ{tíörãëåD¥¬»¸½7n©jÿ~ãÁZ.PaçEB \¯ßÙ\§µ#¼â‘—¹…ÓMÞj¹M›Â·¸O"À#§š3žþ×ÌJó›ï2¦×2¤3p008O£ê½PKH ß§¹=r&t[Åj⬪zÊT ’±µ‚‘J§K«5¨fùåtœARhc‰'©‚î)ú Rî°MgB›^G®Ëû?ÞØ]É̇d÷^íö+9š>ÁŒ›¿_¾B&Þ6~BX]j„Ãxcð—ûáÔ÷;‹š6²hèU+K(ë_#šS¬?;6³`¶Mþ¸²¨fUps«g'09—"µ¹¥™;Ê^†ä6}H³âbÇpa`d‚•ôùf”¼ÛºY†_Lëé3—å³Û÷Ÿ'zÜiþU.Ì ~í›8GËr¸Í2v£Wšœ· Wœ§ýwý–9ÿØB¡œ?àH’Yj˜~a¦øu¸£ÿôKòõ³½q¥áÛg©Q¼Í|þ5<ÿÊq~ âãBd舙¸"󇉗ž9·|ÃÝAA*uÕ.Ю ÷ï—ì/ùcÑ«‚‘äèæÞ‰<•§¹™°s J _2˜yG´@Èm%Z؉œý+²h½å»`êBxB®}ÆÜ†uÂ-‘'ì¢ ê~AéŒu})P9Uf^j(0Ú8wmiD•ö˜_Lª¾ Qµ6—ÂÚˆå¡h [”0"n-²×õìŒìÅ£¡œ€Kó›ÙˆÖ«õQÝ&½Æ÷³›€g¼Û2ô|¢ešjŠŠ*süÐj×Ì/xëòû:V«bÙ3]=öt– ²cÕx£ÚzùÀt¦º)ú¹Å×¢ÒS:«!R•ª”ýÈ¿»p-suFH¶†l?€øüiêéŸ?±zå=ž£ãÓuÆÏ28ì6ŽZÕÖMBFðÚ6)fÂÓGu [)AéjaøuÿC.䈳|LfËY™Z,RçJü,VÅ©e/ó&:8~¡æÂ‹ð²1ËQ,€¶/°ê›gÓ³©Í5’TõBJ–Ó“ü$Z@€MòÎk8E•Ôù'ÆyhR.Mµž(›èé˜f xwBÅÞEÈÑTžqrͅغž7›¶ßxR)mÎoÒRb¢“u\a·ÁC2ówÝg’± ;OþºZP6m*©è&Ø7ë¯rÁ2y0„ªZ1=¢pJ‘ï–Þf5sKaƒ¹„vJË }¨e}qÔ~Uñ_ *ù?öNÁ©é $å³¥:M¦’̵­R4G^»OZF¶L€hšôŽ*H7!ô5 Ô‘´Ç]ø„¯  jñSBø"¤TZÞÖqi@I—£Oiu[Ôÿ_a°> ö“vT¸¥>Û‰A?Ø pÚBD¤X\ðžck|Èüv ¾ù<3r¤!į}· nb63òeôgDºv\ÓFìsèy½<‡]Œ-ŽCoÕŸ÷½•"‡S‡SÓlOÉjÅ% èR;»\7@†¿GX¶·ïl†&GW¥Ñ6ļªû ŒfDž—t´|Ó™TÊgÄÑôѰ :òá‘LŸëE"àýÅh˜—-–Â…ìßË^&½=[VÆPÂû‘ÍŽC?åÅ8³Û‚¢5ªâˆø;½έD®I£ É&¡¨ÐÅð?j.ÁçAÌãï}`Ü4äõkDÖ~×/Bþ_Š?òhûa/Ð+^ªP´51ùCÐÓÇO`AfH£ü–ö¥JgÞò~¤œ%MCèøKøª %Š=8M8h·¡ñðºG×0nï·3—! ð8Ôõ0omØ Ìúk°c§Î¦‹7+'C¨‚ç,)û$Pd p€²Çéð’X­YHJß"Wö{³–u—^n\G~½ÅÛ¿®¦bþ9–'\­ÍaDh¸üJƒ…o¥w÷–÷YÞ=º bÙ’ÆA|û¶‡ãÄzÝûM_Ñ&Œ[k,²#}¿ Oúµ™Ç_ "IºM*Ñ'ÑÅý8Ácàþ¼Óù…«½A.ÿbï¿ ‹GüãLîŒ4OßÕþ9õÁ‡¹dI¶§r¹¢)A`áÈ^L¢{dC䤆u¸¦f0àR1f¢>®{ÕÏ\üM¡Ž‹¸KrÅ1^ø©¨.|n©+{6þA=îé± ÆüÓkSÏ¿û uæôc°WPýÀƒŠ’w S©@÷ʤÚô¶Id%®KçÝÛ³Fi§ôIÜw/¶'°åÙŒªùȧ\vû¹XOŸ¢É¥ÔqƦ•÷ೌ ýÒ¶qÅ][*-™“-ópÞ¼cJ…ÂKÌÓÔ k Dz×ßy{Fiãº;Ý™¸“ÛÀðתH@äSfG"ÛØÁ¼SÁÌýÑœÈ sÒò—´Å -Ÿ"ØË ÌëÆÈæþ«]Mo™2H¿×iIg˜’pfÄÕÇ­ßibü¨`ØLÿ•ìø©qÓ.(y­A¶@°Tøiçr¢i0îUj` …èži‰°g°ñ½WDQ ‹¢¸Œƒxl+sLê•ü^}f÷xáü»©¯¼wæËƒ²ÌO~(K•´,ÿ1ËZh$#›·3»AF×4 ,£îŠ]Ï™$]¢0"*Šê‰ÆÍ½s KkHxÚAš{§U¹Ú'Ül¢œ‡-H|_Æå÷:'>ŒƒY­T[)kS·- ¯rKµîýp$Ô„àÅGßõa<#å¼lźÅj…ä2©ÿhÆóß#2ÒÉBn'œpñCuëèò¿$z¦û6ráf[U¯ÓÈÉë`‡læeÆ[æ^Ò_øÏùË‹¥•N?ë¯.a7̲šµé.b _„˜2<þcàåbàÜ^W Ž*OêpÉ\¡ý‘Š!®‡I߇ބ¤+ºÐwŠcÕ³°"ÚôƒÚú·£¾]±ª9ïóÔ…Á¥ÿóþѲšÙj…¼?i ý#‘eïÕ%ãÓš=#ÆX€<è”õ?ÑH°” Ýãøß¤ÑahvDÑͨX_Õ×¶ºãiÐ<æ›íqh÷HëWù‹n—²Y ¡îÞÓx›$rPɨ+Øþ"ûYH=Åß»cà¦[\­>ù”ýCøwü¢|Hòµ«×®‡Ûæ ‡ô©­nÝæú@ðùýR©Cç­Røå{gaãõ†qN‚«ä=‹[ƒ‘xõwÈ>£µ¼äz…¶Ü 6cÿËiœzR;®N8æNúÄ8pÏçÞv| òºŽ\WÒpï·»ì ¨Þ®«Q“ëœÊz¦xÔz¥4< Ô`͘#Ò”a7?/—ŠÜE'S«[wn¢(&&阬à ¯PÃ/XÙÌ\ØÈð¼éØò%¥pÅbØÄ4q¦kêÊY¥—´:«fuÇ,T§ò6ó-rÔý¸Žøa-°Ô~tì¢eÈ.\=z¦–tLœì{oO]ٗט/p£9%sCuWÓ”F5aé’^DMîTeØ÷Ï |jxìô[ÐØëÎé™d(Ü︂` Ƈ„Hg´@2fI)“ü©¸k̯Ž{É*¡£‚醸d~K]÷gžRb9‚{_ÚÞùvávßo²­ˆs då⹬C¹¤ŸCg/^bÆòTQ“) •¬‹¼?Ôî¶8_Åú)ŽUZ©>êé¬so´E•ž¤áÏE«¬}»…tàŒ|ˆôJûÞWý@ü´2®1˜‘°M¯ûŒQÈ­q4ëåÃW/#µf$ÃØ#ðs¶Z|• 4Ç,ôb‰¢Ì è¾ÄJP“JÄùb¨¶#‚·á?v2+ü#)6ˆ¦ó#ÉÚ­ghkuF)LR†e€ɬK\]РÓpq‘Ín! /ï]L&;Âsèyè[.nCàÑ)Js,=˜+ [OZ…cL¶Î;ž&àw‚¹¯Ì‹ÔR<ÿÁtô—!ìb{1÷¹Øë iZÕ×FùùWx["áGýl(ÕäSv+çõy›ûó*Â;ÙeIð¢÷Ôf½Ý`¹0… ¹uXNÂÌçÄ6–±ßRdšá‘/g{\#ž;yÙ/­­•où`¼ VäÄcÂ?e$4dj:5óåe“0çSÏ÷o³Üê:$¦ùjò}sZýšÿÿmXžÞÇ”Î@|ÆÅÁ½ðŸ¼Ïed¹d&~1 )‹Æ=HØñýõhÖ_HåÁ{c—vur ãoˆ«ÅÞyå°) 'Ì¥A+++¡Œ:†^e09d½³fPÁ…¡géßÂî¥Û_¥ ÉÚ8ϽþísÍb¸ a<*ÿHÄÝb·”IUïƒÁîšóBâwÉá¼ã£Ñ*Í™ MEZ/Ýð×t¼*³IV|³q³®W™÷”V ·3•0'1°HÎŽkéMre~Ôû{ò‘rëÁh&HjLqˆ8"Zæd ,ÐÕ•Ö ë¯2]z ±`'-³ð%gºlt!ýjs¸¨–"›·^ ùJë\©àMT1²¹»ÿF2ª€HÊDº–Ôn°ðÒ È«†oÜg ‰C… Ò-9qmþ@rö›~Ur½â­9 þ*®ë{Tgb•§”ãfø$÷aÕ"‹,*Û)¹ÇÎÝÓ,þK{ÏœªÚm Ý që¶u$ö’wrö~p¨¿›Ë”¨·öüÄ ë’bÒ]†ºñ{l¤“xèf:§²N‚§‡/Úçëi81îí&-ªž´¨x:”3ÝáªZ›®<³Ö„GŠcu®|þŽ 2GÎhÝ^é ™2S-k®F¬<[£>º¨¤˜Î¥XÅ,Ü`¢_ü§%Á—- °¯ŠK¢Ck£4Ô?¿ 9øß\ÝIu–×P—iº›ÖHL€YâT >tnWðH‹ƒ=€TÒÎ@@1²"zêŠÄ? h{'õ»íò=yü­8%妠Ô'¹‹wu¿x>*ÕšåÊ„yÐûFpÀ°Ý¯m…pÉ:ÙþÌ•Ö9Ú6ì ö䨮zçgWRCð½,]³U z¤ æÒ‚÷Oë•Ê9à,rÖÞïÂÓ€ˆ„áô–À!â êè5o Öz˜#~—é_Xª'ÍG |í³O`²Ïu«ÙùÅygú±»ÈîJ¤c£ÐÐEN;.ö«)²{ò—¥5cÁ¦.ÈYêijSÙ2lRRð×*Ú˜€ñ|V^ÏZÞ?~jÖmª5²µµ )f<šÍr0K€éòé~‡|á<Î@kMvgØ-×XϺÈO_¢µz®òÉž@y6)n‘Ęôe}®Ÿcdu$4¬å"Jt¿À°?’ß±Âä{«áSë³3pÉQ˜ÐV–EŽ›Ô~šJNžÝwIU’Z§_Ã0™ Y‚%Ñt<:aH¶^W¹ûßFoܯ>µZ:k¨oÖ‹PWy½®L+‰ëìT<îÌð‚PŸcÎUo…wÃí£újÆZŽÀ±ÿÍ,˜=Ð0­.ôì©§Zÿ8fQ{ïó0FLӄߨ ‹’ÌÊÙ :O¹¬øÊzQñÎ:9kCšžƒnóžK°f·{S‰\œ50!ªÒ sŠ]˜Á®•ÉAps’ÙvW)Wiâç§¼X¾Àg Y‚à7{febx;?Qóm»ì2æØ’áHžµæê%üG/ÖVÓÄnÖ‰ ƒ$½2漌™õ©5óŽiaòI­_óÀ àÍÂ8Fj¾Ç¤¡XÈROh+û’a(º…›äðí¤Í‡–dÑ©²¥ßýƒÔ'…øÃ»v¸‡¹O`pd«Ñ³W ·ïpŒ@")xA@ã%üĆ‘uöd? Úo–­ÅÖÀ`Ò9+§æ­U1ÈöàÙ€SUvYÓµt¢ä–?fBJ„U‘^…?¿ÇÒn±‡jTÒ„Ê3©së¨eòØG³Ô»¢%vÞâ"Ã+²ÝY˸¿C Ë´ÉË☬\ý½.l°žÁ#¸;Š— „Õ·o®ÖÔ²æ|¸ƒDBÿíÐ̽b©…U¯Mu5éïÉ×%hn£êd!wxþÍU! |ç>¦¿ü‰ɧ ½ÊÇhB¶eò³êtjedSðíÛ lÚè׎]ÈÍøübTžVË0ð²~nÊá¹”W=b@˜±ÓÛiâDﲬP¾È&ŽŸ?÷geIŠ›ÿÚy½7Ó ·õ¡ÑH!é{,?(dr®àÜÕzt!Üò@Óåa´”öc÷žù¬nÈÐËsfãìåâPÆ‚.+w~¤Öôðïg6¾½¶3_äS'Ý)Õx{zoÃJëCt†Ý0ày!.®T„/B°‡†Ò.²Z®pÜç"Ö'¹Y2 þw×øtˆÀáé)#4¤t£=ΞÈÑÄZHÓ¬H@µ·YB‰1”Ð ÉŒ-YãG2éü,ìý;I¨·g4á E/á\‹?žҿÑØ;œ§åúá\Ù’Ë}i+qrê%¢fÒ_¯5«¢Íø8Daz^–¢Ü;ÞçÁɶ]Æ@‚­&q·O>3œâP$ 8~dIùä¯:ÞVè— ®éÙ@SzÞ"4½Œ D6Ï—,øŸ$t!“ÂŒsO×S8¿ŸLAÛÀ6Å_Xx_}daä:´ò5S¸òGrÓ“[U’3(™#0‚_4Á½Û‰èÐY^Ôwbi•%çlyäGaã­'½.¦‡éôès1_˜ÆX3?sj˜|Ïj jxØÉ^m“ yÒ,‰j g!­òášÖ³h,+ñ3ILd¦EÄí5{ç20 ­]ãBf¦xoð10¥Ça6Pz/ú˜…–[;¼bÎ¥G½ÜŠùÚ2Ì™y·b©|ŸôÜ/cÈÆ{† ëìiõ¹ô¿ ÌiÍÛ¼ö†¶.ê3 CGU;4kkgÕ»*W±®¥Õ…gb‹‰=oÆ•¼~ÿñÆÎOY @wùÇÞ«Z”Äå§ÂS FÒ;ÛAåp,ÔÒ‰Q%Ôôº+í…Exç¦÷tÈ{.ÏÓ¯~Etx g=ÔNWÛ7¬¢Ú/»È´žK€÷éûë #3°QÛüÇY¦ßå¶5Z£àÎT»Ô͇ÊÃ!ç"â}¯“`+}€w1Ͳv¸Ëã~[}.vâŒlé—Økgr¶ÊLxG“|Ÿ0Ô¸‰TÙwâ>a6€v6"{>¶þqXtêÉ  VøŸÅ¿sEŽ:Õ„Â{C]«y°aˆBKñš®0»%ëÓÚ¼ØL¹ßN@=å¢ ®¾™g‘X[dÊѵU‡¾Õâ™™G³ß}r ]X„(N*³MçÎáÃ6 ^FúWy–]§lY|È\«S)Ìö2IRÔðîY|fw‚×síÊ'øÅ#é_:­R{`f•¨Ý½g¿:Ïj‹*óÑ6`ué,•‹×RËzusO_Ç*Ke?RÇÐJñÇ'¿cœcdªÑŽãOsŠ@Ðf †Täc"Êk¦ÒQŠ"7RŠ­š¾{6E³/`§æÝø+ŽýèŸ)g–ÈüRóØ×vÅ{_™î?pÇRˆ„~£ŸÃWޝ5Ú0ñÀ V^°ítyC.ÃØSIð¥R‘y²*ì.WÿþqeÛí\"B?…6LÄbÝwÝh6µ²†Q*ˆÒT‰à`öZ·ÈOFÿކÃUƒ zb¦ ê¶±GzDWåe…E|Kœ¼Û•bºtæ^?‚9 âÄK¹XÚAàÌò‡Œ Ùx± a®fžµu|ž­ô¶Ùò´x'òÿÙñãƒ]F‰k–5%D§*R39ÿX¸Jl$¬½å[“Jg>s×.€Í™Þ²>èùØ÷L¹í¬&Á¯S•{ÀM©W…|×i׾тsë¾y@ožrƒ&óP˜WI§¡“Ø–r,À!åe{û(âI#*&¿‡/xá9•£Ù°0òĔѽ)¤ÈºKÊ0ðÜ!qav‡¡ó¸‹À«ÙŸañ·N"P‘ Í<@Î{©âf]“âüÓA4ý*³„YgïyàÄÂw$ë­%þM¹ïº=YDÕÊ…ˆWuǺB(Å'üR‘ŽM¼àlë‹´®l:QÑUE¢÷_š]m“å*¿´K¯a” xQŸ–y{Ë#v{ŽÙK4!ô|wÐE³“³Î†·ë—ùAbàDçYR“D°M©Š¼>ñ‚xìyl]G‹.¸I±³0R"íÊïQ›âgïÔæþãb/k±2ö'àQ¡ßÕBÌ®bxŸ%{Bß7˜)ŽïMé SN}~‡GûEi—ˆ²ÂCI•w.öµ°/’nsX/¤®ÒÀtøê]£y0ÝùÐ ¢£#dz·3ä ]Ø"ç‡ô[–¼ŒÇÑ]BÌlù,•Óu…IöŸ,ä'ð«¶›•þ=ff¾J¨#§ «ž¿d9`&nì-Öi(†®~XØøŽ*Š„¯‰~(”Ñ»DM¤'RÒ‡Éà"éÏ ƒâ±‰£1å½¼+ookR?×܃ôšòÑ…î3V÷Œš_°ÀÙj £,m‘º™…>zë€/“Üu­Òh¦2;wPº9¥ƒþžD„¹80¨É>«ó6‹EÖsEÞðLº4yvÊDº G}®u’>¢ôSÝÿtŽñ›öˆ¿bV±¶ÓmO°"¡Ý®txq[uM94{‹ŠÈsHB2ü×»³UgWçö9kX%r¹œ!}(ï³QixIàDº@I¦Þ8¼ø3à™Mw³AÖ Ä7ÿÑë~'tù*¹@ä±Ï/Æw×ÁŽRgãC‡ù”ÌÌâà{’ sÝé×F6Yp=° 4®쩦ä6\:À(ôX¿–¢š4‰Ù¡¾C‰Ž\`ŲU`MÓ\fn”!Iø!.JdûWÝóºÔàÓð©b‡ßHÀ[Þ—F£Ì’CfbRn‘Û1/ ‰©ßÕ÷ÙÚ,NÌgƒÓÒÙ©p2’úu¤ UÅ«[ÎÂXo†-vmøz>`–útjšR2ÌR‰*Ê#½NÂÚð(­¿çÊË0{¤ äeŽÂïfózYwkŸÆÓ@œ ~Hé[‡¤ÃGÚ<°Îm;kñP[nuJ0B,$zΡ!àä‡*öÓMÛ(AX ì=O…‡§öcäËG² +Þ4²ZQ÷Ç"TÔ„`…pyëÁ:à5ÐëÏ*–WïMD8žÂíꙦçLÄ앳¼ï)Ûòõ“<>ìzõkÌœ ¨$›Ÿþ ~“¤tîÜúR©=–{ÜV0•I}Õj7¸¦Ì¢ ˆÙI¶0[ïj(8ÀûÖÝ[¤÷¥2–㕲¸¹´RD`Ä”U¦Y,q,‰ 콺Z\êOò Ësò^^I]éШ5j’ÝÒ•ÇßñRã>º€å*1 G¾4¾z”„^wì×›ë(M?’Úi4÷0>=lüˆ*./4è†lÃB¼nûº4¨P" '¶f'ò$F¿ ¢üMĈÏy§¤ÆöÙ±Ú”ã¤÷£I`ND*¤3QJ”½â¢ÅëòÙ¢8L,xì÷ ¬{œP£%ZÑÓ²’-x”)ßæ%£büÂE`üš½Í“eDG2¡ñb¡ÎŽŠ[Œ5þ w*pïXƒî\ÏÖg&ÛjÈYäƒv=™ìbáKÕÍØ:(°z¿cß•øj·/¶óƒ¼LOpPuÌþÍGr/ˆ¶û·‹Øàüe}ðîyÊ$nú Þô>,ݼ¬`<4Ùï ¦!ü{bÍXsD¾[ »ˆÔFfƒSÞå§:ª€Åñ.a„­t³HÉ«ñ¶9¨ýQÉL&(·z¬u¸…_Èw,”yÙK¼þæ”m;fûüòn™io³éOK¢å¢j|%'Õ#Aݡʕꭌ¿’1‡J»4²ÌhЦ^ó$?Aº !HTpP^I!6ƒm¹", Ù;™7XœF›Ìª|2ÆGÌh6(€DÙ´çgÜWVzÃ`Bú|Qµ;Œ9îK2ým}Å$" (Ƴ~Å¡zéóñË<Ú©€¼ÅRûWˆ-1+¬'OJzÏ­¿6Ày‰ú€2%T'ÏmÆØu·ØPd¿¤š!Œö˜__nÈ®@'ö’!ÆCIŒ/òj¦N¬­šˆ/‰V¨Tòq!âÖ€ôKÓm‹/ \µ›´a­™I^æÀ§n6»Ú­ôb˜µUõ¦ ¤9 ‘­awOE™vµµ>{sÛ¢AF¨ñøÁz9쌅%Lݱ= ,ò)§\?ZÞµ½’Õeù6qåAœó6çs= ³›I©ò¡Ö¤Í æƒSÀVSfì]v f"œDM] ¤åê =˜µS©†‰´²Mr.âr¹ñ²ýÇ'+¤Y%tÜr0»Å1~bˆ-€l. ‹÷åw†Ì ÖÎ#y0ð5¢ÅÑçQ";›™Œ}M°ZuÍA`¾‘àˆ/Û¾Hy4©:”Fó.Gw`ŠÏÈ1ÔኛÀKÑAkûM²òžæç= Ç6½OÜ %dVT;ç³v&«yö‚ëÀgFD £6£ä"—IƒD¤%“ܳo¯¸•sPí®õ¤ íð=?¹i‘‘s#”Ïÿ–êiQ\zlñA°JˆCLåêohñmW!$£d<‹ð@´×Ýñ‰I|&¬Å6Œž¦$­!U˜†îó@Ò©ßGZ¯È.€Ò;n3—­®qž– ÊÅè‹Ù÷T]³ át[n¶ŠŽ(‚jø³r*Žã‚_­g®49}àcÞ‹ðÐbâÊ¡š¡êÜ–3Ry»û.a{Ùô£±Ýå Üg¡‚:åXÌIˆs_yy+.X6²'–œîfÁ i[ sSc{&]xr¼°×¾™Á 5LÉæî|3e‘žõõlX´@ue e4æA¥VÒ Ñyº'®à ¡-VMÝ/ŘO¿2k¸SI2A.xvÒ¢9?T= ù›T5VŽ¥7!—#V~—ªƒ×Ã"Ôº™X"þeÆXÿ¬¨F1§«OY¡''øé—Í£áeYk¬/'¡[ à\Em[Úûª•Ofv;éÉó諜~º{]ûÓgCiuX# “ðùo;ç¡o±Œ•°y5A%èN¿ŽæA†/#ÚAS±Iüa¨ .t0þðx˜ì˜[ðÏd¥g^é4nŸµa“øü:Ö¯ùŒCã¿‘ Z0éÇ·Ï0SqªŸ2*èAçejâmí'ì­ñMÀ_lÇ®÷ïz"´_]E`\œ¬‡¶7ЄáfÂøþ6 Æ"ûÉÿ˜ÃjÍüsY¼z,…N̼¡.ø&玱¤ª ÝyOÛ@©Wß1õ;;uîHØ.ø,wdâó÷{ •%ƒeT ‘“!öËɼù/û|St~„á'œË-‹YÑf‰ìÏŽeû׿óKB`®Áïi„þz,ùŽÏPnx 9™‰¸ÛhwF¬*=›6—K¿€l³DM¿NŽøOdosíoµÔœ¬ìx<‰[Ñ%,Q4WrÕ`LÏ>gW±q:¶$Bˆ¡×Xv3ÎÕ)jý.:;ŒùcEš;îÝ‹•oDpÉ¥Y¿:EÛ–Zü´[3aâœtÿû¦«¨(cž$o3p·Ï fƒÄ¡9û¥Ї3œ.ÓY—Ýžû~` æßYýŧіZN…ZJÝú3Óû–$9¹ëNyÛ$œMÉNØÜrx"#Gv/¬•×u»ð•EmÔ}þXç»q81¶ŸÚã}8™<Œ,N=Ó_¥Ð¨7^"Œi ?ñ+?A]ÁÿJýRÅÿ‡©8( 3l³<æÐ¤ ß©Ä=-ËêA0ÑÂ@Æ0¾ƒÿ3³69%ëÌÁ2T}zÏ•m0²9Ël¶©ÜèvuÞ$Ù¾’ŽÊ‘ƒ\­é!~âÿ·¾ä %¥‚þyÌ̦´¼¦vi8 Ñ-Àÿ°¤jÁðM/^»•ïCOwת8¶v‘Ì­LÁÒM>»^5‰±eT[ï# FSRçiug^/•|÷™ÓIŽªa¡w\;\pø¼(‰X&yp"€•sO$êMW†å¶_š|†Nù6@UÄ%ø»uâÑrt“xÏ£„jpÄ<:Ùè4:ó¨FkÏoqOâºíÕyhpÞ‡—Q¿2$×% îîÍñ[xëR­¾®Þx(eΨNB*åÍ -> øýÖnwåÙ¢ÑäC`“]Rp»8 šÓégðŒù}Ø„èߎȅÀΈbòÝñ,ro`NÛH¸f£ÐôÝG·|ÿnSêf~@/ƒ6-4L·ŒgsINûB% Ó7Á³¶èömù¡w½«•Ë&D€ 9ßTÂÜö‹Âð57**0u÷LB>ØCžP×93¥Ø({_`ÏTec£qèå âFìWVÈž,z Ô˜¡ç~Gçxe.öÍv«Niòjvâ@'Ì>N c7·æ>Þ(=²¥˜G÷ÝÄ^*Ý;LƒT&Gð$fÝ®¿µ!(ßNå¾K·Z«6¤¿Y·K§Søºqž,d_ü›£kcãa©%dZ#9¾ïl'aù QÑ]E”í»ùuÞ/‡øÒÈ?3j­ƒWŽ%AR67ê®pIz´ª œY]öèÆSÖœ÷xÒ†È+¤©|é L`ƒ’‰*%J>®´ô÷eNް˜ ~¨YPû¬ º•Ë]a*Õp®XV…,:«ZÚ9kŸ-¯þÚ©\f‹u§Q2‡}þtîü´+·(b‹RM7Rçȵ,öhZ_H®jptÑ÷à ºö•px"G^¸ Ÿ)®» ß߯"©¢u(ùùÚ5ËÅ (pÚI=Yøàaƒ-¬m™ÇféícP!Þkl~L¨ë:“ñó~Ž'`ºˆö¼ ;k-b1½Nº¢iò<+Yöщˆõ»×~ÏlÌ\p0ãBöÚJ—•ÀlÒ¶I­3/_ ç»À–e˜ÉüÕOšÏÚUã°IIÿ±ÜG\júPö!ˆÉÂ{žœño´,œ2–³ñ*4ÇQè9ÅŸNRør4"V]þF»°:Ïž­= ïÝ3^Í"v•æa³å¢Î¤µÄ²®.'U-eÐ~â$5¼§w…‡« @l‡šÜ~ð—‹ô1ÓL­möup›âZ`dVañ½‡Hîà ÿ8ÚhkV0;K ÓËJ@C¯A@%O I)É$j“cØÚE[ú£›ú¨ä¶*I—mÍ|ïSab#œ3ãz yüG¾t·BƒíÂPí) >ꯎ–µàØá†­G‡@¹:—Ïš/l<AÛ ';–wdýž¶TMŒÏØC½ýÛa ¿kÑå2ŒŽåŽl:ÕÞÅb”¸&ÔV„ªnº[¯ŠÜý$ª$,;K„+¶‘æ q÷@“¡~È4¡W¤/1Ž”šÂ°'š“¾5„¹'hwýù=§mR$ò ÍSáM½XÙ¯ÝüÅØ“èûò¸­aGĆ+=§(׿»Ê¨ÎKªxü=!NÈV’º»DÆÝÂhK0†ãv«–xxZ轞 niÝè]bÐfD£Õ«ñ/˜«w¼°Ôå&x´^@ ˆfÚ¡ý…ªu!÷šXÕ½õ_­²%8Ë$‚¡ñ§hw.¤ä¯Ù޹"ÙÏÓ ‹’Õ–_|FS™ÊÐRg‘ÑÝ.Rã®t¾ 7o®¸ulöþ=b™u0£BUŸ™à k –âž#dƒ IJ•ínøxÝ¡åzÝ0ITnÚUGö>œRg°'d÷%˲š„Áô‚+":­"ÇŽ¶6þòõPØBÈð Yš'Ù6¿¹8koý¼tf¤Hâx+÷-ì‘I³¥Œ‡²,ßKÐu™z:?Hfðù“ÍPc— ¾ü·„”Š-Û‡@úhˆšÐ«‰cÉúÑ; i»Ì6±bf[Øþ ¡®Þ‡$8Í1.Šœû`$“™ôBí¬P“Þ!w&b¦æHð‘á€—Ô²ª1*`™R€Èí"4,±_“$‚NÍZçø#%¸ÇHÆ|WÑCÂj3Ò¨W<õ’¸¹+ü[]™ìÑ€«hæï@î÷‰í‹ àR]ì:—P='5‡a¢äÔn6Aј\çùCIò«¢>ÖlDÇ‚ž8—ð7Ó„Û\ê#³ÐR«`P”™ ðx“a;Žõ@5@q%é"&`DTF£­8Ø¢`Çê+käF¶¯2/T{f@']oÞ‹ö†ÏG™ÜÂh‚×ÞoÐ’w •®$²aµˆÀpc)ÃzCxÆŠfSÕ ö§†78бa0}„/¥‰»Ûqa—è"óöh; ó‘ÌyàÖ”Â2·¢ÄMQòýÇOÊS?nËu IóÅ—„,3‘¼ðüµö·@1o¡ >e/ƒÂÑY;»S ø¥‘^bDú•%^ž¤ä&÷V%­(°x'G°Ͳ4Iž¹ág哺™Íg[ü|tñŽ(N$ƒD¯i³ï+E?f`P7`ÄtN+…ËPÉb‚¼¥ïiꡌáÃ'­—’¿'E:)̊ȧ ´%!€ìøÊøóãë½Ïh€xA¨Cy6L˜JQ<(™žB´ì|ú…¶Æ°%‹Üãp†¦ T ›kf~_}Pã=%}:W$wàö¾Äpé×”T=ä£c <å;š¹Õöw^ísãí.³1gÌIé…økCÆ+€K`wþƒˆG˜\$ÕÖÈâR÷¢nLîÞôT½N–¯*Û¬ê°Éêxѽ2¾á¯à¸þ¹L)‘j§ï’^»×™¹Ä 0·Î]ZFÚµš×Az9X å@ñÉF]ÄζŽ(U2…žrPcqGî\F{h“—á ʼðÚ0C‰È™(È”m Pòá¡uðvÏš"ݾdô^²æ5]Ì TŸ²zp]b#BL‘éD{R0é)Bv˜kf0Ä4SöØo#FpÉÞŒZÄõМÞå?.zC°¬}ô"†ˆô;}Þõ¿/Û¶?¹¼>}¹ƒz¡¥ÙÚÿNª‘ãï7Ñ-Í]€ã;.Yæ+"¨‚ÄÏ róª„È·¿‚±=ÂS ,SÈ’€ûxS™‹ùXÿG»OsãñJ"“f-ïb¬k ·BÑBdQ•’8ÜÆ\Jìо=›Úm¨~””% Ay3¨^GZÜÎS"¯µÉΉ=õxè„h-£;báIœ0GÁš¬ð.tKÐ/ê4ìX¢4•²‚aù ¤÷¬à©âãv«rßüÜ9WèºVÛçË_kˆI'aXô=º·*+Áw¹»~—ÈùiQˆ2I:,!‘6Ìè,(ô"¼&™øÙ¼õœgÉÆµ¬9÷·ëZóÂÇà£mFÈ+ìW˜¤ËI3&Ó¿á ©ä&m2ìµD‰¿i@¼òƒ S6žX² gvM||/l£éôö0#ÐånñäQÞº,{]$WÀ…F։Ÿ¸†J€·2¡ø‡¿ó¨¿Pd°¬‚“›Œ¿²;Oäå³,%lg%Ûž¢JUkkª.žR,0í¨²^<™œ›Goœ$ý`Î/y*‚'0¼yÙ¢e4 U[é·ÆÞ»æ~…7X|~~CYø)oþ6zVPNÊÈã#ò—l—ÒÀßqêþ>Ê̱K>ù ÁšX¯¾ç6rJ#ßLþUI8o¡æX,ôKB5xÅ)öƒææI™'rEçp  ¶gºÕž(þ‚Ág2t€ø$!Yu%èÎXÒY”¾V”“µ‘ä¿l ÿ÷yÖäâêËÚåPqt^ý)ĸÆùÛ[³iITy8¥Ó$9’Ž!ëØjÁÞ´àmŽ k™4¶âåFÍß#ÝœíÚº3äæçîÜÉ¿ç!ŽVPAm¤håQ–ý¯Õª<«læð‚3"ëÞÍ ÓÏ´×Ìiˆþ¯ P¬rzDÙ-Ÿ*y÷²Ë)˜äÎæû°^â6ktHj°OsÊœ)Èú‚•%¼İ&‘ã ß¾%…34­Ç#rnL“}(m´’Æ…–u1ú£Å{ì{óíÁáXWØü–QØ.|ÓFZDÄ«s §$³"ž!lžLC2ç|ôïöW´ òìã²$üŠa¿qD¶Ó²°)b ô\]Ioy¹]²­Ñ¢d"]üÃ]â©u⣡w<åݱêÉ u“Î4aöeeÇÍ«¸Æ:ß;Ã=ÎQã­§‚5V­3ŠÁšÕÛÿ“0?aO®úMša×÷wöFËô`©$çupÀ˜qCÆMdÀnvÃW¡òvjM»çƒGÙº2¬Õ5ëõš€û54"…¹iDÀi(a‹¸»aˆòTody¤(ò–ï=b½`,vK­ùåX½5wœ¥ ½‰Jiز«ÚÓ×QÀ@©]çDÕ :«GœHh{L´¯À4SseÀñÈuĬ¡CãsÔü{¶õ#Æ.J5试¡ÇìlÑéü¨§4ßf!`@"ŸV…¹žùgÂb£°—=Uï¾Ï®T_É‘õ³É‹¤«¼Æ0@áñœŒcÒ±#ú¥jºHñ1:‚,%úºÙù®MÎ𿳖GK¨|òÈë{ÏŒ^$Ço0À¯Ó¾šõ4ØÄð“Æhdd±¸³>Y ‹¼´èØv–î/ÜÁ衺sH0òMQ"äÀ§jñˆ‚syК´ïwj¤óšS'\Æë=~!¥Ù”8L0*ÁSÂ63 Á;)Ã=âY‡ÐÖõ‘Èn#"F¥5Ñn¬º•wÅŠT N ²üæ÷žÅ@×QÚþ¸nX,0JÓâ|7$CpCDÈÆæzÑ‘Èp”ô,"× Äø·ÀEr 9 ¯Â ~]…¼¢¨ÿü„?Tº2< 6ËÓ‘}ñ¶ýs\í»¯ŽV•w÷µdx¯6É%f>^«qèö BõbJ^’g¾X|JŸ;×:.<²ý:?iù˜ÅÎÜcÒžïG+& ÝHÓ²v'Oñ]ˆhøË® õ¿´(Í{)Œ¤¾ÿ, íHtÝÄø‡¶f ÖõB'º·Üðû1ëæ ‚jj°¯-˜¿3Ö'³4¢—W·ñ,ÑpD?q^جmH®žÝz°ƒ=ëk][>üSµ£ :d «õóçÉúUج¥%€ÂoboŒà¬_Þ4´„›6rŠC<¾JnîônFˆÎÑÌ,n-šÈ rµ~K2O¹ó;[ƒ mÐsN@FÃ;ůb.²~WqAÂÃNÔ{…òèÍsE„D‡„sƒ³‹½Ü,(}vòø´œØ¿2l#bu9Ó6À7˜aÄ`Ð^Ä8Ë‘ ¾üÞÍ+€ßSÒÙnΞ§Æä²ý53±æÖgܾ ÕÈÓ±¸ïèéç> ’Gå|»sPùÙµKò4äq"iœ…ó/¶ÿ5ïsu®¸åE«B÷y8«7*7§‰µY߇?ÙŠÈ(^+E¿w5î ÚbûPy{hê?ϵ,Uz“¦ð;3êj €s£ŸÈ­¢9‘~%©Î>oÂw ÅžùJëêQ¤Â/€®ˆ #’Å2¹¬¯Èâ;º£»JkW¦-yÜÁØËå”§{]ªLewˆóÁÌ …R°:©r2­ÂÕKJãB¾54cò6?)Â_Ð'ÏJ…­;í‹áþ%iÕ÷Tíy{½3¤éQ2Û°…º—<ÁTƒ|¤D°}”@¶ç6ˆHKxeæÇ›;ü]Ë$uJ¬×Zâbð7·?çZ¼WÆ$_qmè§4ÝDV “kÁ€%Ë÷Ú:èJQÚ(¿¤`A­V”ÔËL íX=’FJ©uêÊ–#˜;e9íÄ"j\ài*°ó©l̪9¦sKjwþ¨3Eñ0…ÉóªI)ØFꎉ~[½¿ðy½ö#¼øâî  "•â³á äcÙèFB¯<Äò°Ñõ¨…èW‚- ¬YÚ°}2 ÷ó¤Ø ¥»ŽÑ]¡ºm@Éï´Îɉ߮ÇÁïb§Ð¹Îì³paÏìºÿÐëÐjDQq=ŸÄû­]²b”B²§øwp1'&ÏEÛ!ú{Tý[1k´v¤Û×SOæõ$b-¥À÷‰õò_EÕå£~¾6̉—~7àj—ò“h“";¯á-4Â8ƒ¦Çó5•pD;»—û‰ô¢pC•]˜ELAò(C§øwÓ"Ø»ûAÎÅ@Üç jT"mPý+çÊ(ãÈ“ó½øpãU?Ü:dÜráÍË)o BÓlrVî SÑWµVlWy¬¶”¸ ƒ_7‘ú¼,‚ÆÍ§Ü#»)^dÚõ šQ«iÄ¥všLÈ4WwØm¿ Ènxi´³7ì?½aÿò%ád0ÁÚ2÷Pÿa}æB@¥¨mæ•UÊK1 "TTósN¯:»í|Ÿ¸TtG@Öšê‹G%®TVÐ-“ŒœE ™w…•R8+ 唵[8T÷ÝÁ\Vñ˜&M?:ŸêA^ƒ„½Ä_žÒ×ß’þ)cZë¾$‚¥ê¤½ÕYÑ;“‘_‹Šµ¯Ï®wnÙÉo}Ölä„]äšÈÒBIì‘|í‘’@0ó;˜1¾…Ñ!m®£ Ô ûôv½ïàóòì3V¯CCó`É\OÙƒÄ5RÂ]ì¢g€:¯=Wü\˜3þÕ–~Ó$ ö…"?³ÄW©?m}ÒèºN´‰#¦ýýs¨dWƒ¸K$]¥º ‚DXÐýI,B˜c]+&¨îùÀMF™ß¹ÏË O–j²¥  u—½Šm;"{È0÷’*»¸á&¶7p½¬ø©“ÕŽÕ\ÉBü ÉËðlqOÃó8“¼l›Ì$å¼2q˜@ËÎ c³V]kpx„`¥èg,`Û4¼òsebR­¨ 5 `TR2ïm‹#žXƒ ¦ÖRɱb2 ÑIXÜõ‘Ez¡"µÆp[€~5¨6«t T^2…™£&‘¸zKÌE,ñe\åiÆã1Øl3<Í:³ ±‚¢Ýž‰DZ1óîÔæäÂí°H”{0d?£â|i³Øh<µËdÔ ðå‚0Ú¶æFu¢ânmr”pEmŸÙÙÿV¥ÐáqyzWr“¾;—ÏnfåUl/ÇCqºß­~@ ŒjöÔæåkz”À}mñ×À޾õà!4_I„-$¶“èúŒˆcNSßfǨÞ5IA*ËøÔˤª0/Æú*·Ù–|Š#.¸2¾ö]mûÉ”:ÖdA€ýø[?ÖÔªú\òÞPFŒùÛQBÊœÔU9 W»ÒvŽ­ª5‹Ã¹²õÏû*‡ððËRwͶíŽàÏFž &™ÈHÞÎ{Ÿ\F g4^ß±à›EˆËº ¥’#¤¯&ÀÝ^'Òï+÷çÐ_E…Œ)•ŽÕ¢¿šè‰Ø}š¦ž0¢y~¶ ?rVOg ðlƒg„gA¦‘æf¹fì¼)4`h®V‘/’ÎULžspª`N.Ò‚¶DQ?sE°ïË,~£Ê1FB4ÇùRw)sÒ¤qã,H“Ӈĥ hW~îãÁÛ®Û? ‹Ë›ž3uÃÙ4!´^¬s¸‰å^K)SõFxbø¬Rß:ø²ç‚3¦m¡+6­¦‡±-û1Í^½‘ê…¸«ý¦‰xms¨säu{°2eà¤~Ý üI¶ÜÝEýcÔL)ÛâÒÄ%ƒp.5'¯äöîmØ]ìò&õ>«egæclS$è œ ãŠD`óe=$¬A+2´ët•`65ÇvÁ}'£6¨áêôŽëß:5Z0¯Û©øErªò?(÷œ—ÿ9äB›‹³š´<$ŠÏÊ®½ ª%«Æn`¢Œ®¸”:ôÂÏq”¦DI’¤$‰öL¿nQÇ œ^Îs]Á[õ³ø½ü §Æ.›0IQS*â#Rò{ á}ñ”2ÑL‹ó?g¯A?:Ë)=7T€1z¿?¥ ž¦ýŸœ· ‘»Méü•æn Y.$ |$‰¸u܈ñ¿«·+ü&w†ë©Â¥Xg"?GÏÓ "{-œ8JW{}<"j4• Kÿ ¿¢ æ2íÁ­tÆÁr(³š8ˆ–vJòõ üC<ÁGê[³œ5µmòœ^[ ‰?ÚǘbÁ§«³%ÕJ˜ø`[»ý1ÂGÑTý’t¢+ÖEo\§¾qL|ƒ¨ƒ\ˆ:ÿ­Ó9w:>lU‘Ìá4KÏ”ÉÒ <~BðOhµ£ã {íéãïf_Â?“’J†‰éÊKçä›%©®¤ïMÏmÞ« NݨGàÜYŽ€¬“k!ÀÆ5Wô'ýŸöf U!nã.ËÐâzM:ƳÇr 6aÉŸ^Ø3µò0ÉÊ¿DŸyˆ\Z 6 #u²>ö3º'”¾ÜVJåäõ]²j¦bÒÕ@‹ÇӢаtò€¥Nàdd4z8öHv(šÀ2"ùù·ï‹à=k D…’Ÿo ë-½íú€’,&{?ò`@ú>¼uïbQ.ÐlHfëÍf?!'aÑa£÷KÔðæÅg?ã¢NŨiÞO²Ž¶y¸K?Mv×p™F@p]zð,ßþ›\ RÛüJ*›8øUFTí“€Rp®üjôù!eq:ŸÄÈ„ä[aû ªËK™ÁÏÃoäáÀ´úôOr\¾•â:ÆÅc4@Cˆžƒú~iBc}’ÁÝFçMו1€.rp°÷Œô¾> –‚‚,ÙÏ·c†¹×î@ öH_Ê•[À †pSì’¹Yq>R?²$gÊño?“–€ä-ÛâËe«å †]èUGdÇrDÄÁè4rGp5>ˆy”“à=(®´ˆXAªõÎÁ"e½h-­íÓC& +?1WÓ%°Âj{ŒÏ¢Ôäòu×´ýÇïz{Ü+îý?ý\Qý´ h¹×&@cǽOÕí^cð7›’&‡Š (ßËSÆZß- 5™õ%ÇÏNÁÿb,dŒ•êûÎqÕ>ß¹£D„Qiˆri(®›pUÇßÝK¶ÉÚ‘©€T3”\èH4ª«‰w«j31íØ™.R¥´"Оà W^í‡Æ•›C'XUˆ‹Õˆg– qm?/}ê7Õ ÓüaZÞ.Š®ZÀ:lïäø˜Aã€uìm7=,ÜÛ{1_ðÍ%ÌÉ’ò10X8Ä#`°j9XñƒéšÀúmgÕÇE¡ðxãçÞ¸w\-FMK †‰+ó©œ÷è’À|ÆSáÓÀi äxÇ@†›$†¦$L[ûMFô«O‚ã‹ðˆu&ŽÛû0†nLÛWÆ+ÛbQ‘¾"Xcl? Mõ¾EJÓBø¯ö¾û—¥#ƒA¼M;šcË' ÑÕ‡†ÎÝ/_mu'?(Ä/æk‘êRÀ[òeAØXÅFï.NÓÑfÜ“„%ßUð×w•”ìÀC7—õM3Ëb,~."ŠÙšäi«Ê(Kݬš&‡0€m õÆM7W1•ñæp©Ñ]oêCyX_œë£¨Ä9k` ãUwô] P K‹ Äý}fæÔ2Šnöxåu¤6Pv9&‡É•Ȫ*a¢¶‹.‘LFº(nþn|ûêá.—¨‹_ÞÏ›`Kó ßË­ñ˜ëŸ{´°ûlPÄ C‘6; 5ݲáR®Ê¯9€$ߪ_ÝÝÝ%$Ot O*ïÁq{š¥ tVùÁ,g"öUóšŽ{‚ÉÀ†·Ú ý$Š™ã68cQÙéæq~îka™²G×ÛóÒRêër#(C×#û P›ê áô,8—º˜Ë°‘Ia4:m”®—ï´d3.7y¸_çûJ¨ñ#þ».©ywýkT#@€wÑf2Ö- %kùóß=OeB àÁçPøÜâZ‡-ƒ§‰}l+œ~Ñ"š]œU×=³L±ÈÂÞ@ŒìyFWuéqÜùmîþE:¯xIžE¶”ÄXhiÒß„›M¡·%fqh€ÿ8>utàôõXŽ6»Eüïz%rÿcfýPÎfj„q!5f–U©^ÚÚŒÀ*Äg§’ªðÔWòÕ­ñn,ŠŠ4;³l¿Y)±@î"¢æÂ h»¨íB8`!Ä“t ž$‘øªñŽyÍè^"ŒmF,ÛV/€Ù„º‹´~â¾ÿuGý ·´Ïj›C¶”ÚÞ’ ’‘á!ë¿UÓúqy{þ#y“~yúGp*#wG)\®×'æµkènöš0‚uËѶe†u3šg ý\øòi!!§#|46MmIÔäã¬?©[oÞCÏ\Ëû¸±™›9ûŠ)ÑúyMèÒÐäc!\èÃEi“”pìtâSS¨œ=šYd34ˆÏµÈËñç`MÝó‰ãã>É|E _tZSK«,ÉnàÕY üæèpZ2ÙÓ&!á™V4R¡MZÐ ~’£Æ@‹™³¹Ã—)sËAcEáSBþB¶˜2¡’¼u‰2毓8<¥Y¨OXý ¹JiËYg^žª8¢³§/[‹˜O’›³iõ1§gÉ^Ø‘ÒÏâMØ‘6Êéq ƒ^Ô•!óHÙã gTIØ…¿êŠ:o2.é‹7@ɽM=J"bÿ¦Î|u’[DôIHLMµ¹í¥¥aé‘îO è²Õ¦™7Ñ¿ìɶ°º´Žð,wá§Æ˜5…¯0wHÕæ oä¬ ¼†þ~¬@q—žI˜O#óÕƒ>j&E IÄ•àz[§9>ëúZ>úr°OøÃúá#Ń™·ÄÖÙ|¥üeØ 8ûB«œÿ•æ–3± B‡{³Æ(1ݘ‚ÀÍ×Ô0‡ñ§*Óg}’§œ¦×cÀT„Ûž÷N. ®Ó:M¨ªæÆÚ‰€:,8ìÝÈyÏ8¤²V5òÇÕª}ýdî”Æša^âPj7‰…U%êñùÎX‰° ñÓ;¡ÑZÌîv.>=Y´Ûƒ—(–ma<>æÈæ; ¶wŽ¢¢ž’H÷؈ŽöÊ1¤’ü™ÿ&r¨|ï¨:çM³bÜJù‹f–ú¿#᯷’üäÙ㳈¬ã¬û¢ëôs7­Ü q›Hî7?ó>\¢¥¦Ñ‚Þµu‹z¨36ÇνµËm9O`‰¬¬±”o{Å·ºãAu¨0¯Äf—寛Ÿª‰s LI8ùÜK’ÐÕ’êë U¦”òþM‹Šuæ„q=þX²8T€’j\#ü¸f™Qp$ÆÃ®ƒN{×qÏæÛ6Úý°ÿRظ˜ÇÆÔ½(xI˜ì?œ<¨$‚‹NA5J²—Ž!SÉu,  ì¢:i8Ð-î;^O„eK®K3©W0)q¯·’7ÝD/nCPC´‡^ötQ‰ÌÇá}X×ð‹fLÑ3EÄÔ*wRQN e·F{§[vî2¦œVËQ9IvmuÃ2mˆAW[q¬û»Ïf{!˵Óå `ºý™gÒ$RùtW§qe"¬šZç§f>éäµHÊnþ# :,ÑU¨T·6]uäÉÔ><‡ÿs¯˜‹1 ¨Ö8»íËÔ»x,Ê©5:/_ëôó{z*šBs®Ð´¨N·¼Â&Ãan»qäp’«ŸŸ×±AãßÐ0#µ®“òûK€H ÌÁzÅÒûñfB†#¬m€œÊØÆêÛ¾MHÓ¥bɯís‰ a`žN’}` ËGË5nß\¦5³¤ksÏsÞ|wY£ovta¤„;ÇJzùuº&ôjoÆ\#=ÙdËåSH²!„º+£XC"ÓÌv$øÝœÇÀH•uc ——y:)âÀCmñ¶üKéšÏSîú®Ê[zÓ_Ä9XÔ ¿Ì‘9úÑêRn6KPm”4/6‰í¯ÈpO¦Ä†|ÂSzž´òTëQ©eÛ2ãÕ¡³6–¨ƒ¥gôØPš.\ú°Üøýö© RŒ[¬yØÕŽÇÞO—\çlHN‰=”°ÏáóÜœ#k嫳IÓÊÆ9ûi…g›PO]ßµ 8ñoŽV ÿ?³:™¶s/vÓþS=‡}Z6T‘QºsÿjLbƒgiÝÀŸx•¹Ëß͂Ҏ»ÙHÆÉǶe}À‡S§xöPô¯n6ŸÐÞ#®¨l›£ÁQÙŒJÒŠ¼LÕÀY¯°JŒfj:·ç-6€S 2£“S—Ξ§“½’™2³6ެ+GA;Vr†ûJ$Ï_Å40šb3 œã¸}‘yu¿…H&qôPH½ó¡Ò—¦º>ݲ‡Lö•šØ m¨@}FèíN+¥ýÚo<^VZ®ûtæ*˜ùÁ9iç?¾Ý°8µ»¡ ÉÞ­"Z—ü‰"L ûrËèÌ’ÂÆ};{øœh¿s.ÝÒ"cùîÏ ëºÿ«\ìŸÌá|v‘áC-`dçCa[ìp&EÖ|*œk¦±œ|ï é=¶(©G8‰­(éTû2ÿ,šˆn/S<#Yƒñ¡ZIB6‡5Á›C¤_.³ç9¾„‰öòå5S2/¥Ï¥•Š·€EÚýT–ÚRµ‹Ö&X“¶•s¤¥Å…L’7tÕk¾Yã@løø-ø?tÖ§´R”êú­¦Ô2L/ ŒT+f3·ðß'êe/ótþ2CÌ̦ÍUI3%׉€ºïPÊÑ<÷*ÊÁ4ËNûÊ<QÇÚì{µþ4ÊöïfÆŠ‘ð94>’<1^Ãóo)P¼*4ä$0t›a$YHV$¥– š§Õ~r\³X•á$é*1ÖºM,DN5Û0 •Ÿ¯Ð²¹KxmË«|7É3ˆsÄ-zwQ®gì–@ÅC1³¨…À"zɩՃù ªí X,—¤÷ø‚„ÏñˆZ• ]õKÚe^¾YGÉÊÉ™ ƒ€²éP‘Ìnö{çȓť`˜q‰ @e•û®E¬—J_ û `øäA¢µDYf˜×P Þ”Þjbe±ôc-×Çtã¼ÂæèÅ• ì@¨øw¤öÊÔÛÿöú6qQ2Q¡à´U|ÌF{}ÁðÙó€®é%.”¼Åá÷ì\kSg0ŒqmLða½ •†Q¬ïÁsF`ÌoŽò#ò+g˜JÚ—&¹¡V¹Ã$uðÓ\,YÍD„¥‡ÛK’ž²öséÞê­¤îȨ?ZTóýÈŸå´‡úCæyåßÝòÉ›,K¿9Žø|B…—Ÿ®!±Ál º øS>jžh˜KD†|J…28¦(-b¸MN[Q;t-åªb>èœõêë‘ÍÖK"»:)Ôù„pnùë »DhŠ´h¿¡\“…?z@sá'²,$á%;Õz¢~:‰@ T7¨“W•£B°K¯òùP$é—Úæâ »Ó"=õj#• “¢òÓåg Óò8eõ’ÉŸnÿv=˜ªù·Ñmmþ‹A½ä°Þgõ bðÜD¸çëó~Våì; ¡a4E8ªÕ0w†ŠñåakÇ>S] Š1¨ ÑžŠ×r-H6èÓÎcü;|7a[Ÿ¹ÖÑ›%Ęƒ)L•xs¢ý/(͇žjgíjÀM”¹¸šv±‰MÆæ}ˆTwεÌÞþæäyO%åí)Às#>ØÄöM½FÒ€ë×Y©YäF\qr<±œþÞFt&e„¯®OGe·IógÐ&‡9ÅÒ¶&{á¯e€ÿÙ!l=*Њ”£áÆap"íT{5÷Å-êÃÊÎ\òm匎~\á»WvLX]aƒÕ>ì†@{ÒR@劎’?¼šÚ'I} ®›Ðæ±;4à÷­½ˆöš•Ïm,Î;Mjèvº'5¨DÜù³Øœ€BfiM½¿0P€º‘P4<"Ž>@7ëüðرç¿)„i ãŒ$q(2|{td‹‰í‡¤Í3îh§sâÒ°ÕF» ´? €nG)æÚQH`2ÒÅZpÓ§ K6Üm¢ÆØ¼v[-Ö ºÜw¹oQqx-&ª^á\ß& z>è’P ' q¤ÂÛç"Q{‡‹e$?F‘ «‚ºÇ %ágL9ýºº‰b6ÊÓŸ2‰#ûqéø[~GËÖ3vVß2é UÀ[LÀz¶ç¤è\d+Þ{²®ÊÃB €ãÐÌJİC=ñ$ªÂ64«³mF@]úXé7{ö %]QÖ×ø ȺœF»;ùóÿ;J7»¼…Å­?* ‹¾XræÆýȬësœöí[ÿ/¢²a€*O+ݓֈ$Làlln8÷±œ]ÇaÀjáí꣉óŸú9W¦ôîÍaK®¨ð8Ë!3x…²ÎµÄç²Ér^Í©TõмÕK‡n´…E YùãI Ç!¸ÓÏu c¯õïÏïº7ØÆÄ$·ÑbBªê1!fâ¬÷B+g7á ”>ÃáFä¸5 Aº’Ç9h=R!àm|+ÈMÖ,ÔõvvS¤G碩Çp9å%ÌÿõÀLêMèìü)Ö˜èj\x<¸Ý¡P'ûõ‰FŸiyJéègůgŽàgeñŸ“Ê,­ŽjÿGÄ/È^Ƭ l’ð!änˆÚ•£Ïo×eG3j 4tu;±ì–÷ë¬!¢ŒP;A²Pï™ÆŸ ±öd »â¸éE1FàÏîÿè‘lcàaªfçYÕ’•7Æêò·°¥øÎ<#7lôÈPËéV)Ó|eäßó V(&vþN*È2Å{ZݤœpŸÒ¥kb¦24n©‰©X¨Ï"·}ƒ¯ëzi áÖEéô23Õ’R\Ûlu&AÒÉlwDyT^ˆCý;>*AB .úº Ç9œ­`ÈÎØ¼³iˆìŸŽI>újÍb(Oî o»êî٪س\ßa|$Â퀈‹”«‰!*m'Vm`² Fqïvoh¬ÁÚ|IY8€UùÌÌe8$j—;÷ö/©.kÁÀZ9&é­×Ϥq™Mn>ŠÏ"v‘e¾ŠÒ½£ÉÉ3:B¾¶3lë†û 3’Ÿ¤ËÈ ®rä·€îê= w”•gÔ8fÔQ$¤L{%2ZmüM„‚wÄøo'ƒKÖÜÁó0<“í˜ü0Äü×§¤¨ÌF¬YÖˆ«Â-4˜Dÿ–‹è ö‚õè–MXQCï­-ÓZŸ©W¦ÌÛ80ú§e ×!õƒªWA]¦óäz²Q¨_<¸<Áëûï~TTý¼Á» /p¥ ÅÔ’4J§¿¤ˆð @Á_ö/Â…w‘ÖÆ!2Û.Èw5Cù2—jÃFº©‘ n ä{ße{:œï£vqæÁˆaœÞˆ°AÓ’‰Y"Ë0ÑòN—ìéWõÃÄûÍ^h'(± åÍ©™7Pk›[ê4Q±ª<«×0À߸¬©3„&èØǤJÚ´‡tl\M¿T”FS¡Þf©Î®ÝÍ…–»…ȳb³ÛÎ{ÔrPJ~kW‡fƒaÏF£ À³JØ5«j]šÜ*² ƒ)­!I(9´tCkAè7vú“r)ñ²d˜­AʑٰK?E7]|1¢Ü¨DBQH¿"Rb*íŒÙ Š¡øÉ*bÐ^¿ãu7C…YšŸõXÙèISEEÏŽõhÆænV“'þa†ÇÙâÿ=ý‡´QRæë¥´jL¼%Méå:Ðûö.{ \-P'F•V^ x—xØÉøhßdá}ï`ž¨›œÌÄ”®3ñ[ ú<³Qsrºmû±_`÷wØ RwzdöIn‰•v˜Ääš[3ÖD¤êe)JÝ:ÊáAì(Ô•‚z¤ œÕ’ø&4€ëÝåi¥qã§”svâTfpo¢ý*N—¶ˆGh «ú"Œ„PÉÙüšžƒZ]¨È #$Fò›HühOÂê\'ÙäßÔa¼@frëR{räx·æÀîÖ(O€Ñ¬`C©ÚÏÄ:É;*=Ô”ÍÐè4›—kƒò%$%‡¯*N,¡Ö93sÁ–XO~{l;kw÷CñîÇÂ_Îwøj&¡€T*·m;77Út°³þR)ÓçSGp¾GN¿ÃÎLù©Üt0#zô€¸ V—蜆STkøaÉW{$„ÇÑ)[Ož;Óưa ÐÓâCÑYMqL “j§©€>κ9ó§õSœв…;¶Ž™~dÌW^AàÐ\Vâ'€€-š_–ðËóEÍdz«ì‚MË#§Ê÷°°½îu{ùë5ðœ‰Ð‘'Ýf½GîKn£‘ª§\¬q©Ú*9rvác¯Ì$Š{÷N¨Ž—Án„$ÎÏÜeÝIÚì-ßQ?Þ y³á]{H9!½d¾FjòŠ zI„}HõÉ4ºÖ0jCª6þ…KÅt(#§y¨ vÒlJ€(Àz ˜bŠXZ8Žç '”$å/:P§þìæ±ÿÕ»ç8qj­Û?›o×pt¶S°‡Ö‘1´a!¯úå¾_,¤V&&Úµm©xqk¶Zú$ÞÑm¢¬+ƒŒ ÛGb–Â~”V¹L>ûc¶¤ÐˆzÀä[·RJSö~ÄűÊHÆûê wXK³AåíãPôq¶ÃJÀüVµž0@s¹î¦+®(^ïзqeÃÇiï×c4¿WVÕüRT:A< ›`1`SÞ‘I¡Ï´Ð¼?Åè?ÄšêäRͼbìVðäÞ‚YS΋ ¦€?o_Ñ|·õ-¦<±¡¨dXÇ$&3ÚrqÑ• ;ÅÒóŸ8­­®‚?î.‘Ùœ þŠõèâî&YåÛŽË[y,¬_Ç$°ÍŽ^¤ØPÖ0àgVŒÂ'Ã1ÖE³gµÚJm‡] œFŠe| ^à|ˆêņB×z‚e,ÞÒ¹†¼´x}å^=ä‡gé*®Ì¼Bòà{ˆ&Lê*$;9°'`.Ù+’4´8›Wöüé‰Rïua µÎ ߠׯÛ÷)u¢F¤(%7¸‡[`ï}ÁÊۻ—™…f^A ÔïÂ:YPM?ZŠ)zmþå?Gï‰Q+tev)¨ž³…S?®Qá+O¾lþ‘FEã Œ¯¹"ƒ‡þ…`ÅýJRð“íÙ¾Öæ¤ÃïPàbjI¯ýÛ”ó¯¬ýL’í—}œ8²‡®ù{çPß°\´›§Í· e±TÉÚ/ jÁš-`lQ-á[ŒQ''­¼µþU&žpû`+{–A¯y¼F+È7ÀÉÚ™¹€¤ô›<ÄGPÔS\0d'#…IgµåbóÐØ"לµ‚±ŸÖÉSµôY™ö€ü(2#3'—·Fo#§D–Š«´â®°D¨® }iR5Ié&µbŠöÖyÏ^ Œ&ØÌâ÷·§o@ §uèòíBn…à\htÅYÔØ=tB8| ³u¹Wõ@OlIg‡µŽ‹‡ó5ñ™Ñòï_Þ˜»qi7,_‚Î9kV6ÛÝ­ÍÅ0ޱ<&pò…€Þdž£d©~ž×ÓÞ§Z]~L²ëÒó ¥­xeCÝæ…Œ·åPhæà1ÊbópNwõ‰žÀ‚Vœ5Ó¸=WBõh5Ò\ÿ#Œ˜ø[™eàêôA®L£t/8'S©ÿÝɃª(–ÂüV8Ñ×Rûí¿‹öº¶Vå9BhLâz |Ðâ¯XãÞóªm´=¿¦å+Ù `ˆ§h½zïkÔì,Hòí‹—¿[ –o¸\„tCM•òmhìAˆáˆzd‘ž:ï. Zò<~Wè ¶ŠÐ",¿â†¢, Ãƒâ¬›ª+N‡=ã— ÏÓÔDºìJ8‡‹ú’Ke}釛YíªT úi¡/ôK…œæLƒˆ}°Ôþ6¦K0RZB{VïÉ é²°Ýã¶îûns¸,…Ô¶±€núF‰£ËS´`'Ãå¦Dy¤T`/Þé-¯Kò —5*žÄ6['6Êlå(¯2ÐLx¤ÅsÏ3e†nFß,gû:UòWø5Ð#Ñž^äºB­5ºO«z4ðÀüç;,¬>Ä.z4 Y@„гgcÕEÇÞÜ7~[ ´|DhÇE>ó=ºi,¦ç¿mOŠcá«ÕLpÚU:—hb-•¨ôF”´±®š÷ÞÙ„ñ‰6âëBüÄÚ#s²ãçŸò³Ž›n€¡fs`_¾ŸE4&?÷šr]][pÛÿù/\­ÒQ%™Wàç¡…íó×å™™uqúß6!·ÅÎრ¨£%{ Ÿã˜qÚd±ËQÓÕj×Q˜b8s€"¢Wû/’³1ø7TœˆsDã{ê;9£G6;ðEö]íõ¦ÍÖ2Êy­¡™HÍJÃ^î°¹†uOûåÑ'>ÒJŸ2Gúh  ï–U¼|{B /OcO$VFÍ¡vö< Y­Œ¿”Ñv*Ù'LW3@YÛ$Œ¿uÖ£Iç¡­„ nhêå—['â™G°è%äS-Hw k ËiDøòü˜ É?–œœ+päQÏ|æ,ëj-)/g ¹Š"ù,þãº(ç¥ÜÉ+ó¨ýƒ¥;äEñdlWOªÚ çMÝŒk.ÕìúåŠ7o‚(®Ž9W6E§ÐNÒÉ7”èçס…„W ’£8YÁH«î5ÈÜT‹Äj[Ëõ™¹‰ûp¤T£=Z>rÔû@RØjCïE~™¯ñwꃩwo8›äùÄ‹ªFÐt®›.£{´é¯¼{.ÂÔa¯9²4•ëQg¨²íyÜgaþ'ý)F­Ë“'æÉ¹CIœ¥ßqOj ªÜÍ•aÿ(€¸m(µÎYñÛ¿œat«ãKãtäkëÕÄ”g…°voyæ—cÔÄä ²—¯(j¿¥4d}ÑuýÞ™¡AÑ¥%ˆ!àDÏ;RNz˜û¥¼w5éP›„ÜU ½&ÜýÍŸ34pntÞô*€J· •‘S~ˆ¡°Ï>î³;qtLE?\æ}¿Ûü#BóË•[c¸Û‡öœq<•ˆHT-ô lxVG߆î\ñ[Î?Dýh<€Æÿ>K[;tÙ6D„ö-â@¦àq¨’b¹4R‡pÙea&ey"ä–ÁPxkÖPÿ](˾¸@= C‰ïϨžäçx±WFÅM³Ê˃UGSJ~};ñ`k/]!,n¢h)?­Ÿ&)«Nù»´«XmuéŸ2Ȭ¹?¬Ä¤.Ýà9ÅE‚Çd! &56<å:œ‰rú¶6¯]Iè@««5¨£kÛi¯}w(N¼¢ù÷Ì(2³ åxü J Sñ€¹ ‹óÝ4Ð~EÆcï6ràÿ¥úÍÌswfTð‚›“.¦À*k#YŸ¢h•.”£bèýRˆ-lÎ±ÊØ~JLùè6J¡×GeÇÑ>®¹~¯j¹óDÇháÓÔ¶m2ô41îk#ö\½ã³XæsÁŠ|ǨG£c×¢²<Êû4¡!³G…Œ-¨Â|qÜ&ZÖÕ /,‘V1H³Ý¸ypœŒvjyì±Ê´I‘”þ +O0wÞ7S:5‡¬!bü”íá~#6ïP“Æ÷Åæ~ùQUw'ºÿ i³?Ã…ª¼’:˃ªHºQÈ Bço¥ e’w›ŸÝ"(¾­ÖL’£©ÓÏùC‚‘µ%}ÆM*UãôjÝÁ“…_Üë•/ÄèçGØ[©Í$·ʸ6OøÝûÆê'• j©ãymÍï½û¿… „¿,®à<“'y,‚¥G:D n¥«ÖC4êóÎg¡KÀœúuÃñˆ©0(-8'#ƒöÒŽè Û{hx¢[š€¿vv‹z2‚yóŒglú5k°™‰Û“¡´¼û% ˜‰Ñ3OU­¥$å²çÒù¡¯|rÂÌá*±pß]Óšç–ãUösŒÖ.*<ºŠ ³µìA„Ü“!X}½uáoÀœ•551÷¯À¬²ÔÔ¹.› †7sJ.…0Ý\YEO=usÅk—–™Œm}óB‰¢Ÿ…æU‡°¾=_z!ÏŽf@ÞcKöÕOÂ7²‘9Ï l·þÄØŠÈà s“i_; 4VÙàL“~  pƒQ_ËYäqµVÜo^K®ϼQêކºUØâ’—Ž[÷)Zø÷¯ò#﬽ÿ±k9ÂÚ”?«ùkžºø]¡p®SÜÐ-xR +roK-Œ1²aT/„#k½¬ùçzt!Go Þ†s ¯Z²µRfišNuP·Ú9ù× ªÙd+àïšÈ\›«Ðœl¸3š8ÑÒn­OtYÚ¡ç6Hµ_p¨þç/’sO'K›àŒ,Õ¹ºÛmÀOI>MUÊ¡èÀ“_õÂ%·½*S=äöí´Ù^±aõ_ÊNH3$Ze×Vây¿u¿©¡—ºJ£K›mƒ‚†Òú‹¤íÖ"JÊ÷–$rgûÞOÛ@$Mmö¦ Ý$X”ìží ªMM¾?¢ô`»šT,<âÜ®9Æ©Ÿ! ß³cgùmî›Ëóªîš…ö›…ÍòÂ"Ôs=Nh²;ñ ÝÓš÷šûÈc¥ù0µêϯí„7Ä7NQ%dbvsÅù(PK4ÍünÓd;ilÍë Œ!C3‹D,4uK1$›£õi š€…ÒµÖß‚‚WªÖ” e‘a¼W¿ÙvÜ`‚$±»0ïñž—.h†çµÏ¸º>Lô çt,YÄËúõ|Ì'_e–º+Q‘n™—Uù.`êX ïã³»kÓ˜<&f`€ž—;µ=‡Í ©µcÚ¯"•«3½ÈoÇè|ׇl]„‹TÝ-ÕOé7¹oZ:ÎUŠ@ƒï¨±/áOúd6hp+zÎÕQcß—-dþîQ,êßìïDFœjÊäHÑ m~ £WjØ=u°JÉ­œ„ÿäýÐÍœdc“Òb ôô²NpdNǤäÑŸ\dâÛîÝBøUûŸœC„•²æVC€|É5´Ô4¸…¤^’HýŽý>æ(xðºbó5 µ¾¢ê}L¾?•rNŽí?°…¬™­‚–•1Œ3M ë4ñ)ÄÄøòaGpT™è{ëý˜.ƒ¥s¹$ŸDÞÔÊ$3ãBYTÊUƒErQ+¹‹îtŽðºLé$2a=QŒR*PÙ˜«Èë"ܸ4Ê’GýhuôeˆÉ&Éÿä7,¯êrcðmNÙ$“NáÉ¥¶ËìŽXM¬×7>S°·šmòžÊ‰˜£i Y×ÄöWîk™Ž%{}sIþ†ú”NRwÚím—~>È^äaÜÈ&OLìI6êGE]ØåÊœ_³äÅéÅë«4ù©UVt5¶ÚÆÞ „›³–€qb€i¯ƒˆ™se{bûe =UÓ÷n0ZÛV›zÃ(Ø„‡·+_i©Å)úLêùÓ•óÈx;öt<’lpp_²ÏF=®‰3 E«M4êÐ,[y!ÄNÞIž¥2¸Š¶p§²lŒq ¸Çƒ‚Ï4QùrÙQpR$ÙŸQí>Ýä²»;øxSÆd°éùžo_ŠÌ;.°Ç±aÊy4ƒÃà‚‘’ò¶ßSbïcCüÌ| X£ ó{uDJs[AK«Y± ©ÐÕ7á½b¬¨½áà™‚Ež­]‚OlîoQŸÎ•Cp}—CÉû‰í¡£Kóäm2ÐfDÖÍNF&Ò¨¢Ì¸ (€r·ä¥4yÛE¿56èÃïú‹Ä&|0XsN‹ <úž…1‰ã]&¦uº>Qçªüˆ в…Ý!hBZÔ£+é øt.¦DŒË¦Oˆr)ê »tm«“]‹Iኆ™· —ž& ìxŒ©¤_ð%e#3êa®z\וS'ìÀŸ†$R« ‹ëÚIéü@”kóÒ’OE¼èëÉ6b­®^hË’‰ø„ùÓæìåÃè ˜@qR(£ü‘pV ûíãÊd ¦]®Ì9î®í?L‘i¨ µ¦z˜à¬jY— pChhÙ6ÇÙ.A¶ÏÛ´„×+ul°„y©;Ò6y¿èvX/A•Ädjß”gÆCGí¢ÄIËË#y^Âh³§¦¥”®ó,tjÞ³©Rix¦ldžeddÅR©ïߤ Èkä<ÕÕt•=œÍŠöw1ú{’ÿi×@Å!Ÿ-ˆnQ‚«ÝÄ©©¦3¼}D ©JmXÿaªf -Uý.o|¦Öè3fæ¹ÞÖ]ðMÎÑr(’þ—ðÆÁ^àÚ`{›#y2hlÏô4M)s/°ÇÄà@Ùà8|e`……¡`š…ü ™q v@X=s5·Öˆ3CÂ1ÈÁƒ\ #•Óx“D©!‘þÌéÔˆc·rX·0)ɇ鸫ó8…¤HI¯©s%½dq'B+$ßxY»‘^«˜¯òÐNªi~¹¾è~Ï Z_æƒFì8[ÊÔþ"`'#8kŒ0èë »ãCÃ8VzîÓ(ÃÜéC〭ý œÂˆô¤×Av©o#ú\j¸O=ƒš_W­Ìw…QAÜV9áUAÀí¶(œ "aØør>|Õ¡lW%ïä˜õÄ-swQ5 Ƙº§S½6Fsz©ˆ4‡äœ¨J¡rG;sQÆ\ã¨J÷û¬÷òÆÜÜ'-õg8.¶ë ¥Ø”¤ ·G1µ²îàȳÎÙ»íž|,Rß$wŒÙ6Üh¬…úÄ€*ž¨:çñ4Æ‘G3]šŠÀŸ¸'K‰d‚]~Λ@dM KŠQ”"±ŽÀb«ÓʳTÜ‹nO®‚Ým)òÒ ˆœ‰\ô®¢uñá¢Pe Ïqõ÷Šå݈da²NºâK÷°ß#ß«**lM!Ð~±Ž¦m”æÑþ"'è߀WT ÍÝÕB\ wk>lu™Sv¶?gÓ†¦¹…¡!äËÄ™= hä1iq3ZSÚdˆ#]²Ô¦lF¯Bp÷ƒ~‹z°d¹(¦‹`{?û9¡`C©áç.Å ²š¹ï]AXM‘x’@¾Pò~»^æ–ÂU£ÑÅøQSŧ uë«h/ÓUð2XpÁKÞH 4‘Ò=¹>šE±Õ-»Dø²†½#g¤|4'øeä){VÉTæŒÚ)Ðâu bÿNGU áªË>vn8JüÄOY“Ujø~£ r|p»ÃÈ¿&4*½’™ï< ÛÀÁAásº‘— ]¬üÌLxCèöÞrß2ZXÕPcÌX`õ›Äá:*=Q‹ÒÄÕ”ú3’¹†ÝÙ¶_ X8šmòákO‡Ær÷žÜ¢™÷-€Ò8-”&Hqzcr= ®â#-cmdû_ãOžZŽkƒŒð'gáß*‹Fý}!å.@¦š”×`Çà_#BN@l,ß¿ËÚð(I÷ªI³ãV8èz"VË«¦x؈ìn¶’ÔékVsB•¬C¥ð êƒ-VÐ%ã;rõÎzC¦» .Ó3ÁrÑÑf·‘”…Ò\­/W‹Ï¨º×1Þ—eæM°--£p¤KܧRÉŒ˜¬WjÂcùþ«’ã©êîԓω27õÖFÓïQ½ñzk4ù5aKduÕ; ©•š¯ýYhv¬_ùzñY«ãaol“Ù‹ebcÈÚ[}ósÈó¢'„<«rLæáƒõ§#Ôů1:t¸Cp~¨\ðÌ5ý å°}ô òöÿq–˜…‡Ë§u}æZ/&'gÑ#»sì„G£¥xßèF‰¿ „F“¶…ÃËDtä_à­&%<°=ãòNv=£ZÍo»@S`²Ë péE ¼ko»ØG‘Àî÷OP®—,9þq¹æ=rƒª¦¹ë‘ºš6]`ˆ Ç­üK¡oŸx&v÷vl¬åýïóG¦žl¹Æå›þ¸-¹TêÕ¨éª]Ò­©ÄKд{ú!½Ö™Û%ð”·L»hyj7:/ÌçWm"œ46JAô”Öñ©¹£¾o[1d>–-GCy؈ó³à0T ,8sòARÕ4&©¶LïaI%ãø[¹àzgwqÙM`ß”8jŸQÂûÛñ¯ï uaYÆ®æ+¼õBÿl¬‰–#¡!š¬Ø_1ô,gõÈæw#kèÀÿ¿AÙéCÅ ¸J(·Dý*õeFR¸Þ=àâVÿõ:Gº‚õXÚ5«AE´QIwz'_PÀ },^—ó V ë^ìâ-Á¿ùu’Žuü?ª)%7—Î>îÏ2 WÆ…sëãy’xSÔ™¦ç@G_îËËdúk‡¦Ãà>‰¼N¿;äéºâ®×pðp |ìYÍåÆÂeys¯££}ë0ÇÏ4!{Ôé§øÕ-23ýµS +mˆ yÍu•¡ºav§Ài&iX¤Ùš~GüK ׬E¾Ü öœ ê{Tá=Äþ¬ú|.hR1†` ¬JñX7{“¼ÃR—!3d µ¸½{ç9ObýÏÓ¿ajÖÈ=ÎëŠ(O‹‚8»¤ º£$B9ßø3r³të¿*j.S|väˆR\ƒGáp( ô½1ƒ·²á‡Àb ¤—•n.Véú¡?D À³Ú³.ÚÿqÒ«e½|¢£2fÀÉP¤|'ÑgýJ^œ!žNzÓdÖt­D·…Ãm„†Ð’;+) …0«b+ð‚"”Í(mràã‹FaŒ#7<Ù7!¤õhâLPç ®”åOÆ¢gPíN­ Ìùoæ¼¢!°@Õ5šaÑrïrU)…,ë‹ï+ƒÙMWÜ:øü=x-ÍDn<©Dû™Ö¬uÞ÷ï’êíö5m~ôŠÃ˜ì# 5pË€°tù …H•O^„ Ü©K}b öÁ *ÿ.Ï1M|£‚³Œ?“˜nAôTˆ÷(LÍíܵÔÝaµ·tnWÌKTlÍfÎâ§Âº¦ìò„Áȇž­HÑrúdà׌s´~{42#Yרå¼Á’Ù2訦ùš@Ëb^Ul7Ä]ÛnÏURÂnº\ nçŽÂ`«;ƒ…©µÆË©öC‚Ü6¤ÖG²Y³òåœP{¼pôü²\Y …5BNpª)²00ø…¹+—8EšÏPXT„üVÉÄÂÔŽ–×˶ŽᎌÇr¡g]R§9¯£»¹§Q´ý'/X½3ÈeÚ ù»m¾moÙa–±.V¯­ãH: \ !¢FsP‹&¼lìD—0jLî§²2fíæ°Gü\^ö9˜¬’c%0<óÑÁCj½møŒÆÒ‘X}Б?ì b€Ì‚žƒuÊgFß2 ÒÓ%!EogôLûÙŒ•ðÅkÊÑ, >+ƒ‘¥*'Š–LW,ž4Ó3ä~¶)BŠðªcì„Gl‚%yéºÛFðȬ×ÖÙ/Ú‰“£½OªžV.z¡¥3†_x]‹[7ã›c"¾ûŠ2]ÊhõéДáT…ÒÑ ÅðGÌ¡7ÏüMIýzäs»N‚èÍ———u9„°ð±¤¨üYÄü4/®cãæ“dj'pA FIXe½ cK›G0WÌuø|iYË¢¨í8g‚HÔösä: R#¸ëøïb°Þâ$ÎÃ~ÒུïÂø–:eš¿-åGbˆþGÉ…ÒŒÿ\U!B–ÔU¿¾ »¬p·Ñ=/aïD6WͼTèõÈÂÙ¯­rТô?½p YP’ Zó¢» có\öÍ% ”°em¦’'xÿÎèKZaD'шñ5h¥¬@éôç¿çƒü3*¡ñ{&põ€FÆÀ+»aKG…U—PÌÊê£rò P= á7vÍ´Îx5>V|ÍU†‡z¸•\áYá ÷1]œU‡š1‚])úþÀ/<¸}pêG/ý³6qFp»5ÖÓÞ`e¨´áYûtŸ?YNHq­ÚÕyoA É PÁi‰!n0ý8†Át_RœÕ¿|2.ÿ–³ãúç²¥¦d¨b3ÐLäc °Á*nÄ«òdJÃï.‚ «Ê 3i採,l<†ÇÚ T¡ŽÙemÓò'ÈÄçOâ4Vcl’øÜ•RRR0._ã± õBŸÕñåmZ üy¹`DH —ÚNnššVתk^ëD¬¡ß ÈÉ÷áÈïØˆ=[Û±±Tc¥¤R*³°mÝÈ2Ý‚ìœÉ*Z‡Šîɹ2-‚ª#¨ôëZ]Î $뤗ö²Éž¶H„ HÕý(Sq_({¼(ý Ïž¿½ê×PA—4¹ý9îâ*ê2”gºåÚ¡›;YK¿2€µAÙñõÀÓÔa¬qB‡nBö(ó£BÚÔÙî,£Ò &Ý«T‹í_áA4Xëʬ­¯¢{¿ª±*(6‘ƣРž„k:kP×sL2^…ºòÖ—ÿIun—^( ¬§íèSsåJÞ ÿ¥S:ñ½U’ëKÍÍtŽ#é µpKÀeÍ4ÍÁfÊ7B@iÉЂÓAVËœò&ÁS8h¶‹ÈºB¯—Ã$ÈÐèÏè¡yÔÆ¥êXóvâdC­@&ÈKò´<†,œÂ<®Ÿ}šJü’:æ›ëû\”O:ëšʾÃü¼ <ø#°fP+–†‡VB°7ËEswµr/ü,Æåûÿ{¥ÜÀJ¯` ‰Q!P:xéÜKÚö _BÒ!n4*ô†è“Ae&‘u„û™îÌD’TìðAÎdBƳN;õŠwuïIï¡p¶}Ë] ǖ y˜¬Pnö&Znº?ö@÷ó*O‘tçgcÆC‡ O¦‡=»×Ò˜R1Š^1“;št‚?­ë@Ñ㔀Pv‰¶1Z¿±åÇ¥¹PZ<‰ìñ_÷[<Ø'¸âûxÁ¸G&·w'=Aá²;¤³ó¡Å‘-/D¬ãk°uÓÁ;€»~þÜDŠþÄ߆œ˜ ¶k¨Äõßîñ"Ùbh3ÀÕ¸Ú^vdaLA`x|?ê³ëSG¼8èœiž®Y܈ùý—_t9Æ“x.¦˜æN¿˜ 9 ¿qB’,qvf”yáãs‡Kï–2²*}ú$è1³@àÑ¥dü7žlõqÑìèiqµSkP®ÿÖýŸ®âSØkÃbìÙ"{ndA"|uFF)¸%Þ²ÔcÀ2X´ŸP@v9±űEÚ®*„Þ»‹÷y¥pãP‚B|Ô¿îÞÊ+é°ÉçA–›¦#Loû%Y.¬S×zoZÙ'ì*¨'çhœÂpºt¸åØbuß×9XŽ‚W—-4P‡x3§yµ¤»Û-Lu’ék.``ñJ¼iR4̺ô«–“… ÝÅþ`sâš‚Þð2@ÐÒ|©ãó…6e#¾V07¥Åsͳ˜•ý ¦]F,ït~‰a;àj:¥IG‹÷+NËuUñ‚÷ÑP¹çðAÛ¥ÚVo:l¦j”§IN#Zã­JG—&bÚ÷)ð¶Ûݦ²²9ª»"Á¤˜E«˜¨$a³‘e¤4´éXAÈKÉ£G€M®*S¸=m#T¬m˜¿[“9“*J&Έ¡TÏïë9§é2gÒ)J´ô=ÔŒ¾0l!¡x¢ØÙ7E#+ÙÅ „Žòt¤ S!ú/\‹cy¹ðâ¦Ò:“þYB꣤¡Ñ‹=P€&}õ< ÜþÞíºˆ=W‘Y„›PzLbý AG{ •{~ Š_>DLÔ‚`:Ÿkà5SÝuidœ`¹ElŠPÐ5”KRb˜[#L±Ú‹Ó!½ôÂïø›n-?r•a dXB È\§dÝs6ýÇËJÙ<\¸»LV®«IîbH¶†Øõñà¡r¹þFyÙ—kø~‚t"viø^mÛGÖϤK5*SQŒÍV!Vyad$圩tˆÝt/ kø‰'¡y]yƒ®™š‘²Q%O#æt·ñ\ß›å§ i ö*·o8Ë*äÒÎȪt[ù±âEóñù‘g}™ý_Ì\¬>XïUÍ÷ ²ùºnéüÙöm&FίR·V­nèböƒr7 i'ÝJ|aµ#1e*|ÚRJ–ÇÛ@ŠŽÎEÀãÕ Ï&èPìF¡yö°K™¿$Z§Ã™ÔãÓ½,¡@9§ÎÏ3uƒwgjRÑúU„ø¶ë ƒ¼5¹ÖÔ¿LÎ"nµvž5=ÀŽ•ÌZÂèØhPèâš™T¶C"ÎǸ‘ 4ºiÁçeUןCVðLTÒ€õ£aüçGpd§¢÷ÂäË}•ân ®‘þ÷>°ŽóÊ€¨¡ÌZðÒ@U2\¬^?—µÊO§) FÒ"ô8!À#¶yz½‰a/ŸLÓÙ¬áö€øô¬¾Ü>¥Lèv[|i½¤xý‹îºZ«nácÿö!Ÿ’&ëûÆ“‘‡Öín¹3ø‡®+hçë?ª¨'·P³Í‹dBòÆ$r´~•½ª5¼G†/¤—QWÕĈÃF¶ §…2gÏƱ @²ƒuý“«ÜáBöw$ʯŠÔ”}y9EÁu# z<ŸŽH€ Tâzl®sìs/ØèuŸ>:£Ø”o€"½‘#÷F•Ž=ù*=‡Éç›I ÷ð*-IìªßQ Ÿ:AýµkM¢%ãJ³¸m9žÃ”ørtÇÒ¤&Å×ù b®07¶»å—†(k63Ë å@°lk\-e&jKýŸ^ï7øZ¾.Šæq6µ˜­?ŽÛ¢öäØçäh0Y }|a±§Œ…NôEXî]4†”hz7¢”l! ¨ÂtTÛ—…q$¨f £Û\I£‘ä0ÝògséÄøˆg1ç%B ¯7/UÜb@ÁÕÞ×èÕä€ /?ôY¬u¿³Ü'M0 á(®WZ0àbr&_þ(¶w(VryôüôîAÓ–u̦ÞL#ðäñGt$ßÈ>ÜCJe¼ÄV?û´•I!ts‘k ­1µàA*z(Û¥êÄvãÂʳç‹K åaÊ!ƒ“Zðýd¸hó 8l5Ž eµƒºìmëïoÍäVž —ÞQvnµÆÞm²Ö™ `ê#Ò‚5.Z¼ú9y†˜¨” <Stï|7Z) ЇžOÅÈ'6WŠõ»o 7¢—Poc¼ÙŸLDÚP@£Ó²ökT.É…ëKœ7iJ99vßajó‘EŠ6L4¬È!ï+ a;‰о\Ö®z|lŸ0—òAŠ4à5+¢Ù‰Š/µqÝêe:X_v‘ãý¦éj€Ë ™áQ”ED…°‘ÕGzP•óµšÅT³ñûŸh%Îq”^ƒ’Y_Ñ(+A»CQƽîY$¦pþ6äÈ7ãéÜËçàKÝCs´ln* ñæŠ`Aðê&ä:?Ü‹wWX~Ò9AM÷|ó!Þþɔؓÿî·ö5—ócyJÈÙ‰ÏÝ_QÏÝV…ñ)ƒ–›HŸFaéÚHEŽúG?&g „å!}þp8´DB¤ fÔ|û,^ØA¯÷X}fŸ%oÇ€fÀöcâ{îw[”±_u¡OôØÍo—;a³R²TI«nùQ‚jB4:ÉÓŽµEŒ² !?rÛ¿Ò²G]'J›Œ†>ÃS[%_¥píe§þÉ4{7¡Ú[¿MÉÜÉËKœ± öÁ CïbÃT-«$9A tsføXã¤U‰ì¸ÏP· ÚFÓoïÛ|毣n·Ì7„”ï7xjÛcõóÉùÔ‚I¯v]â|ª±$ˆz/sË~‹¡›5¸\Žžü6­N Ê­;vL`ôLuû€+çCÈ•âÊk]-áÄcåZñ,FÙÍ/MfðÁE6ó4…à`DáÃÿM8 í‰NfÜ™9<à¥3lí|Ev֙ȩªï ;H#{n#µ£«¡A$EÞí˹B#\MÍ‘-¹É\…ߨ6ð© §·’ˆ#¦ÿÆ?7—"«0X\¶‹ÇÕŽúùDg(AúO +‘M)"ÁëÄ_–7î6wyY{×nlSæ—îlouðrƒ·2Ompþã>vü¬‚ÕN «ººš”{ƒµÐ9×ñm*—ïõAÊØáåå!$—êJßüŸÈ7±È%ššÉ¬pË™7°UßÁqýܬi3ŸÏ1:àü¬ž†§r:Â×誴 Ñ55«¾=åºà¢š0{83ËCoØ¢&*N9¢CÑR¤í÷Z#6Ÿµ4 îFÖ!ˆƒÁ¡„£—Eï OUåak‚£só1ôJ=U÷ÞT5Iºž¢Ÿ N¡CL~ËÍ6Éyò¡Ú½‘ø£¬ÉŠ2ü üó¬^{“È$È/m;&^Hbå'ÒÆá,¨'ñ'½þD'ÌŒ$¼anLA–I§ ‘î—ã)½ Ñ-¸lç}Æ}A‚Hs]=‘º|Ì>q¾[æµUÚB®G»‰s´×%$¢+á%6{Y£¯g¤ý Ó"­ Þ›•~øŽP'Üϸ,Šh‚)6Ô’¢"š¡ 0pj¾cOg0î5#1àÈñïÓ``½ ì·Ú«¿üÒQ,ý/¡ ÖSÐíl‚VtK; l禄\™OéBUÅ›ŠUãúþSØ ×)õàä já38öM.±°ðô/tèÿoJý¯ ÕŠ Æ„•¿7Æb݇.Wè _èåÎi Š•Â^ü÷ë`[ú8æÍ‘#Ì}B _±9`Zÿsÿˈ½ÛŠ’…Ÿ2ÃÎüAŠNrù_¨žû ÏpF|{_¤Í}ž3 pG¨)¹ê’iø£9·ca^±‹- ähž¼š¦oÜU’Â=öcU?F÷ÐXgDTÊVž0†œû¦·ÖYÈÁîu`‘ââŽFö}sÓËí†ZæÁàèo̪JuVxÛn¦˜+ h‹£{d~‹&æ–È:tI A²áÙζüÿQýÛi ÓrÉÛ#ý´ºÜ• ÕœåSh9›ÜºËM°z¬"Iƒ±ŠBÊ9} "™»ÁüQÀ–é8~¬” ¥&Kš(Ûs@îÕÂlÒ?çæ¼;{ŠÎË}Åš«Ò&¶¡OFuÉÕÍß­,‡÷õ¼øí”×µ™¬¦Ö–%Óê\ÌköRÕ½GLžÜ]^WXÔ:UÆrUý!DûŸÑ[̼Ü8"ÿÞf ÞU ГâÌí·ºÏ—ï,IX 8ši%¶…«ÕáÌV¢Õ_¿<ÐÉ:- ÕmK€( ä¼FJgA l¼'¹š'ü‚õ–¯ûÊѱ§ý"ó V9‹{û<õ†CK9 ­·OÓÜ¡1³Xˆ½dTð`ÒgsG:[(gFôô¯¤ÄI/Eüâ9ùj1gé62„ûy_,’ú ê ·»NWþ2_Ö›C™ÿôá¡=ÇxÍÚË‚<’=g¶v@_CŸé„ïlFΈfóUÙVQnaNyýXt+ áJ~éë®;Ú›ÜùŸÏ»«¯œ¥í7„¤mxÁöIÞè5/WiCÃ8 R8WØÐÕ€áK á%ŠbWúix ï[ÝaſШµã­Âç „1àt„ýc%|p˜/ÓoA*ì8ýd(PN~K¢dhѶŸñ³ŒlãGNÀ9ò\ª8WE/Þû Ó…)?‡`ëxAfÌt  çUžô$›]ŽÿbÓ«ç¡feó39ð¨†Lvl´c3ÃÙmYØôÛ¯ÇÊŠ+/Cg5|<Éá@$BÜ ñ9A3Vá;—xOšI÷þ§ví÷]e&ÆkÇÍ-ú<½aPo}D•<¿3ÎVÎZm}ÖJxG¦Žz ,=éÿu&\¤àwxm÷ŠüÚ~Z|‹°Cżù8+Þ6±´vƒŒØrXœƒt/fæÊÀ×U¤eÍøŠ÷¾éÛ =€rˆÐÁ)# …øº1-¡šð¢Å¥Ìèk["¦É¥~îh¦ ¥›Â#n*Ý;±°&£‰Ö h¢%xïëa”Êf›ht.ïãnWYÐt6vGÄ*±NcÅBst®Ì&qµÚ_âI·„ ´×Tku Ðúþm»%e+­ƒÌ¼ÇÊ©÷ÇgA«bFwä?—z(í?–’k•9-î÷=ô,( IêØž¯Ì´dAÜ>kѶŽåÊVCw lr­Ì^ÀÌ'‰á̼êP.Ÿ6‚Á…Úˆï,H(€«p ÑG8õ³|¹9"þÖ¹e­˜¡|%ЕlÅËЙX &@FoE²FTÔßÏJf)>‘rïþ¿ígÈä4SøÌŒ†ç¨óòÇéÛÔrÁQ âôzº/Z™¥Ž" çý !£Ž¿Fæîícœí©ÕûU}Üå|Ò˜;ÚÅŸ\âm<,Ýq®¶ñI¼ãR„‹K¦rsù?ÄOâ‡ÝôK-7F‡ÆV»2ꛤ^û"ÝçpIÌ›§ŒÒ+Æ[¡G`%¥ÎþñŸå¦º°/%î¸ü0Àк޲¦Äœû'slGp½»GæŒBí³W?t! -L˜b°Ì6ž¡ C—«„‘i8ðöX¸àò8gÐ3V v3Áq5¨£U„áþ)s5Ð|¡Ð‰µºä_,ÖÀ-è¡uò™}W¬:Ê¡òÊûuÌøCµv+ÿç“ Övq³ýæïÂüÓW×µº¿üÐL‡¼'oeÆ"Tþù}6á ÀY`<Ì–±›?Ö>cìFðƒÞ„É `îÖ–wÒ’ðÊ—'¹ZRÄ?üâà•\±kØhZg‰”vyyÉ-K8“Q½ÝBäcTézš,öǃhõqÓ÷²¶¦¾Õ¤‰­mi”6ø0<H]ŠŠŽ/[áëÈèHò‹Å÷øÿßù‹Öì8æiÏôlÎKõdÊ‚«z¨ø?i óѸ†"(ÍïüVû¡Í™Ã‚UD†~§°”¶JjFsUÇÒÙÑ<ËØh,³t+GëóV…¥k6E}uó‹BÈ‚Im`ÌšÿòK)TmVú%·D34¶,ÅÖ/•e†â§¥˜ÓIq›ñîÁTÛ·÷wÁ¢ ŠO³£e“RQòÓðTP]™‚6N—ÒÀ7:îJ‚CËÝ éi®°ÀN`Ïý\bD'Î7ùã¶Ô¬‹ú§WËâíCLkO–iú¨þ·èê³ÞºK2ƻͣÜH‘ÛaÜÉàûÿaÀnÀáZläˆT±‘]ÆÀZÚŸÍ™;_-ñûøè¯9,T™Js>à0¹ÙNßýþmñÜ\¼_{ÈâÓp~êô€ò Ø1M¦·âw,5—{ä|iF¦ùfEˆ‚‚Äq…œÏbyäùšÔž)­ûZ$¼Üñ³¥vç01vd¯úÈ#ÛƒƒYëeÕ2óE#`‚$œÖ¥V¡Å8.°:¤1öÆêy¨!!ÕéÁ¥TŒ9DNµß z̬>!= Z‚a«4>a`€dÌ8 H%|ûzÑäJ>žÔ1pS.Ó(›wÂíÔÛ%ù¥ÿòâ6ÜU÷¸©qó¼¼x‘ÔtKªSµ¡ó{}ãŠõ]Þqaûÿñ†pMU„€z«n§®²ÃmdŸ¨ê6ÍëQ„ü t +>t~®Çp›¦R(¨^­ã~ZIKm¦ÛdÞsL’Ž¢&ëqQÌÞ €»±š}}ÚS˜jþ÷;°lðëz0ÙÉ|ݪú&Ú¸R‘\»4‚°÷:t¾Ù³o‚?ìŽÒ{¥Yfû„²*ÿ¢/ÔìÓ¡èöž£ä-€E• ºÀ ¡8µ¥XË/×y¾šf+äLHÍdU6Ž*¡³BÏ=©/ÍÒlªƒÜf‡àaÓŸ®%D_Qƒx=¿ ”±\¥7Á<d2îïïW|b1Q¬ddøœ‰óˆY4º¤× -Õ¬VItÉGýÈ‘û2$ÚÉ,§T­)¾Öƒ÷èÛû®‡‹cí¬që £'xg+»&N‘bwY@2PÇçóƒ{ÿõNœó^i°é+fc+y8­ £)%B&ÂÀ+uØÔÐYFäÑü÷µ^ÂyVüO×Ö¥œ¹u²þ|O"Ça¼É.Ú£! o6ÌEºKóC©ÿC²3¹OéXX%ÛÖ­xmWO39}×_hŽÅ'­B;¾~ð÷E,²†$ÈÐÄåÉcÑà°KÈ”L úù4h༼‚ésD6ª¦"{S#LH<#¯ÑYRµß~'ëf‚üÝ!D)?F.Ùâ“*(^I–™bO‚ù¿¸èÁOÔv hx!'¯ݶ]nc–€!÷„VC©`Œò©Ò΂)iÇ©zë¬;èÜ'džÛ>øžCëµ, ŠüÑ,‹"øö|®#Ö¤Fvª+íºN#¢ ‰SVfÒ5äìq™Í™ÞHFêðþÚU3"Û¹=$Êœž/ãO|û–N>2ëXv´ÿϘR9HAOúDñd¡×ª•&­>+/­ƒA\3—4 )€¨ýK–m_¼œîÀ2RÝ›e»z¾J¹­dZ†¾¶K?üÕÚÓẨ!mÓw)G¥ˆ:ô÷V†§®’vŽð§ÈE}+/èeSøUÏ^—ÛBÓ•æKŸÛ¯‹»7øø4&¬‚Ýyk8YÂLòuàd„m ãžÐöëεŒyé\j—ËÛëUÛ1jkÀúxëL#pìªeÐ+î³ïq¨²ÜÛë0/F¼ð!}ª"ŸØìÄ“™Þ £ Q‹ÈCûOe•$ÖÁmé€óµNòZ&9ê×îñ+õú­0fßCŸoóa!+Ñýk¿9ÊÁYL6™)àïIµHì O+ûÂÎ)Ò§Úe==Oî½íÃr ëåªÈIOúE4b“?Aù¦Ùohežt(âVÛ&õÍü6”îè§JQëÎî=¾¯»€îi²³¦¼`u~fpIßñrP:ôÑ.ìšHÃA¼*8´}h©Ÿ,·§ZLP<}ÙK5l;UÛ&üÛ¸V]§Ûu¤¢^`lݲ0E@µÿ"鹜ô3…ÚÑŸ·Ì'#v%†]]w‘«óN«$å#E¢ YùºxÕ-!ƒ;ê­L]é衵ÀÎwÏ-;×`.#=”É(½™Ño hÕ(ŽÐ=é­)7¢÷làÚÆU4öÐ` ¥hQUõàªõ%YGÒîÑ Û’kå¯Û ‡Ç! „š]õ/eËg{+¾÷Y_‡=ÝÃŽ /f­[8öds®ÑŠLE 3Þ‘̃ú¿Í"åV¨þÇø)y.Áæ á‚[Íú‚¿Ý^鮄KŸ·Hmÿç`£ë~’ j%ÆÍíõ†ý/íÐæ)ƒ.7†ÎEÅ…×·…°q9´ãÚ"]½€v›*+ôÔ_-ΨœFª%ð¯Zñ¦4ç߯$þºjzÕ€èú"b;öì}â@s©‹½öMb éØË"ìnê³q´Ýrãq?´¯›Éý‰ YC]Žkûþcßåhé‚mÎQù¼} .½¸åÚ&dtyX¾LâŽçÎÐļį@'lĤ?«½NO×D›šê$™Etp’Ð+T¨ }ÙIF%ëï¼*A#Í <Šè%aÜGûŠ WÇôôs/Ü\ˆÉŒ59š»}0©S(ÇP\4T‚YÌ—÷…´M}F=€:0”Ø´8Û{Ðy‰áöò/yëú¡÷!Ð[rÀ0ëÓ0;ç1Åø‡Ò} OîoG¢·Í‘®¦¤ÕÕ¦çOEXзB¡Ã¤ûîH©qYu"¿sP‰ýQ‘W~(Pù®/&Ž q¯¼Ê!ÔR” ´·[Íy‘ðö &äH¾œËÉÛ [ï¡áë‰ô¢‰‘ö*Äð›ëZ—ÎZwØMê~ ºÙq‚ĺéS¹ÅPzÉ…¿3Ý1ݨǧŸÓzȪêQò²'™ýÚûôþÉsKJŒ>3#ŽÏWF6­í »@içq§S*yNx@äŒ+*ˆÌ…Ùko,¼³Uq§E[ñÀŠÝÜëæí†‘óG_ ¡ÑùfD$p“aí ÇÎêé]Ç'"úùyÇ¡” _Ùý”“ß)âùÉ^º#:©Âk±á÷*%²Ñ J{µÊ€jµíÊâè~²«•g¬ÖyjHW•5|òuÙ¹ÓühtçzcË©1Z »–(®v[r°ÿ´D3ìi±|³‰ú­Ö°g³v-<j9Ë=B„ ÷këýB.9‡9“ïÕ(¸užTþõz† £·t_=¾Úý7æÌšý>µhkc‘•݃Ý5v-Wð<_¾Ô8QøÝýUõKÒ¾ý´Œ•]mL™-ñSV_Uü^ŒR€ V—Ÿª}àçÀ £ûNvf•E4é;°ˆ6F¿j¢  #¢“Á®{΋1K–1Ï¿ÍWZï­ó2u1-HÆvçÛØÉŒò˜CZÞz Ûš÷ yå°C™¦ý£=µ®d¶G£^u¥¡¡ä±7%³õÛb?²ÌwûØì¼?»^ýDÄ~ÕÅ-6PèeGæ2ˆÓÀ ¬¢ Þ²}8×kçÀh9óœè¹SëȪ þTî®å%‹£¢S©,`¢›>R‡u¦/s@þ* Á_VÇ/ XË8ß¾IP)s¿#à$)¾pðmf—¾z3%ޱ»õÚ¢ðsw»V¶ G$`ÙÊVeSó•çˆàëj¢hâaò7Þ¯×ú(ÍSìÛC¹S›LÈÎ:%uë{×!Õ¤ŒèEë-·ÌטW0¹¡k3Y¬4øíßç¬G󹤋÷â„Þh(8Á¹:—Úxwª¶L•-ú$±Ö1xCøž(©E‚ÝZ´÷r1Š›]UhlüÊà=j_ºZТ]kƵ§¹“K<)u÷UµŒ êg™F)ÝmŒ¹µ£¼YèÕ9–XàŒ« ÌcM¯Àkß”æ+³Ä€¬¬Tí·bº/ÆÁ‚VUô…GÁê7DXøD˜éd5Â$ÿ`0ßäܶÁ#m¢‰˜,†º=9B¢y/%Ÿ—rsm þ½‚,—m¹ Ǧè\©.¾.Ã8ž=ºbq>yè²v{ø”þ ž­e=âBÍ1þ67p3¦Z/1æ†FV.Y<Þéê¤L²!³]‰MEÆ"2Ù“€Æ‰9ò¯³šðCV×µG±pcÃ@#œI?xcÝ 2âȤˆ—®EDšcb>ã«Wö,a€ëîJv;Èb¹Y"k‚ɶåÞÿB;VXþö æüfÒ@¬Ìœq3FÉä¬x®•á¸ÜmP½8©Íg£9¸eéÃêîgÿ,EE/®¨ªå—ª+¬)W‹jWG&™ÙÁƒÛV«ºÏ´–v1kAb™ˆADRs¡N†ÝSÙÆxß(@ÜÑ÷’t# IXÁµ¹¡?ÐÒªïÜÚ¥£î”½¥™éT¸oCYuºt`ëù¼áÂd³G9°n G10š•Âmv…ê¤WFÁÔJ£ ýy@ìîf_™‰*’•`ž¥q…Wýéa4öè>îgèƒyy­¿ì ÙŽ8"ïW¤ZWŽpvû„‰ÔþW8g¹¤˜U|RÈ&™—Îu%éxçüÏ>ê ÖÅÒžò XA0Ø@I«ö¶;–§-E—rW2‹Šìá|Rúî"‚Å@@§ö òŽ#áwÛ§ç9>t8[³6·MZBäQ¢í{¦Ĉßã‹M»îhÍ¡^ŽÎ<´MÓATwݲ¨‚®]:Š”gBòz&(ýu{pn2iZ½ï¯Ì1œ&ˆþ| à£o"u±zéâ ƒuThŽG¹hþ옲ú¾ ýØ6yÉ€8ü[3ï·Þß´Õø¼CíºÝ" •±—ÂÀ+äJh1h¤vïá~*% „Ž$…•eJnˆ*ÒëÂÞÚ¢H1úuTj7“ºŠÒ²œ PÎ-ŒV }=úÂø-BDê‘j•}E’ôa’52íw‘m‹8DîBQèÓCm Àr»B7ä7ôdeI©÷ÈÌúX£ü žz•8%CÑê­ãÛÅQY±rtÍu ÅÎ £ÔÈ;ð7?7"r=bj!y†5W®@„‹›ºYˆ›b¶zœ©®˜@o­ÐÖüÐE*Šãñdß?n4Ó9e÷@išUÅ~ ͬ#Nßz"\fu¦wzuÊ`H9TÕæihñ·`Y±Ûp¨TñJ®†‰hù~…•þM zš(­ú7êÝ.rfõêVY˜ÉÔAK |‡öޏî&:Òw <³òë°Ã³g˜ÕÈn~Ô-!•ÌúWÍï&{ªÖ€F#ÖMÀjìÞ,Æ1Å\ˆ*¹ü1:Þ9‡‰%µZÈã aø«q3FþFx>‚¢Ï"§×^šJî.¥Y+Æï˜Nn}ªb, µÁÜ_ áŽà£¹/à~Ô-'c¦G˜gµæµp@ó‚ã%Åÿ¦Ì²› Ú¯×Ò Óô h¦RóÔÍ£Oºb6Ø6ùw¤.Î1 ŵé¤fJ°pF‘¼ FZÉUÆ'…f˜Là|<Ÿys£ëaÅç&…û1ÇĤ¸ÉÈ‚œË;ÆË,bPx¡2¡ Yó7_X²pÙo3¨¡AW¥Ö ±à2O J‘Ä1žòÏ߇QΆœ±ÜÄÑü>9kî|ÈHê)JÆ%³uðÜÝ¿©ôò1ÔGN­\PÔ‚òCðB}ÆT'ôf‹“nM-*·7qg‡F‘M„A–ŠfÝÚÕ}Úèpp7Œ8ìª#ÔoTó½Ž ¢7”9¶Ä¿¸Úž&zô•‘¯|ÏnW1= ¦tÜqJß­bvFþjÅF‘ŸRùŽÂL›L"Vpi€§)X$7×¥»AµVŽš ö|ØòkÆ%ýVE+ëê’Èò·T¤uØ ïætfmÈ,C¥ûDv4Ühîß%øDü^âÞ/ë¼c¥&dÞ¢WÄeøÀIRÛÿ‘]bŸHÐóà{ú™$­¤iW·ä¥åA‡§"á®ÓÒ9wUwã$Ar'lÁ²§Èy˜³—ÕÙbL™»“)N™¹ýFpr•uŒÿëéÍäR½f€H™ío¶Ó´NJâiØneB ¢wè…¦fŒ}ÿ™§©ÞR\\\¾:qŸ(¤4N'5½D¯~ëncLÏ#þ9@å@8ÁÏ‘Þ\{¼”šÞî/\ih“¤¨_r­ØZ×1ñ6dÚ/Tme€Î€QÙ†¥ÖÝ&€´[ÚQ²w+çæ±]Û)4üdHò_ß|ß’C…{T{ÖêA– ™HtÌšÉ+ŠÔ¾e‚J•¨Œ”cóþ^u ¤Nt˜¯:z<¹¹~ȹR¹Îv¬ —ûIphnR{® K-@†Q\(­w$LûÄ8ŠßyZ^ØåäÅFÌGK˜t-ó.aE²Q^„á_ Ó QÀÇÊññnÔ›²žJaR°jy{&?aÁîZ'Œì°°Ÿ^·î Bš¨¡³x8awBE=lËV+èk300ho"ÅŠÒ:VfioÇwÔ0@üÝ6júq¾¤Æöh+¶-_1-5 ÈQŸ¼ˆ3‚¬µ¶Uë9#x±¡“ò «Iôt¨ 2³b$±RH¶×|B2Z ÃÈÞÖSõ bT÷+®CMm ¦u¿oº@SƒÚ¿¥‰ŽDûËŒˆIªj¯:ÉV¤ÊžErÚÍõ¨ÂuN§;Ýe𙬽¡¢š]qtÈt¾ñNй§àZìQe; %ÑÔÞnËQ´ Ioñ[oC©À3§ìÌóVrW; ¡6#Z{T\È=ÓA/nØÛ¢`aò€¨}èZÁvŠ{Tu+µÚf¿š‘6ž‡¶P½oRS„veKý4$Úòëã`ȲmÂüĺÔkÂ<¸Ý›v¿ïêý¯B9aÀºúÿ ¯ï³Q~I¨*ÌO~>hf R€ÜàeœðWÅab¼Š5:ä^’/î`/јŽ3(lÆ’OÂqì_ħÔŃ–ƪf“ ¦üÔg½ùó…s†:¤ïT×*äáî&“ÙúÅPp'mù~"n•áàa×é@ƒ„éÛÕLÄ ºÌwáçÍH()åC’ËÿBÓ± 8B)3‹Ô(MW·ñ,F-Âu±TX²;þžê\”aI§„ ÷—öožt¨„Aé7óW礚 ®„ŸsAœÉ«ÌÜÈlwï?´Ë/XK6*×Íy4‡°³Rýäò_ï (ì3UÇkš4ÄÇÙ±Œ”$ó2 î,”[ô@þ%»"GN8_ L·°;;RG ÁEbCÇÃ7è1ú+šU9÷„j¹AÜGíû,¹9”àÿAòfbp^­ôœ çˆÌðâðʦ‚«Á:âUŸü¦}Ö ÐÇ Ù}¸¶¿˜c´æ{ömj#—ö K©tô:õ¶ìà‹oøSàÑó?„Ú¤ˆòyí„`VÝ)5"Öpõ´Zß\ŸË· ˆþ¢è,éÜi¡}Äšaÿ·#ªcõ[öyNþ&ÚúÉ()+|‘{ÅÎóq2döK iõ±PBÙí GnßâÆuY“Ǻ& @­7¯Ç%þ^p\{ÄËjĂï±Ã~ZòëCuº]Ù¬A” )£Xß®‡›ÓæT8Û#i{&£ü'ËÝÝýö׆!Áï•?ÏÓÉÿ<š©i6÷«ð-Ô¬‚#r£Ä6òËl¼ÚaØþ†ºÌ’ÁXr›õeá×FL:Zɺ›Ü×ô—']w+J¾“¿ßÃCÒ1ï^¬æ6¿ÐÞ(/fÖÝ'ýŽ¯Â£ï~üqü9ê¼`·î£¿Þã(ÚBŒö˜± ñHê$ïËÀW²_ZSЬmú`<¡Ïu3,HX¾Vò…jT-iîfmP†·1ÖC‰Ñ ½~Í­ø}í¤$y˜·]|'F>_öìi«jƒ š5Ì£´ÓÖ€j*„Üw¬¸þ?™4`|´²$®åqÊ(Í–Iõmj€b²Î6ʼn(#TÎæOé<öð› _ì¤ÎÌ_W+6¤ öÌy`ñªw¢¼Ä¶H×é4ý&q„þEï~ÊÜrì\©¨DæIL¦§º·èuDÑoŸ™3ù"pÅ‚¡0l©ô¹xmTDâÒpkÍ-ÀL‹- Î® ¦χÓ“JÓåJµCfŸ¸g¬ÿ`ƒË¿êîˤˣ³EYÿÓJò„j³TÝ7Ñ9ÛêÖÖ®û8F¯rFÀƒœDeЖ&ê‹9¤oD×9¸/´ÓPØïju |ðµÃdÃÞ‘HQèZ¾tK͹?öß'>ˆv_I,œÔtËòAqh£ ™™›Ü©ÜÈ€´½ã—‚]Ü%³Ð½S×Y'ð|TõR`w–Œéìðn,—ŠùÕÐE²õ 8RAë>¹P,9îÜ\‰uZ2»þy+/Úï¹­“ 4?!ȽA {g[%ÝÏn™HcFÙOv‘½JËÀ–äC O¥gÅ‹7Û678˜îТŠêYgT5òj ýU‚4êiáíŽó&äÌšd®oí øOA7g\A·™-72×ðÊ!ç÷—3b,šð+à½/y’DŽbÍ|d—ù :Ô÷|×ÂzƒÁøUEdÌzô¢%ËoxàL¬R°={˜”¸“QüR‡÷>v‡×’Üoe'<šÃ…|sîR3ãÿ~¾öš“¸Q韮ۅt_À€çÒ€‡Ï¨<êäç…›Ïö[Šiâ2½È /Šï,ö½<Û'ü[IHêS´ù#¿*øžüò­ýói{+ßxEZÑ|YmfbHÚäùbÒ­O¢‹£¹&!Ÿj1ÇÊ'*k¬`t®¨Ñ¯ÁH€7ý¦ÜYµ^ŠÚDnYÃõ 2GÜøb~¢…UzÂßòƒK˜W+¢¾êÆÿe]—Šê})*åöï¡­5ä¯,•E1v)»ÊCIžgÑñ0ãl}o¡ž§7ëêYUÅ)Úâ.úæ´£¸ :©t©#”ŸG„œz_iÚ<° R o&¸GÕ @ÿ°FàéÓxÛ¹¬ÁgÜË<·Q÷ÝòóhCõïNXI†]? /?Ô …ú†Û°waõ´ÂMÅäúƒq Ži·¶Tyc˵»î–Ëž;ï(æå |]™d]¼SÎÒ£™š¬’ô"2Å«!í"ìéÎDÈhQ™ç—®;¯C½(*(ˆêø9K웇²Nc*‘”«¯E¯2-+¯2ÎsÕ=hâ‘|÷›­”–f°¶_™ÄžÕ\ÓûZgLL ã™üu=<‹Ïj’4ïê—ó§ô¡&Ú Înÿ¥Ã&Ò« P×Ê{þyEoó¤ ´i¢Æª­µËŽïì ¾)G>ù]†Å…ÚÑ#Ã*=ÉÚ,S å”Ck<(Z£™BnÄ'Mv¹VBNbâÊ«@TÔò]ckz·Læ Ú!]c¥kÖë²ÎÍ,Œ « M,Vò7½õNy#½y¦ÐŒ¨p-…X |ħÞw6Úÿ÷¦l^ òT>üžÃIÍ–,…ÒSÒäVmÁ]Yd¹U4Œ4–€‹y*UÀ _­Á뤼e¦ ¥gÀ€TÛqÛ-ŸHô_ÔÚ:ÆzröÃËLzíTâÍ,ÿuhÖ á2  ¨äÒ`̼f%{¼¶Ü6¼ œÏãùú„¬¸ª0¯s;çþÐsªÊ©B#ÈBcÀåÃQeÛS~¡ÊáÔ«ž †ØË´×¤5{®f=µ}gÏu¥Ö{_DÒí½>¿E„`ì­Õ0åÖÈëòXäVk¼üòéaX¸GpÝ© êÃÝ›-vó+kÖ¾Ô—úðï0¯|#æ6WÄ÷;Ø‹í²§æ îŠ/ÃÕvŠ4ØU‹tû]  Ò×Z`ŽðR–¹m×Ù_©î!ÍUàØÚúæÍº&猱µîdi™Í­“d,´£7ž¯g½î`m¯_›žíÉ ¶*‘RO_~#«LÁ­Ë&—•ml„ 5h¯ðüi8È¥t{ ¤{ž^°~±Œ¼~ %.›¹DOY‚”jï=’Fã;7qoÛõ÷=KDÜ’.Ðæ˜¬â¶If·˜•þ‚é¬!F2-ðäjVßé mk±†À¾Ì³àÜAà§’»ÕfWFNœ)ß«<ó ~@-ª™ÐÁ¥`ä¸ÕHå@³¤>ÖKÞÙÍÝž¿€ªN”6 ö96˜7–ŽSÝKýjgT°+Ñ%¡ ýZf3ì›w³GÇ~.]Áa@÷lEq §ªæçjÐ齉Žx~_±B6PÂòX+—<ДIÚ1}ž( Óè‚k{•ün6þd°[Ob©¾ÂröO·7ào¾­‡Q‘¼x† ÞÜàn§…èì,g4°ñ\ýä-2qYÑÉn±lu­zw8l†ÅŒ@*Ö?öó^(̳Ô†D7'HOÁO[2I£j§À­r0cç l£=Ì@Œ¦€DÃÒ"õ$X-2WL"E°_]ªÊˆawOr9˜Æþ±þôÓóÌ' Z5Úׂd2\ÏÛT9ŽÛS…ÔI»K-|=Öç ‡´ÃÔX.öñÍÀ“ðónÅÒUr  Y‰g#Û%Åê÷¨‡f²qº¯ñ+N¯•@Uÿ¾?üt¦1ÑSµ¹—šöÞói[äi*¢bØ…Óœ^.YRÿƒlÖ6-ûœÝ©VUÔò&RPCºñÛ'æ«ÒÅV~ãGþ3ª­N„ÿÁ«#·8ÎL: ¯²SP͇õºÒnlï`,A?] ‰qê½ò²ýFŠƒì5aŽ_OgÆS!|)lѳpOK@Pð>RRî¹[mŠªÈp¨µ¥ôÏ™ÔVqܾ¿e|ÓòÐÌ¥6mFé/Çï§ r¾†ÅBzÆÕÑúbˆ±¼.D;»»ðPã—RÉL8¼}DŠéG'¾‹Öýï2æýàw—a«1a"æ×ïw%ØÃµ)Ín =ãž´]ÀBX÷ SÀ/"S†Ó‰pž×Æ4S‹’$o-ûºœ²çº©·[·©dïžU;CƳ{R‘ùoùk e_¢]$ãMçíbÔcÎÍ",«Z„Zdâê¾L: Ò™SóÈÊ}âb»€±ø²ô¼¥þò°–:$ãÒþ(ƒìŠCb*ïõR‹ŒýgVšH1ö”‡Q{¾5Þ´"QÞö~±MaõÌŸßÍ@m!úÖ %-Û‚h‡—W‰E”÷Í ™`ˆãi»Ò“½ï-Ïñ;ÃH_¬GNù–ç?PÍ3Éñ«Î'MhØâ:M_؆°Jκ…ö.£'•¿½L —z­=—z}bp®Ö†EŸd'Þ³‘hˆ©.¿¿œWßÀèØ÷ÂØà• B1sà:i8Íñ§¬ ŽÍ4E­„Úß_i%™«cEù@ÙõEm¤)Àç_˜5ßú_ˆG¯Ç¹ŠÙV‚7ûÇ~ý¿ÖpqvªÃŒm„M òwyßêÐÿ¤!Œ®…¸u^-Hª[e,6ŸÊ“ÂÛÀKRb5˃÷n8uó¡ lÿQy³Ø$#¥Mg†´0ÏëãnWoü)ƒ£ý_d÷Þ°7ÖwÞµzµÌG|t'X¼ªÍ²,kßàNfQÆ´ØÿÜÅÝÔÄ þ:%G~øîÃ0ÆÊ*â¯Im⨩½‡<êƒí&T}u+De{ù2²còC ¾úïH/lÑ>XNåJ‚±½k͘€Õ‰<ßÒå/vQͽ£©ÙÓKdMð"΢÷,1磌áèK³I«ÝšyöõÐ×§ 'Z‡baÕç' «‡ù—_þÒîÝÿ5Ã'"IîIÄ–½úÚ…ì¾ZhŒ—\ZYñ£æx&ëìk5z4hGöi’qεŒå+© Ã9ÛOÁ§ûIäEÄšP|4Ó\1ði³Ë«è,]{œ7èÿ… á^‘òrÜBÍf“þAAГŸEÛzÐ{ìHŠmˢ2”¾Ëu×îÑm2äÔx,ä)öbR£º=Ò¬;ždR‘Kyëk™|ÊXõèÊVlä‰#D‹ÏÖÞx‘KêÖC*1d8úqΉËUa.¢ÅXH’‘’bÆÆ*AXêÈS¼ÊÜÿƒ·]ŸžKÁ`k‰aMl0ÑRǪ%b~VøSM†³YIcê̽Î~@¯ÅuÇe¢‘È0N!ý?[k7AÏxbEÓàü}÷߉é+Ší²~¨×6¹iå<žó¶±EEü@[´$ZÈ/IÖÐT%åú RކȜGêù/_ æ "¹C/¼L˜e·Þ¸óJçWdÅÖ(nß%ù¶‘°F‰%Àm‘Ò,4’d½žXÝGq±õîhÜAÝ.rÜòÔňz Õ«>žõ‚.©<`ûÉÆQ;VV[ "YE¹ˆº:æ¸fºÎ«ÁÕPØxì2DßfUTOJÅ;ðO­Ð–H Ö?:ÈüÁ{}òÍdÇòÕåU.Eó"œƒœK-Ãõ7ÌsLÁ^„ ÞGçB/N#¼å:×<©&9|lÌãKô‚üÁÆÎ9!:}¶°doH"w–ÝîvÿòÔçr~0¾-Ã\(ã¯2¾‚&ct)ú;tú&->}§ ¹ä– èŠÈ˜ZÿqHb3üjn}M¹E’PÕõWxÚf|8n/ö²÷wL&×d}¾¸M8ëÍ 00W.³“—4…kÍÖŒ …x ƒ€øÎʧ(Pø°ÜsZj.[Ä~)G_!óqå[£­Æ)޵âˆ"Õw1¼$Äb{À-ó¿ã›iàû.k>’õhºÎÜ?W'öGtoçbn¬¼óa” ‡*Nˆ“:tšþ~óÄâÔî‡Þ-®g2Ò·nµ?UMŒônÿ£òsnxèzÎCxóTû1˜ÑÇÌ{‰(Ã;é¡Cƒcë2§[[˜O/ë)—çcj}]áÎ:pN:ÿnH‚â?ïkÆÒâˆw€…\üX´”S[ÖhY$¥65æO2jÏócÃØÉ¹êL•ü²%™ÒêÆ!4x›Ú´ÆYhq§˜sLx;÷Eáÿ´²¬}Ð[ÂÕ¾– a Ê«Ýý3Ö'N3õ)Û[õBrÑãtÈ“xXÔ>Jt3ŠŠ?êyæ<ähÞð¯‘ôßö1ÜÜ9ïP]µM;Ѽ,¸LI(,q§ÿÇ›hñˆ»Ži]<ʈ ¬JW§EYšeEJº›ž`Äå?íùw|ØžRmÅEuܾSsËÆ%û kH+9k,{C?Îfs{R»\¼(ƒ«5ùJ #;4º%àÍÀLa;TÏXóøiцƃ(³>MPªqíJ{lœ³ï4aÊñ´¡ÿ {ï­œÈ º?ñm!Y°SGÍ­óñÔèì(\kÝ*-2”]0ã\z\ÐÂ;(©óy`š6 ™~µ5“F¬i EØhEX'?Üÿå \£u¹š@$,í½à×ñã¨|--+Ð|ίf¾{6e‘´Æs$ªR Ý   È4Í+ƒîx›ˆ¾ùJájT™cù0†ËõC¨5õ»'2M—žU™ƒ¶/Ð ¡}-ý¹Ô$=ªºÉækµŽz÷Ea2M&¡í+ˆ€KúÅj¯Ó¬´Rœ£úÁmèw¿ÏS—Pªé–£5#;vN'ÑæR”óO:ºFÍÅÑñ?jTì—9÷iUAÄ%!Ÿ_(²!‹\ûëå(y8ê¶@ øToEÖA ’¤8÷)Î °®þÊ5„iNîü`åP<À¹®È£•ïQKä&†žâiIëKÂ.›dø–¸eŽDµ@ß-oªfž€‚<5ã:zÁºѬ«Oˆg$ˆ< z­o¥¯[ùÝ…‚£wx[B#—œázBfœKÖZÔêN×lÙ‚€óŸY$áÐÈ »*꺛›Ë§vžÕ¢æC(ŠjpŒAV¡  lzJ€À´û¹|ÀoW]÷¤·»Q— «<¸@TzµˆB‡ODsBÆc!OAgÈ`r¼\zê?‘o­ôyjý²ŽÍØ/ebì7)ÉþÄQ;Ã8ê#EqM $¬Ÿ¡‡ú>ždE7åò¯íyÕØúË‚j’×úãàŸ8ý3'ÑZN¡¼¡AÊ?ê¢~e÷ïÔz‚|Ët–î½qÚ“ûÉ%{3ó*Dr( —æÔ ±m©-¸2—Ç>IÂ.èǦšÓ%¨ú›øû½˜¾)®ý༛Ü×¾m @ŒFÃ\øš¤MzÁéH£h¶I¢7­G€° ´“ñå7ý‡Áùç}_RØ!Ô{tÉHdâ"-ŠÜK…Ær¢Ï­€Ù±¯)ˆ0WKû£®áhNƒ.#V¯ã“îúh¨4W<4º…1©ÞΚ:ÄyÓëö=¥(¢ÙܧãÏaeø5:zd\3IC©Ð4±Õ( C¨oÂä>ŒMÔv„R€Êj™ÿ¥Ì`G{˜P9BKÿAÐF¼»¢Ë ¶Ø{ŽŠSñ&Êù4b­;ºCÕó•ÞR$³VIÁ˜@ˆÔý:]æg_ÝÓì'[Ÿ¡ûìÀœ2ø+öè¾’ëÔ~Òì°Ûí·– ÜÅ;žÐé¤Ýñº‘ ÛVGÿ¼ ü â ‰2à0Æ;J)Ò)ŸÂ$ýú“ æÂüµ­8“)Õ/íŽ(`Fã»C›÷÷µ’±ÑÄžõA…`âIùÂÙ‘Ó åî­%Ã?º¹¥ŠÛøªÊ,$Òº=z@¢œóPÀ®eÍÉ!²WzË>QÄåêDë`uOÞÌojRNäÆ¤Ç½cB>}×í©2™ƒ z÷]ׇp0Ϩ Ê…ÛJ0€ñÃ$r¨uiÃxŠó²å‘´ÓûÍZå›·ö’äAè({Š„Ê>þR¼4P­§ÒÝ¡?€¾Iœï'£ü&BÂHγ®¡¯„»ÑyOÁ´Wâ–Òþ©tÍÅä øb¤·J³¤lõò JÍÙ‘ØT«ú;õ1•}ulõú¯GÝ¡¶±j^Xž7@ËÙÔîÖ½½í„+~â¦#Dÿ•Æ„+týÊBb´Žyê…‹÷OY[|¦™÷ø|¯%KeÐDš\ßõkp¨ Ò9b W€‚BDý¸s¥¹fy?‚ñ ¯Ó’ÐìŒðµHkm\ ‘0÷_–ÔBCîÆÕÞ„àõƒ›ÞgªO"{~šŽr¸÷F ã6-‹®£&ĪádDnçJ;ZYwuã„gWÑü5Ç=½} AÞLñT¹6´Aû7øx²ÖcÖ?CÈÌ)ÐZ1bæ1¶°– µ"í9Ü/TBãš¿c¬}åÊ€æ®y¾Šh‰Ôz¸ä†KË#}XJ½¥òï­‰Ï2Ü?,’ü•<›‘Ré¿ûTÍüùÆËˆ!Ú.0>û5ö+òQt涺7ï €¿¶_kñÙ kzæ7—€³QÎtïã¯D5p@Z~A«§iÀÏjnªzOâÈ©kÿjN r…^ǵëã»æG>%ù£ŽúDÖ¶’é:IKU"[2õƒ¬[Æ‹[pA^äºû %›D³z–Š›Àë¡ØÓxrlh%88ç&(æ1ƒŠòÈëÁœ:xYò¢À5¹0y¥±úsî•~Är¦ÊC눎Tp9¨Ó99³ãòŒã袨̧98:¡c0¢ldƒRiQ²ÞNð$?’úG~™U!j>í¢;%ƒ‘0´±ÓÍ“ËFÓmiáv#`„ˆ9÷^[^Omâ/¶.lÑÍÈ/ºõÍ5&e¾¬v‰¾R¬„>ð‡}¼à‘®I…g¹~ÅÕâyÄTÒå¬×¼Ç&«9´½¹]WáÙüý@ä©fØŸ 5ÆP÷µÎû©LÜüýøÆ¥S!õÕ`Ä+g* ©o¨ÃY씇߬¥³Á¿c½¦eà aÓŽ¥†CÉ_š¾21þ5ËœQbˆFv„‡@” ¢6¥ëË«¿ÛcVv±Üñâ+$Ù y°K3(vYD”ÌT ºæ†÷~6Ì oú¾ºMô¹º šO¡Ëûb;NóË(”k3ÜpÌ@ Ì$*[¸Øö=eú˜Fh5ñîª ¤ý.†\”¯·tµ‹Ë™-Úö;ŽŠœÕhM¤×úÕ"õ~¨!Qÿ’vƒ¾”(F¡;ó¯}6êèì±"¯. X˜ÇfNXTÒ/¹Á¨õQ æ´Ð\’¡)…P‚8lÒ7*6.%ãÙyîI Bëæ2;ž.oU'›ø‚¶WüQíèÀEÊöµÏpºeÁ;Šéˆ…Ì™û ˜š‚Øë¹cÚùàBBñåµÏ]ó·ñ€² Ìv€ÂˆóÁA¥¯-†L Èޏ¾ã½#Fš`Ù\ŒéµøüN \ Ù¡¦±ßQzeŒS1ÀCž–%eËË~4›0Ü;*‹M SõŠòñšPÈ:tZ-RAaƒc]Ónr\±x¨°‰8Õf¦0BqA‰ðô§úY× 4XÉÖ}N„½£v‰óq#ò™*…7rÍÒ–å`r©s Lú÷òn½›'ÅóN^XÐl›|9Q3-¶eLûÈéÚ!¿Jýy-`cºŸÎý~º‘ˆéP+R2äžæ&‰u ììwúÔAó£$æ<çÙ)û5[xìжb’SZ¬W¥Õ ô9”Ñ a»1.úì…‰œ ±5Öƒü/¤ž@}†ž\lMâ|TáŠA©ê`¼>Åz˜ðXÁû O*ïª }#…¶P!¿šò;Î9àñ[Ê‚ÝãT-ŒbF6(â˜ÍÀBÄNüÝœcÛ&â{.Ó»mìÜRkÿ°6ƒ•gm÷ÙªR­[ÏPéaJÓõQà€½2!òÈ­øY %thÖ1 LѾÏõáNZŸ•}€~°»¤¦_Ê÷ñ"¹ÀúRZ²öò ÅØK128Rîh—¿·ó¡e=¹?-Bb•{¾Þ-i¶à+Ë×8š´³]‡¦:×­0Å ”N±Ê¹7éK³ÈÒ/Y`“½ ¥ÃE×Û!æGÒû„ `h¿:®U›¨5b±±LºBAƒwß$ÇG#b WÙ8`‡ú Z×6©#þFÊ"° T °=6-= ÿÜ”ZnJ€ønYªê¢³o‚Ø€º€{kÔ$pJ›ñh½z Ô(~è=Ï¿ûf1s‡³ûM ' Ï X¾—&Šù±Í4{KÝíAVM3=[¨©|€ê §[YçCŸqŽ"¯j{v#2c«‡ý¾·{˜ã0@Úú¾‚Ò>sò$!r?¤‚ã¿ç\w6D¸-Lv¦9—¡Õ&‰ÇíÃ/âmAI'B´¶ßãXg *ëÕ6¨Ho{2n74ëI0 TbØÆ{Ôs œ¶ì{¶Ÿ)i˜¢”w2ÕÁò1³Ú¤±¶ÂgCŸ½@ûYV¢a ʈºŸ¡ŸpWr&®€sóòv¡,ð%wìáhºE±^Ÿ2Å/Šÿ8©Î ᘭ.€NXì"Ÿ2.Á§ˆºÉv˜ZÏkšÀqW*oÞ]–ÙôŸ %‹Û@NÉ·´ƒBx¦$ò²$i-´qÕ_ÜnÚnâªÚó÷wo‚èý¢PåÊˆÕ H?IŽ;˺÷È=/ š«Šéè¢ ;’Eþ_ 5ÁK«•šÝÈUtÛ׸Ѥ«Ì+…•û6…@g»˜²A$…¦¨™+>±kÕŶ·ÛÍÙI:à©È6ð°ñ «Ô¨%C,Ò ÁN¨,‚?¸Ušó°7•þ<¿Âª têd°.b™ATEìôjŒƒ®©e à‡\¥Î7Q)Ô uàOâó)µŽWŽYiÓ=Ñ•-:6òR!uªñ2‹Í WïW<êv"<™ÙeÞcýˆœÒÉ,êM…h¼¨½Ó9j­¢êlpÊrLñ ”ìÇð-l¹°‡*KÞãñRîiÆÐÙf‚ºapeu聯ÃY’’uµ°ØïЙ+¥&{lüÌÔ€è9!³¢À ^¯ÄS¯èw‚îÜÚcq"„&ÕÊâà’ë‹þKVlª†ðŸz]íW,›^käQ ÀMAà²Å×rÆ—N¸ Gs…Ô´"6bÈOé[´±<°·F8MÛΑ-§ž#±|7íúZ…Üö œ£™¾¯fYíï[ն׈¹ÃÊ€§{œšN Y;·KÓâÚIñŠeD®Rêômì£ßÞzMOÍmHb¿úNáˆÞép>î7m´^+3³¤ùy4§cgiÍ"uøÚqÔèÔ¿óoO¢¾Eà1ÍÍð8ž‘EÿX3B Vá€W{Ê”,J(Øy|Hu³ÑÿèÛùÇØxOq¤·&A„ÆÈúmUMXa9O÷ÔŸ&›æ“}û[s7(QQ˶#t„¤oÊÛ¿©°ÌÑcјžßÏn¯™†»8Â8[ÇŠ¶a\œÐÑ–öólðRZŒÅeµÃ®¯ÑþÅ8aF$IE‚¨îL/®ßèÛ§‚$¼pr‹1žÖHB4g*@>ϱÀ×öôiÍÄ“rìHîCÔà/¡YË +‡¸–gÑeAkTùÚh›uœiÂm¦øRuŽNõêÖ#°Á#E{ßTÓÀv°o{V_>Š•°ò-ìÈ .v#dfaÇÿB½ƒÄ¢VRÖ^ˆóv¹%Ÿ(’Ž}{Ý\»ÌL”ÓXñÉ1Eœ”q Ûº'qgïwµlýJgl$Ì?ú@<l×°àµ[PìâælG{Sb:¤–Ç?±¹­.éwDnßörøpª˜yÌ»±±S©ªúM\àu… í; Y%î²¾¿(†îàE,Ä1eâûÊqhG´E0Ng›Iƒ K’?|Șò… Ú87赨˜joãzWêŠ^Pcûj…%™¸Ó‡;SvPˆÖ6ow8ïÅë¥ÀÉ'(.ó¯jr,yê?…LIéxb¦§wÈu—Î*äã7—o(Vا›˜+äÿÛÜôÔ±ºûÒ½'gÐ¥Ó*Hœç;#‡“+v¡Ed–Çê(#½c9‚&6å®êMfžXNfzBï´.¯Îu{…«b c“ÿƒøj¬hBÜÔËät‘þñn ‹.\²#'FÈ ‚ŒY^Õ°Z·,?N7Š@‡™TUòô7ÐoË8‘»»ª(@ðò¾K¦`{§ˆß£}Ðú⇃Ÿ4¶¹ÖtX”¶þ]z›b¥½!¢¾-÷îP@´ÂbŸ§È¸¬gt•qaºÑ'Szh©aÊ“=ýÙÁ¢üo k:OÒ=Ó…Yq¦ô¥£¯*÷Þz «bðÀæ„%)¾}îH]ùÉù͘E(«vž”×–¿'÷lvU~åIÉá‹ÿ&w†Á.˜c.æ,ÌO³2~É=šiþ^êzz¨AýÁ)Ù­€q—Cg/X{ËZkBk–LD¢®MÚF"æÞK.å`&Èd1p/l zòª§s=¥B ÙípÍ"H0 w±¿ BVp¾ÓÐ#h“fð%H ñÏ*ßR7cÄM ;èü_¶0&ÁçÅ­,îGw}Fù²ðœ¾CâGê>sƒ¼zDwò¯PøYà‡œË»\æQQÏsÕ-´êD€¤¼©A%˜ýš·^À?Çõ~‰« §àŒ«ðƒE»]¿ômˆqs~ä‰ãYôüñôµFP·É7ûå]0«Ù#¤]Ï>S¶ª›½ä+Ùb½Ÿ‰/K4¬#4Ž6¥B€ÃqN¯bši‘ÅÙÞñÀºÀ5NSRº„;‹Úl[p€j9׃Qm]¬²иe[œ™?yøC+! g%¼$ý;Þ˜oj; ͬ§ýô#Ý]gðP/Ûçö\,ŒGþ…¿”à— ¹ÙoH$Ò‚|Tj Ë› ¸æ…ÝC?~‰0Îû_òïù•Gt÷Qò^ªƒÝ¡ül&™#(U61„bðhÌÊXÿÁ,ðöË}y_á0çô®Ü2³S>†<"ž1"ùü ߢß|<ÖÂpËà;Ÿ]ø­X3 o© Ùþì"ÐZV­y•ûsÙç¹ëô'í…¸³ãÔþ&R­PÒq…§îY`àæ”rwçh>Ög0Ë?…9”(í.µ ÑeÍáÈé0Ò#Ì?æ_1¢»¶{Unц'P·<.[Vô_Â@Ñœüª6èb úäQz1½MHÆÈ)TïÜþŸa|AƒòŽò¥a?9ŠdªxûeËo+q²8Bþß13lü•YŠË¥R±å­ô¶ór—9¡ç4b}Û ¦\}Ý¡sEŽ©ƒ=¸j«è#¤HÚ¸› ŽnMöÖp®‡›¤ü" Àð”¦b\=ß0DD{ýå€däû¡wÒ|L¾áÅùÍ£â\öPŽ¿¨Õ6Ìßíp›t°«Ì©6óŠÁŽÆd]oMó.ÕaÑýŽyîîðŒe§fÁ ]Ð? C7rÖ„ÄX,~Ê-Nòy+ÿ§º¦¬´Ë9ZGö^× ÌŽ¶@˜‰aÇóiLLè@b¸ž ^_Œ`CÒ$”)è~ ŒÐ>dU·>G·§@ŽQÔæ“q}Î5ÖBdÉDðFÜ ¶ÎŠOÙS'QÍì£Ä,Ë!×<ð¢è»ö×4¦Hï…©µÄº¶1-Àf'è ܦ £˜ž4 ¥ÐcLsµUï–´ôt¼•̵u@7ÕÀDaÕgœ½ÏŠ¥ÿ·…˜™°Z@’–Ѹ9»k³zoκG¾]’#ƒ'Ð;þߟÑlúNrÑ}øBÊ}O€ËÓàÍi”±±ÈŸ„b ñßæÅ#(^C!›È ¾Nd¨AÝ–À¥#æ 6/¤î#Ô¨ÛP£sŽœ@ü!ðoH[\ž¸ÒËâ¥cÝ,ð¸ÿP÷âàeÈL³½ã‡ Z_þ‰YŒÊ!çýÚƒ`¨~k’x•mÐáã­ÒÄñmWC¬Š†SÜÒê܉dàלñIû'¤WµQа‰÷àíº¦èq>õ±iž} *Æ[.òÛhËïe¥¦Pó“©oˆ¦%ÖÉ#ú”P)RÔ58Ô1Ó+©„hmÒ0:™A’ ±åf•ä¡cm8ûÂ7¶š¬b’u™üÊÏ™…€‡‡DÀ«$šôü bb·hukNE¨W¹9x‘Ó|ªƒ¹‚ZhŸê9"¨ù,ÂÆê_Ôäs½Š6[üb›U…¯ò!rYóòkÀhøþ±c¦© |›Zw§þº›SàQÇax‰xÜè`Y ýºÊ«}tn‘àS›º)(IäÆUjié0ñ>°–s8 VsZ±Ðº×R¨m‚äeÀ€ØàO¦Ð´]¶Ì -=ø` ÝìøÀ¸3÷C§"íy3_èŠRCå¬Zǃ²e " 7PIÍÁæ“í0` £¹ynsÑÒx3/¶"ÿÈ»Å#i†ŽyÑÇål£rÊ•„U#‘§Œ)3^ivÁYJ‰»¿.>ü“•fdl£žš›lÑÎhT­O§o+î+KûÌ6ÔcêŒK¹F.ÖžH޼Cà†gOL‰0·4õïœÛyä… \Ì&oP9᩼_Zorkª‹0°àýҨƵÊÙT!¾aÙv!hø©ŸNsF9~>£À™z5Áª µVÑ™to²¹SëÅ"^ôî8šGÅ;è ßña—k £õ«äéT™+µ×©Òmè°‚ˆ{¯/àÇvp,xWua8ß…À€Qã6ÛÂ/™kˆ}¶_Ö)C”£P{«øõÞ$Xôe±b‡¸9¾m‡#{xÓÞlR²‰ƒV2ŸÙ0Ÿ¯§jÝ„6.¢óìqþ3½nYn<ô£Ÿ?wŽk>ùÿÄyEÀ–è*¡ZHcú>iH {UçÁíxm‰:GijN¯%Œ¾ßûi¥C5#ÑUÎîŠÓK‚žó<¸.?FñûÁ3Q%ê{ÍþjÉ‘ˆÙFEŸ”É.¤Æ7£ÝðÎIê×&‘Ø53Z/|$øFލq› ™ÅèEÛË-“äB³À8Ùýh‡$¹¤íBÜÿ¿„¡”@¡;žÌSbU7ÄàCºRBÛ²+LèüXÃæ‹B,f™ÛH½÷œ?Aªø ¡ÁÔbÀ8X÷ŠUÙ½oü׿ÖE@nXQ”±wdͱïØÛê1½òͪLƒÒ¥X²Ç<Äÿ‘qŒ&B}³±S ^BØøÄ’A.>¯Ò¿úêT}ØûÎC×wŸ¦)@185x§šqÉ;·\ xσì;4&ØÂ¾Š}—(ùŽ]Xù¨È‚,gÿËò*vØÃT–Џb–j¹±õ¼'·¾vÆ–ƒ¨öÂ=“Q¨³NÊhØÞ²êÖc!_U!`Y%LÍ¢ßAèC™Þ²ØK¡ÞDûøG泺º‚ì$å½[Þ©ŽMq ÿK¹Ž.#™ù…\ǽpWûüµòNNÖ_ëw# •Íwx†xñM ¦æb­!kV¥¨þz7žÝ˜ÍtA+¤I’«¡žñ`ôä%Å‘ªÓ쬎®Y?Îlçì»wâæËqñ..… !|!Ÿ3{¤‰ŠŠê}ñyî8îmïì€y+U¤çå_6²HFêÓ·Žs±¤ž:6t5ÓòåX€ÿ}P2ä‹;ÈÐh ]=.×ÓÃx±<,¿œµË6“×›>¯Íe“i%úÂtæ?A;þ¹Äp«ý/ší(¾zÜuîœPÍ2!“C%izHF_)“€jaîB½’JÀLSYAA<êiŒŠœjgÙÙµ©­×gц‚]Xïe8Ü9:áXo]x©™dizœ;ÎÏ€$›ƒ<¯rì®7¨]N:dd²H†1Ø.ä4ŽÓAµì üÅ¡>1®_ÈýǯÝÞþA^°îŠŠh½ãŒö{øŸÓˆèÖ© á§Ê£%|6›Ý¶9/µy²S͇º&›é|Úå§Î1—·Ÿ FÎÝ·B«»D¢óÀ o­ ’¼2Ы©öµçvеN4€]`ŒÙê/wÚo‘M•Ûš7;µU³Äù{Ä…ž ½`¬Ö³ùVOì,¤„W~g!ñ§è 4Ë›#´CîR©ßïxÒˆ¹ÓÒ6T¥Foè¨Óˆ™§ÓÁ½W#D¨–X ±7³%¼oqr(O1D[æõ[~ou±Ôtˆ’ɉ83)è[âDzá5’¥ÃÏÈɨ§ê}72Ë ­”bUÿEiâÕ{ ÷üˆk¡”$¥Dš«|Þç6~;á¹ä´¿S˜ÖMKÚ;’­éÁ‚èÖgOkBS¶‰uÈ.>{Ñ(ËYöê?]ÓöˆŒUýTðÑp…ÎL•]+‘þWäUÎéu|Àw>Ë.äm™TŽÁâaÁ¸7re¯ÒÁÁïÎÞ8x—ÌÃû4({ÄóY^S³‡'ðèe;qš['ká5a‹ÊFrÌÆ?j½™uP| nNÇð7fÖU j@ÕÈ‚¥ªl!ø/¬ÏÿˆeOЍ—þÿ€ˆ0@^ë”bþuñ¨Ã¥ÈJìõÉæ­:»Zaæÿ|æw&þGÕ ÚTÁΛS*‚&Ž>€}ü‘Ór`õ÷n :Ô$­Àè€T>gßs¯ãÌ^=ét7>M†¨E¹U¥NõøûôÞ{Ñxq㺒K.Dž¤•$0ÿ ¥Þ3j‘ÔÏŠÏIYên°J0O2#'¸Ñ;Ek„Õpõ·¼V b¹»»‡$)ìo¸ ¾-Ö«ŒÅ-è‘vyó¦ËC ªÜÂj¥ÖÓ6®dnåpÑë‹§éÄZ¨X/Ë^sÁe +j«ÉÆ~[º-ÒU×èhÄófZ›'cüJ^u A¨Œ# ¨‹ì£¯¾/L‰³DþÁcgMý(è Åÿ2ﴶקψ5Õ°ì' Z©F/’—{óšh²ºBL²UÓÈhÙÑWa'ã^ /.±.«àq?ì—;@ý“`%ÃÏú-wW«ƒ²ðnˆ¼à,Ù‚á›.-«û\Îö;¥™p¸"îAU3 èÒ²ô·–=„ÝV!NØœ;$M»nèwÜ_î¶¶ä”·L9†=Eà O mòïw ú 88–ÞsŽOæ3ENmê«|,$—?+ BÅKÓ„ŽKwÁìó°gŒ&«Î·›…[±hyãûF…¥µIêW²àaa‰«¹1ùm•œì‡“êRsòÂ][m§WI.ˆ^¶Å9ÒŦyp˜>ì˜Ür±=Ä̆¤é«‰Ì ÷ëË\ (¡"¦(ï“ÿ¤÷;ý†"M—¹ö1ÿ_Ñ –¤Ø³olP±X S/I—y¼¸äP&–5uðXÏvçœÛÄÒ¿XÊ­ÜRŸƒ;:<:/Qp’f¹‹#åÜÇÜ´ÚL¢Ïsf†¹É"Œ(j¼Æ™óq@;ÁÔ0¥kj:¸HSÄî1ì,Õ¼um[—¨ºGÝ—o±ßÛ ,+nLk…¨ w5)UAF:õmbçlËΚåO¶vl\BÍ*Õ'´ž.8eïÓIž3ýËãLÖ}ð§¶ÌÜ‚p÷›Õ‡Šå̘bÅ {$!â¢Já"ËòÙÜÞcûkÝj5ªǶÝeÃdò]_LZc×kÉOáÐRkt„pß Œa®Ó ÈÞ+¥‹QÉ#ۉ⦵mîjŒîÿ‘Ö"°µ¼e ÙVæzœð÷,¦j&¼öík8< ‡ÿ ͽ¡mµ1/׎ìYɸ-œ¼ý#5Š¨í¥„¦V½À “îð²¡÷¡C,sï#§ÿâ¶ÓJ=(šî”¯ŽÕjìCw²x¢Â=6-Kâ9 8ì…¨GíEê‹Ó…c(of[˜­ÞÉ:|ÔÌ.5€3Ágæbm0[Fó®¦òæÂËKdX˜@wKÿè¹\ÖG±±¬AÑBÁO´ ËÝÝ!SØ“Ë{(¢3óŠL u½0eû'ˆ•Qš ŸžÑš”w@x:µz»gGœMÅ£{ßRÐCÙBh”ưZ%2°q¹@ŒîÔ¶Dd¤É!ÚÿÄö^]>©¤À&¾Ð¯í›ülÔ€Æn}AµÖ!Üjï–êÒ‡–ìôHÞJþùðh3ĦS1ƒóg8Öbþ„¼ÚyÒ¯Ô[Ú7TÖÄgó¾v@?ƒŸb¸µR&MÓH´š·Éó:P¬®‡Óð Ǧ¹õ›k$\ù‚ÿù‡Ÿž>΢˼8 ’ÁÜEˆG•¦"¹ÂáR ¿†¨ˆ ›Õãêé ±V•iš.<µXL7¸çBÊ!{°£Pn¯~Õ¶¸Æf °xàGõ#ží ¦¸áK~x“ÖŽ<Øl#l¨ŠM2?[ tŠetTâÒ4œßz뀯äðN ­—âËf6n^k9»½ ]Öè‡ÎjHú#cÍeê°8~ÏG£ßzj£[ñ.÷¨ ·r©_èEª8Ôú×dn3Tº÷e­ÁõL‚`)@UÿIˆXæþ‡øUD€äòN~ÿ¿Ý}qg›zõálvÔÌã¤boMEÍbÙùÞíß `»½|žÒchb½BE§)ÏÓÕO¡€õÂKn%*/å"'óÛ…þ;’•yf®ÿy|ÒEµKS? • P§¸+±]÷K8sïWÂðݲ Íø1ëß©Tí¹TÌ>`{<8ù˜%ØïvI|]õ‡l¤íÀŰªw.b78@½R8÷€%wè5ÈPcvÀÄ¡ìe£Ê{{ˆõ1ëž=x²àhñ{ü†{¹Èbi.€Zš2—À0ÛSõr8ò ùæ£>ʛЉªLxÜÚÅ«ð­CÏÛß…fÔøW­çœW¾¯CKwã²uôJ®ÒèÄxé6vÒlã|û˜%à£ÈxRtïà·xÂcÛé2a;À¥4½®W{Í  Ö\ãXW`«Âû$jÀy·DŽXßV’ÎöC˜y‘4õS©•=ÝÉ08B ½Z‰Å€ôúpÄöýï±ð’•U¤Áð'öIÝìO}ÝଆĜAn»OÄŒ¬®8_iÂKp1*Í+)áï©ÞXà‚(Äh2.pmj(%êœÍlúƒUaÒtÌàšX Y¹ezœÖ(2ò„¹›ˆ•dÂTDôœXÑ:«²Ý`²çba1äÍ©Rá¾€wDPëcˆ‰àïr”ø)èE‘ÄE*ðOUcÖX!Üe raç‚ô¦…io,ÈRv,bZìÌ\ÞÝSÈ: –ñ¢-Êÿׯ½±sqnä¬Q+Ù¨¢ux*¹ÀyY;g;_¿Ëz›éM¯» cD¹´C'I\Žëò¥æv¨4¸°è¸•ˆ 4^˜‡‰hÓÛkê -… [†í¸ å†sæÎl±¦SÙ_iŒ2$~¶;ë³ÚYÆ ×‰ 4€ó!/Ž•Àƒ–‡" 1Wí¾·{Ü/¹Àû!¼•ÚO»›¼e`Ü<³x}l…*†JMz#üŸQóÕËTVY‚gúðš'!úD–#3ÒYÆdjͿޭÏÄ̦öˆ7—À8Ÿ‡2É ž¦r?ë¹TSìôeO]æã„™ìP.ŒKвÐK4qT?—fÄ|É[¶‹ü ¯¤BZIKš=7Óü5)ËpƒMAQ>Osú »/õ*òÕ'v%w›ÄÚudFˆB*æ¹Ø‹ …ˆU×n7ŒùܘÙ·–s¼¶@Ê+Q1 ²+AÂä>‰UÄ Ž¥ÝN[B+…Y²Øã¨¤„l¢µ•¤ÆéÓ¿Žä&#_ Nî¦gF)G~úÜÈÝÆÈ–ßãúþPàB“>[4½>л³‚ygˆ…²OáÁV[tüÍÄýµ”i×Oã/«þÈ \Ø ¿"Ú_Çòïaî¾Àb¬£~üôº·¶Ù — µ~•ïÖÂ4Ó6,ÁI<>-ÖC]Wvnx†žÈÛØg=áIû¿¥Üj‡ó… èÃg2¸Má¨n&¬ºíkf8Ó À1*ãçÁ$]Ü¢qãM¡|2Ñœ¾ÈpÂþàÆüÄóv3ùÖ'7‡ µèþ¼-âÇZÁ yöDû:füf ëúaiOønž·Á DžÿkÇXrÜÚ9‰¹ÃDÁ¥“þz¸=ºY±ô§XŠÄõ—€ê±ãA#ªÓÞ7͉¹æšmª’¨ã3'Ê~þ7È9C®¢D$tìèQ¨a½£Â¬³Wpv},´ÙÍoìC›]‰G¯x8áf“šÒ\ì„5@¤¦?´•­ ÑšVÚ̯“E:þüewhVᨼBˆsùFdë¹_Zìµ÷(êúª:¿û-vc~$Ô]ZÛà •²mòO2Û#¬NT¥7á%-AŒk3åv¾· ¦®>”´V_μÊ–ÃV­*¯‘\”‡‘g+°­r]v‘º[ Ó§uu†0ÌpkW9ÿ½V GÍÞ—Öß°“€ó¢Wi¦Ïá’¿˜®K*9srtSdäæÀk¯KûÈM‹Gfùý“ú(åÁ@_×j`õŠIP•Ê{ÚäÊšhtØÄâ23(ÔªýCvX­£‘m#¨½4î¹äªÅû58xÕ“º Ì5 ÷¨“P/hÂ;Ü÷™¦„šÇwª—qýÔpÞËn¿2I#­b úé®aÈY[ºŸO\iþˆ"®¤¥¹.UÄ;ÔòݶîÒm‰Q˜‰¥,cÞchÊ’á6¿½¨aDÜhM~€{Þ(ä]6£ ÄãÀ¥†^ .“ÇP8•ì/ä&å½t1x9µnIûQwï_*„õ²Ô§àÿê%ãl `èÜöóJüYä0R p´olý 8ÕI_]å_h méSGÑÌyGîŠ0ã´˜*ç@Œ ŽöÊq¯2Dn™†3A”Ê÷\ ?_noÚÚ4VXâ­ 7:–X?˜¤Á ­À©1 ÿÓc)–ô(½œÙdì}_!NïAm_T†bˆD6¬JûÂì‰u¥A‡—ÒyÏL²—g6¯¨ÔkÛÝäI:‹qlW^Àtüâ¬:—#'Ùž]-Ãi­Æcãü§ ¾ßsVð½$&Æ ­5K z ß•ž°?i0b„³11!rZ˜a÷áä Ö>O ;V[Ì#ì ÅmP™†N=î©jœÄc•l–ܯÒMþ¹¢ê(À„F»³ßþ×À.òÜ¡r„ß,!û¨”2æ&W\dk^-GáÀg‡È®Wc}z“)»ä(Ìïi ç#·KRºÅ“õlÌMvÒ^í%ë™×4‚vÍf§ vÖ’Îù¨èJDNš(Äß)λ:è­yp‚šð³(”’WgfS µÞUá}Í,ùzd Ø*óÒýïóBÄb…3„7&ž³\¬yÅœí¯@eºÃmÆŸ!8hVþñ]°¦æy?ð¨)Ér›´šÉr5«zFš¡Ã‚4/{Ü„…“¾‘®Ñï¶O£Õ9¸/̣܌áMJ±I¤:“Viï‹Ä}y8/¸+‹æÑ”ÆàÔH¦=ÿF[’NÕÉhVÎ5ÚÇ[Ê®;‰¾DL†#ü©f™:¹½OZÜ:YL ç ¢š  äÀ}¼@#û‘° øc®)U‡%ÌG‘æÎ×ËÇVUMǰp?fNS³•8´ÏþOd›6”&@.!• J*m¿^Gþî3dÒ“9©w”ä)‰GzxC{™F*¦Ë „&üÁmêY×áNïÓô… xbÑq¾Çg†õe¥þg›^7þ¹*Î{þ#,Ïí§Œc&Þ vÉô,BÚ ’{bã}î?$ñˆ—ÑvÝj‚Þ*Cè6!˜÷hÁZ¤vG lbŽH·’Ù»Ÿå‘à!œ2Æjh–z¯ZùHxíØ°äîû«¸VÁ ÝÓxßÙéuri‚åD[#i¡ß,ÂììL+cÀH àŸõ:õîö”þo!q6€ ü5ìÓ%(ƒÏƒ t›¤Àñ¦í^åVè§™‰Ý ¾f[˱tkä£Hó^'óíþ~2ÍMõÙôÀö’éÉà¹oUi nõR-§“Ou³yr9P†šÌë„«&ÅÊj”œÜ{®Û±ùÂHLX¬T`·Å&˜ŽFÆgSÛÓײMê…•äÉóÅ >e”¾ÆdhN8JíºØ:–Ñ¢%Ö‹Ÿ7v†;ÑPZ½ºÜU¸½½¸drÌ~b{xææéѱu£ºÆîI'p×õö5ÿ‘6ѽ–roù é0‘ôãYÙ–ñ¿ùÝþfœ;õ¨éøó¡-K• f¦4-;¹+|Ñh¼Œ78o]'¥Ò5”5 ìÈ^Œ$]²-mQìûï›Û¾\Èñ­z!I—Ðh”KB&—”~Ó­0[¯<UêiÑŽ Ü Šš¥ÉktŒÂÚQ.(÷í<ÂREöä¦ÛÐY=¥'¹©²'ŠÑyAQ¹>Bgu-v@»…í&>×Ü}ViçBÙš_¿<”Œ]kGЇIoj2|Yä^´á'TX-ÖÍù}‡n¨$=u}çtfuN CĈ€âþ°ù—j›bЗç$Á¸Ñ\þà),YïŠ?¿uÆhòF<îk黎s/5Júüà/\Êc)ø9ì÷S\<œC bý•P„w+È/*ÊvÃW5ᜉ1´—:J$¾ÙgÇ Ú0€êIÖx7ËØðHà×ÒÑE‰óÀÙsOeM„g‡=;Ûæ'¬ÂÎuZÉ?5–¯³žYêW7XZvd+Ìîjó]1+ÐæMŒ„8ë-!u$µPÕÊÊP¥*Žk̶¨p‰?©â®$$dÅ„áwH¿•X\îÜÖÀ- ~¿ö·¤ý"Ïûg E”À-êr mKà¦sÎÍBDû€òRã¾!»~3 ø×x‹™cûƒØäÄð¬^µüê0o°G%ã®â²¿h®¸6˜fÄK¢ŠxœÚÄDvø¼öÈ’UHYïo…·s,ýèõÀýµq_4®¤u1#—Fš”¡C|? X»M6u½¬X]ê°4û}rËÙKʶÈA÷ÛhÓ(iDÇ8lfHždíþŸ·MÜ(ë) °Ùºì~TšTyïQáó˹û¥%Ú“ ”Ö…#ËŸï;èlujíC¹› fHßd_á„ÛÅÿ¸ °bÎ÷8IUÈVm›~Æ›GUñ1o+оÆÈÛ?»'^†Ž^-”»˜‡\%~~H ï\™=þc“ ØEP3%5µ=‰èÑ põ*J@rl±3м*Míc¬ I}’LE0€Ú!‹šNµ£Äд»ðq’Òµ´ßÌw—›Goc•/ìƒõÒ†~'ž¶Ôɪ12b‹ÄñDÐp[@ŸÝõ–û®z»‰•9³ LìÕ˜DAÕG¹:,Xt+Ä•¥³@T0fö¨LÓT¥ËJŠ’ûk“O OÝæˆëßàdB8åçv9DQ–)a YûŒ6ßy/i†‘Iœð»€™…æêÉ7‚ú=Qá!,ø$tÊlêvÒ…Ÿ19Utb,ïŸËœ'‹ól"=Ó /m Ëm¢‘²r`Ñó0ÌÆ±#U‚Ö}Û±j6RŠ¿˜`ƒ7]NãUÀJxKç±´Ç–ª±ç¾t9Ì5»8ØÁ)ÎÖÛ_¥¶#ËòÑpóŸ{šô1`!ñÑIVS ºÜ ¿HͨF5,üÝõe‘Šj{Ÿ¡×}V.×dëKNY¶Ô1Yª38ÅxºdšÇŸsŸs´Î¦¢´ß …^Jä¢q%ÃÖ•Üüä (­Îþh¢gÝ’\;‚a{òó‚²õ•³ ÐTzH ´üóC¤‹™®$þÈAÄÅK¼ÞW™[ûS»ïDÉ®ßjeÓ7û·_ó^&%é§³—ò™ ú+ÎNÅêŒÎƒÓµ½Þ”³ö8oÿªÞïIY Œ8cSÄSõQ]ÀúÇ·qÇáüŒ01pß‘~ÆÄÔÔFBµ™«Y›ç¨IÄþÒŠj(ÃòÁ?`ËG`9232“pª®;oS¬Ç=tYÉÓ«·}&ãXä¬ð’xµ]÷”Sê5.b ÎÁÔ_Ϻ;bûɼIŒ×.^˜2‚+Å™#ú4M<°ÐN]z4Ð„Ó £’ ®t.m )i¶¾ÊjM÷¨H&šËÄðår°aœïÁ‘±¡üÙMö÷Íé±@ª0ïò»¡Mý³9wJÍ~©ÙÒ/Ù9 9‹g;ýôûaCüÇý;w1àÖ``ÓCÒ÷­†×fÛƒ°qxÛäx(ô7#¸Kí)û†„¼éÀ|Ã?‘•:˜™uÐôëáœÝ8ØšÇí¡ ¶.QÁqqÊ ’’€ ‘G^XŸåïð¾%X^vfŸ ]iU”-,${bý¦Õ H"!,$¤;iÂå9L9¼ñ•¬²Ùð7éq°°üMoH8±‚‡hã gëLγóšû:,l˜@ŸËóÄiÙy¡/¹«NöÎÉO.Æ{à€!úçÈ’íRQR(Å‚û‡¹D üL|¤G MO™¥z„–³ÏUÅ¢9'*ݔՆ­!þµ²¤J»±†°Î°—F8—¸.Œ˜5"›S¢|ŒS…3ɰ6ÐŽ·?ÕSYµ‰;´os-°ôÚj öZ°j~Ôq È‰|=Õ.ûþŠæB‰1 ó$œéÆd5ýÐoÕY‘TÕxÌÞ:¼•3±äþÛ‰¢{OÇÓ¿Yü­m VÑ­±Õ÷™Ó«Pß²ª 4à=ª‚'^šAˆõêø°ñ‰K”úLÀ]½ëß)šXáåO‡Å%3ÏrBúQÍüê+w™Ÿ¥:1¬ÖPo €PŸbpÝw£<„UÂ/ßôã®eíÕO¯`° “ß*rõb Ë>—ÒÂÛ™JÕZî€V𚸇¿;Ô$ÎãO×o$"@¤’±«/\ c„_:y­Ûͨ$8¸ÀŽŸ±6$SjKh’ø‡´´®Í˜Ë–[½üÏüg E®i\)eY•]áÔÙžx%H)b,g3¿,cçíCéÁyÞ~×ôÚþ¹;uÓPuD8&²äÅ¢j)‘ä§$±ç’‡ŒüK‘HZŠ`é2(ÜbÞžsR`æ°€Ë>“ÊY‰Xt(®½­‰~0o>¬©;†ú‚O7{ò4[µ_¯T“ɪØfv¹à‰uÖyïŽÜS”ÞÜã‰5'Й󬏖¶‚À>„4+ŽX ´¼-[å@äaäè #Ö» "&Çb©Q¨½ßª$P«¸å ¬­˜qÓ²µÅÄaf:`†ÍÑzÖÓQµÊ­øÔaÁ_Ln>d8V†h9òµÛ…iå‘ÊŠN¾Q@8vÍÐê+fGx?F‚¹†§¯jX‹µÐÖíІãZÖKÂÐÊS¿EæÜè¦?Ĩ“ÍÓ Þ³¹¸·´LÊÝ!r˜P çsê†WìU|Ø[âÔa~(úªìm-QCz{;vÆ)·sÛEÇ1%»:‹ü/ÅÙûÌ=üNhíÚðâ÷ªÒ±[´Û9]}ikòÁgrälÇó04¹J¡J$åQjG¿õGɳÔY]ì/~É}r‹¶Za$ñ.^ìì³*xòÂë|§2%׫ʂKÚ¼ÂÀbÒ€ìÐ:ô¤w¼°êˆHàºàHâèÍEÁg/‘ªæ4Ȉ‚útÙÇMóòȵØŽMöSô@ª h¡{d0…‰4¾ÐÀW(P ˜âT>?ò"ùÛ M²±o¦[(˜“ž¿{3ÂhÉÌÆ“„B [GnjE+DJH©XÉ©¥Ø&€Æí@.Þ}~iPÃ@.õ±¦³ØõU§kÚý¹c$Ôô^画e[ÿÂæNÅöŒÏ¬aàÜ— Òõ&Ï48MéÖ§½:4;+–îí?;襇Á)ÿ6—©Î4ÙBÃ@ņbƒ§ }'mNÀ[È¿ÀiðÑŠº„A¤AÜRL”“ ÁD~aþÀsG%ñ—6qëgH~`9–Þì\ùO«™Ö«#+)´›§Q&-Q‘I &çžñ=hpž;ëë8…ä'¿¿ú¦ukæ ƒ¯(ìr—¤«K×ý}´hsi™x ’QW©rø\ŸªA `ªÂŽD>–®1›ù¿…ð„ý¼R2|„cØO?#åToTJ²t‡«bF˜7ž’GæFö‚£à@PT¶žam'[UqžÁ«Q‹eàÏmÂГÏÎHãæõ[¸§ÀÖæ1‡ ‘îÆ¨,Ná·c)˜–!;ßã ?”08 TËž8 øÑŽÅºlâä €# IšmWû®d£~&j³/ZL\:¤Yî+•ŸX )¹¥#Ï••oŸ­ÑߤG‘ypn¼§'ã„ýJômžÛÓŠÔ¨‡´=¢¹w¢žôÍïàÚÆ.Õþ °4±tü8bIy¸¼ýz7ºÏ¯Ê} ÆdÍ¿(¶(²Þ¸üðZAßÉ]†Àó©XŽâ{s-ã¸_Ö2_ž}Ñ:S±Êëf·<Åf3$N̾+hJ˜™ØÉÄxö¤tç>g/ ÿ”êMì¾;É›‘ŒX/ªM käV—èºÐ«“*“[ŠÛ ´W‰È ÷v²r›åÉJäÛøõc+ñš…×±EõWqÈÞÇ[¾k/Eïz)ÿFß Æì|Fì5w)ÄÉÁR+ò¸¨—zû§Øó­ê@A¸¬·Ÿsè<Ól¹¢¾ÔÐÚ^5¶ÀßF9<Ýq©3Ô œÄ`-Rf’IüþC7UÞTlä5jLë¾_–¶5ÑŽÁß*)…+ïÓË’H7\f>ŠœT œl±œ¯={y‘ÈuËG…¹m‚ÏN‘?Œu‘+E3åÕÈõáº(—ÙëÇ—¯ñ³?Y‹'†`Üq6z°jXkžÔhˆî8t{±<à]…Ò?xK Ñ{©ÛÀF‘^‡8&Í×Eͦ‡ Ô©òdäÝeH#ÛfUsPPw²&!Èô¯Vš@t…>×I/¸Ñ™&w[ú:'ÚŸº[§ºjn'b¡þé.&>ØÒ„]å&é3”'¹ZlãÖõ‘ñ‡ö*>À‘ÈEîxrÝOØ0“<­fxRV=­ä›¾YèL%;6÷ÓVG:QÑ·rÖng êú6*艹éƤûsÀ6°‚å7Á"¶Ÿ‰IXÜkJé ‚þxŽTeéAR–}ƒ®7ìŸì×o­šGº|7õýØ>Š\¼‹KyOUz$÷ÔÏkM:«Â³ùkò­ÄôGý•»¥ËÎ~óii¿j!Q-JÞ;f ©×fYŽX«s¾l)ýcÿˆ˜7R⤣ÀÿÌA̲‘h>† ÓÈcS<Â]ßp®ñŸ‰¶~D†}N¼|°ñå°A{¼”)¦õ"")~9ñ8m­i˜™ €Š=aD³ˆöË@tT‚ˆ+…pɤîÄ¡¦÷5l&# ÿpž&’ZGÊ®œeA”a ˆiº¢áâÍÓüß”j“ê‹`Lr§óôð)³ ÇÏrÓ/¨g¤â²J1‘i#­T¶U5 &¢Ý.“oÜÝÏÀC› ìJO8½ÉKcÆ/Þ,•Æ8h¾ËänÎÒXDÊEé⟘Í^±¬hW#’òدfyS™L¹•K­d_LCâ~3­ÑÞv3+°Á’a ÔºZcØ< Ø4z:©:¿›¾gF?<¼¯ét¾åÄÞ§qþÕðé¹M=Ê‹¿Hyù¥‰5ÁÀA/¬âhßk¤US;ož=öô­œS‰ìL¶œ$‹jD…·a¶ERžVPz«/±@§Ûâ8¯¸5™ŠÃ@{O'+N¼Àx JktÅ…ªƒaL}))ãÍg~Ô½¿Äý¡½åü5î®l½«SáÞ?ó€•É2¡›Þ™Ô0W  —‘¿D´«Ì}¡[ Á’%é–.§é¢^ÒäSU¢êË'.ÏX$ #¬Ël‚|ÛêÂ;¥؂‚Ì“–$ôöh2b ¨m`ÝÌ>ÂF6ÞèæàÌyDg 7c¡D¬ìË£C¨¿ŽÌMßkÒµ÷f(".Ö=—9@V„rü&Ået·qjßAß,>óçÜ9E9~Þ5ë„Çd8'ìæKP~Â! ó, :´}m×Õ!£(;ñyq4žHÂÚj²,#Í“ØÍsóâ¯LÐhéëÝ>ô;˜cGnQÜh‹ÑUhLô1´ƒQlt¯[ôkÑ9·lËJ&Š[Uï®êÍœ7G€WknÿŽ*ªÝuxó©¾Î|ü²~¼vRYpµh[˜62Ýð=¹ª+n¦e®ƒ1|R­ÕƒCXE,uÍ”D)ãáJRvÙ€‰ž6ù>kpz¤É¬S[Ê›Ãb©o½27DÕ,QŒ$ù3z„­ãCÆ¢n€Ž”Øò¹­S?ÁLoû›ƒf²xQ”©Þ΋ñöï)+¾û:mç…—èšTÑÎ*UÙ!¤ÅÖš…)ɺ¤wø['¬Ð¹¹@—siXªÊ]¬OÜÆaÇœU(Ax5!LÕ=#@%»ìMý¬0œ>H†²e¼½¡Üqø.µ2Y8¾@]GÊè±I¨»¥¦o<è2ãö„B à$`e¬krôû›o/5ÐéìËÂHïA7Þ‡#VñFPœÈ‘´ß“ƒv/uùFãŽàf›-€7±¼ù“~€ÿÏᤥãµ,²¤kÛу&ör&:Ÿ¼Ñ˜·3ßXùOvO µ‚”´¢¢k¾þ‘¶ƒÕ<¬ËLäz‹d¦w| 釞jçÂVrqú,Øå×®Fo Gªö‰L+ç¹útΞw(°åãlAøÏ'Ëy;¥Û- ‘(·èu:M…Ù@ùF+W',26NÝmM´  BglÓnå F»—î6>|îSÂ7­Ñ~“7›ÓÙ˜O‚+š%9úkÊ•ÄZ\Çx÷‡) ÑpÚª1ÑÝòzlõ´èI ë®07SXÏ Ê`³$x<@Ç2›žÖxØ a‚+Ù)åìïˆRÈgЊ©Œ}碇k58µ×—Å`´ðÔÏ醸jħn;ØÂë¡zس‡°ÂæïcñX’ý‹kðvî%'*9w7õÖ’TÀÍivˆ)Æ_ßÍ)Ë¡;ò#Ô€8èùúÄIQéí*þîÿ ýd%ØR{ÎI!ê#K¶‚òyI7yåÑ€²–¿c0ìéÄbc¨e ¿Ö2=®´§4‘Å.–¨ñeÈEÑ╣(Fi£Û2°â!ú`ÕVk\Äd$î]TɨbÇÐf¥z@dßa³Ù†5YŠÌ•>¢§gœLšú¶ë0Cç¨Óž=vˆyhn#>¥û­³jç}<²ÀÍÒR#)YhP…)/ y¡·Ì‰jAöà3B@÷-œ(üú ‘PP÷eMŠ4Y˜ên°í‘ j&[®§õ1Ie UþDúZ£²ß9¥:*þpx3%¢qî±àO8q'è†l@ á.˜¹B2ÏŒ×Ó±“´Áò±»Kkm‘) àýt:mCݲmDXÌ]ñºZ9Üj æ²ý­Ùò‡j>÷ÀÕ´ÄOGÖ€©Ö4¥v±™N þŠº¤Ï"Qˆî`?&Ì*ë ê?Ÿ·Do’$1 19JÞX¤ZÑ•ÍuÑ'ñ«¤¹þ©‹½±érÛd½5xç݇þ9“ÄAý§'½º ø×’¿¡5µ$·0¾ÖÝ è{IE`…7ÄgV[hßjÉomT™Ý½h¢ñ{Ý¡•¡¶~>Ò¤t)ÙæÖU>ÿ‹qÏ©§ŠðÒ•†›K5€Ã ( ä¶ñŽY50f¿|¸}ä ˜Gãx“³Ÿ¦X ¿©Ü ¦ø\Å ¤d^vØè¹CêP$Þ˜}¢rKîÆ&? –ÇEÄ ¾".§h—zúuÆÞ‹03õèÊÍ,Oþx&Á‘w^ŒþtÈbýø0íÄDüFQ2ŸÒ]Ú¨P0;\¼ia>‰jÜÞïö•ùD« T;ÕžoÆ.ø ù®– [ìýµNDHN<õÿÖOñ ’êÀXòåïT“×ÈõíÒÏÐú ;~D›îÉ]U’^lôNq`%E„isÛc“Ÿ½æÅËYž£ã¬þðWyhÎw \7k²ÄrްÓìÉk‡Ì‘b¿º`²,¬Ôûp¸UÐõ}ñés#òƒM8ϦfœÖrFÛn¨]<99 @?¡þn°ì‹£ŠØTŽÃØ×»f§s“X¸Íj3¾Y^“9ù£e¢A¶Ì ‡À6OÉð±A¬&ÑR(a޾ r‚úwÎf¡\íÊWS½¡ÉoAÕRG¸¨)ÍµæÆ¡vgÊS™ÌÜÁ¾lð÷K‘”òj·Pú夨)·E1§ÞŒíԥ΅éªpË úu;b!e0e <ÚÚ”àûÅl…éRåö<“!ÐCãEôsŹîr\·~<|KÂËÉ!I¶±¬ˆ^²™—ôÁï>€ZÐ{²GE¨…ƨ£ÉAt%I`môÇ ŒÆƒJ.Ì}^ÅQû~ÆÔâ(|W.,b½ãª;3(ɰQÃÔ¿~{\’rk·ÛÏ÷Š+×sÿÞ¿=d>H=Ý<Ì&TD3ÙŽ@Ï#Ùª·ï}ä$³*/­.€p=É+‚œëke£Ï测YõQ†®°™ün.nTpÄäÂãf9´`"\Á<¯e–[‡[c—;C‡Õñ[ê Nø§–ËYàž´R×1*qîq;J*êqCß?¶|é4‘Õ ˜ö3ÖíDË€œ7>»5¾7|!./lŽhR{ÙúšÀ.i) d›N÷ ´ÇÉÜ™ËÑÕöѹ†6ñhIÝ$»ÁX z ¸Pxx×f~ëÔ6!–}rròZDñ‘3•k˜•C)ï0Q*níã|ZíB<³äÓ3?ÓÆý—vújãÏZyÚ;'AñísŽÊ°?h(&5ìC…ÉÉ+eïÍÈMÑý=<,Q:Àáÿ —ÒÏê} Ê}^‰+pHà1+—\h2t,ò…5Œ TƒÒ Ú<…t"ZhJ¯>maÊ\.O$]©½$ïNÞ˜R;É9S$^ñ–¨²"3/8¡– *ü¶‰¤ k9O %+7˜7¶¼J‹ ‡Ð¤¨;°‡õ$'¾}^zÝû»Ö¬]| “ £<®…Â@ÌM—V˹R‰)#±ñ# ± 0ØgÑÜH g€l¯–yÏ7üù‚ÆeÁÄU8qäýáº%^E›„{ÚòÞÃRø*×1T­hÁ}2±ü”ÿ¢nÆ€F`o†{}bÞ™]¤Ë©\oÁäÓ_» ò \‘Ïa:E ódó ú/¤_O¡¾0´˜£¿ç#¡GOyü™ÎÚÚÓƒÀu¢M¶H…esÂß ý)ÊCÆrL ÐV±e¤áæEËѾagí´]òÍLÄŠ s¢{[ÄbŒ/®+ÚaèÐ c:WtpŒu<)<«³,yC¿mä‘öN)­ZO à3òÌ~ ·W{­IÍÈãQ }[šÔÇ⟫ IÏ5ºtE)¨T7ñÒxêlºgÞRø*ß!„ƒYF )B>E``žQá"súmr–Ù›&š‡@çMÕìÛ«´O)%o½œ—Zôúf^„;`t¶ôú2{X¯â‹¡+à˯ҭn&·Ëœ»(.òîFa Mnþ †ÁvVüÄnò"˗ͬ÷“¶Hvèj÷ 3 3àÓ‡.Q°ödFž2þsðR’å`8»,Âí°#u¦ðõ) Ig×cQ#d¿qV´p•zÉqµS.dMð3Ð,ÉãæÀ"¸3²LÍ굸kÁŒ6ã÷À[Uw"˜÷š–µ^ØÿÒNò“VÆúí%[<%Üž@‹¾Ö}pŒÚÍ}ÌxÁ09mÆLð½¢éޝ^l’áÌ öéŒdé\"E §1et8t‹#ÉtXóT¨¾“à`JÌ+æ»4»hÞ5}O×Džæ•¸ïV7œÉ1<»tJ¹M¤þºÈpŠœ{?™|X"î1§£’lWÁ¸?@Ud¡ÿ”TÃH|¼âøÞ,]*üöýÃq]{ ‚bâ?"ø K€‡ý1ɱâïÚKGÚ‹“CÈÖ7ÑÝš‚;lùŸhVèNËVæŒ[–þÕìÔ3þñFòïÄýDJühZâ[²E]/ù±{+eªQè&v8·Iè`Îê«bJHÃ/Dž°[½w I4™6ÀølH6¢°麟ÙyRe=+¥ÿ? žg± ã徇nðÅÉræ“æ¶ˆ¸ÈóLô%5¿Ì¯k^k‹1ÇBîßrmdÁ¶|Ô€„ý×ÿÒg!Bë QS5U´IúSÅWb¢ÜGh##„˜ròù¾+ƒcž†\ç >w‘´ÁBðó¨æûú’?ÚÄ2v’–;”vÝiÏp”ÞÞÌHv<ºdôŇs"¯¥aw7@›É3;Ö–ê *›ÍóÜÿ/øÌž¡œ9 E ^•T\ 7’‡s`ÃåL|üaŸ¡‡Úª> •"!žíw€ê1‡:¦§¶R_Ca%ËÞd¬âQ×ñ0‚hHÇ&¬F)‰Íž™Uº¶ІD5ð 7dD› ±ßrZèÛÞÜxÖ×Md iLÝ­#Xñ‚ÉRìä§c K ‘Ž YÁ[S°/«QOÌpP©Ûp,å4½aßx0_–Vª`4àææK¶ãä•ßϺG÷ÍšŒb’¡U 0¨Kɧ·˜0-T]Ã;÷÷Ž=¨g¸§˜aì5¿Ä,“`øÅŸúà`´1(“ƒàÁå®…ˆv2ϰëâå}Éô ¸* ^÷äN¾%¤­S—hä4^5“©“Ý­D^™Ì††­AÜ_O鮸z¾ðùLñáj,÷îJƒ­ ÃsQ×ôÝF*…j¿"Y8ëa™Õ'#= zÒHÎ59ãSÆâÁßµšö;°„Z†4¦å‹„ÿ5î1²™ÍQu:Öö#ÍŒ³ö9kY7Zhú੽>ß³]¡ ”O®_©¹ªö¶W²9:Ñöyyy{˜‘Òε‘f5Ÿ1mÇÓº Žo”ßø† å»N{ºÒ_P|µ[ÙEܬ G²†ÜÅ¢&a™é£ã“Ö ¹ŽÑ"ñ_Éôq¼†ÎµÜ%…n[w@$YÅ1h ™Gÿ‰ªKžhUׄü0DðÞB|Sãð‡çG|sjŸœ~ŽÔÍšï2é³-2·iuòë>Å”&“©?éÚõƒ/ˆ`'3! ×1‹õ¯$ÈtZð©›â%Î},ÄÙòûVÚ¸³ˆ‰Ewä‚»g²¹¨9àgßýndƒ÷ t™âOxOÚ·ë2õ¾¯¡s›¤4Xµ"Юô(¤}?<šßõAiÞü}1,d¹×æœ3_vÓi±â¶c}è¡ d½t=HÿéÆè%¡6„3@ƒ¡‡ùJ›Á¥/u|ë¿H‚˲¥0 îÄ3á&ªå¢¯€¸ç²Ñ3XÍ€yO3Ý £•ؾ¢¤dÚHÆvð*pSg4µ4cŠíæTd–*_W­LUɼ­îZ0ÉÊ6.]ªf>ÜȬšÓ1+ÑÙÀ.Ÿ:Ù¬Lw¹¦oqªž•þ¯b>O’+޶hÒžf Ôå‹éÒƒHÄ/QOk>ÉäZk?7¶å¶òó†wõ@Ç|ÙH!‘0s9ày–u°PåÈ›þ²G€:8w¡J·MÆåy;S &¿üþâ!׫—¹Z0²¿ ÁóïRÈ:u¼Sͬ WüêÉTbj+|à¹2Ãáù@XÕ(_8lkw§GËM{¶u8ÎN: }P/¨ç ?C¡ÄÎG‚êÔŽ/öjGkd|Y¿:æåšxõÆ´HÍmë[Ó®y|§V·(Pk‰°û.nôEÀ„U%Lå\£fêøQœ^fÖXÑ”KÝæ[JïȃБ.Ï¥3góó PÝz¨O!â‚îHæìàh†6dµ•`¿ï¯^÷ecd´ Ó^@TÉ^Lƒ Y ûô¨«ˆwî×îxlcU´ZºÔøVL•D‰iHG®cÔ0ß+»µû¯§Ñ.~»)uQ6¸ìYcѳ©¦î¾òFV&ì´ëøÓÑÊQÛ®Dõ+–WßR„Ë^@»Ãè¡‹ï솓g«qm)>Ö­ä1SMþi»V,ÁiWûã¾) w¿&–¡“ÙËl¢q¥wÓÑ“úTtÓ‹Ÿö’öçÍ'þ‡9€ƒ«†s¶€£LM£éÐX:nLƒTÁIqõ ÔÑë|¬À1(×7ÏOâ8€ TžFöv. °ÁcŠóä§P/äÍ“K`rÈxȲd"PÛ`Ð\ÝèíìjßaÁ¸÷lŸÔ†[Ûâ|güÎ]”ˆdø:–ðÁ½ÐÍFNœZ)|_»f}èø³Ó‡•ž¯ ÊÑA*§UóC dïo®€vGO·!qR·%Lпð@~ÿûPÏÇšöÑ…85!‹#Þ®•ø9Œ1c=°€€Ï¢Nú® ôÅÁuÓPC™X"Àhå;¸0߼̋>«úƒÒ×ýó¡&!fô¶„;ê3Ð>ÒŒŠ n[,xPä’è '+lqt÷¿qØ`h­GþE¼ÓƒácN š -ù{º1…À’ÔŠCizŽ}ÂÙ³­:]ÀƒúÐ*ÞæÊM$LéÓEAýX) nb6!†½)íŽW.°¶:•éRüål& fæ™àNÔß~ŸÃÎí`ëúµð0×½ÙjûËË@aÒÊÃÍúq(¨ý^¡Wo€/·ÖöPÙçÙ|³¿°yt`#m¿Ýw´€12²8!”g!ñB Õÿc\?_F…Mr›Š´¯ 0ÂÕÑKØtW©®ŽÈÄâqL$šT8cžÙJkŽ ÿ†þ,hÿÏþÂú¦É*8,*Œ ÷ÿ1¨myÖœPwše½ö¯pëCX)Q¯XÓHñ-"¬)t¢öHÅWO¾‰iÒ~S¢)9{*«Eöw¸¢sÉ·h‘PŠÓÏn2»1áëÀ±@Ó¾¯‹bSÁ.†9X W€9Ê€ˆ{®º¡5ùÍ·ã(¶.AKõ !o,! ¼ýD$±ãiX¼=Q.Ÿ„ruºèt—7”¡õÆnvþK“|Œ0¥Âˆâ‚Z3§àÒJÝ T¹L^ãAÀR’öû.íƒ f6‹ ;Âo²“WÀýü/ ÿÔ=ˆÝÚ³gÈ‹q–£ÒÛt¤pDÊ¥KÀ£ªåy<ÅÕÖrÔž}]ùüe¾×ØÔë‚ä$+7䕲ÌÓ¯ž–Ú€ƒ+uæP" àéàÓ9ÑÌÄ"•­VJÎ@¹zÊÌë”Do†J,DTìÿHÒ§:rª+‚{—ñGÉìE×¢vSÍ »:mA¹›/ñü¶ p»žÇ®|¿©-Q6Ⱥý‡uªÄâKúušÙyÔhÈuS/Ú5ÈÀ #Ä¡Y»‹xš¶ã˜…©Ñˆ:jh ò´QèöJ-»¨(,þZOT.`ËXv3„ŒDÍvwì8Tñ¤jTj s»F¦Œß«9œ~öÇ['~À Ÿ9rü2 Í.ÿ†Ô‚2È*ýõ†2…䌀×hÁˆ¥ÕÚ3´§WYva|_ Y>.³’ºCÎå ÚV=iäKUnÉON¦BÕ_IÓ<u@G;ùºPøO—k©S<¨Cf8%Ãy!áíÍ›jÙ[Ũ›Àži/³Ciê&{Ђ‚âž¼ìÑ3Dí{œ2ç l+nG ¡ ó8«!زÐuyC^¥ @÷¢ {3t°~‘ eØéñ T EØ«š Öfþ&¤ÎÚÕÞ ÎiŸ¡õPŠ•¬ É|‰Òi(±N`¡zF ì%85g\fãV R“BÓ.ú©’ùAë7k,Bݦ"+ó·úxFl£·¸Àldƒ¥;%­¼3à1A5a:L ýÏ) m®Îâ¿=@¥Gw™Î=K½wܲêÈèÇy³3¡ÿ:6”o.|>)%•)©A};N¶÷ ßüÉ•üfw$  ®oõÌK—µB€äH`ðOÜþí á†ô{. IÇxð€è6÷ ‚»­%á½Yþ7{”çÉéb343nj"ÙëåçÇ6ìû]ip?’Ó[ØyUåÿޝ-R|ñ5`„ÿãBiâ`ÿèíêm³ªc-¿9h!xBBXMAíöË÷½ýÿ1‹ö”BáW»ß7·t2:ø–É´è2Ûw=iU$ˆÊÝ.®¸bûÜÏ–V¼íoäïün\zÜJLÇ™(Þñ}º—W²±Ñ¢Eßšùq’ž9p HÐBGl (W ëì‰3ƒ“UŒè‘iï·J[?êáï3" S 6l• {µ¿îj»2(à`¡ô\’:êíê­Í§ï¦øÙ…ÒŸ.Œ5Ä|Ø— ÒÆ_^Zß}Oñ’,¸­póy?ÿAðç„ˆç © I¼°œL› ó²ÄÙø”¾^æS8ÍCªgƒô–RßHdXr,•xíÈô‘{,ŠX±«¬ c«‹ð[¯³O[#]ðסHŠXBQ7%ÙFê¨ë¨ïœmä±ßvõ)8ÁJŸkùüÙ±ªCF€—ò¿e´Äbž¸wVbk∼Ç~ñÓ 9†8¥Ã‚¢òtBxÖA‘ùGŸm!ïÏL‚ÿÐ6 $>æ‡í5Ç®òFèþÿiB°Y…r0üò9ˆùU K +p`Å8Õ3ß SP_Šãô]2"Ë<»l•Q97 jj ˆbå$h)Ö=ÿ1KцØÒ@]_²zÂ/0n›@{,¥ª~‡R׋ Ë»Ñ¨þßv7úžÏmª‚Õs4P¿’ÞõÏesv%«ñ\X×d<±›åÖD·z[¥Þ|²]qÞ“2îæC‹ÌŽƒ!\;BÑŽX«®§‡ÒGfì(‹ŸKX /èbxJ÷8ÞLM`oƒ[ÎÖ‰(²ÝÎüÜáhn…ÒÔBs#$èCû¨Ì“¬„„ƒÿñüï1èRûº©ŠŒk.`´õ€%çEçe„“_²€»!ëƒÕßîª" g%.‹«/¶ºäÖqXÚ¡àu ¡%@ž­•ðéÅ}•ÓÂÑÜÖ ¢~ ׊ÓŠƒìÆQŸ"£Í*Ãí"´Æ§¹ÌÛEou Ó z·æ½ôî@èu.S£€Ö@è !Êú}ö”5‰¼+m³ASâ°ô/ô–ÏPE»YF6BÌèq°†¸‡Á/h ?ØeGwus@××íú ›Æ$äï]·.«>úÝ']Œ“䔵áÓ@ÇçÙÌ ÒÑî*ÿ€ÅÙàåøaýt-ÆaèN˜ˆ€‹ÇüN…^-=Ç3w (ÎÂþWÙˆ].Ý|R=v÷|lf¤Þ©@–'­×—ïÁ‘p39¤‘»«ìÃÆr÷eÎTFË„ˆù” .õ±Ê†Ýn¤r#¾ÌóöOdGŠ2*× NA€ÒrWj§Õ˜¬öòlëÆþ;&Ã*ÒÀ¾·˜xô3ƒeáfIŠyÖ“äʔ퀭tfƪ¹áp‚Ë£þdÍŠT¼KJTß(ä³XÍú‡BíͰ„MÍ–^ È÷YÝ«~øgä ±G1©ù¹„x¦gð]ÞV–‰0/þ[ß™ ÇCe}’aˆ„²F|2Ô,)ióúÒ^kÍúô´6*u¸¨ÔDè{-æºgøðšE˜Ì€â(Î1HÀÜ‹Bh úbkÃÀzäHçÅ.ÄÎ*û4Lyà•®µ„ò¨vÒšO¼Ótl§×Ô…½ZÊdãáðvw¡Lƒo‡)Þ«ã+éóFSHÌÒI¬ñCµñ¯ê£­|ýù˜U -ÌKœ»›fÿƒžëÔ7`Dû6èH´ûXiˆr Ä®×ã€iÏðLIxü18TúJ¶×™ÁöYÕ!%æ6LálêtX‚錛›“zúr÷¥+pGóF~Ì·^)Ûí䂘îoºÆCt¨hÆW –¢¯fÁAêÃX‚Æš >×Nd–õÂjÂßI›ëÞ+XóWdÈsã\Rg«ý»çÉÆz2žÉ3Ü&Áéé×Êbê’=ƒš¨ðý˜ƒ~Oñc*ùE;“H€8÷ëôD©§jÇÇe½4D$ªbþ"—ḑ&-Ó‘~û´V@>6DÕ–ófZèÔ„·ÒV@&Yî9`¯ÀaKF•ç9°V :ôQt[­ÇiÓ5O¯dC–÷ÿBk)OVàµÅbTQ€>)Jxìãfc:lö±lÊâ´6Ú¡ç§ñ=;OæÈ‰ÖWó±ÍI*çHûbU–X¶·NL÷ †Ã(é!Íe{ðŒÂ÷䔓nëÈÆªh O/ô(€í£ÒåžÐÜ^¡+ïúƒö Ž´ªÊJþÞ‰¥$ª@'4-µÜ‘õB¬éÂŽRîÂ#ÒäB§R¢n=B*,ƒÓ¨?ývè,Î"Ó1Š<ŠF›/Èû&â&ýZˆìígí´fìg•B@ÅjŽß9…jÉÛ´~ä¥l%çØ qn€§>©Ò‚/³tó5†= ic« Ïy"Š­€Ý¥¥ÛY\:€sÕH†Ìh¤«î =7iPn©þÊçþ§j©qÇ}Y§l\äõ3ÄÛ#Á–´'€gG9ŠÚéG•†x¨lAõ޼òÕ«ö´gÂð#‚Õ~“äÎ&ÏÐð5Òóc#›ð®üAV+ë=¶íÐÀ#McyZž£Š‘CêøvQ½dèÚ˜@ ®8´‹Í¬R±“Òú~Vn¡f`<. mŠ—¾\T÷J mO%I›ð?ÉÞ—Ü/(Fv 3™˜‹Gÿh½Ú«_Âìý˜¶øƒÆ0 ÿ#²/K>©~ÑU>ºÍszÒœ>ùmð,g§!dXç«MvÅ¢‘®e^1ƒpi)ÉNv¹¶êºó¸{ãçÜF±†,¯.)îë¢ ¯״’´Kà£1nÖ+ëIÞÅ X§kœ•jÇÅÝ웆ÅÚzB8oe¸y~/Qï𙾜T6§/>J´7ømß)×Ú7 ö‘wøZp‚µ–ôáæù%°ô^hÎXy¹°3¡îW‚ô×ÐrJ1¨2Ý6ŽiÌÄNO÷*úsš‘£ÙWEAÕI¹7ƒqZŒÌB?$ª[£÷¶›8¦úaLáWâÔ“mb„U,™µ?0½AÀnÜÝby‚§àŸ†`€’+ Úx•‹·®q£ªÖ\`*šO€ºY L ¼XâJ¥*ÍÇۺˤ[NŸ[ö”$íäÓ×7xdWV§¡€¬õ•Äe׎u床Bá ]í¡ ÜÀó™±/Š)ìNÞ*êé•‚ZHbÕ b”ð«S“/ÒëZÓ=ÝG‘Ò€–¶(@Õã3 ’ ~_KWÓ;Cðô³@*ü:zË):@*ƒ.èD~e [å}éÃöµO†ª?ÚUtVY‚@P¿¨,Öâ¦pYîÜðäØ×.„vhlìö{ÑeºHXû!þűnôP֕諒•C*Sk7ùàH¥Ö~óhׄÈMét0Û¨úMR’ÿ”~Ž9 ûßLîêHú¡^ÓJ¨T@BZruÛ<ñ0ƒÞ¾-¢,»·äf[9œúSB”°²ç.§Èb¯ù¼tbÕð) #µ°t²Š‹R.¼Q¶fm, ‘#K ND&úIã—W#>*£ïÛ·%â% U>Ôd¤_œy¦ÚVGÏײEÜöT´Ì?"Ak·jJª«²ˆ$>ŠQƒÀŽ£“½~îtXä C—$›0Œ3h(ßýg©â§Ž+_ovð \Á wŽ“=Ù–±ïQ³©E[wÚ€@EÓéôõŸ ºè¶ŠYÎÆœ<º´?Æ/à•« 6›mWð€ Ýw†P ºž<‘‰áÈõÏSÀe™Cð0Üt½6œI>ýÌþã»ÈÆ\°éàÎNÑ>3 –k×Nàåí–ÌÐéoÀÙ®E_(©‹þÚ¦¨o¼C„¼¤?£IñS8¨_ä«&Nœ&r=¤Ú$býœ‹QIE%‡À¤h5ZËxª>ôáé2Šë?º›ð¥ÄöÐ8SÛrʬ#QŒ¯$ñãeIžÞDmx$Ñ÷Ê5ºTgY7˜ëAn¢KÌd• Û‡² H¯Ôc ï²Zˆ{Þµ—ÆÏû¸V™òW:h0}%ü«à­•‚kã”;:Ü_Ûf—ÖÎvR§¤ÍÙâ'¤—Ö…¦ „ý?ˆOuΑÊeŠÅ^Wn×X'ñ3üò ÕEÝ+ɤàD8(€þO“êÄê?¹\ûl0™7¯¹„ºÛN6 ‹:ퟰ û5=JiúdT w¡Ë“ÀÄ¿£ ÐÏgt)ÿúI\‰z*XoN~!›JÅ]~Q"~²ªË¾`3{#Çæ.Âuô.¤I¼‰õé`£©6¬þª–—“Tl¦`*àŒª"ìÃn¢¢ dµ½Ûˤ’°§j\ˆ¦25}F$š î4´[Ï£†µû‚ÿ…Œ=) àüØEéš^ü·yDo X„H½ â ÌÜl`Ä ø‡@à+˜Û¡ÂÈœ‰màOóæÇQ8f 5zaÃ:7â>ùa»ÃýÍS]ÄX°j)'›ðÍ“p1õìì¤ýC Fj¯~_x’n„,i3Oð«õÉÝ8d™‚¼ûÚ0¡=zŽ#^÷^è3# |~ ¹4Þ!¦©˜'ˆ–…uY1<åf7 Z;´d{Ê`[^-¯,KqžJ¿!ð³g|ÔØ_Ìdd©<^\yñè‚o7þ‚Ïrâ‰?»Â‰™îAImç탟<»‹›{¸þNiIVõ‰¿[ÌâçnRpõFõά6FY.ÕÔvlò!Zñ9r²¸|H?>€f¢øJ±¤q ”7ÂÝÀÄ/«ÿëZyÈ|OZe p±è ÖŒÂ`;’Ÿöݦ~9ó5º³›÷0áš­r=ô!ð¬1s"‡´)A±t'“E›áÄéjsxžñ ‘„質ÔdS¼åúbdÝ{»Q…èÖO^ž¸âöŸª³¬ ùÝÚÇ}u”ØUÃ%!ÈoÞ~Ê7÷òdžWìÎP•§Hå¾n~ \¡6»Ð»Th©§¶„ÖeéÔ@°Š{~"Ò ©¼?› H*>-î_aÑ;LZÈüX˜0®PÅ~õ«ï—1Êïªwî9>&{†â˜¨4n{Z¿0¶‰@äq'ÌL£‚^Á‚Û/^µŒÔùú<8e#˜#ëxûÙ—K’&KðBͲªßl3küRŸëv£4“éYÅ_iiA¤-“ùŠBôç?!F@ dOîbòЗóø•ý5~€¯&i¥M~ºÇœÌy wéÅ¥"‹?a—B,¯·=‘æÇó5sJÛx“0{í½MVïrܩك=jXPo"å}±Aó_ÅÍãcÉì òbÊ¿&íh@ºÉ"¬ÄA²>R# ¡a ½#$±Ç¢÷D¹ø¶éhYB«[~ÙL„¶Ä]í²ÏãKdœÉ±’ ‘It:;˜ýBÊÍl…öʬl‰âçt—j`N·£tµ YŸHÞõ±ošíß„ÍúÛ ‹F³¾cMƒñêʸ¼7Å„Ø÷Ð71À²b\ÉQÞÑKú¸Í–S%[4ýä.Á.d2¯Óû­nxK$)4‰]½¢ÉÆïÍÄíųU) tÓt¦æz©0Õ3†o#D3ò¶Èø²†¿³û’n4YLÏZ^ϗѾd¡sjKKöÏ“NK*÷•®º£C”>€hÿ—}PÄ\Ê – \õ‹(´N„¡ø' ˆEáÝõP¾y`bÞŠÓ”,v^W`+ç”N\ÿGF û´ƒÛ¾¥‡3°fä²ÿ¼Ãäk [§KÃY]tÏþÉÄ "©ËHÕ¿ëêùE¨n-9Æú-m PB°ý›ŠïKà$ d&Ëš˜±‰ï­/û „Nlù*óþÔÿñ?ˆ ¡Êâù÷KAu†6sÒ8õùèÍÌÊâ¹ÿG3eõ;E¤Ï›r\ Ãp§S øÞ Ù Ç£Óš ïúšYíAÅ=òžæêùm¨üsø_>Sâ„ÿ]SA™`;lß±$±“ÔŦ*%úû(n¬‰WJ ¸þm<ùF¯gŠ›v\]è]pi˜ ÉL…çMÚÕ"Hpn¿L‹*8G?÷ÃØÂØÚÔ‹ÁS!e<’Ͳ÷êúå‡W•b}9 _š”épW£àdÇ+«¼­Õ>vשׂ)9Fý–î|Ûù*™½Gz ¥0/ïˆô°ç9Kf>àüEüƒÝRú©†PÝá¢fД¥ §­‰uf¸¨Š¥¾›ðW÷Ùû<ðûׄÒ+7dGËhˆŸž.s{$¾T»kwÿŽ4Po¯M‹†,âsüc켟þ!û… ÝGçö-Í Ö´=¿´ešçx]°y€yýÉè:Ø!¡¹þ¯\?íþžcƒüŒLï ÿÌÝ…RWÖ„6eԌӼùãC úSÄØ…‹QŠ«åŷﵸžHÝ$§EO¡:Õ\yµËœª+DÚ‡ËÀ %S¤)â«Þ0ÌãÒY(=áãû³ ìì|w.¤.ŠÞðD·€xußHÄÜïþŠÝìÁ ö *w/¿ë©,e°“éåkò8€¥‹†`Iõ–ÌÈ.ãƒ|Ø»c|ÿ謜(ŸëžäBï†="Ñp`Gê;lñÎYÄ*Š4Ól4)£ xpj8óÇz†™ô}šJë}ûüŠÏ0#+ÙCk ͦœ+k•ÿËæ×öÃÁˆeIÒ„GFã_z¥›¹•ÇS]­ÎájvT¸"™>+­¤ùAïkàÆ°æDÂZ*ðn#”ã[†1},ª>m„äåÍüb‡Áò¡¤%¼¦‰v²ü֨׆OOÕ.½µQpÀœnïðÖä뎡iö ¥tË¿*×¢[‹[Œ>Õó×´ãe”§Pborľg.…±ý5¤Ìò¤~†ÇI •8‰éTiü¨³(þˆsñkŸ9‡‘R¬·i".œ¶Sæ1ÊvÁÇdx#`$I"ؼX{³­²öjºò™fFMrÛ‹V].(zš²Ô˜X¾Î¸;{2oˆÝ0ÎÃHWU]‘ MM¡ÄìöÅBŸ"ŽG¾7¢ù«t¯b‡€Ã^¹õq!GbÖê@•ˆc–ž;îéÉ_sPNh}x :×ÑÓÒæðÑXL‘GØŠØz‚T”Ö£³)žkt¬þû*]u{’;¯6ˆK*Ð"._Ü Ç5mƒQÂûì·îï³Cà‰Nö^¯ UˆZ »Ž½g8 ±’ät±ßÉPT,± 5{É+žs@·¬þÿjB2«è®—TÎ"~©9ŒcÞ¦×W©ð=Á«b>©Yä—îz¸:øv¸6ÒÞ½WVyp¡+¨â¸!oÒ¹ÙHžwB‡qá'¨òqû%T1g¥Ibz«”ðecÊKß<^ì ƒ+á_e©æ /Ï¡1•Mœ,¦ñhYB™«O&Ÿ9â_/»¯¢¹¬Ä,æôóé~¼î}îd͹šµ£b¹0 ¨|'df£ƒ^ç<÷> ë:³èÖÚ´ë¡c `_çÓI«Žh¡ °˜Ðöΰž§ñ”iPkýÎòäâ{`¥ ç&>úb–ÆqeÙ»:FÞG|[JX¹ ðêÓάÍj¨ßËã–˜ˆ|п­ê~ U €è…ë5¡Ô;×ÔÄóZÀS1˜xA5ÿœ¯áž7èçBV4؉im&÷½ÌR‡­{ ²LEéNa.¦ÎH©SnOÌ¢*ÑžsB9÷'™yÎx9½&[F櫪µ6S¦ñE*ÿ{wzKu±’iåNm»Q2€> ø×þsˆœ”ñ1D“EÁ@D‚­A¦Mv[·™ªî8êò¹Æ×þ\(ƒñ³«+}wAÚé¯ýð¬~F ¡Z¥Bÿ?î¨LÔïsZlâÁ´%…À*&ÊÁ„]°”ðׂcè#9¬˜„:“[©––AšNǧ&Ðu+Ó¹2å5™¿üõôÂÄ J—ÈŸœ9#§|ÀŠÿ¤]ܘ֚H—@hämb.êÒ›{—­'ôôÝl^WÆ·ëÅýkÏv!¤CµæÕ ßxá;köÅ7oa?†é›XF ·ÖÐy XšƒÐ½·ûÄ Ú‚ë”ç to¨:ºüQàCÒo z ùœs» Õ öœ¾ÎGGaAu7of~@g _#Æ]òæÔŽ¹Ã¦W¼) ˆôqãŽ)rîÕMìD”5ÇôÌB3™åZICiÓÑRP™Qn£z Ó^ֿɠG{o¸帨<Êš²ñi³ñÕ]H¥¬Ï«ÞÇBr%ÍõN.wrÐɨô FßöBSIG¶ z.¾&ô¥Wwk(^ïÄ;['i€94ÿ‹w¹³+ÿÉ„ÿ  Î%$,ö¥*’(O7Û–4¶™ÕÎð\JÇ7Ûx¾9›ÿŠêEs•K3ÓUPRÔš³6êMåyp•!”¤4–_V8Ê^=©p§°ÊùÌÜÇ0Ñ'GFW)xQžËµÞ޼߅<¨~‰mjé: >Iœƒcä¡õ—•¶^­e’9P :]ªÌoù\çá&ÇgÈ<åPÔB¢îSÄ’äØAL†_›^¢¶˜RS_ÆC¿÷:-í˜*™(Cœ6I³¢|üK`ìWjÕXLýKN•¡åʼ+YÝ-É%›!Û„C‡âOS@ÔÆ’×}Z°åŒäQå`Ù€Ÿ ¡)•=ƒñHf_ãUi6¥e˜‹rÑײõI0ü5þ‚™"a`SI·yËVeUƒVFpÍÕ«á˜Ü8¤Ê-NXµ$o6Ø ¤Ì1T# ©¨¯ô4³I*¸n KGþ¿Ïs’d×®_;ùо:^+C.ÓĤm”Ô53¼æj‰Tq…¡Ëð¸A,Ž)sƃOþ«EPƒ•2H £Ñ;S°Vò$ €¾ÚóÅ!-[>ß±\*­¹)¤¸Ö6¾®×|Ì9BN^³ðÀ$M"µŒþ ª;^^ á;솲)—“¸&ÛéïÇjSÿ3âî“_¢hQǺǭIO‘­Û@®p‹·ð-¾Xfí±j%9F¹Œ ­»œD Ž…Š7þå÷AúkuÊâF±z‹ž±K£‚®²Ñ*B:K{rÐà숒,?&\CÐj§{¸uŸ¨Ç '툠´?;þ»î:—,9PãpïÑ{vª÷L’O¾¯l]ùç…^:•ò·©?¶÷ ƒËo•€¦™XqÙöÒzÀM5÷ñk•™;W_žü¿ÃÜcÑ´µP=TF«WÛÜ«i…e_ñÀ[m¼"Õ3ì€ÓÃù4ÕI‡õžÓÿïô…qn„.ô±˜½ÈÃ3±­¢ž$7ë”RŽÖö¶ƒÜ¦‰tVŒ™3Ú•»pQlÀÖÓ,ÙÝ/ÿ~–oCDZi›»5:ê³Õ8ÞÖ»¢Æ>JÙ‘…Å­äI ©€u­‘£ËÁ¿¶A¾3!c‚L¿å²zË£²qé4cÁøæ¯äB7¼Ý0Ð 3ñäÌòrI !=ãe-%cu[ýÃr%ÔbŽD» ÷5ÃÇ9Ž‹,}tP?o62H;{Ͻƒéh´á†5M— _KäHÇŸl¤Ù Jõ™Ö=;ö´çfìÜ>·nZ|K 4ðLÃQðŒÃ5O†éÍa­wÏï²¶ÌõCž·G‹4âvßçïÐ2IW×dZ–Ôÿ®ˆ\ D„r Ùp£ú³=KÛûÆ   ©FsüBT³,‰~ðÊÌü ËBÏ47Ô®]Ò·G„YËj&úƒ~’ò’}§v{šz¨G5O©å»IsqQŸi1ϲ0cá–l>|͈ªˆÀÍúý¾„Óº®B OM§-vëH-.”Jú7(›“¢! ÄsÖ.LAds×.-WÐÈ4¼Y)7_g;#:&Ÿdθñgïp·ŠˆÅý½ú¸ï‘`žØI!Y‘Eä¿|‹a;!2m P I1Œc3óÈ‹4…ËÛq~ް É6R?œ.¹ÂÖE<ê+l!™™kÏÉJK|3î"ä ÁæŒ3¸£ýŽ®¢o®&‰¤àN/t;žl!ƒXÅå&•1 q#”¯çrÍ‚W 6  ³ðŽÚqøxuë9%>%¢"×r¿%Ž8ÝÆ½ÂGÝdSБµàò˜rv¡‘²>¦…3Uº¬!D&kæÜãÅÐheï{µ˜O˜y È²-”€AHaDV÷òØuð¡zøÉ/CI¦WâÔÊ8YðåøNq gci ´4ëõ;u [©ì~WO»P°o¶ CÆãOê+gNȧ;ù|=–go@JÑB¦[ÀÈ´jÒ­¯U{,Ñ1·×®µÁ_|ìÇ,šDGÀíõ x\}©êø9qÆ7ùP=Z/^´S´ H1sø‡VµDŽÈ®¨‘D@s‰Ua'¼ii}T»ê ê¯ »°B.] J¤ŠG*úçØñÈ>˜ÆÆÌ±Ü¯¨)å!­vÁ,>¸Ø§Ê#{.¼Ü†  K(6ç.÷ت\‘cà¿Øè5™Êž,ÿÚ󭚥¥¯±'vx‚·o¦‘_;þ¸( á¢Ó° v‡(Êf¢(²¥^Dfƒ}¸$ãR®q‚ùOÆŠ…“j¸ ôwéæèÍÌ€²ÿã†clðJ4ÿ3-ž~RŠ8[ïäcÃEÖÛtz—Å 2O‰ê‘N  ü¥¡`«ã©Lçj•ó¯x+}\»  ‰L'˜Ý<§W‹²–s÷ Ù ?ÄeÈÕ:×Ä©žêÔ@'NãÏ;šNH_LõR˜äj»9\å, üíc-U;0øB7‚Ô.!ðãBE£Þ¹¥§‘W×,¥Ê÷NŠ<åøS@L”€ÿCTŸÄJ¤Ê—5”´ ÇŒ SÝ`—B«ùÔói“»KÂZ2·Æ°Ldi}ŽšŠÕœßæmíB,ö¬uÍû‚;j–Õ\sÙ¼hæ¿Oð›y¢_™[e²íj öŒÅÒÉ’(C--þYÇ¡Íu6¹QQ>‘Ü´˜ðóK¹wีҎ„tÏMïVÒä'+C²#TA8]¤È°ÓÂWWˆ^ΧQ‡3è‰\L~¸ï6uåš5ÈøÜÕ‹H»KÝfŸùç€á;kú¦Àóìë&ô ‡®t¶zG¥sî"ãÿK"æYeÜšÝSIÎÒü(RàÓÑ{[™ÓÎ1SRà“³ÚÏ׎=`W9¹`¥cÂ÷†øFG ÞLl“fr(¼°ÏÀ!ʼõ”GqHu¬ój‹>Ý)Þ]wjÝÉœmó'œ´°Db&ß,]Ê qYò.ou"лpø8”Þƒ«=&Èwº›´áìù‰_^!’˜ÒØ«ÕúìüvâÖ¤ ð*[L7à?’›êà¶;uÙ2ŸåÙ˜]¢ïóS¸¢îM­C‡ñên£›°ïÕ9­g}†£U÷'\¦ãr±¿oóIéÉs5Ÿ?Á+:Òv)Ïö¿²ÇË «½|¿¿Ñûª•›ÿVè·)®UÇ™M?ƒÜgâõ8ï\À?ì%4҅ͳ‹õ×§‚»8ÑåsÔèCÕHÌìJ'hWk±&æßâù|'¨Nø105â¦Aal|Ù\RÛ¹ÄæS€æ>j´ |ZóŸLO3ó£#5¸Éñf!aY}+>[F…\žúSÆßmr£ö:£ê§Œ|óêVÏ ­N]o¡kµ1»O‹×$—(õÖŠÜ!‘á×Wy’WNPÜÔ pJ¢•@ªÇ5Ìù•u3r¦-™ËÍñ'~¶ðŸú@³‡÷ìùa6ÛÂ5ŸEbKɲ aùî¥zKIšIÛISáÍ]rûþ=ùh‘!a=vöb#Içèù3ff þdÌ$·FWboŽr¾-ð–m‘1Ó7í×^Ñ1¬Æœää ÀÒOY2i¦¹Dö²GPhL›$ú› ­½Û'9ÖÓ¬zÿP<*™AÓb8ù ,;Ds5ËAÑéÕ¦~¹i'ëNÕ$6lM6‰äÖË6{"MP ÷5¸\v-“üF(©²{çü>ÁJ\¶Dø®†&„c{Èà‡kL›ßa 79lðAuWù‡‡ çžÈ’vˆÍ¥³P›ØtãÄRƒW©Ú×´F¢SA!GLL )ŠÇ³µ8ˆ­1fCŸÑFZ¿Ôl´grØó$ŽF<$åêH/õÓÅÝ7› ø¿É±zºÇCB‚FÌ$'x@y¨­G,{˜\µiÛkDĊܾSÃ\ˆ9Ù<Æ<ëH¥8K³]ÆP)ÑC𙻣QÍŠ-Ê¡M‘`äq˜ý’g˜¿™r¾1è²$qÆ!N—ôô+žfÄBÁ-’iå" ˜9`B_Q…n‰5X²Q ®2™¶Ê ¯zì-Y¥TüÏŒÒΖ¡šÝ.ø‹ É›cßÀXä+Ï@¬î]vÜ5-îQ,SÏHž,¢4«p;1÷)¶S&¶Zù]ÏŸ¬ÈDÔ{ªenîÐÚDÛÂR˜©:àýß:òP³½³ž— Qd|FV‘dz$^Þ“Fÿ{$†Ý BròæõUÓµ&¨wi‹Ò:C–˜A;ö¿—ÃÛLÒ°Ôî°`÷Õ6Gj­°dòÝk>ižÚ»P@Á/rÕA‚ƒnÔlÔðlvZ´R‰i«ÒÂv2òéÉvÙë~·É C"Tƒ¯Þ`뜆Ž"É s&OØòÁ%qÁ+GF×k極‘€qEÁG¤s*”b¢¶/g÷±È»6HZ¯Õ~N \~T‰gû¨‰Ø¹Y={e謞"l®ì~Zl–%høª[¸°Jc/Èß¾‰½¿=†‹fÓÿ÷£ÑW!lÈa¯à3üðøÌ?­ Ü[ÚðNdûúfm¿%tvfдÔq&ÂR@cÉ&H››“¥©r1"ÙÛ¯!W½¶D1(ˆ*OáÊôxE3¦ÿAf†í縢¸[°©žyËÂÊÅLÝ;¹·@n›ts·Áv½¸QÔ¼¾‡Å<¤æCñ ãc½áùä¸à¯Û`¼ /æÞS#¨HY5H’„²·…RÜ3¨ú¹ðMHµî­n^½}râ=ØfÛ~6¹)„75f ÜO”3þí«ÑHV LO“¹½lm@…¨Lh­¤”³ñgÒòväüÿ ¹³tò0K/@è>EMKín;Чî5LˆMÃg5ô=sþôÿpL0O½×ø?AÙœ&HŠf ?…wùÉW1G›(]lP=o%²›ö©'Ô••R÷·‡žB5ñD{wŒd*Œ‘SÒœ··çK>]ÖîVÞäa¬>Žž”°Ñˆ¾ ÷Ô³Î_$öB­iM=ƒw?@Ò„_á†ÄYÔx%6&ï¸O,™a’s?c(x›’<6¦ÐË _ß?"œ'J®¥¬y¤p§[F25ý]Ì5‡âÝÙ¦ÁÚ¿`ãÈl–®Keöæ9]ŸÊ é¨ËŸõ·Î_Ѱ‡|w# ¶„ø­òvBž$¤8…qi¦YÚø®6a,ÌÉWáx,dS'Æ ÙùÖÞª¤¢CxßàMåü9Ý¢ º9Ç÷œÃÄó¡B>`d@ôÑw+Óè©îi,Êr½­}ß;ÿp¿Pí•R[ðg´Ö€IñøøÉÅßç両GÐ7¨ývÁ%è~.dzOŠ¡¹É,`=Ƙÿgp¦¸·ñGÀÌKÊÍ}ŽZ2Ÿ+ë' ÁË÷ÆýG‡ª+‚ó>‘µf%ò\—œ*X#›>ì?»“ç. +Õ'ç5)Œp­& ™qM"!8wy2]œ L)cέîF=;–XJ™FÞ¿;_w…j ­ã¨k¥j}Â-Á™æî1Åç B3ZÎrê¸Dðnî©Û¹òˆ7Ï€Aß'š*ŒÎw/’ ú¯–êø½si3WÌ ©è|Šf½Þ:Eå7Ð~.V†té ©èsÜ.–Ü‘VY8Å÷dÕlN–7Ü”Ø!:#8"‚¤_ÀK§Ïæ‘ÖP×ÍVvˆHZ¹B{ë®TÔÉ{/"]ñTx0)_@Е‡ yФr›nV¯?÷Ù œ|ëµÛÃì&<`ÙY¤’ ¯'n´Ï›j_fyå¶~^>;äɔε¥Ú[¥ ðàšMœ¾–x›ûe:Ÿþ-ŸhàH…AíºÅëùê]Ë-8ž¯&Z_  l8†(î7ÄŸÄÖcïFŽtD& Î>ø—¯öÞhT33±(Œk_7©êÝOD:*§KRtB+@g¤Å’"(â¡àFÊÞ5Jçð3—`6ž,mècÏzZìC½W‡oHJ'rÿïµ?³€]ô[e_¯É*)ßv¾ñÖ wÜø¥¾§¸ùÿ»ÔÌŽ«Â—™î·e›Þ÷½,ô*q-0Ï Ó—ÞÏ%%èÅ¿]±qÇ8Üü=ߌåI.ÖІ_Á³e(bÆxùM‡V YŸ‡ªîóaÐ}̶æµfƒ˜iD´áEA˜Žö÷šh _ÃY˜ˆ½ ºªõ¬/,³¥Øê…†®‰šóS—IÃV1Í›d¸ð’rVÍZ…DJHÙpÑFïsB}e„ Zž½¼†A­pÀùÔ;Qÿ_L÷1#ï)d€ö+Ú9l€¤ÛhtQX±Ø›æ°è‹hFîy‹ësëùŸªüþÚvQú¤õc¿x@x´•þ\&M¨ëT:ëZä\ʦúä W,U°TÓR@ždî)Û(,SJè0¡d̆êk9­Ð*•ÏK ¬ùç ‚’¨ÕÊì‘Ü_:„q•ÛºÊ)ýµ£Âîd~ºMÜx±Ä’,Zâ3‡o ÕTЦ«ê6ôé#µH›8ã²gïÏÔû)mÿ“G´ìk¿÷3M¤PÀŒ…ÉÊ+¯`í%d^lÎ?¬Fh&ªÈuðHkJšÊna e¤tí³ >.ö¡Š4"oжiS¦zìmcŸü%#r«÷ÕÐéóõþ¢üî¾àneþ¾"$EõñÚC‡HzùjWzB q¥K'LÀ„â.<ÇÁ¾;êg–Ÿ©Áí~0ð716nÒ0¢R¿¬Ù&ê½ù®£~Å}%Ö'+~›/ʵÁ¶dµå€cVmìyò²©IÝ>õÄ¢òY¿ºáàu²øx˜ÞoKš¿ðÌ ™7w:¸S)ö·‹ê{àÞãNàô¤¢ƒXºìVfÿ¤Ÿ‰ùu,šãû"ÑW&Û“ˆ´÷äžÉò~X2ÜLÜ÷­i¾yýî¿.ŒôÏîCîeæEfÎÞ'T Á†ÖäÅb4µYfvN§|)Ëã¾d#·±‚œCÞfР“ª‹e7ZÐÌèCå²»haKxóx¹è…Ï­Õx_xÎx…‰ûú¹ý¸&KÍ%*¼[žcî.É×qÒÌLŠa ÖH+¼`è¿Q® ]L§î.ÔëJ9HàîEo ¬½6×¾ìúñKn¢YÅÿº2HÉòÅF…`;ˆ2Àú9Èš@¯¹š˜9À7á‡Áµ[ä_o€TZ0»:D€’o$©ñØ·¯¹¿ÔšõQA†7MjFö¦Pç •WÉÍ€s8£h©iAó±û|…åPà}xx‘d&ËÙtZîÛ.úy´ˆ|·¹òÁqÄÕÂIEtàÑV[¢f‹¨'Uà¼Qᨎh%‰y“ùÌ êÈ‚šU{†N’›Vô|«²,&R ¸‹w\ GÂtÜì„qŠ`¤[KŒâœêêUsåf86D2>§†ìjØœgPhs-Æ>BQWWu?¨XÃúRnjãÅ<ÃoéÄ8bªÂŽšY1a«v×&ú¤ˆµ``Ñ)îD$}îî¿Ð ±êAã²Á¼ñ`ê| ®¾Œ£T¤´² ß JÑö¬‰¾;·¢'"Ò’ÄÓÛ½U1éfeÆðçßóþ@üe@ ¯Ëб°z‘·ÈùxUò¨$+Œìo§ñ¿ëP#ž6Sÿ .¯.¢ÜcŸ€¤&ÛòFƒã'í¡„ãÉÕ˜ÀÝ ³ü L|Gž ¿nð©4÷Á;ý j0Úac¬:õ{éZ·ä¡Ý=ô‚ærY©ŽN¿«K’Hr„ª=ÇÎsŒÏH{p¿×ƒ:I ¿“/J¸»ðKŽ':® ºŸ*Á›± úæ‡UëäžßOí7K"Gî§]-6ÏûaHOy²&/:Ñý¼Å «q°€k¬3³qß&,$-ðH…÷h<0ÿjåW) ÊÀ©5ûÓE¦'eÅR"A ?¹¢øÄ8;º¹€õ !c¦àÄ)Íõ%4²VGœ„ca•¨­Ö4o½LœXb‰:»æv¹ÿ4E‘¬°¼™ìükÅÀ̪äëƒöv.ÿ ¶3s¬¨ø¾-¤o¡á‡j9âÓÉ£‹J’à2šµ (ÈÍk1ëë±”¥A/¶çºDÚç:)OÃcËná^– !_ø÷ÌPê]·Ò£àLž¥HI\ßFÇÐ3+æ`!+ÊZäõ‡==Šª©(ä`P¬u"¬)¸ˆíØûHÓ•.ÜÐó³TL#»ÀØyßÁöÞuaîÀutÝÚÕXu³Iß3Q/‚]§!~ÌÁ aèBš~c KQm[ó¨¥zð:$S_Y2žc8òS 6ûÙßÈ?Ç\íÈoâ"‹·FÖÔ¼j·ÙÄ„Ä7ýÖ;0ÌK²o¦ìÍ„Ÿ:Ÿï£µ„ùã:h£ÖÒ+ò96â7“ÿ'Û-1ö–­]"óÇ“EV#]õï‚ržCMÂÆ@pc»ï„òÙlhb™‘4»µ|ŽŠJ'j7ª7ó£?(«?·+(µÜï!Ƶ͙5šEa%¶pøºMÜ;‘01Œ_êc X`ò©¼Â%4«ÿlH)·MBEñbˆ~¢„CÎ]®ƒéš¤@Ï3¡¢ëmÛ:m/gÅØxŒƒ^0 žRW4¾$utÝžMƒ}÷ñ.êpÂrþö%dQØ|â·ïÉÄ’kÍ¢ÉÚD rÓ—šnÓ˜K E©ÃÒÇäs”m™{K´Š5ÖTlæ(ËÍñÀ,l ACÁ%¤âž ›†ÕwEMo}Øã&c õ†µ¼† -t±VŠØÀÔ¹²Å()ªåh¬Jõ¶Mô _¿1ÀÓÏ-¬SKscoøI½#¸4z_–¨ÏXèܨ{»Í¥7Î}#xgβÑ/eÙ"æÛ­â 8p>¾†1¯x|­Ë.^šðLž®1ÁJ®])«4õHär ˆ´¸6Sq‹ˆsò"ÞMµXJ ‹Ã@!±öBì×<4’Ê­Ûq ê§ý†±Ðgìƒî†.Ÿ?Â#¬½`½$˜ ¤…É@ûeP&Ž L3 ‡XÏ´"÷1ì«ñ²Ü,1•ÐwCÍb®°*S^‘]’P¨gGEœW èëkPy6½&$îaTÀ[ç¢Ú&¤ ,™ÝD…;M¢4ìKËºÊ WâFÀPØÙöŽßkÿÙïódwÜ>-Üþ¥VêÛÇVñ^ò_]-p`Ùa2¶ÑJ«H—¥Ÿ´g!âá€9¡|ÆÈyÃ*Êë-âaã÷”h#>ß1Hä‹q {3³ªÉšÙWŽmR]¿sðÕe.^bGÔgͨ $O#ÍK¼’á(¾  ¢TQMä"å²GTb¥Ì4GánaP <–e÷äå€9<ÁO,ͯOÕC§é « lÌN»râ†mL®&ÎÒ'ÙÖO›¶€ó¸°_È¡ÑgãdÃÂlMt v…èê»O†äUÒV{Dò#Óu÷Ú£Ì=û«òlu< ÑÉ•ý­BcËœÅI9ó|Åx犽åöQT‰…½^ARtƽ!Ž#‹m[¨totEˆ’ ã¼ù‹9tär¦²~ºÝ,Ž®‡ùâdaaßû„æëOY-ÿý –t¬5î0È-Va\ƒ@؆ ˜Lç0ŠÂ޽ɾi­ÿ,øHHj?@¿Ò0 G·”FÈ È¶Æ¥eç¦ 1VÉÞDÔî(جŽü ˆ–nd'Jý Á 6üµ-¥b¢—;šþø8±©Ów›NåÓY|í¤½".nŽ­‡Mõ¿»»Õé¼—v€»Jƒx­ŠŸ[3 "舂D½å dÆQ9×l¯+S_À 8¯üÍKÁ†wïWÈ‘2!æ‰Õ]âwá•0À®iޤiVª;LpJÅxÏÁhÃ1üͶjmSF-wº4’Hu”hÈd“/ßçÁÔæö8ÊË64©Zx=Åïé!ÄL À¤ÎJ\ù€…*›!Ü1Ä!0¶½|‹wÂ*·eˆ2‚ý^¦§wñø;œâœùNå…¿h9›ç '­9Qš aÓ§“î V1¶ˆØ‚àQrÝà®êƒh­º‰Ì:-Æ:ní§±õ”#´Ó‰ŸÈ¾Ðq£!Õðfé®S@&_Bzz!@Ù†hgi˜¼–½«lYk˶¨¸"˜O¾ÉDE{š=¡™Ùh¬–Ü”ÚðS$¼üÓ‘fÅ\KÖáo :øV^ãŠ$CÛ¬9Pa.ö!5”:vS>W27*;Ê À;rXYJešÞé>Žn¨¤'œ0ex©q°îé´íã½XèÊ©ÛP¡þtg’°xcT¿÷‰2ÿ@u‡ó^¿z*”‰XÐó¾q4újòÅHy›@=2 ÞÑ\'Tyºê8ö0ÖkàÙ¾@”¯öž®Ç/–W»6Z¦»¯(e ÉÌK~´L?ˆqSo©¤ö?ø¦Iœ3ÒçlÜ3BUw6µÑÃô÷QŠï¥ìq½½xJC¤‚¯‘5וÉ9¸Ò’äÞ@€vï xU¡ˆ*§tÐâóì[—ìˆkáD sTàƒ•â@q'“Éühâ{77¥8ñu­QnQ[JÒUyö°WH÷ÙÈ\sòUkÃL>:ýOuŸsd§W?T^Ýê€eiÙ°&_s„„ó[èky Ÿç÷0Žò\Ï?L¹— 7:i¦¦˜ÏÞ”J0=,Ãi‰(^\áB¶ˆ@4m›³Åça".0ë{ JÚ4Ñüg>$jM¡:ïÒû1á&åßOo 3 «M!zv:vê¦óâ…Õâu¦ˆ€W"ØÂí`,r/VúÍQ`¥î n+s~DÃ(låoì Ê~%WЃÿ˜MÙRF͸!¨–2é Ís8GµÁMVLP9U“k• ßD‡QÂ:~\ˆSfsªîÐ¥;€úK½t8&-©¸®þÚ4À×(רî,¦‘ hê~•gµ»&‡&$Önº%”É)û¶Œ¯0•,7Sr{Æ}•½”*–3–.DÿVœ¾¿#…±¸•w %ô÷aoŸ”楀ìVmôR¯°úÖ iÔ±ÎÈ)ÛOÙ(x›Ë£&$'&td é[>øÅñ®éóÌŽ–"{å»ý _ºÉæÉÐÇe!çøÏô•C3¼aæxÈ«­[ìôÒØŸëÝ?ðøœ¬§Â×'&`Ýà ÿ¢ÒÔÝ‹Äó`” ¨`H»j K›1sªå¾4€gʺ>1½¹—²·_÷ö<+’BèÛ€9Ƕ²…*6wói».æìx7ª«¯ì Õ%ʨ¹ˆé†Å”9‰é²øª”ªlݺ䫽Ýéºé·ÉQÿOÂmó*/Z¨iŒÝu {ó°¥f•KK¹ÎôÀHAîÄëIh>¾‘3“ÁôÉóR3Ó¥ƒbº’`ð1)iªâ!géö¢²hà䊚ð 0k|hæ±é(jØnÔÎÉmÇLa~Á©´Ü\œwHY[XÆŽ.@[Ìe(«È ÓÛ¼ `§ü b£|£Žj*÷Þ^Ÿb(Q¼A¬´¢êpùd}’+… þƒÙ@þàþ.B¥œ¼)Ôˇ̑X ,Èuöq$rŒ˜s“ц)&ƒRëpá¯Æ>1«ÿI›Oî$”"Æ[½ØòtKú¿@›–øæ"–Nâ¤BˆL°³ ¯’<"À&ø4ø7„ °ü»•,“ÑE@¶´­€™„,,Tc#õ#OK!ý‡uvžˆx­~SA6`8RàÆ tûªXzÎÐðÇý‘ENkÜæûð¾Å¶:‹ÓB´ˆµ{¾€AÂèKþ; }V¥ º§«Q%/g“œ«–áу[»ê5ÑݰQºvdL‰Ž‘Ë^‰Ë+½Ž¤iëýâM¤Ì7(x%ÁimaºuCöòe¢Î ïé¢g?þ¥e˹j«AagÛíúXDÚý 4«WŠ¡;áÛwĵúS'Í^ë+1ŠzÇ'?Tºô©w–?Ê(¦@,8§^z…0· Dy•óÜ[‘p9VÂêp\¡t¤"“F?ŸÉÛ>Êþþì÷Û5ú¢†mUûÁ‡~z›øø‰âg£XWCѩŒ×¸¿hrZww‡úX z2o\´éR°D£átWãàEU8%ßÑ/Ÿ©‹à^¹˰f1í2-ªäÿçb4C!?&aŽŒã<èQ‹„¥SáÁá6±û2¼`¯æ±F÷YØ”æ(ñ;£R̦ß.C9 t —OSŽôxÍÄRfj˜È?#Ã×;=» ES²–Ý=ã,D,+³_J4^(ä‘7ƒb?â‹`¼/{ˆFø‘¶½=ÔˆH:>“àFAçê€ÂD ŽÿÕagC7.|xÔÀŸàvtS¢èT£cW¦Á©qWoT´…ÕL97,ž¾BÙmáÁÜbýnã´õiyãJ£†ÝÔÎc•­7J;®N²˾b±„ܦôúˆQÐ|‡Ò”J+ìpÔ‘‹¡¤¨n™`.åÛѳ°³ ÝþfsJž ¬lð42h5§à³qrP,cçÖ~ML:Bwct†ŠÕVèÓ²È)äÁïÚLzòy1¾El Ôp>‰‡r蚥³Ùî·Ã%*9sÑB4ã”Ù­„v`âC> ”ÃÄÿ;ͤ׷Ü"ãT<Ë8Zàâů|¼¾—H] Ÿâ7òÀ™®d¸ô|-›_SÆ®ü;ïn:I•ƒ äYwL ÜnÂá§éüehXB‚@L>Ò!†s“âÍÉëƒu(ŠÍ¤¦ÚØØ–#8‰àxP'oH>CÌCÌg„ ¹h’—+Ó‰5¡Ü±¤¹îxüTèÅà´ò»ì“‘Miýì“Ùµ!Ãt Ñ—Èoqñ–kÍ>ƒÈœñx$”?؜뗰ªè%!iËå£|ÞZ•±&_˜{利ÈwÏ^•UNøF¢é1ƒïWÓ¨ÿÄVe‹ïK/lÆ‚Ldf1d#«™|œÕFZ™’7L°.<¥¼;zÅzþ²çSÊû`lsQíåw3ä0oK€ñ Ü>b ”oôŒ^APÙKUgbÓµ¤ £âÏ¡w%B·ñ?å´§ö™S@‡ÿ§jyâh…U¦¨Å` ”dBžmk†¾Â-)àÜʤê¸L}Od]¬‡ok€Ÿh†2¬ÅœoŸGá „GôVAS™Ö¦Vâ‘B0*Í„õI"a÷–>Ì´†œ‰JÍIìüçaì/˜&æ /êÆ|>h­ß®1¨gvdzº›5}Àx§š×ª5D Ó«ïtC=ýÖUI&ÒøA ú/š‚®aFѱ"E±Ò„º”)ýGÎ:ˆsWMPYÿ\ ѳš¨ô)Ôk•CÄ5©b¼)ãËî²å6 ô¤Óx ¥Íà;›=Ë­X†ü O»1‘PIº´ˆÓŠ«I4R¥þ!sÃmÀÒ¶TD[À}ú™ª;—+¾¾æ›¦f#ýHCÀsë ­¨dDô8®2YIµ<çTòP¿îq™‰Šï‰žu;çé^wVœ¡‚3å·L(œáÄרúú}«<ïrQS}"†;Ú±[|€#–*Ž7\vÍ+P.±õKɼ֧ŒË¸ß©uL§ ˜C´GlîÜ{‘é "Ê„V’‘ eP¨kl2ÁÅÃdñ)"4›+ž–‚Ë­×)@EÏœ¬{Kï ÛÆ¢—ÛQ~lÑDïBþ:‰¿&Zs„§(¶¸ÜþÀ S ña=ó?QäÈôX=- ×Sjó‡\aØEÖåöL!»K4‹ê•¨.ˆ£»PŸ/0€qª"Ò§ Øýÿð¢Vžq›Ç4™ÖÝ38‚dqŸ•‘wI‚ u &CÙBptö5ÞxIo¾ã¤ýéTl³¥)C,ØÉd8– ' øDP8ôf=¥V Nª \Ã…¤õ3ÓJl¡q€Ø"¹4u¸p°UR;­.Е%4‰Bžœ"zÐ'‚àkýKqйuÿ°ãÞ>n±ªäs—ë8-Ì@ H } ›€ÌîÝ»tË«««#Tš$ü:Ø‚€oO ¨}Jñ÷ÍWìzÁ0òº‚x+ĪlíÄ!ìs½ ù·bè WÜ4¼â¡ýÚàÆ‹ŽbZï# ø¯žS~†Sÿ}Œy9nˆƒjÆ Rq¹.>²&²1êeT¬Ÿ#¡È›±Õ6BâU˜ûñà2¥xŸNH:¸!ŸÏÎp1{höRg[Ó»dÁø ž`­¿Š G§ åÌF3‹ 5hSå;f¯Èy Ø ¦f•žÇiúB,øÏÒÔò9ôǶÛýirzÔ-ïj0¤@£r£É᥽ž?-¸ý \¡9e€pß89HôËù°Šy+¢œª´…€ÑVä%4þ8Ÿv~߬"£½:ü™ÈkvV“®5Ý×hs0‹ðQ«’Õ+… –b̳ž¨ÿšþcd’~'ÂÌEçŽf %R%ÌΘۙ3é`¹O&»ôi0¡ˆ>Ç•^Ç9òÃÛGÔÜ…”ÓôƒuݰW–L”è,¨P¦.þ¼Q,ÒAêÂJ0Ï«å~E ˆêh1Ø0íDõ„:±lï¥TD‚Én!±&6Žæ™à;…x,©mUq¯G÷»&5.NVÒ¾´<þl"òR&4ëRQxw_¹w¹Ê£zɲ×ÃÚ¿™*¾·~sl£!~à;npÍ:4ŽF›p³Ú¯=jûˆT:¶ø5û¡÷ÛÝE´.¿>Áª{ °›Ë&Yʃޮy"ýÚXUïDG&ZqTª¹þèZ 59a)AQy¸“u›®d~\"ðJ7,}6=¼_íT¼–ºuóÅý³¨‚¿tà‘r+ *ß,…Q?L{2Ñ R$ÅšÒëNVÛ[4¡H¾à«Æ·¢= –sú¬4¯QF·%áÖWŸ3÷èh<Bˆ“Ï.~XÜ–rä(Çè{ŸW#ZËnf=GÉìŒszî˜]$'ÚÌ€´NŸä¾SÕ?'Ûì²Â2À)Zéì’T¨·¢k»ýñ°²óÜv¡çÜÛ  É!ÕÃd©>ÇÖÊ)Õ4a¡ÃæÍ@;°êÄ〗€Ës6žËzÈ}i ŠÒÆáªzºÊ}êÅŽ—Èfîr{¾BÞ󱩡ŸtÒ§(Dæ±*^ìÈikr‡Ønx¥¦–EÊ*[©zã{´²DíNýWÁs¶«\RqFçíåcÄäŽÎGÇòÄ*ï¢Þø¨^íAàS®ŠÌ¡*ã·‚„ù—âç=ÂÄ %sÞYÕe˜×‹–¤³§[êûñ‡æ¡ÞƒŠ·¥Vä'ÇôÜWkXŸ•]…樂½7™ñêÉýÊÀé¥ã»ÿçóAq‰¾Ão û”?¸0ï¾0;SÒ ”2r îC÷ ×zð=ë~ ½']ž;e¿Ç1UìQ…Ô`p…—¶S;÷!u—Ä e(¯å$åÓÏsÛ1…þý!èSÑ%¬¹ )iŒ±µdŠEnêâz‹ŸÅpRôËîyÈ’÷Û‹ÜÎÝ Ì~[€x“TYÝCà»Ýùw‡h2\ü£U¢ÒµHYW?¶äðLcß|«Cv*`tæ¶vÅÄÊo‘VVÐÊ!MG𠝳—â4Ù [‰Ò²ˆ÷ âˆ+ç%l6VþѺš åYxÚñˆÊÙâÇzí0r³«2žÇ9è£N0ž×–û»!džŸÔŠÒQ1\$/%5t³6lõ6ùžã‹øCÏïU»û݆ sÈÍqFâ¸qz²&Ä¡í;mBüO\С!ŒmþCLÁ_2òËMN3`X?/Ä«7\›KâÃ+(ÉÚaůœ]““wL¸Ë§ÐÃ[V¨¼{+” a…Þ©ßH²Ñ¶Gòwü^Œ”ªqI¾n×µÚ~Ö®“L=¯ÒÒbO‘5ÿjžÖ—Õ› lLE–Í$ãŒe‘°¥!nµZƒt±Ô[Ð^Êf:0iïöÕªWâx°.é‡ì”t‹¾8nѹÈ.É¢œÚøè­^´Z>z ¶‰%8¢Üz°iÆ¡P=hÐ(¶a‘5H¸8l5sU§ ¶¾ªô3aPXVZùÍ)o¬ÇxÿçŽ,âíúÙv,§‘-•‹”&y1xTÙK$röM †Œ”Ÿ+Ãgkƒ¢©gôn&Ò£·‘ !ÿo]…#6îøB¨M²@¸•oà˜˜Wv :\Mð3Ld|7Ø ¤g×À'!›´uBáäïP^™ßM¸™Ê|Ú¿ËÄÊÔÄ‹ó’œ9߇öR¡”ÀB¸¶Åú˜zmï2 ÕÏÚû*”T æ—=’ÔeÙ1&5ÒL¢iHÒü™Rqã=YŸö"JåY°œC—6Ì’á‡4Æ–£^Ê9älÛ士f‚·³Jõüæ»6%^¥!ëÞéƒçàšé&Pð–¦ýÐbO´ºJE~?°²*¥M ŸJ—›°¶uh[)ŽÛ ¢ÂÈ™-­bð°$Ô–-Y½AÁi¸Éx;Šoºzh1gøÊRպȡ°¾ðu©=2YÒ†=Û¬£“Bx&\QüØí:)»ìêµÂK±âIõÚjUÒ—õÔuÝëÜ‘XÆçgÓ6]¿],í$÷sùçt/ºóàƒ\„B óŸÎ6>ɃDåÂÝT_ü»Œ©Yö– ëu53H(;µ•¬wÊy!./>í×T}c'ÒߨŸñ‰áÐÞOàfi‘ã÷CAÃyð# ~V%äU× ò=¯ÄÀ¦…º+p+'ýd„ºˆX]–I‚˜dù&hPƒÅÙ»Œ`‡q‚¥ÙEyÜ^ÔcDÖ„%Íä¶}q‹ès…±‡\s ô£žb@Ô-¥tK¤)ª››©#{Z'aÉ570ÛÑÆ_¢é!6}‘á åÊãó¢±,-1SÕM ‚j:Ç´QÓ dÿ2·ù=£Ó_DçZÚâ¨W¸”|Šêº²ðÙé;à‚ý`9œä"Ü.NkÓ¬ü`tã.-N¼z­`êqŒoDf¯U$à8zÍé.¸U”WáŒjzbLY‹®ÜXàÎV.¸5¼æ å\Iú/J^éHøó Õ!>+ÑoC9¶*B‘Á©‚æØ–gM¡<<&¦Åg¿)óØNxbË×_pþ$lYMÛÕ'¬;S¼Ã{d:ÛÁÈ@…2eÿ«zj!™ÜÖó÷¦$gP Xâ¹%Æa2ʃ5X•2¢,¯¢TWaÍþ¡÷BlÓËÚ:9j¤Ï™:KˆDåöùĸqÑŽßÿÅ€Ð~À{Îey-Øì|™¾ YëŸ+3&ð0¤ 3{~fÐÃgìì»±¬0„%ð²Ð“d;ò7ËÓw ËüÓ¡>ôbŠÇ?„ êõAÜäàv}ÏÚõ­ÙU´®ËøGÓƒ¹1yèm|(‚è$7ŸØGúH yÚÍQnk<-h<]ýƒÍ+ôÍ`-=¦¾=rºÈÈOØ[L`5“ǦñCÉþ&é¥ÀdÉÏŒò£×¶?~§ÇÅëôÓÏæ+«}â‹ìdõì¡-Kháû¶°q…¬|ƒ‰ ®ÒH‚Um^èdZ=ǰöÆ?­nG›67 ·ËßúŸ@`B» ‘ýeK lPO¿ [^QÂÜ~{• Z…ª‡>gË–÷71—A9]Ñ3„ÅÇá†úAÎ:~4¬€ sÁµçô\·ã_‹bŒ\­ ¾­J%Høk)P)B¢[b‚=ÿú¶ [xúº·Y%Å|óôï7YT=£´í•ö ÷ØË¦Üq>΂˜M œ<ž]ö¤`l“²ŠÑú3 :. Åžz(8 “c±Qز £¼TGÿ“ uÙtgy\E<«n|^xž+©†qŸþf'€­#âùéÙgã4ßæ•ã*8û_6ˆ\Oó^pGDqïœÀIVb.–^ÿuDDNx€, }øè¢ ÷%7$×Z³Rw gÉës¸‰9wPÞJ^9<G\°ˆuÂ$Ù²ú‘+îOòsÊŠ'¥ AÈÆ!‰igÞýô„-{©R+[Ì)8ÅÜ;"š‚V+R„,Ûð%¯]6vºú£ž>°Ü»ýíBâGüH£ò–3*jçÌÌb¿9,I„ÇSQ¢óVưs§—çQ=M1I°7ÅZÔZ·…’®gýZæ‚5¹I¸1Æ0Iê‘êRÛ4)¸`8yÄYÒiŸÑÀ‹Ð«íì¥MÏnz—¥”LZ}‰4ú“³š/÷h*.0©®¶‘æU®lWŒºÔ´Êc=þÐ÷à&£/MGõ>qýÖ$¥ÛŠ9á[MD3˜‰ÉL-¥äØu+%3С,îÄ[MߵжÔ×:ïõŠ=ímæÒ¯äú¬µó .¡]@ä—‡2¯)¬,x¦´¬øäæ-a,$¬ær´‡B ¿ 3BÙ*æc—à R6´ Z-;k¢~—¾‡L”ÎùÔ”Sº9ÇÖÀÅb Àù¤ŸC¡vLá”ò¤.l+¦?q–?µOø#u¹€–[ÎVÚfâ8™/ÔÔ0HÖ8‰|5oû‹Îûøx'uµÏ6£°bKYèÍ‘£f“æš-w¦ ‘*ÈÔñ/+‚ˆýj©ÄË$ù–i¨9C×H–q%ÿl&ß±‘±ÿ Â1©Ál²›ý²4R68¡‡•<(F MÅNõÐL#NÚ+¤#>apÛ&çÑ’d¼ô0y3 䦧‚ÃåÛè‰+ ·â!”ç7ƒåÑ.À•N?Ôe®š 7E¢¦ˆPíãzmZ¦“vëÛ{µËA4Ú¸c(`¹µóç¨é?&MYøm|u¾.!$úÛ¦Ò¶Þ¼2gj×y/ª§zAúnÌÛŒ2l­Ÿ.Æ2‚6Û ¤""1LÒ:÷}¶"¡µWºƒ7ÿ©CkHU€,ɵN#â ¹¢o˜B+-"ñæ‰ò!Ùã4«s•†)1…σŠRœÀ>¢5‰x9k˳Ѓ>¤ôéC9÷_K0‹o˜Á9¤hìf¬Ê^íÞÒÏ>ä¢ 8ß0õ Äþ$éu#HÂk³9RRÒ‚¶ÝëÀ4Û@Ç!·/Ü®o åx0P}kk)ƒˆãЃy¾à–©»ýw—„«´@37Z„?_J*p š*ȧ81»ÂÎÀ d¢û¤«Á.%{‚ Vs§5ù”¢}8$üTÃGt÷ë:§´@^ÐÀ‹ šÊ/¤Œ(¹ŽÍDŸ¿â ¨€¿d © 6å Ðv•Ús4Í«55êª)ñ˱GæÄ¦ÈæÐR³ŽA·*åõŽö /i®˜a»öE0¥7Îbæ5‹Ä¥”&ÐÊ> E rZn99]ñ (Y""#Á8€5»ŠÚ‚á³Çx¤ _‘ÑÒ1VÁ“-Ï¥‹Ó³¹ÁU+Œžï¦:(¤O>œ2©0P]Khª™å±ë\~0ÿô©÷ÊŒ/ÿŠÑÏ™[Q¢Og¬öë­²¤¨Ãüj¿ÞÅȤ}2^ÇÉÁé—OßlÕÛÓ´_ýž»ÝïyÖNx$±¦Àv·í¾).ïg†‡+:Å—ˆì²Û¢>•UËr’Æ¿¸½ßðïè" Ëß Ô/7p¹ öˆçþ°£xûl·våü  ™ß Z›Å9®¨‘1¼•–Oµ7œ©‹çÍ.¸üÉ”[õ¾=µÆ·Ã²f_j„Š´…K…rIIllÛÞ~sjö·'ï·n)»tÇy¼Õ†þo(e%¬t7yNˆkµì¤g*›}qìíØíÕ¼C58Ž+câ†ìG%¤‡@åæ¿Í^›”…Ú*$buY(­£v›îÅЩêŠaDLA*p³Õó+%Þ&1ô!„2žSò›$HOCØÒí ¿ð]ÕÐÚ¨¹É]ð“3œÀÞ†™Å4ÝßÕ8—År±Ì9hy¦¨/†£a¸'–w °‰i‹¤RÄýa]PÉlýV‘G¶(»ê°OnÄLu«(³\…\ÆšOAûœðÇ'ý±×§}«UàŒ^åéÊRe².ºCye ChþqrØNH½ÍsÊ‚GÍÕ5B©Òº¶ó²Ê¿¯lËf• ¡UbœŒî¨ÖoZçuÙtígŽ}¦„Z\m â.÷d¢Û6upÐ$5]nf åt%,m‹¦n&ø8q娂 >j Ï×–èÖ‚ËæçÜ×’×ñÔê$‚” ö¸ m²Û]e¿¹{ÊÔßÿv;³áX™µÁ/Št묘1:0Ê •ŽP¶¤+7½Ù[KT:æc)-¿t”ðÁÛ¿žârÇs¸4`H8Ù’U£j™”¨ž¦Ú ¤“_š•»äV3k·ßM/¯´nP¼‹+,_3~+uéÑÄu™ Œ€Àdü ÛÚö­˜¨rè®Ú5W"Äês‡õ–ð?‚’÷5OÀ‰n9­·V<2PUF/ÀG8?&.(…¨w #µ„zirMO;l˜E÷ ¦­¹±Óv§‹  yH\+[mß3°w+ÅTc냆㟤7l‰ÛPÚ@fñªº1"Ú­ài×q‘Yz2ÞöŸLV0ºÿ™¯žvq¨°\0[mu˧åæáœäÒPøàÔ*ëÂÜÒ¬ÑMøìtðF±S´™.z»ùu&kD•83¸ oæéóMÑqË{ÎØÙpW®j‰¿›ýw?Éü$Güîä"vdªòÅL?…¤*ýAäûÒ·ê²—CXR¡ Qr˜r0E“¹í7sÄ%d0€ò4LVAš“DÈìƒdú%€ñ.æÞ·‹@ ˆè6Qö7joðDCÉirÇ1M0tl`¶š’'mÚ$ÜZ4ÿMS£QM±/Ì%ØÃ;@~™Èä|6‹B€†#'Õ„öËG'‡LâÒÖ ýfQý°º˜Æel›d­IÌR’ŠÙuD`,¾fj¿Aaµ³´‹`Á­6C WÐ2`“ k*¶€ÆᆡÇYÌ"2ð¥tED“"fïVÒß-0exKKÀ¹ä]WÒªQguf;èÂýÝl/nfi½«”¡ÚgE&®"uÆ =ì{áFÃS–cÉÎYeLL/‰3âÝW•ûò§‰¤,¼(£¬zPür’å6™ +Y(¾Ù{4TÂ|“`£ò¹aj£>–Æð†Âúj8€s ¶qNýóê'·¥7ê¸ÒªØWF&jœíu‘­ñÌw9ÓKü‰rŠy‚8»Vˆ;"˶i†ù’EôV@€[X”—µì©¤:66ˆý>Dmù„íÂÂ×êì$ÞΤй¯é‡ý¶, “”7é‰mfÙ õJB~$RV_XÌYs–ªo¼¬ßzãÔ9•J¯7Æß;^¸ CU êþ-Ó­k‹çÝsê É1Bºü¬· J[üO¨ÈÕ[ótn`Oã”EªË¯oz†­ûÚîÝýy»ák ³¥[4<ùßR(M†-Ͻ;ñ¨„íàm¯áKQ‰O˜ 8²¥½p@§2¸oz×+Ñöô¦ú\B’î Ÿ÷F ú¿Ã®wÇ<ƒöcP¨H­ÍÀ·¢Ó–’«çyZSLŒQÞH}ñ‘ŽÑyz‚’EÜÚˆšüý:ËýÁ›ôi“ÏI¦D¶¨‹H ,É,’î {70¾kü¥¶zï èdz Aeă™ÓORex掭Þçå|;`vXÊå e†Îã$—Ÿ»²h̘ÐhŠ˜{}—\Þ„%Ö•ŠPæÃe÷¦âŽJS!H@W#Ïa;­.jDÒJôamGzx¼æ -÷“_ ä黦„­J›x:c:z’‚?èR¹ž½% ÔO'‹r½&.Ø÷ìå^£›ÂÚ÷êÌGÍjŽ8g€Eªõ Šé@a>ÜV«þÁÛ’=4D°GÚs´ÔõSq¶r‹û:⃪·‘ÀÏ›+jûzZ¶Jõ§ÇÚL2ÖÖ!WŽêÞØö+Û®nh®ûåõOO±Î_›LXÃç¶ôøXÇ$[Âu£@Ê *å4Û o!s5zld}±ß"b,˜+©@…3iù"Ä‘oo íÍä>›ºôíJ@ÖJ©9覸XÎ+@výpîQ¸ÈÓ"´ÚÚ_â‰}‚a'Åö¬´øÉ<3~oh‘>{ÄZþAÞõq¨9]2l"! ã€ýÀ’œÙWŽˆjôÁˆ·Z»<‡z!ŸƒÎo$Iç•î­ÎyYdÜaT+Ñðáæ™×%À·Z}?›UÙ„EvͧþaØu¦H µ½ÜÑ·Y;A~¦gþþq‚à²Ü™ œ¸Sy®.'£‚EËS¤ë([®Ãj°L¶õ†ü.߃·ºÉ(©Ë\psí\è¯1Þõ!Ywù‡vÎõ§a—åõ8.ë#yEz’*ñ†ø[º‚ÎóÆÐʼí)Ö™äm£tQWo|6è̼ВÀ±áâí=%¡ÔƒÃBŠ)rã{ÓÑ1Ÿ”’wûÍŒB¤?·¿úƽ!k‘ߢ±"¸…ÞÚ„—’FJ­G€È KŒï×@€0ÓŸ’ 7´ýæMT‹7•” !!éªpõ® LT-Ìíj€yº¾R{"1—ò »¡:¢¤Zê|î½›;>Ú¶ýy&vÕûO ÂæíçLâ3â)§Oö^^„‰Éʹ$õvž8¤¯˜c}éQåaö}pT3¢ðöðjSCÛL"r¹ƒGjàB=Ÿ}®Ëí´"n©’/ë%Á ’êå…¾k„ègÏ4µùƒõ›’7"Þ9 Æ¢ìxáÉ&¨ýhßä©M–E¥w¤ìÎîþÅײB8ó±/P†Ø* Qý?(’¤önO6ëþÆ›Äã&ÇBZuBHô…3v\‡œþü…ä)­=ó:ª/óßåœ ŽÅ/Iæ¢p^ñ÷ÎëÀŒV7³Úl rÁ’Zš}¥ÌGÑ@I-,Ðm³ÆÎÒê-Ï;¨\ 1;I(ÎØÂO§»á,WJ «¼œMQÛšxÖ&!ªN\ˆ'o0‚øV:á¯.þ¢šâSmŠç¬[=æ%ÜCêû®óÿ5¥„iDß{ì83[ú‹"¶yjLµÉµ"+“™®;=1ÏêÌ«Êé½-Šï—j]b­bmÈÀç2íUË´—Hu´8¥}Ö&I«?´¥÷>ø]•ù€üÎY»mq ËÄ*ÌÏpŠ’n­çë”ÊXÉ‚cÅߊry~.‹»'ˆ¤ ÉkëíôçÒ¶,ö{Öp‚ž{ØÃ,ªR­nÁ#7)üYBf‡ªU^'vÂ5\ë”"ï«W¥mRj¼4Ï'ì­'Óåã¡Èï¿6Zt¨šs®lÕ‚½!ŽÙLXïwŠó, ܆ü†æîôÛx¯_ºŒÖ;€ô½"= eËìœØäAg¹T%Ã^&ág]l%V>²F) ‡¥l3”.ádT®j½Š½]Ò@ÃØ6-  %cÂ~¨š’U ·&‰Ò˜ý¯ Ûz†ïBZ=¸ØCô&©_I¸ ÊR Yù§·CK¾/'B ?ƒ“Íÿ}Ͱƒ â¿¿-â@Ÿ\,€J7Ã-Ò4É‘%œFßi4·O›OÃòc;¡Oe€:ù0ø½ãˉø7¹uA Š.–øÜVàΑjÔî áÇ;‹–¿7Þ  !sògÐ~*8Ø8xIÃiRЩ”ŠÔœÊ!q_|©Ù`£%ûnÈüàp‚¶£©^«~ã<âÔÑ^HÆãhÎ}³ÒËÿ"âœ4­rÆŒÉÓßüê4qxškÓñÝ+Tßßpõ…¿Ëã?ä4 Ç Ä[wn ¹`î¡G—Ú:=¿K›î4pD·% q$äXĈÿnT7?fÂ'{L ý|¾í™4/‚j»²›s¢è¨ÆÞD̺™9•D‰×‹2nN9›ŽI‰…(¦aëx2ÈnÀ& õ4Âįώi± @dˆÉíú­†¤Hn‰äò%·z ¬G÷¸C»\ÝÙnãÖÜçÛÛã|©Uz[ú@hœÛE¿’ؘš#9?'ÓD–J¡4òqRLâèðê–õ»šd%°žÅq¹b’1í£«òG?zú¾ y¾·˜tKááÙ_‚òRIÎ=\°i÷¦)#`Uw|= éèPê‡+ñãƒä¹Zµ­¸z{F ùü[9e W—ðª"bù6#~²pýSzV^b]‡p ®Aª¶¸¥íÏâgÑ¢-ï)°]Ú…¸‰ýŽý—qK4U5Ø¿6°Œ×IfË‘£œaÇOXª'l)uÜÜáÎÖZ˜tXåiX:âÀ)4 öS¦£øö¼²…Q4´ç>Jt3]Jn–äïÅc’te%߇|p®£õ»!*­™!U©¯ÆFJ¶Ú"tVà íÆå uÅobrí³ Ç±X|BN­¤==·bÙuÍýnÆú”ZëlÀèÚ[ ( JÝ(u°a)ÅÜ2Ê3*Çê¾cÛŒ§D” ýó¸ú1sW|'ìÞ¡jÜ÷¹v*ŽYÓ,Í›^ÉQ”ÏàS¶ÆŽÄ^ZÚA’º7‹Ê¿)W[+Éö,‡s¯‘@CfUxþø¡::¶Þ_ºxV²¹OIú]PÊLÁ¯Cs§J“:šÑùÇ}ºdÌ!Bèb…|˳ ‡è>ÌÓŸi®ÅTKí\­ã?ô9Éþ\¤„3Èæ¾VŽ"ûÃû>'‚çñtAìâíR"Ø£QP›.Ó‹áÙe§¶?¯ëÓÔ‰ÖŽC fF `‰Ò@˜NïX÷}ŒØ†1Wj·}’ýBòIf2TüŒýÄÃúÅ!ÑÕ@ÁN1«¹®Öª=’ÿ NöQð3¥öÏ*yÖ |zMBÚð”n£ï»—ŸAªœ…”בù°¬ †bQ'÷™‘r„Eäâh‰I1 Kb=ïŠwècB×1¡öbÖiÜSnŠ•œ<•{®½L5(¿ŸžKu—Ê´öGP1œ4]AFUN–HAÀÝ¡  *u. ­w“xÅ—4aIè{]¿KŽÅ®;rCBLËò†ê©+´{ÅÓ­sÞ•*òAŒèÜ·ûкhK±Èôš] ˜nthÃ)J„sˆ°Í A´F(½Á Êc’Ÿ™?_?é@ 1#È“mËñˆQHfmNž‚\ÒâöPìïB|F×ZÊy1ôpÑÁÄà©£pz[ödÌààš¢k½j¾‚[D÷«aØå7C™VÈÚÕœräõbÃËÏŽJGÂLëÌ?…’g”^Ò-RrC³¶pLygÔ¡V\ôÌ õtº“·ÅD­|U£ñ3þ¿‚†_7–°(Æt9âk½Ó¯¸-EWì’•¤³CÐE”=€7êæ ²qNÙf¸"G|v%¡Q]ôÝ»'çÿóäÎ,Oo¸­f¿íïSxÌD€§Œ2+"³å˜Á©/æìWèLéJ½uíòÉ V]عÚXlkìõÈ ð{3iÍv{±w`ŠºñRõ‘Zvód˜¤­k&·…žhì˜-‘Ia¬ðü²sá ˆÕmK˜ºÌ·»:冚ô!Êüüð8ÍŒGΓ`ÛAVÁ!ÏÂØû*©ÝÅ•öú—É¢´EÉß’|¥¡z‚ݦª£SÔ$ñH~Röˆì1 –@;VD€ªÜI4üR§>Ë,†—ãI=›±tÝ-\È$nó‰®z-é|4÷Fú£Á¡Þ¹$i<UŸƒ ^Æz¸¦0`³ÄÔ°óãPc¢©¡©8žZ‚l‘§˜ë‘… ¾,‚œ™r@Û©å Ël|ÿ3)]§*¦qàxDÓ°a*0ªì>BÜXA'û-dýÁœ;ûÒE•µ÷ÈûDÐŒCû!l1˜§üµ96gõg æòë†ÐçÒPîßÚ«Þm­SÆð'‹žN ’4HmzÑÿH£¥8ËŽ Æ–^„g›:Þ AÔUuý„*{ñœÂ¡K‹åiÐâɦ˅ÁM“Rðç4i{ìÜîr¶¶¿c¹7LùÀEGqSÛ×ßfid‡xDúiÝym&Ò ÉP¸qÐÃWU Ù„4ðcoxÚ¨ wÛ™u–>z‘aÙæ—üL4kæÒBóWÿíáTè »¡[á‹JV°AõDá_l.½×åÖá"zŸrÙô(çûîtû6*’ü¯h‹i]m’}`Æç–Mg¦+ÈYruy7â­¬¼l¿£uý’G¼õ³¡&áÍŒ³Û<­¿’_ýw]½¤_ÏTsêBøb¬YhfÙ¶¯ 40€\}è"7ð"ÔØ7îå$õ@4Ï}zÁª*’®ÑÒrã/8H”(øo-ŽbžJøÒqqƒL›R„ž³×¤’ëõª;ÎcO·B¦‚íÞ *2\¨p0&­ŠX3†ì®ìuƒÀÇÅ'BX{aåfjyuôÓél¥½ëÛf ”šoXzbÖh5®‰¿Ußkþ Úëu¦âj¼`š6댨V°ü(ˆ,ePàû^‚Ô‚ÊyòÁ.̨ ÏC%8Ì:‰ÎZ#—_‘ ˜x&æ~08†ç>×Ð-äPpúÁ_óä…fž‹çï‰^%Ošj­÷J”Œ8ës´ôêÇçØ•éÔgNVü™=¡~3’@+½Çoã0Qx.2.ý$1¹ b[)嵨.o´C2ÈÒê®Ò‘fÿ¯Fýeûtk¢Èƒê…µó_Fš³lëca…šÃ¶–]Dð¶¡þsÈΡÞˆD ¤+8bÇ…8Œ™Oz¯¥nٌ߷ mÔc3ä¼)ÑŒ7lÑB•Õ\¥?…|ZŠÙ5[°`” ѧãüBÏÉϺ¼\熼Tó›m{3clMYÆ5Fs¹öÅ1N=oœüÔí]Hœtk½ –“)Ö—*× Tè6oÛŦñyÂ&wæLG€ã„R¢Ep,ÚU•¦N2¶Ã¨;Âö ©‡¼3—JmWWw ½þ(é;þՓE) HÔúÉHÐt;±ç[žß‹ó“"¢‹êjŠù³’ð~/®Ëu0;ÉûËZ‚øÎCc „8ÛŒÊ5 ÁHÈ+ PƒÆë?¶Pá,ÑÅê.±wêMGc¼G'7)`¸‹W<Â…íÿ_}Û0ÿurŠVóª+}ªô/OØÊñ#Áâš«º†Í‚Ž&„?]3þ-á c©'n`§£á‹$ #@üôy š ®Ô*¡Àm{TX@‚"ß!ÿ‰þ(ÅÒÚ(€ Aæ¿×NZTŸéÎ%ŵ[®*`ÔjÕ ©²aåÂo>·æ,æï}§qÅwͪ]ÝxZ0ÃÞýúÕŽÐ!Œ_ÒlÒô'ú#ŸrTîhÝôÔt"5eö~fÑä „øƒíå³éE –[|AxþÍÞO–-T9þD»€Ðe'IŸ%ò¶ÒV=€Õ€\ÈVôÊîw‡ÄY?žþe5#hÜí]{LdsMž5¸9Ä{cŠh 8:ÄL©~.êúâ—ü…&ÿ -ssí‹xÓ|Û7hdÏ4ß@‚î+™Âµ%µ0¡a°<Óýã©ã ³D+­¤B&!c ýZ¬;<†¢Â–‡ìÏás-Ëc|[1ûOçÜ1)‰æÐ€ëŒï]½\Ùú1Ùñ¡ÀæL²9¹kÓîs=g´„öuóð(ª× Ã9»6Ñ[Ÿ’Àif.v'¯è,’Ôò|lÔß±O›x^aF¨e6o.ƒAÃ1ÿÚe?K؆•è]æ©A°ò¹¾Á0ÃÕžý:)¤É‘N»hI&‡Tß>÷P¶0 (½˜ ¾»ÛC{ÅÍm +=ˆÅ%1Hº²Mæu MÐÌA(ª*­Î ÿ7Dœ‰Gm®ÆåÛ•«8)¤Ì9¼}IÁ„Bº{§¦å–ðW;ŠÖK§ªælcvG³¦p¢ž¿ÿI–õQéÌ„®øTRK:Ëý`æ—íì4JÞÖÌL……æû¸‘`¢„Ú(I¼ó`‘ß¼“¾-{üð\=N\PHÏNF¸±ºç àSݷפ êŒ`ÌõÅ ã‘øH¾Mx]Œî©c¥ot¼ÉwíÝm„„õ¯Ob骹uÐG†k ã|Ë>“Vyk*§¡hÉóß>æûf, Šìufð „mþPoJð¶[µ°«ÛµqÏx¡?•nú `±L~ëé¿¡,Úä Ax¦"ŸpUc»é›÷‰ã‡?Üþc9»O³Å2~:bþ&äáoÃOkÓZ‚Iê²M%T¼ ÇØÆýµÍþ€‚ô¥¡ßÁjã dçÖ`[ÊGsç¯8øx²HŒÖI'Ž(»k¶Lù¤a&UÙÐþ&^àª4ì˜á鄸“¨H‡¥ã–måe¦*YG,Æ=g-(I&ÞÂÎ.ýaC~'¿ð­{Ê•yR/]Æ»â8 ŠsÁX±YÛS×átUfI~™ÖÀò î"; [oi9“^– ›©Ø,—VÀå"cÒŽa_o`HiøNü7cöY{Ù¸T§¦•N SðyßJÝfÜ2NX=ùI¦j^ÁùÌe…èú%¨Û1~W™ 7L´{\Këô35öþ“éw¯â\<…LïpšM”™ã‚SâA]`C5M}#« [õ,±¦y{0œ«yÛÉ95øœIKÕèÐÔ`RXdÁ}ÚêÖ=­UæW=14ÐÎÒ.âÈ—1Eû¤]DŽWç”v þ¶IO|ѸðÞâdjÛ;Ð. NŽEסވY) ‡¬-‰vU£±lëM‘¥n¾x²¡—›$ÍÞ±IYAãà g¹gnÞÊ0>\寈­…×è¡1}#¨h9gRþÆÅi–ÉXG_÷~Qlm£eÞïBÎ.m‰¸£½sð*¿¨_üÏá˜4¡ãCðð . £r®O„öIE¾6Uú¨æ|_¤øøN C$ÌjÐí²ªh+ãÕÀ£?¦”ò%Y ÀéIž?×tÑ;Åý7~ ™\1ý5s}iÕ@ÎNÒ JfRŸc}ë„>ª°q舵q—'˜,#™ŸµçК4œ–K‹} ÔÖÑÚ¡þsŠ-ƒ”K^R­–üq„añ´Ñîëâ°á?ÌÝòGBf´3C9A­ ™Í<—IöÌb`æZXªhª9ˆ C,šóƾéOÛÒ*LÈ®§z[–ܧåÒ½wEl¶g~O– œ3„*q,|…À±i‹ÄZ] cCeJÝH¶ëWf6™‘¡Žßh«ÿÀ烦²íÚ’ÂJ2,ì!iùÚ¾¾ Øÿ4øè ÜW%g¢?Bë'÷Ý~èL¿mG¸‡ñÐ.bž°&Šè©W˜²}h| ~ŽF¸æak¤brM`H±™Q Œ­Ñ†eQ©¥¹¾*$_°˜ê“‚“Ö¸%Ý öŠ}«¾¨7ˆ™ú,ësJ:F×z“‘æúsˆF³µ{øÒLÍä7ÊÒ™ç'¨·å¬6¸`û&£1²”újÐ/ù ƒ)ÜÞo6gö×V–ˆ}–þ¯6 w;¤ßþž( Ù¢ýth©ÿ’ÉQû¿à¾ ô°"Õê¶%‰”\ó |Iì–>õœã¯*ìÎ¥Üt“Kš< MXôøŽ¢Èf#@MÄ<ì÷¬¢œdøkçCæú]Û×KÊmî)‘WdÁy¢ãlÒÖ9NõÉ&$on’íw1ÍJâøh¤Z" nL ÒàøHágl«´lžsçTK²a»éÛ¤êHõDöï µ§ž²Yš6EûeΖ <¸`纂> h-§£ë?OÐÆgº»‘šl0!7vîM‡iqŠ25R›GÙê©yÔGÒljqMò×ÔÜȉwü³®\H9Ì2ŸdO|ñNýH)E2îèŒ[(ŒùÉyâ k*q‰6À´a\<®oVÄQšâ% @8Ç–Æñ®ƒp³m 4:FÒ'„qƒûÉŽò“B®¶|Ÿ:ßuÀF›¶N‚}Ú­x C÷8ý¶tþSÖv‹ø»µkº5¶Ó2< Ô„—ªþö)U˜€NÚ‘ÄÃT(sS pÛ©{å@2ǬŸNrIÓèm«^¥ÇÚK¤²’ä9Ê:;ÒIS¿6×aŠŠ¼áBSt¨ø¨„:‡wˆ{¥ãL%ƒ$-i¨“.•]=O|·¥È› /”-ï”S„?w~{/œRÁlós¥F±+¡«…Ý$ªšžƒ´/ à;ñü¾`Ïå%Æ]ŸG0ˆáMôÉ»døÕ&Íå°=@ц_”k döÂlÊîC(pŽÚ/N­mgm_äBáYFc»Gp†Ñ±e.¨²™_b–nY,¼¤µÎS‡„ZW>üE´DYh~dºÎ¤®½-hÝÒaýÁÄåуE–Õ{‡<æ!8±q;¿#ýX"£a3îGc6[s"sO5¢ÍT®*@žø<Zc¢Ós¼©WÜ4Hl\qïZ¢åH¶‰AÇjÓç ²$zÓAŠ8Ø¢¶ŸfŠr¤yøÀzÇÜì Xt%"t û¡‡ßé™fb/VØðk.Ø¿ûDE­hÝlu4vÅÚåþ„9~1Tü^>e†’¡Ñ’8²>Ù}û•bó"rÓ£¤ Ž×€•â®)dT›sLSæ‘iRk·¬«‡R®CÉXS} Ü!­«»”‹= ôIÂQ’¼ÐÓ' 7þFåòêµz*ȼ\sB&7èÞŒ¬ù)‡M¿_&lš5_ ¾BXpÇËü{@±˜3Y¤Üò ðíìîx6ÕEÏJ“UÍDÑyÍžNÏ XC|·5ZBl<íA•-ˆÙÿÊç×Ï¡Ž6Á®üoÀ‹™\…+²¶›vû“¿ ¸7žc AuxQ÷PbÊWœSÒà_YÃ4GJ²b›ÉÇݘ؞™k¬¨RáuÝÓpgæêì$,óí ²x4‘…þ×Ë{ϬÈ#"%ê (ë@[Ä`îG¤„$uÔ?}› ñ:G¾‰>›Ù¡anM¦O3cåß™Ë4Ú%ŸŒº«Zqƒgš«ý¬S9B0*=w7Ç"ç=µ‘ßyd°Ÿˆí³y){b¡ÆTwÙ†Ô<ı-©Âx°7Ög™h¤%ÇYÆMu¿W¶Ûvæ¬ë>á]‚{ÅÞï}„@óç>»ù‘ãôí‘›@Šï'›ÓNxÈ}"ÊŸ©EU:çH5E[½ŽÐvëß^sdÞÚ²×§.:-;VøÅGÅ5±”"#ÏIÂw¢9àÀx¶!“ꪇšfîv)¦’Lfµs†Õ¹7äzÃfà1þ=qÇ„ò„ÐÛ›þmx„Äöý¢Jÿ¡d¯Q©xÔãB½kQÀ°Lm/2vñ4¨ªyô¦=ÕÛ߯€UIÉꊣ«²¦-ºÜ &–çÏr[n¨I6ë 5å"×|²9çQ¡IZ!×sÏgذ©õÎ(ª:¢» ÙÍÀ-Ãf.Õ™~TìÿIN>¤â†ŸíHzÀÌâ@žc¿ïö ¼ÂH ýyô¼—lÊ9tÓ| KªéÄk=±¸ÕiwÑ}óR8qš“ºÐ²œ¦Pó¹à,Õ.£I¤¡ƒT^šÚb2rÿ…»Eú3Ðt6DE¥ÊtL ŽW{<¼WHާÓ­V³ãŸ¹œIœö¬™ZŒ µê»y¦Û°s0Ϥ¯ÔËʯU“=ÈÕ‰ý5b> ]}JÙA8V¥uL ÍæuðŒé8Añ¬zH$.¯t [³8×_ꢖ,¿m´¤–“Ç+L€~T?TÕdp§`îõ¡^³p>÷‰Ú þähjó² L„$Šÿ4 ©¾èHÔô Æ(nw‘æsg–$Ø'\+ò~u> µõV¡M>v¹Õ“çõι¯ª(çw"q‡/¤y÷·fÇÔZwhµ\Žôéÿ6nò~‚î¬áæ²W†g=\w¶Ë•_eˆ¾¢±>Yhø{PÛ$ŽÄwiõœì˜N9cB§æ&©âVéÀÿXû뺸–:Èî_êºq%Âúêô?Nj¬#ÙpËG'íëÑtHº-Ï?Xa|U µý7ôJ¬+ °g[çÆö;ßÁ,F懓wÛÉN¹›*VtÕÀ…ÌZ8±:;,«iŽ{¾NsïvfÊê@çBª®Ž«GÁC÷vƃ¡hóÝUJªÐ)½ç zO´ûøõ휖\¢bÏ’Be¬ÁYt'8Ô/Îs@í¶ì5ÂS)X…âìpA ì„›â¾Á_¿»W±¾º0¿çY)y¢~cÿ¾³mÀÆ£{ÛÜ‹Èh°‚8âN}ç¨Ð.ÿ»ù³÷A¦ùÖ„}£[‚‚8R6† Åh²ÙåôâwDÑ$!¾Ñ¨#c¨.86Cçw’ÅlÜ ÁM2ð‚l«M¡š–⑽™ÎÞN_÷_ôm9jç’ ~®þ&#®ˆ]Î8|…Hj\P”¾å;O—*:8ê§D•–ÖÓ,ÿ5ü»öTŽûrrÉ«ò&á[‘¹Ø (|“÷TD‹²a}¨ß;”âw/ð"óËY¤ªóí†À©#Ü7П5ï$@™<ÉY=6‹áŠu£Â¡gs>(UNŽîÎ9Ñh3v°t<4<~ßpË5$¨á.¢ûÿâí6Ý@µD¾„¬mÔ#p½fÌ4nc¹k5× —Eo¡é<ÖP,L7·™bêA)u ¾nÌyê îMAÏ?î(«Çèý¢È,•®8‹/—-×cæn‡J…‰# xjIñgq/^Ѫk½4å|(ãh=$;¡ºùNv‰Ë-Ô•‹ZHü…²ÓC¤ô^_ÃãJ?{ÚºoÛÄ¿V¾(¦_rAoëêæïëø¥ÇÐkI}‰¬(ÿÖmœÚCHGs·Ìÿà±ükyXOëž@oìã‡4z¬ÿáÕ/‘‹‹-ÝA ç%Ûàï]ñ`ûbÓˆžÇ¯¤}…¥6VïÙ™Ø×ts—êIÿÓ‰§˜´&Ô ³ðzâ£tUËC3‚ˆ– À`õgÙÑnUL'¼q…@~œMa-³k³ÚÓ¨^zªå55–÷¿–Œo/òD²q¢6mÛ 1¸ÜWÿîéÆ'a%mxð`Ë},c~>ÂQc+4¯3‹ÍóGraüÇÚ¸¼]s™¡[Ák”ó¬1¹NÎn½´ûîp‡Ýa_ï¶—BzzhxèØ&ÚÊç£z©ä¾‰¥!*L³÷¬°`G–¶"!šà«½xµ[Ö̬ŽV04Fâ ´n¿ü)ÁBv_a!zÇVV`V;šîdÌ6•’†eÁ0ËÆ‰[9­Ü[Î VD¨¼Ç®Å#rT‹#¦ežþьⷾí<ˆ”nû²U³ÌYyM.”7ºé[*Û¾ñ¥6®OÉ_n¡¸ô‚ÙmTÈÎ_âŸ+¼þ®\™•žILh#éÔKP&'Œ}13‘ÿ‹,Y–FSc˜ã,eH‰v·ìËnÆyr¯6‡-Ç?ÊC—åN_Pù6Ôã”(RÖ¹^îÝ%žåJüw¤eÒ•t¶<á[9Äß5è{ÚÙLkìQ@U!”ë2Dâ™]­T˜ÆU@œ‹õžŠâÇŸåT˜u¼Íu¢¥Û´ÛŸØzÏÃW8» 1<#Å®¾¾iÅ~X’PÄ~BË­jø˜f-×VÔ@‡Wèvsl9ÅÀb957aHªã{¹ˆa?ì©è¥½aØ$v]YÇéáù†¦”‰lš&Ü™ˆÏwÆøaÂ÷…pðPÃw2ê1Hû£xBs56xhç:y­j­Hœ¤’òo>Ä‚1›¾2vßÚž1¡àÁî AESIÞX;ºâéDh£’k(D;¶:=.á*ÖŠöO‡8Q§üÀ Ècò[&©A¬²Àtj!ûºJ«”c {°,×ÿÈy‘ò8¢ÎȺç"…LÕpÛQÞŽ´¨T2%ÝUÀ÷h¸¨_8°<¾¼I«1Å+bCáký"+¡2+P‰8a;, uj2Üaâ|dy-‡oPÒ§`?Ù%>P®‰È‚λ,“ʘkþd 祷¨L„òUc–ÁãP˜µÜ-÷`¹0tð01Ê{A¼uÀ)*aø·™žbúlþ n°+{r "/|jq›< ë³ñH!¡yHÊ0«_Eµ€Â• PL4iGÜ¿ &Kñ³¬-ŠÐ®tõ¾åµiùˆ§ªôtJ B‹òTƒßnïÛ´]ª‹ù;û±ÃØMë:ã]¸yaö>2öJÖLïï¹ÚåFöÉÛT½‰(ÜbTÞŠ»sû {îlÝ7¶!º\x²ç`Ãäÿ+õ4±°+an´íx×ÇÔjj„$4v‡×}áÀý7˜±‰RÆö9h!üiÁûéCÒY ¢lÔJà•4€?þ¬:ócª…ø³LìÀzóÇmàÌ«sÆòͱdé‚ÿÃÌAé6„ ô•ƒykÚƒfÎýîbÿÜÇ]yh‘„@{«t¤í'{Nªæ\huŠÉœjjJø±š7ÓÓ&:"çXó=袎cãñõé§‘[ ™¿¦j•-aIš®ÁßÏâuî„x£r㈎s6!Ø#R ‰Ý$æ@x [>àGýÂ<'™a„ÅuÇñ#.ûO8k6º¥üჃ.9{ŠÉÙñ±¨D¡¨Âõ,ch¬ÁIÜúä?×`>»høhÒÆ*kâ(íù9–u‚½Eý. qˆhŸfÔ¨ÖÚóægÿ•Åèó?üd®Ÿk"rïSUÙã‡ø‘Œ_ºK°Ýús%þ›:™y“ÙcÑt¿jú°v â¹B鮯@“-*“–PPÕ1ú`¯=Àµãä1 TÛäì¦)Þñ€§Ä±$’:d;þŠd?r„ÇD ïD“’þ£ IÈÆ$¢aÓxV9F_øºW6,u‚Jú*å^ñ1»ÈŸÞ™—cr¼½Ÿ(û…p&ãLhØ<m³ú,{™–g8ß1û«ÎYM–y¢n}nöGôäBIYä#‹g>w½RÝ¥7éÚU¥ir.à~ïˆÓœ†ï©è…<=‚ 91™ FM£÷C^$ÁŠîÐ…‚ …ã÷Bž¾ùœ»ì›â©â–—o÷a`@a© èæOwJpzñiŒ½Ó_Õp`5_ jÓ‰xê1ô@jddöæaãÏãË–C{Ö.cðÉl޳0IA ž>Ò¬/¦`ÜâäfÛ[ùx¶òèÅ€‰°ÊPãx¹¥¤DÇ“Zvj,ÑX¥ÅìiŦ|Ö%…ÕÓ9Í/"aho¬73 Úµê„,¿³wŽébÉÚó«çLS7àJ“»w¯¤í²‚*§0xïï¾×«úóI–7S¢l3ÈóK¡Ëêi]óÍ"EzFMHЖÚðÅ!U0ÙXÇ/OÅ= ~ $³Ð’màx£ejñu]è\žª®f‰IC ¯Pa6ë‹#oX;9Òò5deŒèÑêgˆ£ÕÆ*%ñžÙñÜöÄ]UðønhU‡•oÄÎ'wŽŽ¢k‡ŽYf÷ ë$ât,¶¶fÛÍ7Š;×øö6+•¶B8ˆèÎ;²º¥™õªÙΉîå«no׊ܺQýƒ,ÃOÚôi|N‰'󬆸Jâ.Kžˆ¥[¼|ІnŠ>ŒªA=wÄEX¼!{ jÜÁÇz_PDwàvk­–©ûðWl§=²ºc†´¼¬ò|ÊoUÜ݆\åƒÐÖÊÖ« Ï{ÕÁÉ/-®Šô#MQ€ ;(ä¦U¾ÿ£…ê…튽ð&‡çšœt¨éÙäÛ½ÌÝ:xÉZ´Šà9BXóÃÂú»@Yì_=AËžàìÓ®}¢Çö60À!žŒCŠö&BKüŸãûëk©àÙñV$mHi‚¼¦Ìòk± Š'N5`Ð¥£ITæüPÊ%ËE×”~ÑymQ}¹èFà8p,í¤I W™tgïˆ@Ï­;…¬˜Ya\‹7×qø?ÅÍCŒçN0ØRtñ<=¿l€ï#· ³™ ŽëÛVÖO·ÎÔÿÏÆ£—îs_AÂ\•ï×ë«‚D¨M¶î%áC_¡Y\;ÙÇRåTC¡Ûä_êš'Ø9oðEû°­µѱՓkQ>)ª0†#›ï >¢P+íú®[çÙ#Q ˆ¿¹Ÿ©V~¢¸€†2£Ç¡úÞ‡ª…#7Û¹ã)ãÑírqa^³˜ :®Âb:{vs-;ZÃYû¼úŽP'’Ÿš7BÇ:· ªüô¯Ô°mýŸôÀ\0 ‚C+ç—í9F„®c¥ÎcdDVúx‚þÀÍQME€A:âþXݾ1ò¥m×÷gRÌ%°Hà8ìgNoèȪ˜“ \Ûµ½þâk\st•ÁþˆMßÓ™Y_ r/Ä×îcØ;0Úºÿï™æ «²ô¦¸ff°òUaÐÑ6R”úèû-ö¯QQQÕyˆ^›"a;|<#‡k‚ШJnÙBØXSlK?šŸyp¹óÒ».²wRVÀÂ%ç«-‰¹o%©;6 ÂÏ1sÏ‘ÐQgz ³w"˜ÚQÊ÷Fãÿ-)̓ól ¤Íò:CÜ-”''Â~ݦ'Œg*Ci)ÑÚ9½…daéÆT6™!Øåç{€Ã£0¦¸]•¼7VVg Æ„ÑÊø‰…Ü&R\ˆÇð ¿u‡QS3Êp?Ƈ[Ó‘ cH|8_|ÆÈ*Ž\¹h‘«ÎX³±p[qW¿!6â×£=Á3°.éEfÁx,Ð:sôÝ]‡&º%ªYù!¯Wµž©µ(IÎfY½Š•!J}‰?£MÒf >S¼…^s üÝš°‹?•Í÷ o”¹òS½DÑN½nÌÙZœØuó©G·À»h„ÕZ´î°F¼Íá×°å²\|JkêÙbû:‰Eû5¨jò6åÈšÑ)‰äÕzëöÀ”5†ö È –üYT}RnLù‰‹›šÍ-;¬Ï¢éÉÁvš¡:1Æë¿Ðä¯J‹(1žlÉ q~ƒÛê,p? #¢?!˜ao™¯X‘v¹5²Å¢J-Zlý­‰E³ôpÛ1´Á_m-êUÆÝ×—qî˜ÿJTÝ)oÔGSýÛÖàBµlV^º%wkæÔú·#çV-Jv8éñšw‘ÑÞt7îsì½tq¿Ìá¸Q‡¶gl`x‹ƒM¸W$ý3#ÁcbÆû/!­’Zt™—ku@®'bóhÃØë€î\ÚtQjJ2¼ŽuŒ³âG^9Å¡·Žk]Âr¾ÏÄ›Kêséç*{òy¿ML<9”"C”ÞŸb§R¢º·eÉÄÁå‘o°‚½~¾¾µ¸>aäêoÖ»&Û† ŒþYÎ…›xÜ%^ep«³ž÷{"^¦YOÿƄ߆:€e¡êAi9:{mð}h7û¬0~Þê•ûûYŒÖÍZ  ïô¯®[ïÙ'7bLw=b’â ÈÌ#XÏO)Y•‰›ìg×Ëñ#QRçXý]8ppzmzÙû/íÌ¥[:]ÄqDšƒ¢­æÂml|v ¿¹EÔaëŠfq5õ/8õ>vòÝÊó‘?2¬V £X8ƒÕovxséA~yšÈé@ÛB fÕ)‚ÕO”p#eoûvdÄ£Ìe¥Ç%å@& ïzTéê BKÖ©âó%Qîó™mxƒv.î$gžüWC}}¹/ùÇßñô.þØwcãïÛ¯h¯)ÆÎ½/Ê?mìxøC­^ì—³)£n/ùº1†Æ"…›W!<¥¹L–Ž£—€Ž;dgg/ê\o´1[Ê'³7º,ua"\ˆÉå"ñ5ÇéØx±â.¿Z¾Ê H—»'VD6Ùf[ÝUýÀ׫E«(ðºÊ–ÆÁ³k-‘µ.5ãÔ]³Om`kí²ñEnAe7\"! Ôžmý@åÌvø—RŽ£F?,³`tNúw€¢upÔ¶•[<¶ŒgÁs†:Ç a»D%úª+ ÈÇ}Cº±ÿÔÄó‡sxà4ÝFÇJ¾…¹!–ÑDLÄGp°²ì:ã¥å¶³½†ö ¡ ¨e×ÒIÉS‚CáM®CÀbªðò¬ÉÀ–¸E4Ï0 ñ<’RÕTµÐ¹FüZ¤uåà)¤Ì%Òh*Ÿ T/Š«f…JF¹XºFÊÐM0i„™¾E’ xAGVÈbÉͨ6ïï\@‡¹Iý z/ÙMQ ¨%ä!ç¨ò‡Z$$i¿:#Ç,û(a»u‘7fà½I¯Y¥Ä=/âDÅÈR¨Û ¨ý†€$ö¹s‹PïËD†˜UVðÜAMA€žc­šõ}ì`b>Y>cws_*µq­½,Æ)ÀF¼Ǭ’NÈ ‘\na¯'Z+ ú³d`§˜d"xZ»à™h¹[¡$¬O•Ì’6Ó=ˆÄaMŠ=E÷z‰Çãp†?Ïkx!ä=D½N˜Þ³å ¡ˆ•åïý¿ïºèøz=ÀæÜŠgæŸg‹7ϼ~»$ÒnqÒ µó¸Xt¡ò½˜-å¼ïPýǵ\ÛóÂe±µz¡CßÖoÙ£\I0Î`Ya‡g¸™DnËÎÀR=@ÍÁ‚2Œpqoxo‡q`8~e\Rëš¡lWFî¤GXÄVBÒ¤Ð*D*¢…Již×'“™íÄ$uvµô4¯r|+aO„`©©ú:‰b±²B¨ÕpÚžÁ®-8fÃÌÄ k3pó»¶Y3õÓ¥Wº+Oͺ/ažiЈ)1`+ãÊt0OX.):w¤$d]öÏq€ôájgÀ¥²Žs;–„xÆÛ·®Ð±vôˆ²Á MÅ./ÿlÇ‹„_Z5«%©òÒºG<Šû³ìLê7Ú·a†pü?EÞÎ5ç˜ç®"Y‚c‚LŸ%{Ièr[Žo£…¨_èð¨1<4wxr5Řx&f÷íÖ=»#%“"*f#c¼6zs2LPwf‘Äñ?øu”Ì\Î.!ÒAüåË5°±QÖè«?aƒh”Iu¶'âʯPz™‚¥¹™GñÆ/À"{Ð&<²Øb;¦¥~iò¯ÐrS O¨ HÅme§ž2c›¬þÇé±äKèÁÐv9ú®‡®ZK~îeeÌ À}O“ €†iƯM©›bô¢¯ãî­vX cjÚ9¼'¿äŽ>ЉæÜÿ“tÕ²îÊô'“ÏK|˜u¶¤°%/EºÖeƒw©a¹H²Â,KÊ=€Y°zT¾„5˜SPyBE¡§5ñå ¥¤â.¸ˆYºÅxý{@´Z×±G¶Wp»T ë-qز} •~Ühð]òŸ½¶³e!"Y~Ðão¶\°êxGx¥Ä릘‹šÍ~ð©ü’*$ë„ncäå¡TÚ’üIWØ ½C@‘N»éK5Ú‚àÓé¹³GÑá5#“ˆr³„±Sç\µ0ãb¯WɼîÝG¿³é¶Mƒo êŠh?Ú^È„dÉ·ºþ1•Šûƒ ÎÓÜ`gî•î¦à:kS¥nb/X ΪYÒº±•E&ûÁl¼ËgÌUçÿ¾yÞ’aÙ©0¹û†‘ºcÞšÛõLìÐ^ž5“Šò'©>–QkV«>ÆíÁ& ‹çea‡F›NK5%yùßy…Çüfn®nj¥I2%…_¢Ãí%YÛ$-­ê–á?ÃʲJï÷D¨æµM¢PLów³ŠŽƒÏáÜ´XÓ˜ƒ2 lG~¢‹C´Kb±$ý‡Æ¥Ã7ùb—ó?Y¿•32Uæð„“Ÿ Ã7ÁBq÷(ô}Œ‘@„Ù#Ñëùó±f| p4òÜè™ » žCݘ8Œá95&°-»cé瓎0ª0˜áÀ¶4ßgQJ›ê=ŽÍl²ÒÛÌÄ9Ù8óé¦ßjQ›Sì<ð=Ç:”öL"DÑbp±ô'k¤¢…P´„h ’ïê3€”XRÎS¾æ^BÐJ$Éa¤—UôÏ>ºQ‰ÞþÑì«#äëmºÝš¥Q½Ç6]‹Ú&ƈr‘¼SnÎ6ën® n»gíí5)? _QîúóÓÁ>M™å—ßQ$»ÛqQ@Ø>ì'^÷(AµøŠãN‡ë;F’ë,˜Ÿ¡¥ýÃàcÏ‘ðy›åÊ˸C`¶>æî6°á?&h¶Cng6j Ñ?ãȜٱŽBÅ€¸LíÑ:a^ž:õ-ëÎS`ÁÀ0NŸmò¥tU¼›yÓ ›åTwWl´· ×hâ6þ‹“ž ÉOã¼À«6-«DÍ#¯B×Ú{½ou„å9èöêzú‡Â(AšÇç³*‚Np8ø}ôfÓ«„ÁƇcJ˜OK+ν¤D%¶¦ Y#g€[jãûo˜ÅW4N+K(Ý2’ÜçĶ˜|q°ˆˆ®,~n¦c¼'€{ {SÑdͲD¯Øªü7Y*îwg.\©Átrñ˜Z»üCp—sûùk¿[•ÉÀ‰4A( îû¤+'ar˜;ɬ:½1£f ±é­å8:ÍomÈ fñslÖœ¥aòÁ'œ“VOv—YDïÛIs‹ÖøÇv0Þ<¦f’™<©ëšdü3¾î)È×;N`÷¨ h&À€T2ªtú`ñ«~«ŸÕ<=ÆtÚÿ®ÙDåÜ r¿.Å6i옜1}ƒ2 ÛÀ,;]Ø­¦ ß*ÙNÞV9œ± 6ë °NSÚ2·4/“(xÐXL>ݳ~ó·­ÚX|2)vKN’<е#á+Êí7::ílßMÄklf¤Î0<4™” Ñ`u(2[³c|€‰4ˆú´½Èsêçù{@ú„A^Or½Œý.ßÐäêž¹,æÞCAŒŠ2è/ÒhH'iØ:MY4ò"+Å ø!jj¶v„‹Ž,A®ÿ 3úEØÀáŸðp*é¶…QõH3}AŸ¸ÄóW÷Àëù~-ö€_#®ýfcv¡0Ì ‰Ç|Ë\¦!¤°XN:ãùí¢N ¤Ð@ Íûþž3ñs;õ0Ðt!«ìôü†[Êó0ô¼t8¸áü‡@ÂY‚ÜôB4RååLHÈoOI´üY«BÇ2á’5ÁÅ`ŽÁ@ø¤¶—våö¹µf„?µ¸àõÿM%© ^G ëhÁÒˆ»ÂFeE•]ßÍ›„3Á5Ph6B”­w±ÝH@ 2Nè@ÖèS?Ù†y$é´ òüżƒþêÈN¡0²?•m A¨¦›úÞ¦ó‹Z=7¯/3‚Ú?ZéGeA; ´zÊñ^×óªØX/ÔY= 㮲}²) – 瀡œgŸÈE­{©Øz÷ ò{ü“‹qñ~"§˜lÊN&<¦ q+æá¥JîD¤1m\”n€æ#Ôž¶fþñ…6ÇÜDåØàP…ìå#È£ öÒ¡¸ ¢èn”•ÏFþ¶ÔÆâ9¸)v¤¬o±Ë‡YF`Úœ \PEd4@RÄ´«%§Í·x­(¬Ÿ› G<{ ãúÓQß36Oʰ>]:ò’L¤Ï™ŽòLÈí©ˆ’2/uz¯kjN¥˜JS†Œ´†Wã¼¥ê»õåÄ ‹Ò5s“v˜'µ&¢ br6¨o¾ÝÙ·ðèUÜĹŠQÄH‘ÁÝî7•_y9c³ÙP+¤L„x†èŸmR Þ{ö‚ÒKñE_<7D#ĉ}±î2sÊŽ-hóÄ…~ÒNé6ç*RuŽ·r$ªì=ù|áT«"ó¾¥ÝÅ\Â,q¥CtD)„I>©+¡&“Η4ÒçxßÞ$ê£iHù—~;ôq ÉKZГÄà)ƒcDŸ`‰ˆ(lÌõ|†lçmqµWÃÆ«¾Ã¸=‹ù\u$èÝ/.óEÿ:ž5Ú²e(~>ÎÇ þÑU^4ìU’“ F)»±4ßõþp¯°òg(¨Ä>ì‹»ð‹_e×,lG³ü¾Ûý^×hŒ›ãœT *›Z2 Œ$;J¦”ýew­6î`ùËâý!ØzAöÙ ­ˆ‚IîÑZ#×Êë%Œa»¥ãz&ГnISéRªgê)ŸáÚ™Ÿ% ýCe*öÐÉ™•{ÎܱˆŠð*òKŽ$ĶŠbbXWn½k0fÿõûsW)ï½Æ|¥Èþy8¸3çc°‚™Aœòq-Ì]A ƒ´|»[0zKZïÙñŒžõ*Cí6 ä…V`Ok*)h- %Ë^Â0¨pz±ú%rˆq–¹r¾Jš‡Ï¢/æÝ:ŒžväÂß¡Sø[‡ƒïÇâÁݾŽdÈBjnQ'n†¸Ò`¹¨ß’{ÃÔ#éÛ]Õ…Ôwäµ¾q¤dWvy4îµ°‹sб±Çñ™¸áçgÌì…VR;¹¬†gIï ÎeB1üw&ô%SR*ÈèÐÊeÅ΢ÃÐèž¾náf`-–V6°”àÍÚ¬Frš"‰=ÁÇÈÛ¢lW¦·:P1ööM9—Ñ …d¤Ð{"ÛWÕŸµllîÖtà7[I¿*-¸Ô–Õð“¯lDD¸» ͘ Mߨɼi"1Ú?ÔÒB‹i²$3ž¬¢L„Г%ŽÊ°£8ÝÜ­]Ëa_NªÓ<=ÜT6·Ý°È¼é]¤x—Òô¾ÙŒaرè6伜"=,v #Ðöp=Ìè“t¡‚*½›*OuôVÂî=QÜLôµñ?+6úB%c98>áŒf“¬M†*÷v”ÔC¢>5nÌ•ñŠw(X¬ëRI¯…@“ÓM8ÊÑÿúÕË@j¬ XÜ*cŠ–ÄW’¥a="|Ëd|†Ÿ:ˆGy:SG`\ù£ú;„'=¼Vn2[ÒÒ<\º+‡ …ïuú>Upˆè©û@×é䳂ýÐ8d¼ŠåIþtÞKš†õkõ9@Z  |*:éx'ˆ~ìá` ý€ÚÒÿ–=ëÄNX~\Ò»œ,@ nG›9\@F‚óT(_ÃgdFÜAŹ’â=ÊÐrRM¿á~Ulɼրyè˜Nürô÷`›×ârãz5ˆñÈÀ/Ô· l]þ \w¥)–_€¨1qÔ×mjwù]b`Ÿ|üàÓó@ѱ۹o——3´€‰K0b¿áqÝùcjÃíÌ?Bc&Æ W÷£’Í ªOH.½ÒB·¡´4ÒkÛÇà“¥èˆ,Ìßß^‚þAV¥Õì»ÆÐ»Ö8¢á½Ú­¹òß=ð ÕXlç $Ê5Æ67¤1ÌE ÁöÉ/“[̬ïÇ SÍwì›…XGñ $¼'ùkÞù¼2yIÞyÿ6­—™HI[Ôs”å¾Üñ<ÚBÍ­ZL Ð,Ú3¹U-ÜuÌüÊ®å zBµldTgìKõ%›]ǹXÏr î&¨§5HˆÈX£Á™Ã›Ï%FCÖ÷É'c(Ñ:uBîç³×*DÂJœ›ypKn᥹ù¢mh…Äv7bI01öÀí{Wxw umÅ?n‰[ìN2U¬¢;­Évœ·§‘-úÞõ5-)]ôu©Z4ÌI€ÕaG”FþR P€£D_¿ªJÀ\jÔáØ¿ŸÕãìqµß]2…lpÐPÛSÄY¹/\L<0Xαó«æ9ê@£;îCIU 2DêV»rë)üÝmÏŠÆe| ™(BÇÍž=0¥Ê3î Óè¼QbDÜ+ÊS%ºoIý‰§™ÇÅZHv ö”hN‹~ª8ÌÆM®Íô_é­˜Ñ6¡/ÿ!q¨™§R‰^•ìËpm$Ž€žC¯zìËXR]~tô\iuóË?©‚ÚìkÝí¶x¦.Á;FfaÓf»|§Ð´pÏF1eÊÝþ†êæH"ú/îIÃHÔÚ~ EfvÜßhXc˜ƒgêÚø*‚:ÄéQá8‹/I´Ù,k=FbÏæ/Ü¿‘Ž=µ®Ãôäi8ú$¸;W‰VÓ}ð5tÈîzNÈØdƒÌ)®‰UÉ›¨ï••yðï•ÿôîË@uŸaÉîH¦‹z³ñ¸’cý¡$q÷´íª -³g°CjEëC²4©É_­žÒ  ~bY¡…ÿyRÃÏh5CDJA[έðÔÏÁ2G*bD9[^ßU™]‘Në³3PtbÂlâUx·7[rÕaR¹šýÛˆ¤º~Ωº*3®nÆ…§ Rô w:šS”Ù¿íÇÍ)J’l-&;aRD£§ƒ4!/=ôJ `ã$ï.¾]%c Ø“tÄpw[’4ZpfDªÒ)vº¡ßåTªä¢ä,³äŸùÙóéc6¬[Q;Àºh!èÔ$^ˆµ®%’¨¡õÁlû6ê¿°¾µì'DÂÜ]®ñpt´ëéñ,žõxAŒ¥J„ªh0NGÊ ô£ßYäⳟCáTPË€åròÕŠ]†áL6#+L¤ElEßÀ"y àG qI½Oé‹Ùb©a¬'º:oåÕ†H ±0Ž­Çf‹”Ç Ý_AüK¿Ëa‘ÝìÄŽæv'»”$eÖç,aйå1–ALÑYº°wª &µ³­3’ÉFCE*fù¼§Æ§¼¾oº.šÚ.’MuÛ‡vgX\|œ§ .ÿT¢£a—ˆ+ÍÄÿ<¼Æ@¿>Ÿx¬„‚Ù_"Ήhàa_a`ÕÐgÌLvó<ðc« ‹—fÔ¨lžO'S«¨ä¦0X– ˜ÞeÐN%zN-nȱS—iŸ·üsåË.&FÏ'ìÚ';*"7‚³u’H&-ÿe5¯[’G+E»±g3(BlÁþ–×û0ÃT… “×_e>ã¥EΦ×ß§\Üä@³.,±»®wEŸéÙ4•ªÈ`Ò¬g•ß³5Ö®jå^\RÈ9›à¾úJL¬ *«Npã³WB'‘˜ü?“M,ÈøgâO*ÄìÜD¿çäN%ªØ°uìóo]ÐüPúÙtå†DA=´Ô>mÿëõy.ËÊ«¶)'Fìº$¨ê"nÔkú`ɳ;ITKò3ñíÍhü‡Úãz¤×è NµèË †øþ kפè4‹›«¬V¿®4(õÞ‘~È‚TŠ«]…äp˜"ÁŒîOª¯Aª0Y¿t7ïØe˜döÐ 8q@‰¾ÿïë ÉÙ90ß=hwÞl¥csä`×¾­°ý¥cw±nIºztg~×,l‰JyÜKÚ@‚/UJdþ<…¤Ð4ƒB*UµPÞQ››˜úhJ«ÆL ¹Øt<¹Hž¡VO`4žB1ø?$ßmžO rTÏh3M4­6ÝŒôÿä9ââ_Wò<ôþ)éáÍrphhÊ£ã0’ñ’Ñǃ¡'A]Zi$4"ýMþÖ÷‹0*óÖÓí:Îq5¼ðÎsº£OÆtF8n~¨?0)D’ä‚@¸<À•Ìg_>KÓ8=-Çu•Ú”?Œ¸óýä;š›¿“pã|sr´Q¿ß”2(·ee‚M&Ìý=‹Ÿ†ÛR[^â²þ±I@¹gæ €Èò‚Í?;3_Î}ŠþƒNS3.“çöwmÐJÌû: íO×öÏQ¦Ã¹LSWCVFþK=¤EwÿðSL¸“ú4½r:€ÕCسr‚^s¼7Ê 4¡Áˆdœ{r’|ø)ŠYªw¦iC)÷ÓƒZOŸ†™µQsØ{[ƒŽ/Âw‹Ðe©¯jþÐÞà8OãZnøºâƒ¯• Zåx!ì#߸^Ä[K©jå1MþÈ•v„ñNDèˆR(øºêeL%h¹¤ù°« M{¨8…i‰xëz%á‡ï b/ŒqXGD?õ¹7J-XW3XÖñü`£Ñs48 À3`ÓΚAÍÐp´i$''1êÞÒrÌJð4´Äkˆnàð#!ŠŸ»o/n@Æâ¦]ö·x—¾Œ| fE3޹ÆX17Û"ÙKÓµ@rýKƒ8† Ùå†YÂ<{ÓF•òº)ñZQ^Rº–Ã-ŸI…Дš±HÆŽn‘þ“/€óÛ³éEªxÜÙcµðEgˆÎu±ìtlÀ*­ªé‡¸±tËùªCf3E¨£EHZ{œòš"ó%¯è'(—åEþœ¯ó»´~ÙP\F©-]î0x ¸…¦ @[Äsû5›†~ÞS ú(ÔD•,zïP’+Í/"¢¹Åzt?Õ}QqUì¶]òþÿsPÍÞ™®ƒ³åÌ,ábrߌx>ÉæÂ-@ÃßV°k+«ìc¡S–ŸROÄZUÙ«“Å.=`ŠÐßþ\ IIç-)Õ~ , ú2µá[”Jé;~i:±[Æ(T46¾ÆÔ¤=+\åz8<‡ÆóÝѪI=ùé™2€ñ YcYÞm0r2ÞËèX•íÆHíY•l%A7¡“¾À&ªäaNG?•"K <Îde»²q·bKXäCˆç1òZ °Î(~5pâå“‹ ÑFø£Ô÷ÄØÃ+?•Ÿ(óâ씄ÆÖÁœ>Ô•Æñ…ÄÁ`âÞÒ»4†cX‹ž2 PeîS]ZÌL­“d 6 ÈžÄpp³ÕÖ|àf•t”†L¯LÀOvíÎãÑgI„àÅ#¢âGíÝÏus^Iù½ “Œ N²ªH-ó.µ“VæÀ‘?6ì¦S‹üЊa#ºŒ'ÜE%§Î¶éÂÑ+ÎñÍ í£!y5sËLšþH£öD¥J&t®Â|Ò©>Ý\w~ú6ÿfenÔ'é’«}¢íxÜÆxõnVÄGqâ øùf9 á#1¶†áRj?ýq¢kÑ>ØŸ Gâ…çjùÖ ŸÄMîö.í@¥[gÐ=ãÉ7ß{d ù>°â³‘Lwfq1D˜Ôã¡E…çš°¬N̸JRH–%z¿°¿ýZ`ÒzÙdäå_Æ-.½Sæ5· _š¸çJ8ç|}q”äêˆ31Pð·~IÔ£ÏÛ*þYQ0;RV–ž•󾂛Ò4Zépë_mÐ@¢‹”{ÎdøW>" *amëYíÉEpr,tÉä*2|R±!Ñ)¯î¨Y¨)^bdÁËl]Ú÷ÿ?r´ïÛf'<“Ê¥øE >dÙ¶-²´&ì‹yi ŠlžI˜çC·g”[‹¨: þ2 äûgŸr ¶³öŠÞ„8Ñ\Û¶¢"_ë)3ÿ:ÙöaqƒXâBj&é,Ý™=,{v^d‡˜œø±Â%Žy:µ#!-ŠòÕQ‰}àÑ^lŽ‚À¸Óõ¶ˆ#ÅìâΑŸç†áóHIÉLûhÊMÙ”Œrª¤Çf}Ù|8 é:楥²°Ó4Ú'œµÔbÆb Ž^µ\Íã×½FȶÒ;4`^܉!P%„<n@Ìs&ÝõÀ£°Ó.Å‚÷xÄ+‹µ2¾ª+¦–'çîòEtÔm”C/˜d‡•˜juµˆÅDF¯•LÄЙ,î9"I,ÈuüÖgŠ:‹Öù²[L•P°Ôqº'uµ³ùÄŸÓŸáÅ‘xÈêGV•9÷™PÜgç—ôeÕÇËR ¸WG@ÿ]%hN•¼d³u¶ØF£Êöâ&†ÓøÍsR$c­’U0w–£äÁT–_ÜV’²ûNšø»b€˜S±¿+Ë¢l¶ zŽ%'õç¡›tšÒ|Ï:à … ®fy·=ß—;°`ψt?ž¾hDñãTè8o-Ò±Cÿ,A“& •2hjs:Rwz)P7€O:¬sȰ¼IÔ‚F'9;F`¼{ƒìóå sl`ÜŸ¹ 7 ®dxSÉïË4JÄÍí•@ä«ÌçSÑ?¡à  ¯*ÜV4ÙsZJ^¢\%>õ³n× /€¼.t8í H4oD–p1W‡#![Æ#Å—iá»åÞ¶û1šžûXAGĶ_#œs °¿[‹à?ÿ¹Övf…².>ùÊ<¶Ðäë)`0*S6"—Ö•B³ÂÜój°‡{—µ)‚¢Gt2(5Ò’£§ž}¸µ(•íc‡ mJ¿ÆúÞj>WàáX‘I–Ú›2j”'KÒLí´²›ü¬?Ìp^@Ÿ|åˆ©Ú c!nÓ3prz³¦QJ‘y.Çn{ÅY¢0d+ìÿ¯tgGtõŒ‹.ÐóÉó™›¾¹›¡û™=•ZUO…ý*ö-eÄžN”L\bb{gÝÔo¯¹öt•”æ$¤Y#ô¶zÆ<ð!#6,b‹”ÌLŸqb¬Æƒ‰Sw². o.¤¹yà¼k/ãŽnkz#Ñ­ƒ8Uã’Yláú/‘ä]WȾ6ÛˆÓÑ Û'Yxó>É} H%xöš { û'«DC%ÿã¼7[:jœe~NÑ`Î=ò Âšç… jLÿŽEÛÝë¦ß5 BjŒ¥SÊù5%ó··Gˆìý‚¬m‚ƒœ¥nê*Á’¹Â›zÀB¡{>2Š-j¨-:Œ$£…pìÍ_çx”azÖ·6^ÂøïÛr³O+äÏC”V€IyRˆh[ý¹V±áÎùëSþ™€\]ì¬ÆÓÖÑŸ#´3/¼² ~ÙQ'òã…Ev¹Æ6‰¶´‡¨û.ê>þ6ÙWÙžÔD$­èõKaó0Ô_˜ž´MnH ùAÆÁey)…ß© 5•îuìÙË÷ªK|ã8–?òÊx¬Ô¦[Š;< T©D•£GÊ5Ð æp¹¸Ö9€ é.úç ®šhزáÁNý5ö†Jis3“ú>ÆH«zÚŒ[ŽÍÓЩÝ凄èè>‡uë¥a–¿0qr9n"`B0¯öHWÄ:: ³­2â1©¥e•„¢Ó@è’Eˆ† XØÙ9­OJgs=€ÔY«ž˜©[AŒó’¢1ºb°)/k¹µÛù€­uMFEý)P(ˆ˜™·G)bê€÷ÖKÝÃOiLYQ‚äý Ù%Ì ¿vPb­àGKò@ØÔ ¨Æ×b¢|;­hf<$KϹ¨ íì‰ÐKÔðÏ€áéß’÷Ä2C¾¤—==bNâiMçMI}Šhû"µO¸ƒ²Ñ¤>Íâ5ö‰Â0 ‡lî‘tムšJ‚?‰08A4(…°ñÊÄ“H‹¡ú›ü¥O&Ágx µ^’´uÿºÀxæûлüéHb4hÒ*ýó•S„¤¾ ÂŒÅ%'õý”Þ.y'ˆV‚&ÁY¥w“/2Ž\¹¢%nOùH°ô8kß<ŠRÖ“\P)¡Þ}îaZí¢â™j~=(ØãòWŽ¥¢Ÿú5–œÒ€·rdëØJÚ8àø}B {—ð'S´x6e®8ެ]̉͡°l ÇgˆÒvDÈÃ˧oWß ¶a г2:¶~{ŒO-6rïžXÙ²5žà€^ˆ‡œ•‡®#|×y™ÿ­Z$Í¥QÆáÂz<‰WËß=Ä´þL)á-ï¯ç´;vÁ”¦RÀ­n­@у)çŽó²É%ñÅûf)þESè̸Ý‚c<%y#‘.Fë¯Õ嘼›ªþ´¥PøÕ»n躽 ã,.¨n]2ý2q(ÏåL.! [Là:Úø;íÂSë{¦zÁý/6à¶ÈC¥âgCþެ߂‚Ò)ˆ)Om3lÚ‰ñ_Ò .†[“·‚v×VªW]#åY³‘©XõDæöQ!XðæÍZÜ&°§"ì‹^p#¥OˆQ¬)ÝŠÑvï ÷@—@ôâ$ÄFàªë«›š”\€£Ëçº º¯…Ø…"†d ?¤Ìöâ)Ì®›¾ñ˜0¢¨‡Ü‰óÑÏ¡îþú`¢C•ei´O> E+r&”ƒØÝ‹‘‰"úІS<‚[ §LŒ–€|²9¦{wWÓ[©½®cyÝör¡A(möOâïºéª3t„ý©¾Ú©t¤Lm½øå]:æ½°aá `½¶=R½íÿ˜òÚ¹WyVþ~ UQ×ÿA‘â|pò—­/Ùmhw¡\™3¡áùþGu›hÅvêÑý —w3Þ@n[HŒO]&^Œièë/{™kgÌa½q‡âòèÎ|ø“0ÊQÀrÇ7bü%˜ð>ÂX×͇>¬Ñé…®y>öRˆÔ€Ð\Ïä·‹ü¡ÃKtq<&sC÷eS&FÚ*jq @K "#Ôôë3·R…ßZVc§ëCÀþ¯ ^J<(RãÄöŒ$ö¯‚ I6^ Dåc7Û({ç˜èg]—i µšy‚ œå²¤¹l†.©ÜXï2AîøíàœºÕ)È.@ŠÊ‚Îߟy° ÉAEöx<“jìÕéqÖ$5¢U0·þÿ ²Óá dãÏçôõÛ©$"/0]CÊp$’ލS{Àð$u›2[Û‚mˆ‹Ò'ôFGE)ïÚРŒ­—`À[Q)ÃÛʹ=Zt3–Ì-ÂÚ’õ¤ËM2Ìçr´+!ŸqØF¾p'œe%7áÎ]U€9È䡎”·"}$Ná¿B,¹…ër>~ÛÛ™ü÷ÍsÐC!`\ÕEvfb¦-°ñ’)ul“º™Ú÷$Ÿnêà€+ ŸÞý¥»)Bg@þ[󯙢Va¡ž?¾DWª=ít"©ó¡Ø/gBSï ÇbLA­³q§·L°ŠàÆHá’<[ìa˜'¼ôïÔuO¼ÄˆæÂMÚ“ìDA§šÆÌ)ÍKâq€ž_X—¿Ÿx{Ùbd&)ˆÉ¼ºí'ç(Ïæ0Â=ÇC4 ØÒœfî]è¶I=CvèÆ~ÑäÐx4ž0]Ôk²FaꛀÔáˆî =™hZÊèþ’ãZÙ¾–Þíèß“ŠÈÛ•kf¯¤ñþý™Ó*¢\ºœçÌÌK¹#Ý…Uœ }ÅÓ¼zOG›ÖéWþQ¶$:šjœò¾Îæ´i™Ñ*î ÿ“ •ZX“'9¥0¥èâì郕Ù{ÿÊÿø]WCGç!¥]~´bœ1›<Ú3Ú¾ÜHJßV«:- :{Û·$Š>UÀ ÜBiRK«™u¯S‹Õ›6_¥“çÅ®T=›ÕÇ~Ó°åfÚX²D…·­ÞHß&4¦§fdÿų·5ø¨†,£YÚa½jP—ó1$94钲ߌ³À›aÖ²óÿ-·ÓTZFàÙ¾û µ…j³²öb ?ŠoõðúB±ÀCfû-ʰ÷v>«¯ÐãˆÌœxÜ–û ˆ'¯­Kiè'ê™ Lúº×åni rM? oU× å vÏhìÇŽc~˜¢¥Î€†jD^´ð{÷æ»js2•‡Zu3À¡´ÜØxbp‰Ð˜80C¯&EL£gËP‡Qšš"µÒuë¨ßháÚöÙºNgƒ]ðP„ÒëÊ[ Ì 2¤§þ0¥‚ Ùò&ùÁŸÞÄÀãK¤‹˜‡®º‘)Ô7e‹qŠ7âå"êãOGöU(Y ë¾’€ãÁ0Ž)Á—Æuöô“j¢žø0GXùÿÍÏƒÍæºŒžQ»³Ø(b ä½ ¹ˆƒX^Á"þù‹TBs«)Y¶¡«¤}ôMèü6ý§Óâ(À¾02rjüLp•E¿5(fë>þ*Aþ o×ûæi…Ž›È¹”ÇùÄúÈß®~`‡‡mA™çGüö溓L7¨ÜA—›í@ñ*BýŸÞQŸ¼U;?DÏôzŒŠb¡ZÄ,Í¥.)Ý[1}½Y_×=XELr¦À¤ iã³6£“ˆüÒRþK GS°k°›{Ý¢“¿êHzÿ+He厈iƒ. bñON)éãÏ_¼寉i2zVùk?¸¯˜—{BU¿±Š‘[ú?ƒ¯„ .qÿoиf ÜÔ›3I ×9†ÝùûI ¸)&ƒíbvwC°Ôì)‘óØÉóÔ€˜¬Ôq=›;0YZsquashfs-tools-ng-0.8/tests/filename_sane.c000066400000000000000000000025061360235375500210660ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * filename_sane.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include #include static const char *must_work[] = { "foobar", "test.txt", NULL, }; static const char *must_not_work[] = { ".", "..", "/foo", "\\foo", "foo/", "foo\\", "foo/bar", "foo\\bar", NULL, }; static const char *must_not_work_here[] = { #if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) "foo", "fo:o", "fo\"o", "fo|o", "fo?o", "fo*o", "fo\ro", "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "LPT1", "LPT2", "con", "prn", "aux", "nul", "com1", "com2", "lpt1", "lpt2", "AUX.txt", "aux.txt", "NUL.txt", "nul.txt", #endif NULL, }; int main(void) { size_t i; for (i = 0; must_work[i] != NULL; ++i) { assert(is_filename_sane(must_work[i], false)); assert(is_filename_sane(must_work[i], true)); } for (i = 0; must_not_work[i] != NULL; ++i) { assert(!is_filename_sane(must_not_work[i], false)); assert(!is_filename_sane(must_not_work[i], true)); } for (i = 0; must_not_work_here[i] != NULL; ++i) { assert( is_filename_sane(must_not_work_here[i], false)); assert(!is_filename_sane(must_not_work_here[i], true)); } return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/fstree1.txt000066400000000000000000000003531360235375500202440ustar00rootroot00000000000000# comment line slink /slink 0644 2 3 slinktarget dir /dir 0755 4 5 nod /chardev 0600 6 7 c 13 37 nod /blkdev 0600 8 9 b 42 21 pipe /pipe 0644 10 11 dir "/foo bar" 0755 0 0 dir "/foo bar/ test \"/" 0755 0 0 sock /sock 0555 12 13 squashfs-tools-ng-0.8/tests/fstree_from_file.c000066400000000000000000000051361360235375500216140ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_from_file.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tree_node_t *n; fstree_t fs; FILE *fp; fp = open_read(TEST_PATH); assert(fp != NULL); assert(fstree_init(&fs, NULL) == 0); assert(fstree_from_file(&fs, "testfile", fp) == 0); fstree_post_process(&fs); n = fs.root->data.dir.children; assert(fs.root->link_count == 9); assert(n->mode == (S_IFBLK | 0600)); assert(n->uid == 8); assert(n->gid == 9); assert(n->link_count == 1); assert(strcmp(n->name, "blkdev") == 0); assert(n->data.devno == makedev(42, 21)); n = n->next; assert(n->mode == (S_IFCHR | 0600)); assert(n->uid == 6); assert(n->gid == 7); assert(n->link_count == 1); assert(strcmp(n->name, "chardev") == 0); assert(n->data.devno == makedev(13, 37)); n = n->next; assert(n->mode == (S_IFDIR | 0755)); assert(n->uid == 4); assert(n->gid == 5); assert(n->link_count == 2); assert(strcmp(n->name, "dir") == 0); assert(n->data.dir.children == NULL); n = n->next; assert(n->mode == (S_IFDIR | 0755)); assert(n->uid == 0); assert(n->gid == 0); assert(n->link_count == 3); assert(strcmp(n->name, "foo bar") == 0); assert(n->data.dir.children != NULL); assert(n->data.dir.children->next == NULL); assert(n->data.dir.children->mode == (S_IFDIR | 0755)); assert(n->data.dir.children->uid == 0); assert(n->data.dir.children->gid == 0); assert(n->data.dir.children->link_count == 2); assert(strcmp(n->data.dir.children->name, " test \"") == 0); assert(n->data.dir.children->data.dir.children == NULL); n = n->next; assert(n->mode == (S_IFIFO | 0644)); assert(n->uid == 10); assert(n->gid == 11); assert(n->link_count == 1); assert(strcmp(n->name, "pipe") == 0); n = n->next; assert(n->mode == (S_IFLNK | 0777)); assert(n->uid == 2); assert(n->gid == 3); assert(n->link_count == 1); assert(strcmp(n->name, "slink") == 0); fprintf(stderr, "'%s'\n", n->data.target); assert(strcmp(n->data.target, "slinktarget") == 0); n = n->next; assert(n->mode == (S_IFSOCK | 0555)); assert(n->uid == 12); assert(n->gid == 13); assert(n->link_count == 1); assert(strcmp(n->name, "sock") == 0); assert(n->next == NULL); fclose(fp); fstree_cleanup(&fs); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/fstree_fuzz.c000066400000000000000000000012571360235375500206500ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_fuzz.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include int main(int argc, char **argv) { int ret = EXIT_FAILURE; fstree_t fs; FILE *fp; if (argc != 2) { fputs("Usage: fstree_fuzz \n", stderr); return EXIT_FAILURE; } fp = fopen(argv[1], "r"); if (fp == NULL) { perror(argv[1]); return EXIT_FAILURE; } if (fstree_init(&fs, NULL)) goto out_fp; if (fstree_from_file(&fs, argv[1], fp)) goto out_fs; ret = EXIT_SUCCESS; out_fs: fstree_cleanup(&fs); out_fp: fclose(fp); return ret; } squashfs-tools-ng-0.8/tests/fstree_init.c000066400000000000000000000022131360235375500206060ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_init.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include "internal.h" #include #include #include #include int main(void) { fstree_t fs; char *str; str = strdup("mtime=1337,uid=1000,gid=100,mode=0321"); assert(str != NULL); assert(fstree_init(&fs, str) == 0); free(str); assert(fs.defaults.st_mtime == 1337); assert(fs.defaults.st_uid == 1000); assert(fs.defaults.st_gid == 100); assert(fs.defaults.st_mode == (S_IFDIR | 0321)); fstree_cleanup(&fs); assert(fstree_init(&fs, NULL) == 0); assert(fs.defaults.st_mtime == 0 || fs.defaults.st_mtime == get_source_date_epoch()); assert(fs.defaults.st_uid == 0); assert(fs.defaults.st_gid == 0); assert(fs.defaults.st_mode == (S_IFDIR | 0755)); fstree_cleanup(&fs); str = strdup("mode=07777"); assert(str != NULL); assert(fstree_init(&fs, str) == 0); free(str); fstree_cleanup(&fs); str = strdup("mode=017777"); assert(str != NULL); assert(fstree_init(&fs, str) != 0); free(str); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/fstree_sort.c000066400000000000000000000041711360235375500206370ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fstree_sort.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include "internal.h" #include #include #include int main(void) { tree_node_t *a, *b, *c, *d; struct stat sb; fstree_t fs; memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFBLK | 0600; sb.st_rdev = 1337; a = fstree_mknode(NULL, "a", 1, NULL, &sb); b = fstree_mknode(NULL, "b", 1, NULL, &sb); c = fstree_mknode(NULL, "c", 1, NULL, &sb); d = fstree_mknode(NULL, "d", 1, NULL, &sb); assert(a != NULL && b != NULL && c != NULL && d != NULL); /* empty list */ assert(tree_node_list_sort(NULL) == NULL); /* single element */ assert(tree_node_list_sort(a) == a); assert(a->next == NULL); /* two elements, reverse order */ b->next = a; assert(tree_node_list_sort(b) == a); assert(a->next == b); assert(b->next == NULL); /* two elements, sorted order */ assert(tree_node_list_sort(a) == a); assert(a->next == b); assert(b->next == NULL); /* three elements, reverse order */ c->next = b; b->next = a; a->next = NULL; assert(tree_node_list_sort(c) == a); assert(a->next == b); assert(b->next == c); assert(c->next == NULL); /* three elements, ordered */ assert(tree_node_list_sort(a) == a); assert(a->next == b); assert(b->next == c); assert(c->next == NULL); /* four elements, reverse order */ d->next = c; c->next = b; b->next = a; a->next = NULL; assert(tree_node_list_sort(d) == a); assert(a->next == b); assert(b->next == c); assert(c->next == d); assert(d->next == NULL); /* four elements, sorted order */ assert(tree_node_list_sort(a) == a); assert(a->next == b); assert(b->next == c); assert(c->next == d); assert(d->next == NULL); /* force merge sort to go through LRLR pattern */ b->next = a; a->next = d; d->next = c; c->next = NULL; assert(tree_node_list_sort(b) == a); assert(a->next == b); assert(b->next == c); assert(c->next == d); assert(d->next == NULL); /* cleanup and done */ free(a); free(b); free(c); free(d); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/gen_inode_numbers.c000066400000000000000000000040141360235375500217560ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * gen_inode_table.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include static tree_node_t *gen_node(tree_node_t *parent, const char *name) { struct stat sb; memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0755; return fstree_mknode(parent, name, strlen(name), NULL, &sb); } static void check_children_before_root(tree_node_t *root) { tree_node_t *n; for (n = root->data.dir.children; n != NULL; n = n->next) assert(n->inode_num < root->inode_num); for (n = root->data.dir.children; n != NULL; n = n->next) check_children_before_root(n); } static void check_children_continuous(tree_node_t *root) { tree_node_t *n; for (n = root->data.dir.children; n != NULL; n = n->next) { if (n->next != NULL) { assert(n->next->inode_num == (n->inode_num + 1)); } } for (n = root->data.dir.children; n != NULL; n = n->next) check_children_continuous(n); } int main(void) { tree_node_t *a, *b, *c; fstree_t fs; // inode table for the empty tree assert(fstree_init(&fs, NULL) == 0); fstree_post_process(&fs); assert(fs.unique_inode_count == 1); assert(fs.root->inode_num == 1); fstree_cleanup(&fs); // tree with 2 levels under root, fan out 3 assert(fstree_init(&fs, NULL) == 0); a = gen_node(fs.root, "a"); b = gen_node(fs.root, "b"); c = gen_node(fs.root, "c"); assert(a != NULL); assert(b != NULL); assert(c != NULL); assert(gen_node(a, "a_a") != NULL); assert(gen_node(a, "a_b") != NULL); assert(gen_node(a, "a_c") != NULL); assert(gen_node(b, "b_a") != NULL); assert(gen_node(b, "b_b") != NULL); assert(gen_node(b, "b_c") != NULL); assert(gen_node(c, "c_a") != NULL); assert(gen_node(c, "c_b") != NULL); assert(gen_node(c, "c_c") != NULL); fstree_post_process(&fs); assert(fs.unique_inode_count == 13); check_children_before_root(fs.root); check_children_continuous(fs.root); fstree_cleanup(&fs); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/get_path.c000066400000000000000000000023311360235375500200670ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * get_path.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include int main(void) { tree_node_t *a, *b, *c, *d; struct stat sb; fstree_t fs; char *str; assert(fstree_init(&fs, NULL) == 0); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0750; sb.st_uid = 1000; sb.st_gid = 100; a = fstree_add_generic(&fs, "foo", &sb, NULL); b = fstree_add_generic(&fs, "foo/bar", &sb, NULL); c = fstree_add_generic(&fs, "foo/bar/baz", &sb, NULL); d = fstree_add_generic(&fs, "foo/bar/baz/dir", &sb, NULL); str = fstree_get_path(fs.root); assert(str != NULL); assert(strcmp(str, "/") == 0); free(str); str = fstree_get_path(a); assert(str != NULL); assert(strcmp(str, "/foo") == 0); free(str); str = fstree_get_path(b); assert(str != NULL); assert(strcmp(str, "/foo/bar") == 0); free(str); str = fstree_get_path(c); assert(str != NULL); assert(strcmp(str, "/foo/bar/baz") == 0); free(str); str = fstree_get_path(d); assert(str != NULL); assert(strcmp(str, "/foo/bar/baz/dir") == 0); free(str); fstree_cleanup(&fs); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/mknode_dir.c000066400000000000000000000030211360235375500204040ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mknode_dir.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include int main(void) { tree_node_t *root, *a, *b; struct stat sb; fstree_t fs; memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFDIR | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 4096; root = fstree_mknode(NULL, "rootdir", 7, NULL, &sb); assert(root->uid == sb.st_uid); assert(root->gid == sb.st_gid); assert(root->mode == sb.st_mode); assert(root->link_count == 2); assert((char *)root->name >= (char *)root->payload); assert(root->name >= (char *)root->payload); assert(strcmp(root->name, "rootdir") == 0); assert(root->data.dir.children == NULL); assert(root->parent == NULL); assert(root->next == NULL); a = fstree_mknode(root, "adir", 4, NULL, &sb); assert(a->parent == root); assert(a->next == NULL); assert(a->link_count == 2); assert(root->link_count == 3); assert(root->data.dir.children == a); assert(root->parent == NULL); assert(root->next == NULL); b = fstree_mknode(root, "bdir", 4, NULL, &sb); assert(a->parent == root); assert(b->parent == root); assert(b->link_count == 2); assert(root->data.dir.children == b); assert(root->link_count == 4); assert(b->next == a); assert(a->next == NULL); assert(root->parent == NULL); assert(root->next == NULL); free(root); free(a); free(b); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/mknode_reg.c000066400000000000000000000017641360235375500204170ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mknode_reg.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include int main(void) { tree_node_t *node; struct stat sb; fstree_t fs; memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFREG | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 4096; node = fstree_mknode(NULL, "filename", 8, "input", &sb); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == sb.st_mode); assert(node->parent == NULL); assert(node->link_count == 1); assert((char *)node->name >= (char *)node->payload); assert(node->data.file.input_file >= (char *)node->payload); assert(node->data.file.input_file >= node->name + 8); assert(strcmp(node->name, "filename") == 0); assert(strcmp(node->data.file.input_file, "input") == 0); free(node); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/mknode_simple.c000066400000000000000000000047431360235375500211330ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mknode_simple.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include int main(void) { tree_node_t *node; struct stat sb; fstree_t fs; memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFSOCK | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 1337; node = fstree_mknode(NULL, "sockfile", 8, NULL, &sb); assert((char *)node->name >= (char *)node->payload); assert(strcmp(node->name, "sockfile") == 0); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == sb.st_mode); assert(node->link_count == 1); assert(node->parent == NULL); assert(node->data.target == NULL); assert(node->data.devno == 0); free(node); memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFIFO | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 1337; node = fstree_mknode(NULL, "fifo", 4, NULL, &sb); assert((char *)node->name >= (char *)node->payload); assert(strcmp(node->name, "fifo") == 0); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == sb.st_mode); assert(node->link_count == 1); assert(node->parent == NULL); assert(node->data.target == NULL); assert(node->data.devno == 0); free(node); memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFBLK | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 1337; node = fstree_mknode(NULL, "blkdev", 6, NULL, &sb); assert((char *)node->name >= (char *)node->payload); assert(strcmp(node->name, "blkdev") == 0); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == sb.st_mode); assert(node->link_count == 1); assert(node->data.devno == sb.st_rdev); assert(node->parent == NULL); free(node); memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFCHR | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 1337; node = fstree_mknode(NULL, "chardev", 7, NULL, &sb); assert((char *)node->name >= (char *)node->payload); assert(strcmp(node->name, "chardev") == 0); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == sb.st_mode); assert(node->link_count == 1); assert(node->data.devno == sb.st_rdev); assert(node->parent == NULL); free(node); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/mknode_slink.c000066400000000000000000000026711360235375500207600ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * mknode_slink.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "fstree.h" #include #include #include int main(void) { tree_node_t *node; struct stat sb; fstree_t fs; memset(&fs, 0, sizeof(fs)); memset(&sb, 0, sizeof(sb)); sb.st_mode = S_IFLNK | 0654; sb.st_uid = 123; sb.st_gid = 456; sb.st_rdev = 789; sb.st_size = 1337; node = fstree_mknode(NULL, "symlink", 7, "target", &sb); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == (S_IFLNK | 0777)); assert(node->link_count == 1); assert(node->parent == NULL); assert((char *)node->name >= (char *)node->payload); assert(node->data.target >= (char *)node->payload); assert(node->data.target >= node->name + 8); assert(strcmp(node->name, "symlink") == 0); assert(strcmp(node->data.target, "target") == 0); free(node); node = fstree_mknode(NULL, "symlink", 7, "", &sb); assert(node->uid == sb.st_uid); assert(node->gid == sb.st_gid); assert(node->mode == (S_IFLNK | 0777)); assert(node->link_count == 1); assert(node->parent == NULL); assert((char *)node->name >= (char *)node->payload); assert(node->data.target >= (char *)node->payload); assert(node->data.target >= node->name + 8); assert(strcmp(node->name, "symlink") == 0); assert(node->data.target[0] == '\0'); free(node); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/str_table.c000066400000000000000000000034021360235375500202530ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * str_table.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include #include #include #include #include "str_table.h" #include "compat.h" #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static char *strings[1000]; static int read_strings(void) { ssize_t ret; char *line; size_t n; FILE *fp; int i; fp = fopen("words.txt", "r"); if (fp == NULL) { perror("words.txt"); return -1; } for (i = 0; i < 1000; ++i) { line = NULL; n = 0; ret = getline(&line, &n, fp); if (ret < 0) { perror("reading words"); goto fail; } strings[i] = line; } fclose(fp); return 0; fail: for (i = 0; i < 1000; ++i) free(strings[i]); fclose(fp); return -1; } int main(void) { str_table_t table; size_t i, j, idx; const char *str; assert(chdir(TEST_PATH) == 0); if (read_strings()) return EXIT_FAILURE; assert(str_table_init(&table, 64) == 0); for (i = 0; i < 1000; ++i) { assert(str_table_get_index(&table, strings[i], &idx) == 0); assert(idx == i); for (j = 0; j <= i; ++j) { str = str_table_get_string(&table, j); assert(str != NULL); assert(str != strings[i]); assert(strcmp(str, strings[j]) == 0); } for (; j < 1000; ++j) { str = str_table_get_string(&table, j); assert(str == NULL); } } for (i = 0; i < 1000; ++i) { assert(str_table_get_index(&table, strings[i], &idx) == 0); assert(idx == i); str = str_table_get_string(&table, i); assert(str != NULL); assert(str != strings[i]); assert(strcmp(str, strings[i]) == 0); } str_table_cleanup(&table); for (i = 0; i < 1000; ++i) free(strings[i]); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar/000077500000000000000000000000001360235375500167175ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/CREDITS000066400000000000000000000017251360235375500177440ustar00rootroot00000000000000The tar archives in this directory have been obtained from here: https://github.com/mgorny/tar-test-inputs git commit hash a2110a6 This repository was linked in the following article on interoperability of various different tar programs: https://dev.gentoo.org/~mgorny/articles/portability-of-tar-features.html The original intention of the example archives was to test various tar programs for interoperability with each others extensions and format quirks. The following have been removed since there is no intention in adding support for those features: - volume-label tests - multi-volume tests - longe user + group names - sun tar samples - star samples In addition to that, the files in "file-size" are truncated, since we are only interested in parsing the header. The following addtional files have been added: - xattr/xattr-shily-binary.tar Created from xattr/xattr-shily.tar by manually patching in a capability xattr key/value pair. squashfs-tools-ng-0.8/tests/tar/file-size/000077500000000000000000000000001360235375500206065ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/file-size/12-digit.tar000066400000000000000000000040001360235375500226300ustar00rootroot00000000000000big-file.bin000644 001750 001750 10000000000013375730126 014134 0ustar00mgornymgorny000000 000000 squashfs-tools-ng-0.8/tests/tar/file-size/gnu.tar000066400000000000000000000040001360235375500221010ustar00rootroot00000000000000big-file.bin000064400017500001750€13375730126012015 0ustar mgornymgornysquashfs-tools-ng-0.8/tests/tar/file-size/pax.tar000066400000000000000000000040001360235375500221000ustar00rootroot00000000000000./PaxHeaders.7839/big-file.bin0000644000000000000000000000015513375730126013066 xustar0019 size=8589934592 30 mtime=1542959190.916897254 30 atime=1542959522.512018391 30 ctime=1542959190.916897254 big-file.bin0000644000175000017500000000000013375730126014133 0ustar00mgornymgorny00000000000000squashfs-tools-ng-0.8/tests/tar/format-acceptance/000077500000000000000000000000001360235375500222735ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/format-acceptance/gnu-g.tar000066400000000000000000000040001360235375500240120ustar00rootroot00000000000000input.txt0000644000175000017500000000000513375560044014561 0ustar mgornymgorny1337556176213375561750test squashfs-tools-ng-0.8/tests/tar/format-acceptance/gnu.tar000066400000000000000000000040001360235375500235660ustar00rootroot00000000000000input.txt0000644000175000017500000000000513375560044012370 0ustar mgornymgornytest squashfs-tools-ng-0.8/tests/tar/format-acceptance/pax.tar000066400000000000000000000060001360235375500235670ustar00rootroot00000000000000PaxHeader/input.txt000644 001750 001750 00000000162 13375560044 015625 xustar00mgornymgorny000000 000000 30 ctime=1542905892.629967955 30 atime=1542905911.020942023 30 mtime=1542905892.629967955 24 SCHILY.fflags=extent input.txt000644 001750 001750 00000000005 13375560044 013650 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/format-acceptance/ustar-pre-posix.tar000066400000000000000000000040001360235375500260570ustar00rootroot00000000000000input.txt000644 001750 001750 00000000005 13375560044 013610 0ustar mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/format-acceptance/ustar.tar000066400000000000000000000040001360235375500241330ustar00rootroot00000000000000input.txt000644 001750 001750 00000000005 13375560044 013650 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/format-acceptance/v7.tar000066400000000000000000000040001360235375500233310ustar00rootroot00000000000000input.txt000644 001750 001750 00000000005 13375560044 006461 test squashfs-tools-ng-0.8/tests/tar/large-mtime/000077500000000000000000000000001360235375500211225ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/large-mtime/12-digit.tar000066400000000000000000000040001360235375500231440ustar00rootroot00000000000000input.txt000644 001750 001750 00000000005 100000000000013623 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/large-mtime/gnu.tar000066400000000000000000000040001360235375500224150ustar00rootroot00000000000000input.txt00006440001750000175000000000005€011504 0ustar mgornymgornytest squashfs-tools-ng-0.8/tests/tar/large-mtime/pax.tar000066400000000000000000000060001360235375500224160ustar00rootroot00000000000000./PaxHeaders.11530/input.txt0000644000000000000000000000012077777777777012714 xustar0020 mtime=8589934592 30 atime=1543015522.291866334 30 ctime=1543015033.979919105 input.txt0000644000175000017500000000000500000000000013622 0ustar00mgornymgorny00000000000000test squashfs-tools-ng-0.8/tests/tar/long-paths/000077500000000000000000000000001360235375500207735ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/long-paths/gnu.tar000066400000000000000000000060001360235375500222700ustar00rootroot00000000000000././@LongLink0000000000000000000000000000024500000000000011707 Lustar rootwheel012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/input.txt012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/01234560000644000175000017500000000000513375567346022655 0ustar mgornymgornytest squashfs-tools-ng-0.8/tests/tar/long-paths/pax.tar000066400000000000000000000060001360235375500222670ustar00rootroot00000000000000012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/01234560000644000000000000000000000041013375567346020303 xustar00174 path=012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/input.txt 30 mtime=1542909670.281837797 30 atime=1542909708.308731672 30 ctime=1542909670.281837797 012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789/01234560000644000175000017500000000000513375567346024155 0ustar00mgornymgorny00000000000000test squashfs-tools-ng-0.8/tests/tar/long-paths/ustar.tar000066400000000000000000000040001360235375500226330ustar00rootroot00000000000000012345678901234567890123456789/012345678901234567890123456789/input.txt000644 001750 001750 00000000005 13375567346 033463 0ustar00mgornymgorny000000 000000 012345678901234567890123456789/012345678901234567890123456789/012345678901234567890123456789test squashfs-tools-ng-0.8/tests/tar/negative-mtime/000077500000000000000000000000001360235375500216325ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/negative-mtime/gnu.tar000066400000000000000000000240001360235375500231270ustar00rootroot00000000000000input.txt00006440001750000175000000000005ÿÿÿÿÿÿÿÿí/úp016500 0ustar mgornymgornytest squashfs-tools-ng-0.8/tests/tar/negative-mtime/pax.tar000066400000000000000000000240001360235375500231260ustar00rootroot00000000000000./PaxHeaders.12320/input.txt0000644000000000000000000000010600000000000012601 xustar0020 mtime=-315622800 20 atime=-315622800 30 ctime=1543015908.675050405 input.txt0000644000175000017500000000000500000000000013622 0ustar00mgornymgorny00000000000000test squashfs-tools-ng-0.8/tests/tar/sparse-files/000077500000000000000000000000001360235375500213145ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/sparse-files/gnu-small.tar000066400000000000000000000230001360235375500237160ustar00rootroot00000000000000input.bin0000644000175000017500000002000013376224003021541 Sustar mgornymgorny00000000000000000100000000100000000000010000000020000000000000000000002000000test test squashfs-tools-ng-0.8/tests/tar/sparse-files/gnu.tar000066400000000000000000001040001360235375500226100ustar00rootroot00000000000000input.bin0000644000175000017500000010000013376223472023616 Sustar mgornymgorny00000000000000000100000000100000000000010000000020000000000001000000003000000000000100000001000000000004000000000000100000000500000000000010000000060000000000001000000007000000000000100000001000000000000000000test test test test test test test test squashfs-tools-ng-0.8/tests/tar/sparse-files/pax-gnu0-0.tar000066400000000000000000001060001360235375500236150ustar00rootroot00000000000000./PaxHeaders.21740/input.bin0000644000000000000000000000120413376223472012610 xustar0027 GNU.sparse.size=2097152 26 GNU.sparse.numblocks=9 23 GNU.sparse.offset=0 28 GNU.sparse.numbytes=4096 28 GNU.sparse.offset=262144 28 GNU.sparse.numbytes=4096 28 GNU.sparse.offset=524288 28 GNU.sparse.numbytes=4096 28 GNU.sparse.offset=786432 28 GNU.sparse.numbytes=4096 29 GNU.sparse.offset=1048576 28 GNU.sparse.numbytes=4096 29 GNU.sparse.offset=1310720 28 GNU.sparse.numbytes=4096 29 GNU.sparse.offset=1572864 28 GNU.sparse.numbytes=4096 29 GNU.sparse.offset=1835008 28 GNU.sparse.numbytes=4096 29 GNU.sparse.offset=2097152 25 GNU.sparse.numbytes=0 30 mtime=1543055162.245810774 30 atime=1543055172.420245075 30 ctime=1543055162.245810774 input.bin0000644000175000017500000010000013376223472013617 0ustar00mgornymgorny00000000000000test test test test test test test test squashfs-tools-ng-0.8/tests/tar/sparse-files/pax-gnu0-1.tar000066400000000000000000001050001360235375500236150ustar00rootroot00000000000000./PaxHeaders.21748/input.bin0000644000000000000000000000045013376223472012622 xustar0027 GNU.sparse.size=2097152 26 GNU.sparse.numblocks=9 29 GNU.sparse.name=input.bin 124 GNU.sparse.map=0,4096,262144,4096,524288,4096,786432,4096,1048576,4096,1310720,4096,1572864,4096,1835008,4096,2097152,0 30 mtime=1543055162.245810774 30 atime=1543055172.420245075 30 ctime=1543055162.245810774 ./GNUSparseFile.21748/input.bin0000644000175000017500000010000013376223472017047 0ustar00mgornymgorny00000000000000test test test test test test test test squashfs-tools-ng-0.8/tests/tar/sparse-files/pax-gnu1-0.tar000066400000000000000000001060001360235375500236160ustar00rootroot00000000000000./PaxHeaders.21754/input.bin0000644000000000000000000000030213376223472012613 xustar0022 GNU.sparse.major=1 22 GNU.sparse.minor=0 29 GNU.sparse.name=input.bin 31 GNU.sparse.realsize=2097152 30 mtime=1543055162.245810774 30 atime=1543055172.420245075 30 ctime=1543055162.245810774 ./GNUSparseFile.21754/input.bin0000644000175000017500000010100013376223472017045 0ustar00mgornymgorny000000000000009 0 4096 262144 4096 524288 4096 786432 4096 1048576 4096 1310720 4096 1572864 4096 1835008 4096 2097152 0 test test test test test test test test squashfs-tools-ng-0.8/tests/tar/sqfs.sha512000066400000000000000000000110571360235375500206240ustar00rootroot00000000000000bbccea0583c1085d3c9ab2e415c52a33c7cf02413ddb964b31021380144865aef3bb611896f0577a2e6a00c7cea0539120e4cfca572c24de0bb325fca81648bd tests/tar/user-group-largenum/gnu.sqfs bbccea0583c1085d3c9ab2e415c52a33c7cf02413ddb964b31021380144865aef3bb611896f0577a2e6a00c7cea0539120e4cfca572c24de0bb325fca81648bd tests/tar/user-group-largenum/pax.sqfs 60d72f8fe23acdea7c9328c198d7a28da7f5985f1c1f523c1aad947358d57c789a559c26424b79890839aad5480065fcf68ca0a237e894869e8b995c2926d26a tests/tar/user-group-largenum/8-digit.sqfs e707c3059f678f04d911e706d35c111e7c3d5f7bdfdf49b9893cf952c6f8414a5e4a0fd49ea8d57b7f9c9518bd9be60d8ef3366e2a8efc70d378ac9b637c1c22 tests/tar/negative-mtime/gnu.sqfs e707c3059f678f04d911e706d35c111e7c3d5f7bdfdf49b9893cf952c6f8414a5e4a0fd49ea8d57b7f9c9518bd9be60d8ef3366e2a8efc70d378ac9b637c1c22 tests/tar/negative-mtime/pax.sqfs bff8a33471bd1eff37236f5e9f4260854ea9227544c4d4ff5723dee09b87b12da38bc7b76b45fc7653a3b40f3b557a280feb2996a9dde26ac36484625d5a90b1 tests/tar/large-mtime/gnu.sqfs bff8a33471bd1eff37236f5e9f4260854ea9227544c4d4ff5723dee09b87b12da38bc7b76b45fc7653a3b40f3b557a280feb2996a9dde26ac36484625d5a90b1 tests/tar/large-mtime/pax.sqfs bff8a33471bd1eff37236f5e9f4260854ea9227544c4d4ff5723dee09b87b12da38bc7b76b45fc7653a3b40f3b557a280feb2996a9dde26ac36484625d5a90b1 tests/tar/large-mtime/12-digit.sqfs dd97f85260511b3f10570b427b941e790d999a92cf74cc2a314fd8632860e87ff7089717ea149de56d51a22080245f79cb1752fb96f695d1baadd20d3c33070d tests/tar/xattr/xattr-schily-binary.sqfs ed643a9e1ab27ecec909c7dba1c6d3a4be3f3ef7fb5eb76ecee5ea8d5458b51aea3357ab939985c7ca8da23c9cab68e2ee07628ba30baf1fca74599bc97c088f tests/tar/xattr/xattr-schily.sqfs 6bcefa03a9aff2e7b269fd9b0517f5ba2f0fdc1688391d76c4d52ea41d8efb4ba73e8e46dca90d07e32ea0d687cbe2fa3c0fac7950d5f6555f65db93f423c623 tests/tar/xattr/acl.sqfs 2ec7efd2670ce095219f4362d8c5e856e04724a9b129168792c5a19110643dd396bbb0ff2f0bb4663d63b859ebe85313f3ac8314f7a2cb7a353621b3ed5b3003 tests/tar/xattr/fflags-schily.sqfs 2ec7efd2670ce095219f4362d8c5e856e04724a9b129168792c5a19110643dd396bbb0ff2f0bb4663d63b859ebe85313f3ac8314f7a2cb7a353621b3ed5b3003 tests/tar/xattr/fflags-libarchive.sqfs ed643a9e1ab27ecec909c7dba1c6d3a4be3f3ef7fb5eb76ecee5ea8d5458b51aea3357ab939985c7ca8da23c9cab68e2ee07628ba30baf1fca74599bc97c088f tests/tar/xattr/xattr-libarchive.sqfs 4acd111192eb00c251b4c336872f36e58da64622385c3da438572f97185dfda17d66be5af53a335b00fdb2d40aada61d9f44e5c01285b7f3e46c13222fe27a5d tests/tar/sparse-files/gnu.sqfs 4acd111192eb00c251b4c336872f36e58da64622385c3da438572f97185dfda17d66be5af53a335b00fdb2d40aada61d9f44e5c01285b7f3e46c13222fe27a5d tests/tar/sparse-files/pax-gnu0-1.sqfs 4acd111192eb00c251b4c336872f36e58da64622385c3da438572f97185dfda17d66be5af53a335b00fdb2d40aada61d9f44e5c01285b7f3e46c13222fe27a5d tests/tar/sparse-files/pax-gnu0-0.sqfs f841b2bc9ef6a950dadff8dcd36c8d8fc4beb99605bb85e733c477cfa301de31be48b9dd9e974619a08577aaae002fdb02944f30296381702dca3748a21bbc62 tests/tar/sparse-files/pax-gnu1-0.sqfs a314f577dd10b3f84cea322d52e53ae3c9cf696f3a6dc47be845e57f05776e58c3ba852ff3fe53eea1e94a785b35415f8b70866ff5c1237e26dce8a4ab6a8e05 tests/tar/sparse-files/gnu-small.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/gnu.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/ustar.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/pax.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/gnu-g.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/ustar-pre-posix.sqfs 4cf4ad348a141728669b414cb0e0111f6d533caf8f144bba7558ff952c392ac51fc5247658c2224a3f523a5504eec05d6a7462dedcfdb53d1b08bacfac4d6999 tests/tar/format-acceptance/v7.sqfs e34bc4d700a232e20aa5cf69dae04dc765b3b477b5dedd7d814822f0f353a75ec6749625c7ba5aaf80cf62f08f08bf3951c6f655392e739fae39a173588d6bcf tests/tar/long-paths/gnu.sqfs e34bc4d700a232e20aa5cf69dae04dc765b3b477b5dedd7d814822f0f353a75ec6749625c7ba5aaf80cf62f08f08bf3951c6f655392e739fae39a173588d6bcf tests/tar/long-paths/ustar.sqfs e34bc4d700a232e20aa5cf69dae04dc765b3b477b5dedd7d814822f0f353a75ec6749625c7ba5aaf80cf62f08f08bf3951c6f655392e739fae39a173588d6bcf tests/tar/long-paths/pax.sqfs squashfs-tools-ng-0.8/tests/tar/user-group-largenum/000077500000000000000000000000001360235375500226375ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/user-group-largenum/8-digit.tar000066400000000000000000000040001360235375500246060ustar00rootroot00000000000000input.txt000644 400000004000000000000000005 13376036700 011334 0ustar00000000 000000 test squashfs-tools-ng-0.8/tests/tar/user-group-largenum/gnu.tar000066400000000000000000000040001360235375500241320ustar00rootroot00000000000000input.txt0000644€€€€0000000000513376036700007404 0ustar test squashfs-tools-ng-0.8/tests/tar/user-group-largenum/pax.tar000066400000000000000000000060001360235375500241330ustar00rootroot00000000000000./PaxHeaders.25012/input.txt0000644000000000000000000000014013376036700012645 xustar0018 uid=2147483648 18 gid=2147483648 30 atime=1542999264.054938739 30 ctime=1542999260.518139451 input.txt0000644000000000000000000000000513376036700011144 0ustar0000000000000000test squashfs-tools-ng-0.8/tests/tar/xattr/000077500000000000000000000000001360235375500200615ustar00rootroot00000000000000squashfs-tools-ng-0.8/tests/tar/xattr/acl.tar000066400000000000000000000060001360235375500213240ustar00rootroot00000000000000PaxHeader/input.txt000600 001750 001750 00000000337 13376310551 015616 xustar00mgornymgorny000000 000000 30 ctime=1543082993.344948841 29 atime=1543083015.18807739 30 mtime=1543082345.191275018 24 SCHILY.fflags=extent 110 SCHILY.acl.access=user::rw-,group::---,other::---,user:nobody:rw-:65534,group:nogroup:rw-:65533,mask::r-- input.txt000600 001750 001750 00000000005 13376310551 013635 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/xattr/fflags-libarchive.tar000066400000000000000000000060001360235375500241350ustar00rootroot00000000000000PaxHeader/input.txt000644 001750 001750 00000000302 13376330416 015620 xustar00mgornymgorny000000 000000 30 ctime=1543090644.884841667 30 atime=1543090446.880616513 30 mtime=1543090446.880616513 104 SCHILY.fflags=sappnd,schg,nodump,uunlink,compress,noatime,journal,securedeletion,sync,notail,extent input.txt000644 001750 001750 00000000005 13376330416 013647 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/xattr/fflags-schily.tar000066400000000000000000000110001360235375500233140ustar00rootroot00000000000000././@PaxHeader0000600 0000000 0000000 00000000270 00000000000 0015751 gustar00rootroot0000000 0000000 00000000000 00000000000 56 SCHILY.release=star 1.5.3 (x86_64-unknown-linux-gnu) 27 SCHILY.archtype=exustar 47 SCHILY.volhdr.dumpdate=1543095975.083524831 25 SCHILY.volhdr.volno=1 29 SCHILY.volhdr.blocksize=3 ././@PaxHeader0000600 0000000 0000000 00000000256 00000000000 0015776 xustar00rootroot0000000 0000000 00000000000 00000000000 30 atime=1543090446.880616513 30 ctime=1543095910.191669426 30 mtime=1543090446.880616513 84 SCHILY.fflags=sappnd,schg,journal-data,compress,noatime,nodump,secdel,sync,undel input.txt0000644 0001750 0001750 00000000005 13376330416 0016505 0ustar00mgornymgorny0000000 0000000 13376330416 13376343146 test squashfs-tools-ng-0.8/tests/tar/xattr/xattr-libarchive.tar000066400000000000000000000060001360235375500240350ustar00rootroot00000000000000PaxHeader/input.txt000644 001750 001750 00000000243 13376340315 015623 xustar00mgornymgorny000000 000000 30 ctime=1543094606.340136302 29 atime=1543094642.61414619 30 mtime=1543094477.803174898 24 SCHILY.fflags=extent 50 LIBARCHIVE.xattr.user.mime_type=dGV4dC9wbGFpbg input.txt000644 001750 001750 00000000005 13376340315 013646 0ustar00mgornymgorny000000 000000 test squashfs-tools-ng-0.8/tests/tar/xattr/xattr-schily-binary.tar000066400000000000000000000060001360235375500245020ustar00rootroot00000000000000./PaxHeaders.31616/input.txt0000644000000000000000000000022213376340315012655 xustar0030 mtime=1543094477.803174898 29 atime=1543094642.61414619 30 ctime=1543094606.340136302 57 SCHILY.xattr.security.capability=0 input.txt0000644000175000017500000000000513376340315013666 0ustar00mgornymgorny00000000000000test squashfs-tools-ng-0.8/tests/tar/xattr/xattr-schily.tar000066400000000000000000000060001360235375500232200ustar00rootroot00000000000000./PaxHeaders.31616/input.txt0000644000000000000000000000020313376340315012654 xustar0030 mtime=1543094477.803174898 29 atime=1543094642.61414619 30 ctime=1543094606.340136302 42 SCHILY.xattr.user.mime_type=text/plain input.txt0000644000175000017500000000000513376340315013666 0ustar00mgornymgorny00000000000000test squashfs-tools-ng-0.8/tests/tar_fuzz.c000066400000000000000000000013721360235375500201440ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_fuzz.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include int main(int argc, char **argv) { tar_header_decoded_t hdr; FILE *fp; int ret; if (argc != 2) { fputs("usage: tar_fuzz \n", stderr); return EXIT_FAILURE; } fp = fopen(argv[1], "rb"); if (fp == NULL) { perror(argv[1]); return EXIT_FAILURE; } for (;;) { ret = read_header(fp, &hdr); if (ret > 0) break; if (ret < 0) goto fail; ret = fseek(fp, hdr.sb.st_size, SEEK_CUR); clear_header(&hdr); if (ret < 0) goto fail; } fclose(fp); return EXIT_SUCCESS; fail: fclose(fp); return EXIT_FAILURE; } squashfs-tools-ng-0.8/tests/tar_gnu.c000066400000000000000000000105061360235375500177360ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_gnu.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } static const char *filename = "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/input.txt"; int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("format-acceptance/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542905892); assert(hdr.mtime == 1542905892); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("format-acceptance/gnu-g.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 013375560044); assert(hdr.mtime == 013375560044); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data1", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("file-size/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 8589934592); assert(hdr.sb.st_mtime == 013375730126); assert(hdr.mtime == 013375730126); assert(strcmp(hdr.name, "big-file.bin") == 0); assert(!hdr.unknown_record); clear_header(&hdr); fclose(fp); fp = open_read("user-group-largenum/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 0x80000000); assert(hdr.sb.st_gid == 0x80000000); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 013376036700); assert(hdr.mtime == 013376036700); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data2", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("large-mtime/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); #if SIZEOF_TIME_T < 8 assert(hdr.sb.st_mtime == INT32_MAX); #else assert(hdr.sb.st_mtime == 8589934592L); #endif assert(hdr.mtime == 8589934592L); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data3", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("negative-mtime/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == -315622800); assert(hdr.mtime == -315622800); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data4", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("long-paths/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542909670); assert(hdr.mtime == 1542909670); assert(strcmp(hdr.name, filename) == 0); assert(!hdr.unknown_record); assert(read_retry("data5", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_pax.c000066400000000000000000000074671360235375500177510ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_pax.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } static const char *filename = "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/input.txt"; int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("format-acceptance/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542905892); assert(hdr.mtime == 1542905892); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("file-size/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 8589934592); assert(hdr.sb.st_mtime == 1542959190); assert(hdr.mtime == 1542959190); assert(strcmp(hdr.name, "big-file.bin") == 0); assert(!hdr.unknown_record); clear_header(&hdr); fclose(fp); fp = open_read("user-group-largenum/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 2147483648); assert(hdr.sb.st_gid == 2147483648); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 013376036700); assert(hdr.mtime == 013376036700); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data1", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("large-mtime/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); #if SIZEOF_TIME_T < 8 assert(hdr.sb.st_mtime == INT32_MAX); #else assert(hdr.sb.st_mtime == 8589934592L); #endif assert(hdr.mtime == 8589934592L); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data2", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("negative-mtime/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == -315622800); assert(hdr.mtime == -315622800); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data3", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("long-paths/pax.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542909670); assert(hdr.mtime == 1542909670); assert(strcmp(hdr.name, filename) == 0); assert(!hdr.unknown_record); assert(read_retry("data4", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_sparse_gnu.c000066400000000000000000000055531360235375500213210ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_sparse_gnu.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tar_header_decoded_t hdr; sparse_map_t *sparse; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("sparse-files/gnu-small.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 524288); assert(hdr.actual_size == 524288); assert(hdr.record_size == 8192); assert(strcmp(hdr.name, "input.bin") == 0); assert(!hdr.unknown_record); sparse = hdr.sparse; assert(sparse != NULL); assert(sparse->offset == 0); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 262144); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 524288); assert(sparse->count == 0); assert(sparse->next == NULL); clear_header(&hdr); fclose(fp); fp = open_read("sparse-files/gnu.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 2097152); assert(hdr.actual_size == 2097152); assert(hdr.record_size == 32768); assert(strcmp(hdr.name, "input.bin") == 0); assert(!hdr.unknown_record); sparse = hdr.sparse; assert(sparse != NULL); assert(sparse->offset == 0); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 262144); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 524288); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 786432); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1048576); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1310720); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1572864); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1835008); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 2097152); assert(sparse->count == 0); sparse = sparse->next; assert(sparse == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_sparse_gnu1.c000066400000000000000000000041431360235375500213740ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_sparse_gnu1.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tar_header_decoded_t hdr; sparse_map_t *sparse; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("sparse-files/pax-gnu0-0.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 2097152); assert(hdr.actual_size == 2097152); assert(hdr.record_size == 32768); assert(strcmp(hdr.name, "input.bin") == 0); assert(!hdr.unknown_record); sparse = hdr.sparse; assert(sparse != NULL); assert(sparse->offset == 0); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 262144); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 524288); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 786432); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1048576); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1310720); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1572864); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1835008); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 2097152); assert(sparse->count == 0); sparse = sparse->next; assert(sparse == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_sparse_gnu2.c000066400000000000000000000071171360235375500214010ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_sparse_gnu2.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = open(path, O_RDONLY); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tar_header_decoded_t hdr; sparse_map_t *sparse; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("sparse-files/pax-gnu0-1.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 2097152); assert(hdr.actual_size == 2097152); assert(hdr.record_size == 32768); assert(strcmp(hdr.name, "input.bin") == 0); assert(!hdr.unknown_record); sparse = hdr.sparse; assert(sparse != NULL); assert(sparse->offset == 0); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 262144); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 524288); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 786432); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1048576); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1310720); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1572864); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1835008); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 2097152); assert(sparse->count == 0); sparse = sparse->next; assert(sparse == NULL); clear_header(&hdr); fclose(fp); fp = open_read("sparse-files/pax-gnu1-0.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 2097152); assert(hdr.actual_size == 2097152); assert(hdr.record_size == 32768); assert(strcmp(hdr.name, "input.bin") == 0); assert(!hdr.unknown_record); sparse = hdr.sparse; assert(sparse != NULL); assert(sparse->offset == 0); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 262144); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 524288); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 786432); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1048576); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1310720); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1572864); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 1835008); assert(sparse->count == 4096); sparse = sparse->next; assert(sparse != NULL); assert(sparse->offset == 2097152); assert(sparse->count == 0); sparse = sparse->next; assert(sparse == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_ustar.c000066400000000000000000000105341360235375500203040ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_ustar.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } static const char *filename = "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/012345678901234567890123456789/" "012345678901234567890123456789/input.txt"; int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("format-acceptance/ustar.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542905892); assert(hdr.mtime == 1542905892); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("format-acceptance/ustar-pre-posix.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542905892); assert(hdr.mtime == 1542905892); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data1", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("format-acceptance/v7.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542905892); assert(hdr.mtime == 1542905892); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data2", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("file-size/12-digit.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 8589934592); assert(hdr.sb.st_mtime == 013375730126); assert(hdr.mtime == 013375730126); assert(strcmp(hdr.name, "big-file.bin") == 0); assert(!hdr.unknown_record); clear_header(&hdr); fclose(fp); fp = open_read("user-group-largenum/8-digit.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 8388608); assert(hdr.sb.st_gid == 8388608); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 013376036700); assert(hdr.mtime == 013376036700); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data3", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("large-mtime/12-digit.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); #if SIZEOF_TIME_T < 8 assert(hdr.sb.st_mtime == INT32_MAX); #else assert(hdr.sb.st_mtime == 8589934592L); #endif assert(hdr.mtime == 8589934592L); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data4", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); fp = open_read("long-paths/ustar.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1542909670); assert(hdr.mtime == 1542909670); assert(strcmp(hdr.name, filename) == 0); assert(!hdr.unknown_record); assert(read_retry("data5", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_xattr_bsd.c000066400000000000000000000025301360235375500211350ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_xattr_bsd.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("xattr/xattr-libarchive.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1543094477); assert(hdr.mtime == 1543094477); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); assert(hdr.xattr != NULL); assert(strcmp(hdr.xattr->key, "user.mime_type") == 0); assert(strcmp((const char *)hdr.xattr->value, "text/plain") == 0); assert(hdr.xattr->value_len == 10); assert(hdr.xattr->next == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_xattr_schily.c000066400000000000000000000025271360235375500216660ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_xattr_schily.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("xattr/xattr-schily.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1543094477); assert(hdr.mtime == 1543094477); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); assert(hdr.xattr != NULL); assert(strcmp(hdr.xattr->key, "user.mime_type") == 0); assert(strcmp((const char *)hdr.xattr->value, "text/plain") == 0); assert(hdr.xattr->value_len == 10); assert(hdr.xattr->next == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/tar_xattr_schily_bin.c000066400000000000000000000030161360235375500225100ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * tar_xattr_schily_bin.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "tar.h" #include #include #include #include #define STR(x) #x #define STRVALUE(x) STR(x) #define TEST_PATH STRVALUE(TESTPATH) static FILE *open_read(const char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror(path); exit(EXIT_FAILURE); } return fp; } static const uint8_t value[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; int main(void) { tar_header_decoded_t hdr; char buffer[6]; FILE *fp; assert(chdir(TEST_PATH) == 0); fp = open_read("xattr/xattr-schily-binary.tar"); assert(read_header(fp, &hdr) == 0); assert(hdr.sb.st_mode == (S_IFREG | 0644)); assert(hdr.sb.st_uid == 01750); assert(hdr.sb.st_gid == 01750); assert(hdr.sb.st_size == 5); assert(hdr.sb.st_mtime == 1543094477); assert(hdr.mtime == 1543094477); assert(strcmp(hdr.name, "input.txt") == 0); assert(!hdr.unknown_record); assert(read_retry("data0", fp, buffer, 5) == 0); buffer[5] = '\0'; assert(strcmp(buffer, "test\n") == 0); assert(hdr.xattr != NULL); assert(strcmp(hdr.xattr->key, "security.capability") == 0); assert(hdr.xattr->value_len == sizeof(value)); assert(memcmp(hdr.xattr->value, value, sizeof(value)) == 0); assert(hdr.xattr->next == NULL); clear_header(&hdr); fclose(fp); return EXIT_SUCCESS; } squashfs-tools-ng-0.8/tests/test_tar_sqfs.sh.in000077500000000000000000000014151360235375500217570ustar00rootroot00000000000000#!/bin/sh set -e TARDIR="@abs_top_srcdir@/tests/tar" SHA512FILE="@abs_top_srcdir@/tests/tar/sqfs.sha512" TAR2SQFS="@abs_top_builddir@/tar2sqfs" if [ ! -f "$TAR2SQFS" -a -f "${TAR2SQFS}.exe" ]; then TAR2SQFS="${TAR2SQFS}.exe" fi for filename in $(find "$TARDIR" -name "*.tar" | grep -v ".*/file-size/.*"); do dir="$(dirname $filename | sed -n -e 's;.*/tests/;tests/;p')" imgname="$dir/$(basename $filename .tar).sqfs" mkdir -p "$dir" "$TAR2SQFS" --defaults mtime=0 -c gzip -q "$imgname" < "$filename" done sha512sum -c "$SHA512FILE" for filename in $(find "$TARDIR" -name "*.tar" | grep -v ".*/file-size/.*"); do dir="$(dirname $filename | sed -n -e 's;.*/tests/;tests/;p')" imgname="$dir/$(basename $filename .tar).sqfs" rm "$imgname" rmdir -p "$dir" || true done squashfs-tools-ng-0.8/tests/words.txt000066400000000000000000000145721360235375500200410ustar00rootroot00000000000000a ability able about above accept according account across act action activity actually add address administration admit adult affect after again against age agency agent ago agree agreement ahead air all allow almost alone along already also although always American among amount analysis and animal another answer any anyone anything appear apply approach area argue arm around arrive art article artist as ask assume at attack attention attorney audience author authority available avoid away baby back bad bag ball bank bar base be beat beautiful because become bed before begin behavior behind believe benefit best better between beyond big bill billion bit black blood blue board body book born both box boy break bring brother budget build building business but buy by call camera campaign can cancer candidate capital car card care career carry case catch cause cell center central century certain certainly chair challenge chance change character charge check child choice choose church citizen city civil claim class clear clearly close coach cold collection college color come commercial common community company compare computer concern condition conference Congress consider consumer contain continue control cost could country couple course court cover create crime cultural culture cup current customer cut dark data daughter day dead deal death debate decade decide decision deep defense degree Democrat democratic describe design despite detail determine develop development die difference different difficult dinner direction director discover discuss discussion disease do doctor dog door down draw dream drive drop drug during each early east easy eat economic economy edge education effect effort eight either election else employee end energy enjoy enough enter entire environment environmental especially establish even evening event ever every everybody everyone everything evidence exactly example executive exist expect experience expert explain eye face fact factor fail fall family far fast father fear federal feel feeling few field fight figure fill film final finally financial find fine finger finish fire firm first fish five floor fly focus follow food foot for force foreign forget form former forward four free friend from front full fund future game garden gas general generation get girl give glass go goal good government great green ground group grow growth guess gun guy hair half hand hang happen happy hard have he head health hear heart heat heavy help her here herself high him himself his history hit hold home hope hospital hot hotel hour house how however huge human hundred husband I idea identify if image imagine impact important improve in include including increase indeed indicate individual industry information inside instead institution interest interesting international interview into investment involve issue it item its itself job join just keep key kid kill kind kitchen know knowledge land language large last late later laugh law lawyer lay lead leader learn least leave left leg legal less let letter level lie life light like likely line list listen little live local long look lose loss lot love low machine magazine main maintain major majority make man manage management manager many market marriage material matter may maybe me mean measure media medical meet meeting member memory mention message method middle might military million mind minute miss mission model modern moment money month more morning most mother mouth move movement movie Mr Mrs much music must my myself name nation national natural nature near nearly necessary need network never new news newspaper next nice night no none nor north not note nothing notice now n't number occur of off offer office officer official often oh oil ok old on once one only onto open operation opportunity option or order organization other others our out outside over own owner page pain painting paper parent part participant particular particularly partner party pass past patient pattern pay peace people per perform performance perhaps period person personal phone physical pick picture piece place plan plant play player PM point police policy political politics poor popular population position positive possible power practice prepare present president pressure pretty prevent price private probably problem process produce product production professional professor program project property protect prove provide public pull purpose push put quality question quickly quite race radio raise range rate rather reach read ready real reality realize really reason receive recent recently recognize record red reduce reflect region relate relationship religious remain remember remove report represent Republican require research resource respond response responsibility rest result return reveal rich right rise risk road rock role room rule run safe same save say scene school science scientist score sea season seat second section security see seek seem sell send senior sense series serious serve service set seven several sex sexual shake share she shoot short shot should shoulder show side sign significant similar simple simply since sing single sister sit site situation six size skill skin small smile so social society soldier some somebody someone something sometimes son song soon sort sound source south southern space speak special specific speech spend sport spring staff stage stand standard star start state statement station stay step still stock stop store story strategy street strong structure student study stuff style subject success successful such suddenly suffer suggest summer support sure surface system table take talk task tax teach teacher team technology television tell ten tend term test than thank that the their them themselves then theory there these they thing think third this those though thought thousand threat three through throughout throw thus time to today together tonight too top total tough toward town trade traditional training travel treat treatment tree trial trip trouble true truth try turn TV two type under understand unit until up upon us use usually value various very victim view violence visit voice vote wait walk wall want war watch water way we weapon wear week weight well west western what whatever when where whether which while white who whole whom whose why wide wife will win wind window wish with within without woman wonder word work worker world worry would write writer wrong yard yeah year yes yet you young your yourself squashfs-tools-ng-0.8/unpack/000077500000000000000000000000001360235375500162505ustar00rootroot00000000000000squashfs-tools-ng-0.8/unpack/Makemodule.am000066400000000000000000000006741360235375500206610ustar00rootroot00000000000000rdsquashfs_SOURCES = unpack/rdsquashfs.c unpack/rdsquashfs.h rdsquashfs_SOURCES += unpack/list_files.c unpack/options.c rdsquashfs_SOURCES += unpack/restore_fstree.c unpack/describe.c rdsquashfs_SOURCES += unpack/fill_files.c unpack/dump_xattrs.c rdsquashfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) rdsquashfs_LDADD = libcommon.a libcompat.a libsquashfs.la rdsquashfs_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) bin_PROGRAMS += rdsquashfs squashfs-tools-ng-0.8/unpack/describe.c000066400000000000000000000047601360235375500202030ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * describe.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" static int print_name(const sqfs_tree_node_t *n) { char *start, *ptr, *name = sqfs_tree_node_get_path(n); int ret; if (name == NULL) { perror("Recovering file path of tree node"); return -1; } ret = canonicalize_name(name); assert(ret == 0); if (strchr(name, ' ') == NULL && strchr(name, '"') == NULL) { fputs(name, stdout); } else { fputc('"', stdout); ptr = strchr(name, '"'); if (ptr != NULL) { start = name; do { fwrite(start, 1, ptr - start, stdout); fputs("\\\"", stdout); start = ptr + 1; ptr = strchr(start, '"'); } while (ptr != NULL); fputs(start, stdout); } else { fputs(name, stdout); } fputc('"', stdout); } free(name); return 0; } static void print_perm(const sqfs_tree_node_t *n) { printf(" 0%o %d %d", n->inode->base.mode & (~S_IFMT), n->uid, n->gid); } static int print_simple(const char *type, const sqfs_tree_node_t *n, const char *extra) { printf("%s ", type); if (print_name(n)) return -1; print_perm(n); if (extra != NULL) printf(" %s", extra); fputc('\n', stdout); return 0; } int describe_tree(const sqfs_tree_node_t *root, const char *unpack_root) { const sqfs_tree_node_t *n; switch (root->inode->base.mode & S_IFMT) { case S_IFSOCK: return print_simple("sock", root, NULL); case S_IFLNK: return print_simple("slink", root, root->inode->slink_target); case S_IFIFO: return print_simple("pipe", root, NULL); case S_IFREG: if (unpack_root == NULL) return print_simple("file", root, NULL); fputs("file ", stdout); if (print_name(root)) return -1; print_perm(root); printf(" %s/", unpack_root); if (print_name(root)) return -1; fputc('\n', stdout); break; case S_IFCHR: case S_IFBLK: { char buffer[32]; sqfs_u32 devno; if (root->inode->base.type == SQFS_INODE_EXT_BDEV || root->inode->base.type == SQFS_INODE_EXT_CDEV) { devno = root->inode->data.dev_ext.devno; } else { devno = root->inode->data.dev.devno; } sprintf(buffer, "%c %d %d", S_ISCHR(root->inode->base.mode) ? 'c' : 'b', major(devno), minor(devno)); return print_simple("nod", root, buffer); } case S_IFDIR: if (root->name[0] != '\0') { if (print_simple("dir", root, NULL)) return -1; } for (n = root->children; n != NULL; n = n->next) { if (describe_tree(n, unpack_root)) return -1; } break; } return 0; } squashfs-tools-ng-0.8/unpack/dump_xattrs.c000066400000000000000000000042711360235375500207720ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * dump_xattrs.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" static void print_hex(const sqfs_u8 *value, size_t len) { printf("0x"); while (len--) printf("%02X", *(value++)); } static bool is_printable(const sqfs_u8 *value, size_t len) { size_t utf8_cont = 0; sqfs_u8 x; while (len--) { x = *(value++); if (utf8_cont > 0) { if ((x & 0xC0) != 0x80) return false; --utf8_cont; } else { if (x < 0x80) { if (x < 0x20) { if (x >= 0x07 && x <= 0x0D) continue; if (x == 0x00) continue; return false; } if (x == 0x7F) return false; } if ((x & 0xE0) == 0xC0) { utf8_cont = 1; } else if ((x & 0xF0) == 0xE0) { utf8_cont = 2; } else if ((x & 0xF8) == 0xF0) { utf8_cont = 3; } else if ((x & 0xFC) == 0xF8) { utf8_cont = 4; } else if ((x & 0xFE) == 0xFC) { utf8_cont = 5; } if (utf8_cont > 0 && len < utf8_cont) return false; } } return true; } int dump_xattrs(sqfs_xattr_reader_t *xattr, const sqfs_inode_generic_t *inode) { sqfs_xattr_value_t *value; sqfs_xattr_entry_t *key; sqfs_xattr_id_t desc; sqfs_u32 index; size_t i; if (xattr == NULL) return 0; sqfs_inode_get_xattr_index(inode, &index); if (index == 0xFFFFFFFF) return 0; if (sqfs_xattr_reader_get_desc(xattr, index, &desc)) { fputs("Error resolving xattr index\n", stderr); return -1; } if (sqfs_xattr_reader_seek_kv(xattr, &desc)) { fputs("Error locating xattr key-value pairs\n", stderr); return -1; } for (i = 0; i < desc.count; ++i) { if (sqfs_xattr_reader_read_key(xattr, &key)) { fputs("Error reading xattr key\n", stderr); return -1; } if (sqfs_xattr_reader_read_value(xattr, key, &value)) { fputs("Error reading xattr value\n", stderr); free(key); return -1; } if (is_printable(key->key, key->size)) { printf("%s=", key->key); } else { print_hex(key->key, key->size); } if (is_printable(value->value, value->size)) { printf("%s\n", value->value); } else { print_hex(value->value, value->size); printf("\n"); } free(key); free(value); } return 0; } squashfs-tools-ng-0.8/unpack/fill_files.c000066400000000000000000000075431360235375500205350ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * fill_files.c * * Copyright (C) 2019 David Oberhollenzer */ #include "config.h" #include "rdsquashfs.h" static struct file_ent { char *path; const sqfs_inode_generic_t *inode; } *files = NULL; static size_t num_files = 0, max_files = 0; static size_t block_size = 0; static int compare_files(const void *l, const void *r) { sqfs_u32 lhs_frag_idx, lhs_frag_off, rhs_frag_idx, rhs_frag_off; sqfs_u64 lhs_size, rhs_size, lhs_start, rhs_start; const struct file_ent *lhs = l, *rhs = r; sqfs_inode_get_frag_location(lhs->inode, &lhs_frag_idx, &lhs_frag_off); sqfs_inode_get_file_block_start(lhs->inode, &lhs_start); sqfs_inode_get_file_size(lhs->inode, &lhs_size); sqfs_inode_get_frag_location(rhs->inode, &rhs_frag_idx, &rhs_frag_off); sqfs_inode_get_file_block_start(rhs->inode, &rhs_start); sqfs_inode_get_file_size(rhs->inode, &rhs_size); /* Files with fragments come first, ordered by ID. In case of tie, files without data blocks come first, and the others are ordered by start block. */ if ((lhs_size % block_size) && (lhs_frag_off < block_size) && (lhs_frag_idx != 0xFFFFFFFF)) { if ((rhs_size % block_size) && (rhs_frag_off < block_size) && (rhs_frag_idx != 0xFFFFFFFF)) return -1; if (lhs_frag_idx < rhs_frag_idx) return -1; if (lhs_frag_idx > rhs_frag_idx) return 1; if (lhs_size < block_size) return (rhs_size < block_size) ? 0 : -1; if (rhs_size < block_size) return 1; goto order_by_start; } if ((rhs_size % block_size) && (rhs_frag_off < block_size) && (rhs_frag_idx != 0xFFFFFFFF)) return 1; /* order the rest by start block */ order_by_start: return lhs_start < rhs_start ? -1 : lhs_start > rhs_start ? 1 : 0; } static int add_file(const sqfs_tree_node_t *node) { size_t new_sz; char *path; void *new; if (num_files == max_files) { new_sz = max_files ? max_files * 2 : 256; new = realloc(files, sizeof(files[0]) * new_sz); if (new == NULL) { perror("expanding file list"); return -1; } files = new; max_files = new_sz; } path = sqfs_tree_node_get_path(node); if (path == NULL) { perror("assembling file path"); return -1; } if (canonicalize_name(path)) { fprintf(stderr, "Invalid file path '%s'\n", path); free(path); return -1; } files[num_files].path = path; files[num_files].inode = node->inode; num_files++; return 0; } static void clear_file_list(void) { size_t i; for (i = 0; i < num_files; ++i) free(files[i].path); free(files); files = NULL; num_files = 0; max_files = 0; } static int gen_file_list_dfs(const sqfs_tree_node_t *n) { if (!is_filename_sane((const char *)n->name, true)) { fprintf(stderr, "Found an entry named '%s', skipping.\n", n->name); return 0; } if (S_ISREG(n->inode->base.mode)) return add_file(n); if (S_ISDIR(n->inode->base.mode)) { for (n = n->children; n != NULL; n = n->next) { if (gen_file_list_dfs(n)) return -1; } } return 0; } static int fill_files(sqfs_data_reader_t *data, int flags) { size_t i; FILE *fp; for (i = 0; i < num_files; ++i) { fp = fopen(files[i].path, "wb"); if (fp == NULL) { fprintf(stderr, "unpacking %s: %s\n", files[i].path, strerror(errno)); return -1; } if (!(flags & UNPACK_QUIET)) printf("unpacking %s\n", files[i].path); if (sqfs_data_reader_dump(files[i].path, data, files[i].inode, fp, block_size, (flags & UNPACK_NO_SPARSE) == 0)) { fclose(fp); return -1; } fflush(fp); fclose(fp); } return 0; } int fill_unpacked_files(size_t blk_sz, const sqfs_tree_node_t *root, sqfs_data_reader_t *data, int flags) { int status; block_size = blk_sz; if (gen_file_list_dfs(root)) { clear_file_list(); return -1; } qsort(files, num_files, sizeof(files[0]), compare_files); status = fill_files(data, flags); clear_file_list(); return status; } squashfs-tools-ng-0.8/unpack/list_files.c000066400000000000000000000100141360235375500205450ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * list_files.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" static void mode_to_str(sqfs_u16 mode, char *p) { switch (mode & S_IFMT) { case S_IFDIR: *(p++) = 'd'; break; case S_IFCHR: *(p++) = 'c'; break; case S_IFBLK: *(p++) = 'b'; break; case S_IFREG: *(p++) = '-'; break; case S_IFLNK: *(p++) = 'l'; break; case S_IFSOCK: *(p++) = 's'; break; case S_IFIFO: *(p++) = 'p'; break; default: *(p++) = '?'; break; } *(p++) = (mode & S_IRUSR) ? 'r' : '-'; *(p++) = (mode & S_IWUSR) ? 'w' : '-'; switch (mode & (S_IXUSR | S_ISUID)) { case S_IXUSR | S_ISUID: *(p++) = 's'; break; case S_IXUSR: *(p++) = 'x'; break; case S_ISUID: *(p++) = 'S'; break; default: *(p++) = '-'; break; } *(p++) = (mode & S_IRGRP) ? 'r' : '-'; *(p++) = (mode & S_IWGRP) ? 'w' : '-'; switch (mode & (S_IXGRP | S_ISGID)) { case S_IXGRP | S_ISGID: *(p++) = 's'; break; case S_IXGRP: *(p++) = 'x'; break; case S_ISGID: *(p++) = 'S'; break; case 0: *(p++) = '-'; break; } *(p++) = (mode & S_IROTH) ? 'r' : '-'; *(p++) = (mode & S_IWOTH) ? 'w' : '-'; switch (mode & (S_IXOTH | S_ISVTX)) { case S_IXOTH | S_ISVTX: *(p++) = 't'; break; case S_IXOTH: *(p++) = 'x'; break; case S_ISVTX: *(p++) = 'T'; break; case 0: *(p++) = '-'; break; } *p = '\0'; } static int count_int_chars(unsigned int i) { int count = 1; while (i > 10) { ++count; i /= 10; } return count; } static void print_size(sqfs_u64 size, char *buffer) { static const char *suffices = "kMGTPEZY"; int suffix = -1; while (size > 1024) { ++suffix; size /= 1024; } if (suffix >= 0) { sprintf(buffer, "%u%c", (unsigned int)size, suffices[suffix]); } else { sprintf(buffer, "%u", (unsigned int)size); } } static void print_node_size(const sqfs_tree_node_t *n, char *buffer) { switch (n->inode->base.mode & S_IFMT) { case S_IFLNK: print_size(strlen(n->inode->slink_target), buffer); break; case S_IFREG: { sqfs_u64 size; sqfs_inode_get_file_size(n->inode, &size); print_size(size, buffer); break; } case S_IFDIR: if (n->inode->base.type == SQFS_INODE_EXT_DIR) { print_size(n->inode->data.dir_ext.size, buffer); } else { print_size(n->inode->data.dir.size, buffer); } break; case S_IFBLK: case S_IFCHR: { sqfs_u32 devno; if (n->inode->base.type == SQFS_INODE_EXT_BDEV || n->inode->base.type == SQFS_INODE_EXT_CDEV) { devno = n->inode->data.dev_ext.devno; } else { devno = n->inode->data.dev.devno; } sprintf(buffer, "%u:%u", major(devno), minor(devno)); break; } default: buffer[0] = '0'; buffer[1] = '\0'; break; } } void list_files(const sqfs_tree_node_t *node) { int i, max_uid_chars = 0, max_gid_chars = 0, max_sz_chars = 0; char modestr[12], sizestr[32]; const sqfs_tree_node_t *n; if (S_ISDIR(node->inode->base.mode)) { for (n = node->children; n != NULL; n = n->next) { i = count_int_chars(n->uid); max_uid_chars = i > max_uid_chars ? i : max_uid_chars; i = count_int_chars(n->gid); max_gid_chars = i > max_gid_chars ? i : max_gid_chars; print_node_size(n, sizestr); i = strlen(sizestr); max_sz_chars = i > max_sz_chars ? i : max_sz_chars; } for (n = node->children; n != NULL; n = n->next) { mode_to_str(n->inode->base.mode, modestr); print_node_size(n, sizestr); printf("%s %*u/%-*u %*s %s", modestr, max_uid_chars, n->uid, max_gid_chars, n->gid, max_sz_chars, sizestr, n->name); if (S_ISLNK(n->inode->base.mode)) { printf(" -> %s\n", n->inode->slink_target); } else { fputc('\n', stdout); } } } else { mode_to_str(node->inode->base.mode, modestr); print_node_size(node, sizestr); printf("%s %u/%u %s %s", modestr, node->uid, node->gid, sizestr, node->name); if (S_ISLNK(node->inode->base.mode)) { printf(" -> %s\n", node->inode->slink_target); } else { fputc('\n', stdout); } } } squashfs-tools-ng-0.8/unpack/options.c000066400000000000000000000137621360235375500201200ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * options.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" static struct option long_opts[] = { { "list", required_argument, NULL, 'l' }, { "cat", required_argument, NULL, 'c' }, { "xattr", required_argument, NULL, 'x' }, { "unpack-root", required_argument, NULL, 'p' }, { "unpack-path", required_argument, NULL, 'u' }, { "no-dev", no_argument, NULL, 'D' }, { "no-sock", no_argument, NULL, 'S' }, { "no-fifo", no_argument, NULL, 'F' }, { "no-slink", no_argument, NULL, 'L' }, { "no-empty-dir", no_argument, NULL, 'E' }, { "no-sparse", no_argument, NULL, 'Z' }, #ifdef HAVE_SYS_XATTR_H { "set-xattr", no_argument, NULL, 'X' }, #endif { "set-times", no_argument, NULL, 'T' }, { "describe", no_argument, NULL, 'd' }, { "chmod", no_argument, NULL, 'C' }, { "chown", no_argument, NULL, 'O' }, { "quiet", no_argument, NULL, 'q' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, }; static const char *short_opts = "l:c:u:p:x:DSFLCOEZTj:dqhV" #ifdef HAVE_SYS_XATTR_H "X" #endif ; static const char *help_string = "Usage: rdsquashfs [OPTIONS] \n" "\n" "View or extract the contents of a squashfs image.\n" "\n" "Possible options:\n" "\n" " --list, -l Produce a directory listing for a given path in\n" " the squashfs image.\n" " --cat, -c If the specified path is a regular file in the,\n" " image, dump its contents to stdout.\n" " --xattr, -x Enumerate extended attributes associated with\n" " an inode that the given path resolves to.\n" " --unpack-path, -u Unpack this sub directory from the image. To\n" " unpack everything, simply specify /.\n" " --describe, -d Produce a file listing from the image.\n" "\n" " --unpack-root, -p If used with --unpack-path, this is where the\n" " data unpacked to. If used with --describe, this\n" " is used as a prefix for the input path of\n" " regular files.\n" "\n" " --no-dev, -D Do not unpack device special files.\n" " --no-sock, -S Do not unpack socket files.\n" " --no-fifo, -F Do not unpack named pipes.\n" " --no-slink, -L Do not unpack symbolic links.\n" " --no-empty-dir, -E Do not unpack directories that would end up\n" " empty after applying the above rules.\n" " --no-sparse, -Z Do not create sparse files, always write zero\n" " blocks to disk.\n" #ifdef HAVE_SYS_XATTR_H " --set-xattr, -X When unpacking files to disk, set the extended\n" " attributes from the squashfs image.\n" #endif " --set-times, -T When unpacking files to disk, set the create\n" " and modify timestamps from the squashfs image.\n" " --chmod, -C Change permission flags of unpacked files to\n" " those store in the squashfs image.\n" " --chown, -O Change ownership of unpacked files to the\n" " UID/GID set in the squashfs image.\n" " --quiet, -q Do not print out progress while unpacking.\n" "\n" " --help, -h Print help text and exit.\n" " --version, -V Print version information and exit.\n" "\n"; static char *get_path(char *old, const char *arg) { char *path; free(old); path = strdup(arg); if (path == NULL) { perror("processing arguments"); exit(EXIT_FAILURE); } if (canonicalize_name(path)) { fprintf(stderr, "Invalid path: %s\n", arg); free(path); exit(EXIT_FAILURE); } return path; } void process_command_line(options_t *opt, int argc, char **argv) { int i; opt->op = OP_NONE; opt->rdtree_flags = 0; opt->flags = 0; opt->cmdpath = NULL; opt->unpack_root = NULL; opt->image_name = NULL; for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'D': opt->rdtree_flags |= SQFS_TREE_NO_DEVICES; break; case 'S': opt->rdtree_flags |= SQFS_TREE_NO_SOCKETS; break; case 'F': opt->rdtree_flags |= SQFS_TREE_NO_FIFO; break; case 'L': opt->rdtree_flags |= SQFS_TREE_NO_SLINKS; break; case 'E': opt->rdtree_flags |= SQFS_TREE_NO_EMPTY; break; case 'C': opt->flags |= UNPACK_CHMOD; break; case 'O': opt->flags |= UNPACK_CHOWN; break; case 'Z': opt->flags |= UNPACK_NO_SPARSE; break; #ifdef HAVE_SYS_XATTR_H case 'X': opt->flags |= UNPACK_SET_XATTR; break; #endif case 'T': opt->flags |= UNPACK_SET_TIMES; break; case 'c': opt->op = OP_CAT; opt->cmdpath = get_path(opt->cmdpath, optarg); break; case 'd': opt->op = OP_DESCRIBE; free(opt->cmdpath); opt->cmdpath = NULL; break; case 'x': opt->op = OP_RDATTR; opt->cmdpath = get_path(opt->cmdpath, optarg); break; case 'l': opt->op = OP_LS; opt->cmdpath = get_path(opt->cmdpath, optarg); break; case 'p': opt->unpack_root = optarg; break; case 'u': opt->op = OP_UNPACK; opt->cmdpath = get_path(opt->cmdpath, optarg); break; case 'q': opt->flags |= UNPACK_QUIET; break; case 'h': fputs(help_string, stdout); free(opt->cmdpath); exit(EXIT_SUCCESS); case 'V': print_version("rdsquashfs"); free(opt->cmdpath); exit(EXIT_SUCCESS); default: goto fail_arg; } } if (opt->op == OP_NONE) { fputs("No operation specified\n", stderr); goto fail_arg; } if (opt->op == OP_LS || opt->op == OP_CAT || opt->op == OP_RDATTR) { opt->rdtree_flags |= SQFS_TREE_NO_RECURSE; } if (optind >= argc) { fputs("Missing image argument\n", stderr); goto fail_arg; } opt->image_name = argv[optind++]; return; fail_arg: fputs("Try `rdsquashfs --help' for more information.\n", stderr); free(opt->cmdpath); exit(EXIT_FAILURE); } squashfs-tools-ng-0.8/unpack/rdsquashfs.c000066400000000000000000000101471360235375500206020ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * rdsquashfs.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" int main(int argc, char **argv) { sqfs_xattr_reader_t *xattr = NULL; sqfs_compressor_config_t cfg; int status = EXIT_FAILURE; sqfs_data_reader_t *data; sqfs_dir_reader_t *dirrd; sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; sqfs_tree_node_t *n; sqfs_super_t super; sqfs_file_t *file; options_t opt; int ret; process_command_line(&opt, argc, argv); file = sqfs_open_file(opt.image_name, SQFS_FILE_OPEN_READ_ONLY); if (file == NULL) { perror(opt.image_name); goto out_cmd; } ret = sqfs_super_read(&super, file); if (ret) { sqfs_perror(opt.image_name, "reading super block", ret); goto out_file; } ret = sqfs_compressor_exists(super.compression_id); #ifdef WITH_LZO if (super.compression_id == SQFS_COMP_LZO) ret = true; #endif if (!ret) { fprintf(stderr, "%s: unknown compressor used.\n", opt.image_name); goto out_file; } sqfs_compressor_config_init(&cfg, super.compression_id, super.block_size, SQFS_COMP_FLAG_UNCOMPRESS); cmp = sqfs_compressor_create(&cfg); #ifdef WITH_LZO if (super.compression_id == SQFS_COMP_LZO && cmp == NULL) cmp = lzo_compressor_create(&cfg); #endif if (cmp == NULL) { fputs("Error creating compressor.\n", stderr); goto out_file; } if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { ret = cmp->read_options(cmp, file); if (ret) { sqfs_perror(opt.image_name, "reading compressor " "options", ret); goto out_cmp; } } if (!(super.flags & SQFS_FLAG_NO_XATTRS)) { xattr = sqfs_xattr_reader_create(file, &super, cmp); if (xattr == NULL) { sqfs_perror(opt.image_name, "creating xattr reader", SQFS_ERROR_ALLOC); goto out_cmp; } ret = sqfs_xattr_reader_load_locations(xattr); if (ret) { sqfs_perror(opt.image_name, "loading xattr table", ret); goto out_xr; } } idtbl = sqfs_id_table_create(); if (idtbl == NULL) { sqfs_perror(opt.image_name, "creating ID table", SQFS_ERROR_ALLOC); goto out_xr; } ret = sqfs_id_table_read(idtbl, file, &super, cmp); if (ret) { sqfs_perror(opt.image_name, "loading ID table", ret); goto out_id; } dirrd = sqfs_dir_reader_create(&super, cmp, file); if (dirrd == NULL) { sqfs_perror(opt.image_name, "creating dir reader", SQFS_ERROR_ALLOC); goto out_id; } data = sqfs_data_reader_create(file, super.block_size, cmp); if (data == NULL) { sqfs_perror(opt.image_name, "creating data reader", SQFS_ERROR_ALLOC); goto out_dr; } ret = sqfs_data_reader_load_fragment_table(data, &super); if (ret) { sqfs_perror(opt.image_name, "loading fragment table", ret); goto out_data; } ret = sqfs_dir_reader_get_full_hierarchy(dirrd, idtbl, opt.cmdpath, opt.rdtree_flags, &n); if (ret) { sqfs_perror(opt.image_name, "reading filesystem tree", ret); goto out_data; } switch (opt.op) { case OP_LS: list_files(n); break; case OP_CAT: if (!S_ISREG(n->inode->base.mode)) { fprintf(stderr, "/%s: not a regular file\n", opt.cmdpath); goto out; } if (sqfs_data_reader_dump(opt.cmdpath, data, n->inode, stdout, super.block_size, false)) { goto out; } break; case OP_UNPACK: if (opt.unpack_root != NULL) { if (mkdir_p(opt.unpack_root)) goto out; if (chdir(opt.unpack_root)) { perror(opt.unpack_root); goto out; } } if (restore_fstree(n, opt.flags)) goto out; if (fill_unpacked_files(super.block_size, n, data, opt.flags)) goto out; if (update_tree_attribs(xattr, n, opt.flags)) goto out; break; case OP_DESCRIBE: if (describe_tree(n, opt.unpack_root)) goto out; break; case OP_RDATTR: if (dump_xattrs(xattr, n->inode)) goto out; break; } status = EXIT_SUCCESS; out: sqfs_dir_tree_destroy(n); out_data: sqfs_data_reader_destroy(data); out_dr: sqfs_dir_reader_destroy(dirrd); out_id: sqfs_id_table_destroy(idtbl); out_xr: if (xattr != NULL) sqfs_xattr_reader_destroy(xattr); out_cmp: cmp->destroy(cmp); out_file: file->destroy(file); out_cmd: free(opt.cmdpath); return status; } squashfs-tools-ng-0.8/unpack/rdsquashfs.h000066400000000000000000000026551360235375500206140ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * rdsquashfs.h * * Copyright (C) 2019 David Oberhollenzer */ #ifndef RDSQUASHFS_H #define RDSQUASHFS_H #include "config.h" #include "common.h" #include "fstree.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #endif #ifdef HAVE_SYS_XATTR_H #include #endif #include #include #include #include #include #include #include enum UNPACK_FLAGS { UNPACK_CHMOD = 0x01, UNPACK_CHOWN = 0x02, UNPACK_QUIET = 0x04, UNPACK_NO_SPARSE = 0x08, UNPACK_SET_XATTR = 0x10, UNPACK_SET_TIMES = 0x20, }; enum { OP_NONE = 0, OP_LS, OP_CAT, OP_UNPACK, OP_DESCRIBE, OP_RDATTR, }; typedef struct { int op; int rdtree_flags; int flags; char *cmdpath; const char *unpack_root; const char *image_name; } options_t; void list_files(const sqfs_tree_node_t *node); int restore_fstree(sqfs_tree_node_t *root, int flags); int update_tree_attribs(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *root, int flags); int fill_unpacked_files(size_t blk_sz, const sqfs_tree_node_t *root, sqfs_data_reader_t *data, int flags); int describe_tree(const sqfs_tree_node_t *root, const char *unpack_root); int dump_xattrs(sqfs_xattr_reader_t *xattr, const sqfs_inode_generic_t *inode); void process_command_line(options_t *opt, int argc, char **argv); #endif /* RDSQUASHFS_H */ squashfs-tools-ng-0.8/unpack/restore_fstree.c000066400000000000000000000145431360235375500214560ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later */ /* * restore_fstree.c * * Copyright (C) 2019 David Oberhollenzer */ #include "rdsquashfs.h" #ifdef _WIN32 static int create_node(const sqfs_tree_node_t *n, const char *name) { WCHAR *wpath; HANDLE fh; wpath = path_to_windows(name); if (wpath == NULL) return -1; switch (n->inode->base.mode & S_IFMT) { case S_IFDIR: if (!CreateDirectoryW(wpath, NULL)) goto fail; break; case S_IFREG: fh = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, 0, NULL); if (fh == INVALID_HANDLE_VALUE) goto fail; CloseHandle(fh); break; default: break; } free(wpath); return 0; fail: fprintf(stderr, "Creating %s: %ld\n", name, GetLastError()); free(wpath); return -1; } #else static int create_node(const sqfs_tree_node_t *n, const char *name) { sqfs_u32 devno; int fd; switch (n->inode->base.mode & S_IFMT) { case S_IFDIR: if (mkdir(name, 0755) && errno != EEXIST) { fprintf(stderr, "mkdir %s: %s\n", name, strerror(errno)); return -1; } break; case S_IFLNK: if (symlink(n->inode->slink_target, name)) { fprintf(stderr, "ln -s %s %s: %s\n", n->inode->slink_target, name, strerror(errno)); return -1; } break; case S_IFSOCK: case S_IFIFO: if (mknod(name, (n->inode->base.mode & S_IFMT) | 0700, 0)) { fprintf(stderr, "creating %s: %s\n", name, strerror(errno)); return -1; } break; case S_IFBLK: case S_IFCHR: if (n->inode->base.type == SQFS_INODE_EXT_BDEV || n->inode->base.type == SQFS_INODE_EXT_CDEV) { devno = n->inode->data.dev_ext.devno; } else { devno = n->inode->data.dev.devno; } if (mknod(name, n->inode->base.mode & S_IFMT, devno)) { fprintf(stderr, "creating device %s: %s\n", name, strerror(errno)); return -1; } break; case S_IFREG: fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) { fprintf(stderr, "creating %s: %s\n", name, strerror(errno)); return -1; } close(fd); break; default: break; } return 0; } #endif static int create_node_dfs(const sqfs_tree_node_t *n, int flags) { const sqfs_tree_node_t *c; char *name; int ret; if (!is_filename_sane((const char *)n->name, true)) { fprintf(stderr, "Found an entry named '%s', skipping.\n", n->name); return 0; } name = sqfs_tree_node_get_path(n); if (name == NULL) { fprintf(stderr, "Constructing full path for '%s': %s\n", (const char *)n->name, strerror(errno)); return -1; } ret = canonicalize_name(name); assert(ret == 0); if (!(flags & UNPACK_QUIET)) printf("creating %s\n", name); ret = create_node(n, name); free(name); if (ret) return -1; if (S_ISDIR(n->inode->base.mode)) { for (c = n->children; c != NULL; c = c->next) { if (create_node_dfs(c, flags)) return -1; } } return 0; } #ifdef HAVE_SYS_XATTR_H static int set_xattr(const char *path, sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *n) { sqfs_xattr_value_t *value; sqfs_xattr_entry_t *key; sqfs_xattr_id_t desc; sqfs_u32 index; size_t i; int ret; sqfs_inode_get_xattr_index(n->inode, &index); if (index == 0xFFFFFFFF) return 0; if (sqfs_xattr_reader_get_desc(xattr, index, &desc)) { fputs("Error resolving xattr index\n", stderr); return -1; } if (sqfs_xattr_reader_seek_kv(xattr, &desc)) { fputs("Error locating xattr key-value pairs\n", stderr); return -1; } for (i = 0; i < desc.count; ++i) { if (sqfs_xattr_reader_read_key(xattr, &key)) { fputs("Error reading xattr key\n", stderr); return -1; } if (sqfs_xattr_reader_read_value(xattr, key, &value)) { fputs("Error reading xattr value\n", stderr); free(key); return -1; } ret = lsetxattr(path, (const char *)key->key, value->value, value->size, 0); if (ret) { fprintf(stderr, "setting xattr '%s' on %s: %s\n", key->key, path, strerror(errno)); } free(key); free(value); if (ret) return -1; } return 0; } #endif static int set_attribs(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *n, int flags) { const sqfs_tree_node_t *c; char *path; int ret; if (!is_filename_sane((const char *)n->name, true)) return 0; if (S_ISDIR(n->inode->base.mode)) { for (c = n->children; c != NULL; c = c->next) { if (set_attribs(xattr, c, flags)) return -1; } } path = sqfs_tree_node_get_path(n); if (path == NULL) { fprintf(stderr, "Reconstructing full path: %s\n", strerror(errno)); return -1; } ret = canonicalize_name(path); assert(ret == 0); #ifdef HAVE_SYS_XATTR_H if ((flags & UNPACK_SET_XATTR) && xattr != NULL) { if (set_xattr(path, xattr, n)) goto fail; } #endif #ifndef _WIN32 if (flags & UNPACK_SET_TIMES) { struct timespec times[2]; memset(times, 0, sizeof(times)); times[0].tv_sec = n->inode->base.mod_time; times[1].tv_sec = n->inode->base.mod_time; if (utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW)) { fprintf(stderr, "setting timestamp on %s: %s\n", path, strerror(errno)); goto fail; } } #endif if (flags & UNPACK_CHOWN) { if (fchownat(AT_FDCWD, path, n->uid, n->gid, AT_SYMLINK_NOFOLLOW)) { fprintf(stderr, "chown %s: %s\n", path, strerror(errno)); goto fail; } } if (flags & UNPACK_CHMOD && !S_ISLNK(n->inode->base.mode)) { if (fchmodat(AT_FDCWD, path, n->inode->base.mode & ~S_IFMT, 0)) { fprintf(stderr, "chmod %s: %s\n", path, strerror(errno)); goto fail; } } free(path); return 0; fail: free(path); return -1; } int restore_fstree(sqfs_tree_node_t *root, int flags) { sqfs_tree_node_t *n, *old_parent; /* make sure fstree_get_path() stops at this node */ old_parent = root->parent; root->parent = NULL; if (S_ISDIR(root->inode->base.mode)) { for (n = root->children; n != NULL; n = n->next) { if (create_node_dfs(n, flags)) return -1; } } else { if (create_node_dfs(root, flags)) return -1; } root->parent = old_parent; return 0; } int update_tree_attribs(sqfs_xattr_reader_t *xattr, const sqfs_tree_node_t *root, int flags) { const sqfs_tree_node_t *n; if ((flags & (UNPACK_CHOWN | UNPACK_CHMOD | UNPACK_SET_TIMES | UNPACK_SET_XATTR)) == 0) { return 0; } if (S_ISDIR(root->inode->base.mode)) { for (n = root->children; n != NULL; n = n->next) { if (set_attribs(xattr, n, flags)) return -1; } } else { if (set_attribs(xattr, root, flags)) return -1; } return 0; }