From: bruce Date: Fri, 18 Mar 2011 17:40:00 +0000 (-0700) Subject: LU-135 Fixes for builds against Lustre 1.8.1 to 2.x. X-Git-Tag: v1.41.90.wc1~2 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F45%2F345%2F4;p=tools%2Fe2fsprogs.git LU-135 Fixes for builds against Lustre 1.8.1 to 2.x. This patch set is for e2fsprogs v1.41.14-161-g7d9e316 This patch set includes changes from Andeas Dilger: Author: Andreas Dilger Date: Fri Mar 11 01:54:51 2011 -0700 LU-45 update e2fsprogs for pre-1.42 build This e2fsprogs release adds support for filesystems > 16TB. Update the lfsck code to build and run with both 1.8.x and 2.1. Zero large inode space when expanding inode to avoid leaving garbage. Validate inode creation time caused by non-zeroed large inode space. Change-Id: Iebac0d6147cacc386e5c1a0a44df57785ad7c8fd Signed-off-by: Andreas Dilger Change-Id: I243c2520a99113db31dd499d2d706ca7c6f7f41f Signed-off-by: B.Cassidy --- diff --git a/patches/ChangeLog b/patches/ChangeLog new file mode 100644 index 0000000..a9c67e5 --- /dev/null +++ b/patches/ChangeLog @@ -0,0 +1,519 @@ +2011-01-20 Whamcloud, Inc. + * version 1.41.14.wc1 + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.42. This release + includes functionality for filesystems with more than 2^32 + blocks. For standard architectures, this allows filesystems + with more than 16TB of space. Not actually tested with >16TB + filesystems yet. + +Severity : enhancement +Description: allow lfsck to run with both 1.x and 2.x filesystems +Details : adapt lfsck to use FID-based inode and object addressing, + so that it can work with 2.x filesystems. This depends + on the llapi_path2fid()/LL_IOC_PATH2FID ioctl. If needed, + this could be worked around on older Lustre versions to just + return the IGIF inode number via stat and EXT2_IOC_GETVERSION. + +Severity : enhancement +Description: avoid creating the lfsck size database +Details : lfsck was creating the "szinfo" database on every run, but + it was never being used. Disable it until it is needed. + +Severity : major +Description: flush client DLM cache when cloning duplicate objects +Details : If the DLM has multiple locks referencing a single inode + it will trigger an LASSERT on the client. Flush the DLM + cache after cloning the first file to avoid this case. + +Severity : minor +Description: zero large inode space when expanding inode +Details : if "e2fsck -E expand_extra_inode" is run, the newly freed + space was not zeroed, leaving garbage in those fields. + +Severity : minor +Description: validate inode creation time +Details : validate that the inode creation time is after the mkfs time + in the superblock, and before "now + margin", or ask to fix it. + +--------------------------------------------------------------------------- + +2011-01-20 Whamcloud, Inc. + * version 1.41.14.wc1 + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.41.14. This moves a + few Lustre patches into mainstream e2fsprogs, like debugfs + printing of flex_bg bitmap offsets. See RELEASE-NOTES. + +Severity : enhancement +Description: remove patches to configure +Details : Avoid patching the generated configure script, which was + cumbersome and error-prone. Instead, running configure with + the --enable-maintainer-mode option will cause configure to + be regenerated automatically when configure.in is patched. + Add this as a default configure option to the RPM .spec file. + +Severity : enhancement +Description: add checks for db4.7 and db4.8 on newer distros for lfsck + +Severity : minor +Description: add "Obsoletes e4fsprogs" for installing on RHEL systems that + provide an e4fsprogs RPM for ext4 testing. + +Severity : enhancement +Bugzilla : 4424 +Description: Add basic regression test for large EAs in inodes + +Severity : enhancement +Description: Improve dumpe2fs output to print bitmap/itable offsets more + sanely when flex_bg is configured on the filesystem. + +--------------------------------------------------------------------------- + +2010-09-29 Oracle, Inc. + * version 1.41.12.2.ora1 + +Severity : normal +Bugzilla : 21704 +Description: add lfsck support for LOV_MAGIC_V3 (pools) EAs + +Severity : normal +Bugzilla : 22162 +Description: Support journals larger than 2GB +Details : libext2fs wasn't handling the high bits of the journal inode size + +Severity : normal +Bugzilla : 23502 +Description: Fix slowdown when creating large extent-mapped journals (> 1GB) +Details : When ext2fs_block_iterate2() is called on an extent-mapped file + with a depth > 1, it will erroneously calling the callback + function starting all over again with logical block 0. It + shouldn't do this, and it cases mke2fs to become very slow when + creating files with very large extent-mapped journals. + +Severity : enhancement +Bugzilla : 21683 +Description: Add --lazy-journal-init option to speed up mke2fs. +Details : This allows creating large journal files quickly during testing, + but is not strictly safe for production, since it is possible + in theory to have the journal accidentally replay the wrong data, + IFF the journal is not overwritten before the first crash. + +Severity : enhancement +Bugzilla : 4424 +Description: Add large ea support to e2fsprogs + +Severity : enhancement +Bugzilla : 23041 +Description: Don't start MMP for debugfs if the filesystem is opened in + catastrophic mode (read only, minimum metadata loaded). + +Severity : enhancement +Bugzilla : 22421 +Description: Add check for ensuring that file system is writable before + starting MMP. + +Severity : enhancement +Bugzilla : +Description: Improve filefrag output so it can print new-style extent + lists even if FIEMAP support is not available. + +--------------------------------------------------------------------------- + +2010-02-24 Sun Microsystems, Inc. + * version 1.41.10-sun2 + +Severity : major +Frequency : never +Bugzilla : 18779 +Description: Fix a corruption problem in upstream e2fsprogs-1.41.10 when + "e2fsck -D" is run on a non-indexed directory with a directory + entry that sorts before "." or "..". This was never in any + Sun-released e2fsck package, but is recorded here to clarify + that this bug was fixed in this release. + +Severity : normal +Frequency : only with a corrupt MMP block +Bugzilla : 21543 +Description: Add check for e2fsck to correct a corrupted MMP block before the + filesystem is opened. Fix segfault at close if MMP wasn't started. + +Severity : enhancement +Bugzilla : 21564 +Description: Print message if MMP timeout is very large. + +Severity : normal +Frequency : SLES11 only +Bugzilla : 20830 +Description: Allow ext2fs_attr_set() to include attribute prefix in the name, + instead of using ext2_attr_index_prefix[] outside of libext2fs. + +Severity : enhancement +Bugzilla : 14548 +Description: Improve ZFS device probing in libblkid. + +--------------------------------------------------------------------------- + +2009-06-13 Sun Microsystems, Inc. + * version 1.41.6-sun1 + +Severity : major +Frequency : always +Bugzilla : 18779 +Description: Fix a critical regression in e2fsck introduced version 1.41.5 + which can undo updates to the block group descriptors after a + journal replay. + +Severity : enhancement +Bugzilla : 19536 +Description: add regression tests for MMP feature + +Severity : major +Frequency : always +Bugzilla : 19536 +Description: Free block statistics correctly when MMP is turned off + +--------------------------------------------------------------------------- + +2009-05-12 Sun Microsystems, Inc. + * version 1.41.5-sun2 + +Severity : major +Frequency : always +Bugzilla : 18735 +Description: e2fsck reading cached MMP block misses MMP block update + +--------------------------------------------------------------------------- + +2009-04-30 Sun Microsystems, Inc. + * version 1.41.5-sun1 + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.41.5. This moves a + number of lustre patches into mainstream e2fsprogs, like extents, + uninitialized groups, and many smaller fixes. See RELEASE-NOTES. + +Severity : enhancement +Bugzilla : 13419 +Description: lsattr print 'H' flag for huge files; document it and extent flag + +Severity : normal +Frequency : if MMP was enabled with e2fsck, and e2fsck exited uncleanly +Bugzilla : 18735 +Description: clear MMP e2fsck marker if e2fsck is interrupted +Details : clear MMP e2fsck marker from the SIGINT and SIGTERM signal + handlers, or if e2fsck hits a fatal error. + +Severity : enhancement +Bugzilla : 18735 +Description: add "clear-mmp" option to tune2fs to reset the MMP e2fsck marker +Details : add an option to run "tune2fs -f -E clear-mmp" to reset the MMP + block, which is easier than disabling and re-enabling it. + +Severity : enhancement +Bugzilla : 10555 +Description: Add FIEMAP(FIle Extent MAP) ioctl support to filefrag +Details : FIEMAP ioctl allows applications to efficiently fetch the extent + information of a file. It can be used to map logical blocks in a + in a file to physical blocks in the block device. filefrag has + been modified to use the FIEMAP ioctl. + +Severity : normal +Frequency : if MMP was enabled with tune2fs +Bugzilla : 17531 +Description: Free block count should be updated when MMP enabled using tune2fs + +--------------------------------------------------------------------------- + +2008-07-11 Sun Microsystems, Inc. + * version 1.40.11-sun1 + +Severity : major +Frequency : rare, if on-disk data is corrupted +Bugzilla : 15320 +Description: kernel assertion with invalid eh_depth that e2fsck does not fix +Details : fix invalid eh_depth in the inode if the last index was invalid + +Severity : enhancement +Bugzilla : 15604 +Description: display i_version in debugfs "stat" command + +--------------------------------------------------------------------------- + +2008-05-20 Sun Microsystems, Inc. + * version 1.40.7-sun3 + +Severity : enhancement +Bugzilla : 9570 +Description: improve e2fsck error message for invalid HTREE depth + +Severity : major +Bugzilla : 15872 +Description: tune2fs cannot disable uninit_groups or mmp features +Details : Upstream changes to the structure of tune2fs broke the + ability to disable the uninit_groups and mmp features. + This is particularly serious for mmp, because it will + render the filesystem unmountable. + +--------------------------------------------------------------------------- + +2008-05-20 Sun Microsystems, Inc. + * version 1.40.7-sun2 + +Severity : normal +Bugzilla : 15725 +Description: fsck (e2fsck) -m hangs headless node +Details : -m support for SLES10 patch was removed as this feature was + included in upstream e2fsprogs. But upstream e2fsprogs uses + "-M" whereas SLES10 assumes it to be "-m". Added this patch + to provide compatibility with SLES10. + +Severity : normal +Bugzilla : 15320 +Description: OSS crashes as e2fsck doesn't fix the header +Details : When the last extent index contained in an inode is deleted + it resulsts in a condition, eh_entries = 0 and eh_depth !=0, + which ldiskfs doesn't expect this and crashes. Fixed it by + clearing the eh_depth. + +--------------------------------------------------------------------------- + +2008-03-14 Sun Microsystems, Inc. + * version 1.40.7-sun1 + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.40.7. See RELEASE-NOTES. + +Severity : enhancement +Bugzilla : 13025 +Description: Free space fragmentation reporting tool +Details : Add e2freefrag patch. Remove e2defragfree patch and changes to + further patches in series + +Severity : enhancement +Description: Add basic ZFS filesystem detection to libblkid + +Severity : enhancement +Description: Enable DIR_NLINK feature in the superblock +Details : If there are any directories with > 65000 subdirectories, enable + the DIR_NLINK feature in the superblock. + This is not yet included in the Lustre e2fsprogs patch series. + +--------------------------------------------------------------------------- + +2008-02-01 Sun Microsystems, Inc. + * version 1.40.5-sun1 + +Severity : normal +Bugzilla : 13150 +Description: e2fsprogs install error on SLES10 due to different library names +Details : On SLES10 the e2fsprogs package splits out libcom_err and libss + into a separate libcom_err RPM. On RHEL5 the libraries are + split into a separate e2fsprogs-libs RPM. Add an "Obsoletes" + and "Provides" line for each distro to provide compatibility. + +Severity : normal +Bugzilla : 14662 +Description: e2fsprogs does not contain et_list_{un,}lock() on SLES10 +Details : On SLES10 the e2fsprogs package has patches to add new functions + to the libcom_err library for making it thread safe. These + patches were added to e2fsprogs to provide compatibility. + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.40.5. See RELEASE-NOTES. + +--------------------------------------------------------------------------- + +2008-01-10 Cluster File Systems, Inc. + * version 1.40.4-cfs1 + +Severity : enhancement +Description: update to latest upstream e2fsprogs release +Details : Update to upstream e2fsprogs release 1.40.4. See RELEASE-NOTES. + +Severity : normal +Bugzilla : 12723 +Description: lfsck segfaults on SLES10 due to different db4 header +Details : lfsck was being built with a db4 header file different than the + shared library installed on the system, causing it to access + data structures incorrectly. Use the right header file. + +--------------------------------------------------------------------------- + +2007-12-10 Cluster File Systems, Inc. + * version 1.40.2-cfs5 + +Severity : enhancement +Bugzilla : 13108 +Description: e2scan lists directories with -D option +Details : Add the ability to e2scan to list directories when the -D option + is specified. When specified with a date range, only directories + modified since that time will be output. When a full listing is + requested all directories will be output. + +--------------------------------------------------------------------------- + +2007-11-09 Cluster File Systems, Inc. + * version 1.40.2-cfs4 + +Severity : major +Frequency : filesystems with corrupt inode tables +Bugzilla : 14085 +Description: e2fsck aborts if a non-regular file has a corrupt EA block +Details : e2fsck incorrectly set an error return code if it read a + corrupt EA block and in the case of a file that did not have + any data blocks the error was not reset, causing e2fsck to + exit with an error. The EA block read should not be returning + an error in this case. + +--------------------------------------------------------------------------- + +2007-10-29 Cluster File Systems, Inc. + * version 1.40.2-cfs3 + +Severity : enhancement +Bugzilla : 10827 +Description: Add e2defragfree program to defrag free space in ext3. +Details : e2defrgfree program tries to increase percentage of free chunks + in free space on ext3 filesystem. It scans inodes and migrates + extents to align free chunks. + +--------------------------------------------------------------------------- + +2007-10-12 Cluster File Systems, Inc. + * version 1.40.2-cfs2 + +Severity : enhancement +Bugzilla : 10657 +Description: Add journal checksum support to e2fsprogs. +Details : Changes to e2fsck to allow recovery of filesystems using journals + containing checksums. + +Severity : major +Frequency : only on Lustre OSTs systems where page size > filesystem blocksize +Bugzilla : 13812 +Description: e2fsck can corrupt files by changing the i_size +Details : On systems where page size is greater than filesystem blocksize + e2fsck would round off the i_size to the page size boundary. + Fix the check to allow blocks to the end of PAGE_SIZE. + +Severity : enhancement +Bugzilla : 13108 +Description: Add e2scan program to efficiently scan filesystems for changes. +Details : The e2scan program scans a filesystem for files that have changed + since a specific time. This is usually more efficient than + doing a filesystem-level scan as it avoids seeking as much as + possible. + +---------------------------------------------------------------------------- + +2007-08-16 Cluster File Systems, Inc. + * version 1.40.2-cfs1 + +Severity : enhancement +Bugzilla : 11644 +Description: Improve e2fsck heuristics for detecting corrupted inodes +Details : Instead of doing piecemeal checking of inodes, this tracks all + errors detected in each inode, and if a certain badness threshold + is exceeded, the inode should be considered garbage. + +Severity : major +Frequency : rarely, only for failover machines +Bugzilla : 6334 +Description: Multiple mount protection support +Details : The INCOMPAT_MMP feature will protect the filesystem from being + mounted more than once simultaneously, even on different nodes. + It will also protect against changes by e2fsprogs to the + filesystem if it is mounted. This assumes high importance in a + shared storage environment where multiple mounts can severely + corrupt the filesystem. + +Severity : normal +Frequency : always on big-endian machines +Bugzilla : 12774 +Description: Corrections for e2fsprogs test failures on big-endian machines +Details : Correct upstream errors which caused some e2fsprogs regression + tests to fail. Also add support for in-inode extent swabbing. + +Severity : normal +Frequency : unknown +Bugzilla : 13111 +Description: Disable resize2fs if extents are enabled +Details : We have received reports of resize2fs corrupting the filesystem + if extents are enabled. Although we are unable to reproduce the + problem, resize2fs has been disabled for filesystems using + extents as a precaution. + +Severity : enhancement +Bugzilla : 11640 +Description: Random corruption test for e2fsprogs +Details : This test script randomly corrupts a filesystem and test the + robustness of e2fsck in cleaning this corrupted filesystem. + This test is done with random features enabled and with random + amounts of corruption. + +---------------------------------------------------------------------------- + +2007-06-04 Cluster File Systems, Inc. + * version 1.39.cfs8 + +Severity : minor +Frequency : always +Bugzilla : 12362 +Description: lfsck segfault if comma-separated OSTs are used on command-line +Details : If the list of OSTs given to lfsck is comma-separated, instead + of space-separated, lfsck will segfault when freeing memory. + This problem did not actually affect any lfsck operations. + + +Severity : enhancement +Bugzilla : 12608 +Description: Report IO statistics to e2fsck +Details : Report IO statistics for read/write performance for various + stages of e2fsck if the '-t' option is given. + +---------------------------------------------------------------------------- + +2007-05-03 Cluster File Systems, Inc. + * version 1.39.cfs7 + +Severity : normal +Frequency : always, if using uninit_groups +Bugzilla : 12334 +Description: uninit_groups support was marking the last group UNINIT +Details : With mke2fs -O uninit_groups the last group would incorrectly + be marked BLOCK_UNINIT. The kernel part of the patch did not + handle that gracefully. Fix mke2fs and e2fsck to not do this. + +Severity : enhancement +Description: update from upstream e2fsprogs (2007-04-18) +Details : Includes most of the LLNL Coverity fixes. + Includes equivalent fix+test for e2fsprogs-check_filetype.patch. + Adds e2fsck support for external database for many directories. + +---------------------------------------------------------------------------- + +2007-03-26 Cluster File Systems, Inc. + * version 1.39.cfs6 + +Severity : enhancement +Bugzilla : 11264 +Description: Add uninit_groups (GDT_CSUM) feature support +Details : With an appropriate kernel, it is possible to improve e2fsck + performance to be a function of used inodes instead of total + inodes in the filesystem. + +Severity : Normal +Frequency : always +Bugzilla : 11781 +Description: f_extents_eh_depth regression test failure +Details : The e2fsck regression test f_extents_eh_depth was failing because + it wasn't fixing the problem in the first pass. + diff --git a/patches/README b/patches/README new file mode 100644 index 0000000..6fbcdfe --- /dev/null +++ b/patches/README @@ -0,0 +1,14 @@ +README for e2fsprogs/patches + +This directory contains patches required for use with Lustre that are +for a specific e2fsprogs version, as shown in e2fsprogs-version.patch, +in the order specified by "series". Some of the patches here may be +"historical" in the sense that they have already been added to the +upstream e2fsprogs repository since this release, but they are not in +any official e2fsprogs release so are included here for reference. + +Unfortunately, it isn't possible to have an SRPM that doesn't have the +patches applied, because the patches change the "configure" script, and +that in turn changes the .spec file (built from .spec.in) and that is +sourced by rpmbuild before the patches are applied... + diff --git a/patches/e2fsprogs-add-io_channel_readahead.patch b/patches/e2fsprogs-add-io_channel_readahead.patch new file mode 100644 index 0000000..035096c --- /dev/null +++ b/patches/e2fsprogs-add-io_channel_readahead.patch @@ -0,0 +1,93 @@ +Index: e2fsprogs/lib/ext2fs/ext2_io.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_io.h ++++ e2fsprogs/lib/ext2fs/ext2_io.h +@@ -88,6 +88,8 @@ struct struct_io_manager { + int count, const void *data); + errcode_t (*discard)(io_channel channel, unsigned long long block, + unsigned long long count); ++ errcode_t (*readahead)(io_channel channel, unsigned long block, ++ int count); + long reserved[16]; + }; + +@@ -101,6 +103,7 @@ struct struct_io_manager { + #define io_channel_close(c) ((c)->manager->close((c))) + #define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s)) + #define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d)) ++#define io_channel_readahead(c,b,n) ((c)->manager->readahead((c),b,n)) + #define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d)) + #define io_channel_flush(c) ((c)->manager->flush((c))) + #define io_channel_bumpcount(c) ((c)->refcount++) +Index: e2fsprogs/lib/ext2fs/unix_io.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/unix_io.c ++++ e2fsprogs/lib/ext2fs/unix_io.c +@@ -15,6 +15,9 @@ + * %End-Header% + */ + ++#define _XOPEN_SOURCE 600 ++#define _DARWIN_C_SOURCE ++#define _FILE_OFFSET_BITS 64 + #define _LARGEFILE_SOURCE + #define _LARGEFILE64_SOURCE + #ifndef _GNU_SOURCE +@@ -34,6 +37,9 @@ + #ifdef __linux__ + #include + #endif ++#if HAVE_SYS_TYPES_H ++#include ++#endif + #ifdef HAVE_SYS_IOCTL_H + #include + #endif +@@ -43,9 +49,6 @@ + #if HAVE_SYS_STAT_H + #include + #endif +-#if HAVE_SYS_TYPES_H +-#include +-#endif + #if HAVE_SYS_RESOURCE_H + #include + #endif +@@ -119,6 +122,8 @@ static errcode_t unix_write_blk64(io_cha + int count, const void *data); + static errcode_t unix_discard(io_channel channel, unsigned long long block, + unsigned long long count); ++static errcode_t unix_readahead(io_channel channel, unsigned long block, ++ int count); + + static struct struct_io_manager struct_unix_manager = { + EXT2_ET_MAGIC_IO_MANAGER, +@@ -135,6 +140,7 @@ static struct struct_io_manager struct_u + unix_read_blk64, + unix_write_blk64, + unix_discard, ++ unix_readahead, + }; + + io_manager unix_io_manager = &struct_unix_manager; +@@ -767,6 +773,20 @@ static errcode_t unix_write_blk64(io_cha + #endif /* NO_IO_CACHE */ + } + ++static errcode_t unix_readahead(io_channel channel, unsigned long block, ++ int count) ++{ ++#ifdef POSIX_FADV_WILLNEED ++ struct unix_private_data *data; ++ ++ data = (struct unix_private_data *)channel->private_data; ++ posix_fadvise(data->dev, (ext2_loff_t)block * channel->block_size, ++ (ext2_loff_t)count * channel->block_size, ++ POSIX_FADV_WILLNEED); ++#endif ++ return 0; ++} ++ + static errcode_t unix_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) + { diff --git a/patches/e2fsprogs-add-trusted-fid.patch b/patches/e2fsprogs-add-trusted-fid.patch new file mode 100644 index 0000000..461e5a0 --- /dev/null +++ b/patches/e2fsprogs-add-trusted-fid.patch @@ -0,0 +1,101 @@ +Index: e2fsprogs/debugfs/debugfs.c +=================================================================== +--- e2fsprogs.orig/debugfs/debugfs.c ++++ e2fsprogs/debugfs/debugfs.c +@@ -494,9 +494,38 @@ static void dump_xattr_string(FILE *out, + fprintf(out, "%02x ", (unsigned char)str[i]); + } + ++#ifdef ENABLE_LFSCK ++#include "ext2fs/lfsck.h" ++ ++static void print_fidstr(FILE *out, ext2_ino_t inode_num, void *data, int len) ++{ ++ static int fid_size_warning; ++ struct filter_fid *ff = data; ++ ++ if (len < sizeof(*ff)) { ++ fprintf(stderr, "%s: error: fid for inode %u smaller than " ++ "expected (%d bytes), recompile?\n", ++ debug_prog_name, inode_num, len); ++ return; ++ } ++ if (len > sizeof(*ff) && !fid_size_warning) { ++ fprintf(stderr, "%s: warning: fid for inode %u larger than " ++ "expected (%d bytes), recompile?\n", ++ debug_prog_name, inode_num, len); ++ fid_size_warning = 1; ++ } ++ fprintf(out, " fid: objid=%llu seq=%llu parent="DFID" stripe=%u\n", ++ ext2fs_le64_to_cpu(ff->ff_objid), ++ ext2fs_le64_to_cpu(ff->ff_seq), ++ ext2fs_le64_to_cpu(ff->ff_parent_seq), ++ ext2fs_le32_to_cpu(ff->ff_parent_oid), /* f_ver */ 0, ++ ext2fs_le32_to_cpu(ff->ff_stripe)); ++} ++#endif /* ENABLE_LFSCK */ ++ + static void internal_dump_inode_extra(FILE *out, + const char *prefix EXT2FS_ATTR((unused)), +- ext2_ino_t inode_num EXT2FS_ATTR((unused)), ++ ext2_ino_t inode_num, + struct ext2_inode_large *inode) + { + struct ext2_ext_attr_entry *entry; +@@ -536,6 +565,16 @@ static void internal_dump_inode_extra(FI + dump_xattr_string(out, start + entry->e_value_offs, + entry->e_value_size); + fprintf(out, "\" (%u)\n", entry->e_value_size); ++#ifdef ENABLE_LFSCK ++ /* Special decoding for Lustre fid */ ++ if ((entry->e_name_index == EXT2_ATTR_INDEX_TRUSTED || ++ entry->e_name_index == EXT2_ATTR_INDEX_LUSTRE) && ++ !strncmp(EXT2_EXT_ATTR_NAME(entry), ++ "fid", entry->e_name_len)) ++ print_fidstr(out, inode_num, ++ start + entry->e_value_offs, ++ entry->e_value_size); ++#endif + entry = next; + } + } +Index: e2fsprogs/lib/ext2fs/lfsck.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/lfsck.h ++++ e2fsprogs/lib/ext2fs/lfsck.h +@@ -42,6 +42,14 @@ + #ifndef IDENTITY_DOWNCALL_MAGIC + #define l_object_seq l_object_gr /* for lov_ost_data_v1 */ + #define lmm_object_seq lmm_object_gr /* for lov_mds_md_v1/3 */ ++#define ff_seq ff_group /* for filter_fid */ ++#define ff_parent_seq ff_fid.id /* for filter_fid */ ++#define ff_parent_oid ff_fid.generation /* for filter_fid */ ++#define ff_stripe ff_fid.f_type /* for filter_fid */ ++#else ++#define ff_parent_seq ff_parent.f_seq /* for filter_fid */ ++#define ff_parent_oid ff_parent.f_oid /* for filter_fid */ ++#define ff_stripe ff_parent.f_ver /* for filter_fid */ + #endif /* IDENTITY_DOWNCALL_MAGIC */ + + /* Unfortunately, neither the 1.8 or 2.x lustre_idl.h file is suitable +Index: e2fsprogs/debugfs/Makefile.in +=================================================================== +--- e2fsprogs.orig/debugfs/Makefile.in ++++ e2fsprogs/debugfs/Makefile.in +@@ -24,6 +24,7 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $ + $(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \ + $(srcdir)/htree.c $(srcdir)/unused.c + ++@LFSCK_CMT@LUSTRE_INC=-I @LUSTRE@/lustre/include -I @LUSTRE@/include -Wall + LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \ + $(LIBUUID) + DEPLIBS= $(LIBEXT2FS) $(LIBE2P) $(DEPLIBSS) $(DEPLIBCOM_ERR) \ +@@ -31,7 +32,7 @@ DEPLIBS= $(LIBEXT2FS) $(LIBE2P) $(DEPLIB + + .c.o: + $(E) " CC $<" +- $(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@ ++ $(Q) $(CC) -c $(ALL_CFLAGS) $(LUSTRE_INC) $< -o $@ + + all:: $(PROGS) $(MANPAGES) + diff --git a/patches/e2fsprogs-attr_cleanup.patch b/patches/e2fsprogs-attr_cleanup.patch new file mode 100644 index 0000000..b216a79 --- /dev/null +++ b/patches/e2fsprogs-attr_cleanup.patch @@ -0,0 +1,536 @@ +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -280,12 +280,11 @@ static void check_ea_in_inode(e2fsck_t c + int problem = 0; + + inode = (struct ext2_inode_large *) pctx->inode; +- storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE - +- inode->i_extra_isize; +- start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + +- inode->i_extra_isize + sizeof(__u32); ++ storage_size = EXT2_INODE_SIZE(ctx->fs->super) - ++ EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize; ++ entry = &IHDR(inode)->h_first_entry[0]; ++ start = (char *)entry; + end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super); +- entry = (struct ext2_ext_attr_entry *) start; + + /* scan all entry's headers first */ + +@@ -403,7 +402,7 @@ static void check_inode_extra_space(e2fs + e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_HIGH); + } + +- eamagic = IHDR(inode); ++ eamagic = &IHDR(inode)->h_magic; + if (*eamagic != EXT2_EXT_ATTR_MAGIC && + (ctx->flags & E2F_FLAG_EXPAND_EISIZE) && + (inode->i_extra_isize < ctx->want_extra_isize)) { +@@ -586,9 +585,8 @@ int e2fsck_pass1_delete_attr(e2fsck_t ct + int in_inode = 1, error; + unsigned int freed_bytes = inode->i_extra_isize; + +- start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + +- inode->i_extra_isize + sizeof(__u32); +- entry_ino = (struct ext2_ext_attr_entry *)start; ++ entry_ino = &IHDR(inode)->h_first_entry[0]; ++ start = (char *)entry_ino; + + if (inode->i_file_acl) { + error = ext2fs_read_ext_attr(ctx->fs, inode->i_file_acl, +Index: e2fsprogs/lib/ext2fs/ext2_ext_attr.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_ext_attr.h ++++ e2fsprogs/lib/ext2fs/ext2_ext_attr.h +@@ -38,9 +38,14 @@ struct ext2_ext_attr_entry { + #endif + }; + ++struct ext2_xattr_ibody_header { ++ __u32 h_magic; /* EXT2_EXT_ATTR_MAGIC */ ++ struct ext2_ext_attr_entry h_first_entry[0]; ++}; ++ + #define BHDR(block) ((struct ext2_ext_attr_header *)block) +-#define IHDR(inode) ((__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE + \ +- (inode)->i_extra_isize)) ++#define IHDR(inode) ((struct ext2_xattr_ibody_header *)((char *)inode + \ ++ EXT2_GOOD_OLD_INODE_SIZE + (inode)->i_extra_isize)) + #define ENTRY(ptr) ((struct ext2_ext_attr_entry *)(ptr)) + + /* Name indexes */ +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -1004,6 +1004,10 @@ extern errcode_t ext2fs_dup_handle(ext2_ + extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); + + /* ext_attr.c */ ++extern errcode_t ext2fs_attr_get(ext2_filsys fs, struct ext2_inode *inode, ++ int name_index, const char *name, char *buffer, ++ size_t buffer_size, int *easize); ++ + extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, + void *data); + int ext2fs_attr_get_next_attr(struct ext2_ext_attr_entry *entry, int name_index, +Index: e2fsprogs/lib/ext2fs/ext_attr.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext_attr.c ++++ e2fsprogs/lib/ext2fs/ext_attr.c +@@ -262,9 +262,12 @@ static errcode_t ext2fs_attr_check_names + return 0; + } + ++/* The unused parameter used to be the blocksize, but with in-inode xattrs ++ * the xattr storage area size depends on where the xattrs are kept. Keep ++ * this parameter for API/ABI compatibility, but it is not needed. */ + static errcode_t ext2fs_attr_find_entry(struct ext2_ext_attr_entry **pentry, + int name_index, const char *name, +- int size, int sorted) ++ int unused, int sorted) + { + struct ext2_ext_attr_entry *entry; + int name_len; +@@ -336,8 +339,6 @@ static errcode_t ext2fs_attr_ibody_find( + struct ext2_attr_info *i, + struct ext2_attr_ibody_find *is) + { +- __u32 *eamagic; +- char *start; + errcode_t error; + + if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE) +@@ -345,17 +346,13 @@ static errcode_t ext2fs_attr_ibody_find( + + if (inode->i_extra_isize == 0) + return 0; +- eamagic = IHDR(inode); + +- start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + +- inode->i_extra_isize + sizeof(__u32); +- is->s.first = (struct ext2_ext_attr_entry *)start; +- is->s.base = start; ++ is->s.first = &IHDR(inode)->h_first_entry[0]; ++ is->s.base = (char *)is->s.first; + is->s.here = is->s.first; + is->s.end = (char *)inode + EXT2_INODE_SIZE(fs->super); +- if (*eamagic == EXT2_EXT_ATTR_MAGIC) { +- error = ext2fs_attr_check_names((struct ext2_ext_attr_entry *) +- start, is->s.end); ++ if (IHDR(inode)->h_magic == EXT2_EXT_ATTR_MAGIC) { ++ error = ext2fs_attr_check_names(is->s.first, is->s.end); + if (error) + return error; + /* Find the named attribute. */ +@@ -573,7 +570,6 @@ static errcode_t ext2fs_attr_ibody_set(e + struct ext2_attr_info *i, + struct ext2_attr_ibody_find *is) + { +- __u32 *eamagic; + struct ext2_attr_search *s = &is->s; + errcode_t error; + +@@ -584,11 +580,10 @@ static errcode_t ext2fs_attr_ibody_set(e + if (error) + return error; + +- eamagic = IHDR(inode); + if (!EXT2_EXT_IS_LAST_ENTRY(s->first)) +- *eamagic = EXT2_EXT_ATTR_MAGIC; ++ IHDR(inode)->h_magic = EXT2_EXT_ATTR_MAGIC; + else +- *eamagic = 0; ++ IHDR(inode)->h_magic = 0; + + return ext2fs_write_inode_full(fs, is->ino, (struct ext2_inode *)inode, + EXT2_INODE_SIZE(fs->super)); +@@ -752,6 +747,7 @@ static errcode_t ext2fs_attr_block_get(e + goto cleanup; + memcpy(buffer, block_buf + entry->e_value_offs, + entry->e_value_size); ++ error = 0; + } + + cleanup: +@@ -760,6 +756,22 @@ cleanup: + return error; + } + ++static errcode_t ext2fs_attr_check_ibody(ext2_filsys fs, ++ struct ext2_inode_large *inode) ++{ ++ const int inode_size = EXT2_INODE_SIZE(fs->super); ++ ++ if (inode_size == EXT2_GOOD_OLD_INODE_SIZE) ++ return EXT2_ET_EA_NAME_NOT_FOUND; ++ ++ if (IHDR(inode)->h_magic != EXT2_EXT_ATTR_MAGIC) ++ return EXT2_ET_EA_BAD_MAGIC; ++ ++ return ext2fs_attr_check_names(&IHDR(inode)->h_first_entry[0], ++ (char *)inode + inode_size); ++} ++ ++ + static errcode_t ext2fs_attr_ibody_get(ext2_filsys fs, + struct ext2_inode_large *inode, + int name_index, const char *name, +@@ -768,26 +780,16 @@ static errcode_t ext2fs_attr_ibody_get(e + { + struct ext2_ext_attr_entry *entry; + int error; +- char *end, *start; +- __u32 *eamagic; +- +- if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE) +- return EXT2_ET_EA_NAME_NOT_FOUND; + +- eamagic = IHDR(inode); +- error = ext2fs_attr_check_block(fs, buffer); ++ error = ext2fs_attr_check_ibody(fs, inode); + if (error) + return error; + +- start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + +- inode->i_extra_isize + sizeof(__u32); +- entry = (struct ext2_ext_attr_entry *)start; +- end = (char *)inode + EXT2_INODE_SIZE(fs->super); +- error = ext2fs_attr_check_names(entry, end); +- if (error) +- goto cleanup; ++ entry = &IHDR(inode)->h_first_entry[0]; ++ + error = ext2fs_attr_find_entry(&entry, name_index, name, +- end - (char *)entry, 0); ++ (char *)inode+EXT2_INODE_SIZE(fs->super)- ++ (char *)entry, 0); + if (error) + goto cleanup; + if (easize) +@@ -796,7 +798,8 @@ static errcode_t ext2fs_attr_ibody_get(e + error = EXT2_ET_EA_TOO_BIG; + if (entry->e_value_size > buffer_size) + goto cleanup; +- memcpy(buffer, start + entry->e_value_offs,entry->e_value_size); ++ memcpy(buffer, &IHDR(inode)->h_first_entry[0] + ++ entry->e_value_offs, entry->e_value_size); + } + + cleanup: +@@ -813,7 +816,7 @@ errcode_t ext2fs_attr_get(ext2_filsys fs + error = ext2fs_attr_ibody_get(fs, (struct ext2_inode_large *)inode, + name_index, name, buffer, buffer_size, + easize); +- if (error == EXT2_ET_EA_NAME_NOT_FOUND) ++ if (error == EXT2_ET_EA_NAME_NOT_FOUND || error == EXT2_ET_EA_BAD_MAGIC) + error = ext2fs_attr_block_get(fs, inode, name_index, name, + buffer, buffer_size, easize); + +@@ -856,7 +859,6 @@ errcode_t ext2fs_expand_extra_isize(ext2 + int *needed_size) + { + struct ext2_inode *inode_buf = NULL; +- __u32 *eamagic = NULL; + struct ext2_ext_attr_header *header = NULL; + struct ext2_ext_attr_entry *entry = NULL, *last = NULL; + struct ext2_attr_ibody_find is = { +@@ -894,10 +896,9 @@ retry: + if (inode->i_extra_isize >= new_extra_isize) + goto cleanup; + +- eamagic = IHDR(inode); + start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize; + /* No extended attributes present */ +- if (*eamagic != EXT2_EXT_ATTR_MAGIC) { ++ if (IHDR(inode)->h_magic != EXT2_EXT_ATTR_MAGIC) { + memset(start, 0, + EXT2_INODE_SIZE(fs->super) - EXT2_GOOD_OLD_INODE_SIZE - + inode->i_extra_isize); +Index: e2fsprogs/lib/ext2fs/Makefile.in +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/Makefile.in ++++ e2fsprogs/lib/ext2fs/Makefile.in +@@ -152,6 +152,7 @@ SRCS= ext2_err.c \ + $(srcdir)/tst_byteswap.c \ + $(srcdir)/tst_getsize.c \ + $(srcdir)/tst_iscan.c \ ++ $(srcdir)/tst_read_ea.c \ + $(srcdir)/undo_io.c \ + $(srcdir)/unix_io.c \ + $(srcdir)/unlink.c \ +@@ -224,6 +225,10 @@ tst_iscan: tst_iscan.o $(STATIC_LIBEXT2F + $(E) " LD $@" + $(Q) $(CC) -o tst_iscan tst_iscan.o $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) + ++tst_read_ea: tst_read_ea.o $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR) ++ $(E) " LD $@" ++ $(Q) $(CC) -o tst_read_ea tst_read_ea.o $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) ++ + tst_getsize: tst_getsize.o $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR) + $(E) " LD $@" + $(Q) $(CC) -o tst_getsize tst_getsize.o $(STATIC_LIBEXT2FS) \ +@@ -339,7 +344,7 @@ mkjournal: mkjournal.c $(STATIC_LIBEXT2F + $(E) " LD $@" + $(Q) $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS) + +-check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount tst_super_size tst_types tst_csum ++check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount tst_super_size tst_types tst_csum tst_read_ea + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_bitops + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_badblocks + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_iscan +@@ -347,6 +352,7 @@ check:: tst_bitops tst_badblocks tst_isc + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_icount + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_super_size + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_csum ++ LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_read_ea + + installdirs:: + $(E) " MKINSTALLDIRS $(libdir) $(includedir)/ext2fs" +@@ -379,7 +385,7 @@ clean:: + tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \ + tst_byteswap tst_ismounted tst_getsize tst_sectgetsize \ + tst_bitops tst_types tst_icount tst_super_size tst_csum \ +- ext2_tdbtool mkjournal debug_cmds.c \ ++ tst_read_ea ext2_tdbtool mkjournal debug_cmds.c \ + ../libext2fs.a ../libext2fs_p.a ../libext2fs_chk.a + + mostlyclean:: clean +@@ -736,6 +742,11 @@ tst_iscan.o: $(srcdir)/tst_iscan.c $(src + $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h ++tst_read_ea.o: $(srcdir)/tst_read_ea.c $(srcdir)/ext2_fs.h \ ++ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ ++ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ ++ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ ++ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h + undo_io.o: $(srcdir)/undo_io.c $(srcdir)/tdb.h $(srcdir)/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ +Index: e2fsprogs/lib/ext2fs/tst_read_ea.c +=================================================================== +--- /dev/null ++++ e2fsprogs/lib/ext2fs/tst_read_ea.c +@@ -0,0 +1,219 @@ ++/* ++ * tst_getsize.c --- this function tests the getsize function ++ * ++ * %Begin-Header% ++ * This file may be redistributed under the terms of the GNU Public ++ * License. ++ * %End-Header% ++ */ ++ ++#include ++#include ++#if HAVE_UNISTD_H ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#if HAVE_ERRNO_H ++#include ++#endif ++ ++#include "ext2_fs.h" ++#include "ext2fs.h" ++ ++#define NR_XATTRS 256 ++char tmpvalue[NR_XATTRS + 1]; ++ ++struct ea { ++ char *name; ++ char *value; ++}; ++ ++struct ea *ea_table; ++ ++static void init_ea_table(void) ++{ ++ int i; ++ ++ ea_table = malloc(sizeof(struct ea) * NR_XATTRS); ++ if (ea_table == NULL) { ++ perror("maloc failed"); ++ exit(1); ++ } ++ for (i = 0; i < NR_XATTRS; i ++) { ++ ea_table[i].name = malloc(i + 2 + strlen("user.")); ++ if (ea_table[i].name == NULL) { ++ perror("malloc failed"); ++ exit(1); ++ } ++ strcpy(ea_table[i].name, "user."); ++ memset(ea_table[i].name + strlen("user."), 'X', i + 1); ++ ea_table[i].name[i + 1 + strlen("user.")] = 0; ++ ++ ea_table[i].value = malloc(NR_XATTRS - i + 1); ++ if (ea_table[i].value == NULL) { ++ perror("malloc failed"); ++ exit(1); ++ } ++ memset(ea_table[i].value, 'Y', NR_XATTRS - i); ++ ea_table[i].value[NR_XATTRS - i] = 0; ++ } ++} ++ ++static int set_xattrs(int fd) ++{ ++ int i; ++ ++ for (i = 0; i < NR_XATTRS; i ++) { ++ if (fsetxattr(fd, ea_table[i].name, ea_table[i].value, ++ NR_XATTRS - i + 1, XATTR_CREATE) == -1) { ++ if (errno != ENOSPC) { ++ perror("fsetxattr failed"); ++ exit(1); ++ } ++ break; ++ } ++ } ++ printf("\t%d xattrs are set\n", i); ++ return i; ++} ++ ++void get_xattrs1(int fd, int nr) ++{ ++ int i; ++ ssize_t size; ++ ++ printf("\ttesting fgetxattr .. "); fflush(stdout); ++ ++ for (i = 0; i < nr; i ++) { ++ size = fgetxattr(fd, ea_table[i].name, tmpvalue, ++ NR_XATTRS - i + 1); ++ if (size == -1) { ++ perror("fgetxattr failed"); ++ exit(1); ++ } ++ if (memcmp(ea_table[i].value, tmpvalue, nr - i + 1)) { ++ fprintf(stderr, "value mismatch"); ++ exit(1); ++ } ++ } ++ ++ printf("%d xattrs are checked, ok\n", i); ++} ++ ++void get_xattrs2(const char *device, ext2_ino_t ino, int nr) ++{ ++ ext2_filsys fs; ++ int i; ++ struct ext2_inode *inode; ++ errcode_t err; ++ int size; ++ ++ printf("\ttesting ext2fs_attr_get .. "); fflush(stdout); ++ ++ err = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs); ++ assert(err == 0); ++ ++ err = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode); ++ if (err) { ++ com_err("get_xattrs2", err, "allocating memory"); ++ exit(1); ++ } ++ ++ err = ext2fs_read_inode_full(fs, ino, inode, ++ EXT2_INODE_SIZE(fs->super)); ++ if (err) { ++ com_err("get_xattrs2", err, "reading inode"); ++ exit(1); ++ } ++ for (i = 0; i < nr; i ++) { ++ err = ext2fs_attr_get(fs, inode, EXT2_ATTR_INDEX_USER, ++ ea_table[i].name + strlen("user."), ++ tmpvalue, sizeof(tmpvalue), &size); ++ if (err) { ++ com_err("get_xattrs2", err, "getting xattr"); ++ exit(1); ++ } ++ assert(size == (NR_XATTRS - i + 1)); ++ ++ if (memcmp(ea_table[i].value, tmpvalue, size)) { ++ fprintf(stderr, "value mismatch"); ++ exit(1); ++ } ++ } ++ ext2fs_close(fs); ++ ++ printf("%d xattrs are checked, ok\n", i); ++} ++ ++int main(int argc, const char *argv[]) ++{ ++ ext2_filsys fs; ++ FILE *f; ++ struct mntent *mnt; ++ char *name; ++ int fd; ++ errcode_t err; ++ struct stat st; ++ int nr; ++ int tested = 0; ++ ++ initialize_ext2_error_table(); ++ ++ init_ea_table(); ++ ++ f = setmntent(MOUNTED, "r"); ++ if (!f) { ++ fprintf(stderr, "failed to setmntent\n"); ++ return 1; ++ } ++ ++ while ((mnt = getmntent(f)) != NULL) { ++ if (hasmntopt(mnt, "user_xattr") == NULL) ++ continue; ++ err = ext2fs_open(mnt->mnt_fsname, 0, 0, 0, ++ unix_io_manager, &fs); ++ if (err) { ++ com_err("tst_read_ea", err, ++ "opening fs %s:%s", ++ mnt->mnt_fsname, mnt->mnt_type); ++ continue; ++ } ++ ext2fs_close(fs); ++ ++ printf("(%s)%s:%s\n", mnt->mnt_type, mnt->mnt_fsname, mnt->mnt_dir); ++ ++ asprintf(&name, "%s/readeaXXXXXX", mnt->mnt_dir); ++ fd = mkstemp(name); ++ if (fd == -1) { ++ perror("mkstemp failed"); ++ exit(1); ++ } ++ if (fstat(fd, &st)) { ++ perror("fstat failed"); ++ exit(1); ++ } ++ nr = set_xattrs(fd); ++ ++ sync(); ++ get_xattrs1(fd, nr); ++ close(fd); ++ ++ get_xattrs2(mnt->mnt_fsname, st.st_ino, nr); ++ ++ unlink(name); ++ free(name); ++ tested = 1; ++ } ++ endmntent(f); ++ ++ if (!tested) ++ fprintf(stderr, ++ "\tno ext2 based filesystems mounted with user_xattr\n" ++ "\thope it is ok\n"); ++ return 0; ++} diff --git a/patches/e2fsprogs-bad-ininode-ea.patch b/patches/e2fsprogs-bad-ininode-ea.patch new file mode 100644 index 0000000..5ee01d2 --- /dev/null +++ b/patches/e2fsprogs-bad-ininode-ea.patch @@ -0,0 +1,51 @@ +Add check for in-inode xattr to make sure that it is not referencing an offset +that is beyond the end of the inode. + +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -319,6 +319,13 @@ static void check_ea_in_inode(e2fsck_t c + goto fix; + } + ++ /* Value size cannot be larger than EA space in inode */ ++ if (entry->e_value_offs > storage_size || ++ entry->e_value_offs + entry->e_value_size > storage_size) { ++ problem = PR_1_INODE_EA_BAD_VALUE; ++ goto fix; ++ } ++ + hash = ext2fs_ext_attr_hash_entry(entry, + start + entry->e_value_offs); + +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -890,6 +890,11 @@ static struct e2fsck_problem problem_tab + "(size %Is, lblk %r)\n"), + PROMPT_CLEAR, PR_PREEN_OK }, + ++ /* Bad extended attribute value in inode */ ++ { PR_1_INODE_EA_BAD_VALUE, ++ N_("@a in @i %i is corrupt (@n value)."), ++ PROMPT_CLEAR, 0}, ++ + /* Pass 1b errors */ + + /* Pass 1B: Rescan for duplicate/bad blocks */ +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -520,6 +520,9 @@ struct problem_context { + /* EOFBLOCKS flag set when not necessary */ + #define PR_1_EOFBLOCKS_FL_SET 0x010060 + ++/* Bad extended attribute value in inode */ ++#define PR_1_INODE_EA_BAD_VALUE 0x010061 ++ + /* + * Pass 1b errors + */ diff --git a/patches/e2fsprogs-bigjournal.patch b/patches/e2fsprogs-bigjournal.patch new file mode 100644 index 0000000..db69e55 --- /dev/null +++ b/patches/e2fsprogs-bigjournal.patch @@ -0,0 +1,382 @@ +Allow an internal journal size larger than 2^32 bytes. The +write_journal_inode() code is only setting the low 32-bit i_size for +the journal size, fix it to set i_size_high also. + +Use s_jnl_blocks[15] to store the journal i_size_high backup. This +field is currently unused, as EXT2_N_BLOCKS is 15, so it is using +s_jnl_blocks[0..14], and i_size is in s_jnl_blocks[16]. + +Rename the "size" argument to "blocks" for the journal creation functions +to make it clear that this parameter is in units of blocks and not bytes. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/debugfs/logdump.c +=================================================================== +--- e2fsprogs.orig/debugfs/logdump.c ++++ e2fsprogs/debugfs/logdump.c +@@ -209,6 +209,7 @@ void do_logdump(int argc, char **argv) + memset(&journal_inode, 0, sizeof(struct ext2_inode)); + memcpy(&journal_inode.i_block[0], es->s_jnl_blocks, + EXT2_N_BLOCKS*4); ++ journal_inode.i_size_high = es->s_jnl_blocks[15]; + journal_inode.i_size = es->s_jnl_blocks[16]; + journal_inode.i_links_count = 1; + journal_inode.i_mode = LINUX_S_IFREG | 0600; +Index: e2fsprogs/e2fsck/journal.c +=================================================================== +--- e2fsprogs.orig/e2fsck/journal.c ++++ e2fsprogs/e2fsck/journal.c +@@ -288,6 +288,7 @@ static errcode_t e2fsck_get_journal(e2fs + memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode)); + memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks, + EXT2_N_BLOCKS*4); ++ j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15]; + j_inode->i_ext2.i_size = sb->s_jnl_blocks[16]; + j_inode->i_ext2.i_links_count = 1; + j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600; +@@ -301,7 +302,7 @@ static errcode_t e2fsck_get_journal(e2fs + retval = EXT2_ET_NO_JOURNAL; + goto try_backup_journal; + } +- if (j_inode->i_ext2.i_size / journal->j_blocksize < ++ if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize < + JFS_MIN_JOURNAL_BLOCKS) { + retval = EXT2_ET_JOURNAL_TOO_SMALL; + goto try_backup_journal; +@@ -310,8 +311,8 @@ static errcode_t e2fsck_get_journal(e2fs + retval = ext2fs_block_iterate3(ctx->fs, j_inode->i_ino, + BLOCK_FLAG_HOLE, 0, + process_journal_block, &pb); +- if ((pb.last_block+1) * ctx->fs->blocksize < +- j_inode->i_ext2.i_size) { ++ if ((pb.last_block + 1) * ctx->fs->blocksize < ++ EXT2_I_SIZE(&j_inode->i_ext2)) { + retval = EXT2_ET_JOURNAL_TOO_SMALL; + goto try_backup_journal; + } +@@ -322,7 +323,8 @@ static errcode_t e2fsck_get_journal(e2fs + goto errout; + } + +- journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize; ++ journal->j_maxlen = EXT2_I_SIZE(&j_inode->i_ext2) / ++ journal->j_blocksize; + + #ifdef USE_INODE_IO + retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum, +@@ -943,6 +945,7 @@ void e2fsck_move_ext3_journal(e2fsck_t c + if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) { + memcpy(sb->s_jnl_blocks, inode.i_block, + EXT2_N_BLOCKS*4); ++ sb->s_jnl_blocks[15] = inode.i_size_high; + sb->s_jnl_blocks[16] = inode.i_size; + sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; + ext2fs_mark_super_dirty(fs); +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -1374,7 +1374,8 @@ print_unsupp_features: + * find the default journal size. + */ + if (sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) +- journal_size = sb->s_jnl_blocks[16] >> 20; ++ journal_size = (sb->s_jnl_blocks[15] << (32 - 20)) | ++ (sb->s_jnl_blocks[16] >> 20); + else + journal_size = -1; + +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -1250,11 +1250,11 @@ extern errcode_t ext2fs_zero_blocks(ext2 + extern errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num, + blk64_t *ret_blk, int *ret_count); + extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, +- __u32 size, int flags, ++ __u32 blocks, int flags, + char **ret_jsb); + extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, + ext2_filsys journal_dev); +-extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, ++extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t blocks, + int flags); + extern int ext2fs_default_journal_size(__u64 blocks); + +Index: e2fsprogs/lib/ext2fs/mkjournal.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/mkjournal.c ++++ e2fsprogs/lib/ext2fs/mkjournal.c +@@ -42,13 +42,13 @@ + * returns it as an allocated block. + */ + errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, +- __u32 size, int flags, ++ __u32 blocks, int flags, + char **ret_jsb) + { + errcode_t retval; + journal_superblock_t *jsb; + +- if (size < 1024) ++ if (blocks < 1024) + return EXT2_ET_JOURNAL_TOO_SMALL; + + if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) +@@ -62,7 +62,7 @@ errcode_t ext2fs_create_journal_superblo + else + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); + jsb->s_blocksize = htonl(fs->blocksize); +- jsb->s_maxlen = htonl(size); ++ jsb->s_maxlen = htonl(blocks); + jsb->s_nr_users = htonl(1); + jsb->s_first = htonl(1); + jsb->s_sequence = htonl(1); +@@ -90,14 +90,14 @@ errcode_t ext2fs_create_journal_superblo + * filesystems. + */ + static errcode_t write_journal_file(ext2_filsys fs, char *filename, +- blk_t size, int flags) ++ blk_t blocks, int flags) + { + errcode_t retval; + char *buf = 0; + int fd, ret_size; + blk_t i; + +- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) ++ if ((retval = ext2fs_create_journal_superblock(fs, blocks, flags,&buf))) + return retval; + + /* Open the device or journal file */ +@@ -117,7 +117,7 @@ static errcode_t write_journal_file(ext2 + goto errout; + memset(buf, 0, fs->blocksize); + +- for (i = 1; i < size; i++) { ++ for (i = 1; i < blocks; i++) { + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { + retval = errno; +@@ -284,15 +284,16 @@ static int mkjournal_proc(ext2_filsys fs + * This function creates a journal using direct I/O routines. + */ + static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, +- blk64_t size, int flags) ++ blk_t blocks, int flags) + { + char *buf; + dgrp_t group, start, end, i, log_flex; + errcode_t retval; + struct ext2_inode inode; ++ unsigned long long inode_size; + struct mkjournal_struct es; + +- if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) ++ if ((retval = ext2fs_create_journal_superblock(fs, blocks, flags, &buf))) + return retval; + + if ((retval = ext2fs_read_bitmaps(fs))) +@@ -304,7 +305,7 @@ static errcode_t write_journal_inode(ext + if (inode.i_blocks > 0) + return EEXIST; + +- es.num_blocks = size; ++ es.num_blocks = blocks; + es.newblocks = 0; + es.buf = buf; + es.err = 0; +@@ -360,7 +361,12 @@ static errcode_t write_journal_inode(ext + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) + goto errout; + +- inode.i_size += fs->blocksize * size; ++ inode_size = (unsigned long long)fs->blocksize * blocks; ++ inode.i_size = inode_size & 0xFFFFFFFF; ++ inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; ++ if (inode.i_size_high) ++ fs->super->s_feature_ro_compat |= ++ EXT2_FEATURE_RO_COMPAT_LARGE_FILE; + ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); + inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); + inode.i_links_count = 1; +@@ -371,6 +377,7 @@ static errcode_t write_journal_inode(ext + retval = 0; + + memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); ++ fs->super->s_jnl_blocks[15] = inode.i_size_high; + fs->super->s_jnl_blocks[16] = inode.i_size; + fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; + ext2fs_mark_super_dirty(fs); +@@ -467,7 +474,7 @@ errcode_t ext2fs_add_journal_device(ext2 + * POSIX routines if the filesystem is mounted, or using direct I/O + * functions if it is not. + */ +-errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) ++errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t blocks, int flags) + { + errcode_t retval; + ext2_ino_t journal_ino; +@@ -504,7 +511,7 @@ errcode_t ext2fs_add_journal_inode(ext2_ + if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) + return errno; + +- if ((retval = write_journal_file(fs, jfile, size, flags))) ++ if ((retval = write_journal_file(fs, jfile, blocks, flags))) + goto errout; + + /* Get inode number of the journal file */ +@@ -544,7 +551,7 @@ errcode_t ext2fs_add_journal_inode(ext2_ + } + journal_ino = EXT2_JOURNAL_INO; + if ((retval = write_journal_inode(fs, journal_ino, +- size, flags))) ++ blocks, flags))) + return retval; + } + +Index: e2fsprogs/lib/ext2fs/swapfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/swapfs.c ++++ e2fsprogs/lib/ext2fs/swapfs.c +@@ -81,16 +81,16 @@ void ext2fs_swap_super(struct ext2_super + sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); + + /* if journal backup is for a valid extent-based journal... */ +- if (!ext2fs_extent_header_verify(sb->s_jnl_blocks, +- sizeof(sb->s_jnl_blocks))) { +- /* ... swap only the journal i_size */ +- sb->s_jnl_blocks[16] = ext2fs_swab32(sb->s_jnl_blocks[16]); +- /* and the extent data is not swapped on read */ +- return; ++ if (ext2fs_extent_header_verify(sb->s_jnl_blocks, ++ sizeof(sb->s_jnl_blocks)) == 0) { ++ /* ... swap only the journal i_size and i_size_high, ++ * and the extent data is not swapped on read */ ++ i = 15; ++ } else { ++ /* direct/indirect journal: swap it all */ ++ i = 0; + } +- +- /* direct/indirect journal: swap it all */ +- for (i=0; i < 17; i++) ++ for (; i < 17; i++) + sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); + } + +Index: e2fsprogs/resize/resize2fs.c +=================================================================== +--- e2fsprogs.orig/resize/resize2fs.c ++++ e2fsprogs/resize/resize2fs.c +@@ -1879,6 +1879,7 @@ static errcode_t fix_sb_journal_backup(e + if (retval) + return retval; + memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); ++ fs->super->s_jnl_blocks[15] = inode.i_size_high; + fs->super->s_jnl_blocks[16] = inode.i_size; + fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; + ext2fs_mark_super_dirty(fs); +Index: e2fsprogs/tests/m_extent_journal/expect.1 +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/m_extent_journal/expect.1 +@@ -0,0 +1,84 @@ ++Filesystem label= ++OS type: Linux ++Block size=2048 (log=1) ++Fragment size=2048 (log=1) ++Stride=0 blocks, Stripe width=0 blocks ++16384 inodes, 32768 blocks ++1638 blocks (5.00%) reserved for the super user ++First data block=0 ++Maximum filesystem blocks=33554432 ++2 block groups ++16384 blocks per group, 16384 fragments per group ++8192 inodes per group ++Superblock backups stored on blocks: ++ 16384 ++ ++Allocating group tables: 0/21/2 done ++Writing inode tables: 0/21/2 done ++Creating journal (4096 blocks): done ++Writing superblocks and filesystem accounting information: 0/21/2 done ++ ++0/21/2 Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent sparse_super ++ ++Pass 1: Checking inodes, blocks, and sizes ++Pass 2: Checking directory structure ++Pass 3: Checking directory connectivity ++Pass 4: Checking reference counts ++Pass 5: Checking group summary information ++test_filesys: 11/16384 files (0.0% non-contiguous), 5200/32768 blocks ++Exit status is 0 ++ ++Filesystem volume name: ++Last mounted on: ++Filesystem magic number: 0xEF53 ++Filesystem revision #: 1 (dynamic) ++Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent sparse_super ++Default mount options: (none) ++Filesystem state: clean ++Errors behavior: Continue ++Filesystem OS type: Linux ++Inode count: 16384 ++Block count: 32768 ++Reserved block count: 1638 ++Free blocks: 27568 ++Free inodes: 16373 ++First block: 0 ++Block size: 2048 ++Fragment size: 2048 ++Reserved GDT blocks: 31 ++Blocks per group: 16384 ++Fragments per group: 16384 ++Inodes per group: 8192 ++Inode blocks per group: 512 ++Mount count: 0 ++Check interval: 15552000 (6 months) ++Reserved blocks uid: 0 ++Reserved blocks gid: 0 ++First inode: 11 ++Inode size: 128 ++Journal inode: 8 ++Default directory hash: half_md4 ++Journal backup: inode blocks ++Journal features: (none) ++Journal size: 8M ++Journal length: 4096 ++Journal sequence: 0x00000001 ++Journal start: 0 ++ ++ ++Group 0: (Blocks 0-16383) ++ Primary superblock at 0, Group descriptors at 1-1 ++ Reserved GDT blocks at 2-32 ++ Block bitmap at 33 (+33), Inode bitmap at 34 (+34) ++ Inode table at 35-546 (+35) ++ 15827 free blocks, 8181 free inodes, 2 directories ++ Free blocks: 557-16383 ++ Free inodes: 12-8192 ++Group 1: (Blocks 16384-32767) ++ Backup superblock at 16384, Group descriptors at 16385-16385 ++ Reserved GDT blocks at 16386-16416 ++ Block bitmap at 16417 (+33), Inode bitmap at 16418 (+34) ++ Inode table at 16419-16930 (+35) ++ 11741 free blocks, 8192 free inodes, 0 directories ++ Free blocks: 21027-32767 ++ Free inodes: 8193-16384 +Index: e2fsprogs/tests/m_extent_journal/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/m_extent_journal/script +@@ -0,0 +1,7 @@ ++DESCRIPTION="extent-mapped journal" ++FS_SIZE=65536 ++MKE2FS_DEVICE_SECTSIZE=2048 ++export MKE2FS_DEVICE_SECTSIZE ++MKE2FS_OPTS="-O extents -j" ++. $cmd_dir/run_mke2fs ++unset MKE2FS_DEVICE_SECTSIZE diff --git a/patches/e2fsprogs-blkid-zfs.patch b/patches/e2fsprogs-blkid-zfs.patch new file mode 100644 index 0000000..581ab4e --- /dev/null +++ b/patches/e2fsprogs-blkid-zfs.patch @@ -0,0 +1,59 @@ +Fix the ZFS device detection by looking at multiple uberblocks to see if +any are present, rather than looking for the ZFS boot block which is not +always present. + +There may be up to 128 uberblocks, but the first 4 are not written to disk +on a newly-formatted filesystem so check several of them at different +offsets within the uberblock array. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/blkid/probe.h +=================================================================== +--- e2fsprogs.orig/lib/blkid/probe.h ++++ e2fsprogs/lib/blkid/probe.h +@@ -193,6 +193,16 @@ struct jfs_super_block { + unsigned char js_loguuid[16]; + }; + ++#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */ ++struct zfs_uberblock { ++ __u64 ub_magic; /* UBERBLOCK_MAGIC */ ++ __u64 ub_version; /* ZFS_VERSION */ ++ __u64 ub_txg; /* txg of last sync */ ++ __u64 ub_guid_sum; /* sum of all vdev guids */ ++ __u64 ub_timestamp; /* UTC time of last sync */ ++ char ub_rootbp; /* MOS objset_phys_t */ ++}; ++ + struct romfs_super_block { + unsigned char ros_magic[8]; + __u32 ros_dummy1[2]; +Index: e2fsprogs/lib/blkid/probe.c +=================================================================== +--- e2fsprogs.orig/lib/blkid/probe.c ++++ e2fsprogs/lib/blkid/probe.c +@@ -1434,10 +1434,19 @@ static struct blkid_magic type_array[] = + { "iso9660", 32, 1, 5, "CD001", probe_iso9660 }, + { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 }, + { "jfs", 32, 0, 4, "JFS1", probe_jfs }, +- { "zfs", 8, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs }, +- { "zfs", 8, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs }, +- { "zfs", 264, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs }, +- { "zfs", 264, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs }, ++ /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */ ++ { "zfs", 128, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 128, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, ++ { "zfs", 132, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 132, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, ++ { "zfs", 136, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 136, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, ++ { "zfs", 384, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 384, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, ++ { "zfs", 388, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 388, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, ++ { "zfs", 392, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs }, ++ { "zfs", 392, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs }, + { "hfsplus", 1, 0, 2, "BD", probe_hfsplus }, + { "hfsplus", 1, 0, 2, "H+", probe_hfsplus }, + { "hfsplus", 1, 0, 2, "HX", probe_hfsplus }, diff --git a/patches/e2fsprogs-config-before-cmdline.patch b/patches/e2fsprogs-config-before-cmdline.patch new file mode 100644 index 0000000..e098fae --- /dev/null +++ b/patches/e2fsprogs-config-before-cmdline.patch @@ -0,0 +1,55 @@ +The patch changes the order that the config file and command line are +parsed so that command line has precedence. It also parses the -E +option for every occurrence, otherwise the -E option is not cumulative. + +Signed-off-by: Jim Garlick +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -654,7 +654,6 @@ static errcode_t PRS(int argc, char *arg + #ifdef HAVE_SIGNAL_H + struct sigaction sa; + #endif +- char *extended_opts = 0; + char *cp; + int res; /* result of sscanf */ + #ifdef CONFIG_JBD_DEBUG +@@ -686,6 +685,12 @@ static errcode_t PRS(int argc, char *arg + else + ctx->program_name = "e2fsck"; + ++ if ((cp = getenv("E2FSCK_CONFIG")) != NULL) ++ config_fn[0] = cp; ++ profile_set_syntax_err_cb(syntax_err_report); ++ profile_init(config_fn, &ctx->profile); ++ ++ + while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF) + switch (c) { + case 'C': +@@ -716,7 +721,7 @@ static errcode_t PRS(int argc, char *arg + ctx->options |= E2F_OPT_COMPRESS_DIRS; + break; + case 'E': +- extended_opts = optarg; ++ parse_extended_opts(ctx, optarg); + break; + case 'p': + case 'a': +@@ -851,13 +856,6 @@ static errcode_t PRS(int argc, char *arg + argv[optind]); + fatal_error(ctx, 0); + } +- if (extended_opts) +- parse_extended_opts(ctx, extended_opts); +- +- if ((cp = getenv("E2FSCK_CONFIG")) != NULL) +- config_fn[0] = cp; +- profile_set_syntax_err_cb(syntax_err_report); +- profile_init(config_fn, &ctx->profile); + + if (flush) { + fd = open(ctx->filesystem_name, O_RDONLY, 0); diff --git a/patches/e2fsprogs-count_wrong_valid.patch b/patches/e2fsprogs-count_wrong_valid.patch new file mode 100644 index 0000000..eb44569 --- /dev/null +++ b/patches/e2fsprogs-count_wrong_valid.patch @@ -0,0 +1,52 @@ +Don't consider only an error in the superblock summary as incorrect. +The kernel does not update this field except at unmount time. Any +other unfixed errors will themselves mark the filesystem invalid. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/pass5.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass5.c ++++ e2fsprogs/e2fsck/pass5.c +@@ -401,8 +401,7 @@ redo_counts: + if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { + ext2fs_free_blocks_count_set(fs->super, free_blocks); + ext2fs_mark_super_dirty(fs); +- } else +- ext2fs_unmark_valid(fs); ++ } + } + errout: + ext2fs_free_mem(&free_array); +@@ -679,8 +678,7 @@ do_counts: + if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { + fs->super->s_free_inodes_count = free_inodes; + ext2fs_mark_super_dirty(fs); +- } else +- ext2fs_unmark_valid(fs); ++ } + } + errout: + ext2fs_free_mem(&free_array); +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -1571,7 +1571,7 @@ static struct e2fsck_problem problem_tab + /* Free inodes count wrong */ + { PR_5_FREE_INODE_COUNT, + N_("Free @is count wrong (%i, counted=%j).\n"), +- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, ++ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG }, + + /* Free blocks count for group wrong */ + { PR_5_FREE_BLOCK_COUNT_GROUP, +@@ -1581,7 +1581,7 @@ static struct e2fsck_problem problem_tab + /* Free blocks count wrong */ + { PR_5_FREE_BLOCK_COUNT, + N_("Free @bs count wrong (%b, counted=%c).\n"), +- PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, ++ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG }, + + /* Programming error: bitmap endpoints don't match */ + { PR_5_BMAP_ENDPOINTS, diff --git a/patches/e2fsprogs-data_in_dirent.patch b/patches/e2fsprogs-data_in_dirent.patch new file mode 100644 index 0000000..bb2db8b --- /dev/null +++ b/patches/e2fsprogs-data_in_dirent.patch @@ -0,0 +1,567 @@ +Index: e2fsprogs/lib/blkid/probe.h +=================================================================== +--- e2fsprogs.orig/lib/blkid/probe.h ++++ e2fsprogs/lib/blkid/probe.h +@@ -120,6 +120,7 @@ struct ext2_super_block { + #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 + #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 + #define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 ++#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 + + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ +Index: e2fsprogs/lib/e2p/feature.c +=================================================================== +--- e2fsprogs.orig/lib/e2p/feature.c ++++ e2fsprogs/lib/e2p/feature.c +@@ -78,6 +78,8 @@ static struct feature feature_list[] = { + "mmp" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE, + "large_xattr" }, ++ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA, ++ "dirdata" }, + { 0, 0, 0 }, + }; + +Index: e2fsprogs/lib/ext2fs/ext2_fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_fs.h ++++ e2fsprogs/lib/ext2fs/ext2_fs.h +@@ -698,13 +698,27 @@ struct ext2_super_block { + #define EXT2_FEATURE_COMPAT_SUPP 0 + #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT4_FEATURE_INCOMPAT_MMP|\ +- EXT4_FEATURE_INCOMPAT_EA_INODE) ++ EXT4_FEATURE_INCOMPAT_EA_INODE|\ ++ EXT4_FEATURE_INCOMPAT_DIRDATA) + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) + ++#define EXT2_FT_MASK 0x0f ++ ++/* lu_fid size and NUL char */ ++#define EXT2_DIRENT_LUFID_SIZE (17 + 1) ++#define EXT2_DIRENT_LUFID 0x10 ++#define EXT2_DIR_PAD 4 ++#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) ++#define __EXT2_DIR_REC_LEN(len) (((len) + 8 + EXT2_DIR_ROUND) & \ ++ ~EXT2_DIR_ROUND) ++ ++#define EXT2_DIR_REC_LEN(de) (__EXT2_DIR_REC_LEN(de->name_len +\ ++ ext2_get_dirent_size(de))) ++ + /* + * Default values for user and/or group using reserved blocks + */ +@@ -770,16 +784,6 @@ struct ext2_dir_entry_2 { + #define EXT2_FT_MAX 8 + + /* +- * EXT2_DIR_PAD defines the directory entries boundaries +- * +- * NOTE: It must be a multiple of 4 +- */ +-#define EXT2_DIR_PAD 4 +-#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ +- ~EXT2_DIR_ROUND) +- +-/* + * This structure will be used for multiple mount protection. It will be + * written into the block number saved in the s_mmp_block field in the + * superblock. Programs that check MMP should assume that if SEQ_FSCK +@@ -812,4 +816,7 @@ struct mmp_struct { + */ + #define EXT2_MMP_MIN_CHECK_INTERVAL 5 + ++int ext2_get_dirent_dirdata_size(struct ext2_dir_entry_2 *de, char dirdata_flags); ++int ext2_get_dirent_size(struct ext2_dir_entry_2 *de); ++ + #endif /* _LINUX_EXT2_FS_H */ +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -572,6 +572,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ + EXT4_FEATURE_INCOMPAT_MMP|\ + EXT4_FEATURE_INCOMPAT_EA_INODE|\ ++ EXT4_FEATURE_INCOMPAT_DIRDATA|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #else + #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ +@@ -582,6 +583,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ + EXT4_FEATURE_INCOMPAT_MMP|\ + EXT4_FEATURE_INCOMPAT_EA_INODE|\ ++ EXT4_FEATURE_INCOMPAT_DIRDATA|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #endif + #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ +@@ -1641,6 +1643,24 @@ _INLINE_ __u64 ext2fs_div64_ceil(__u64 a + return ((a - 1) / b) + 1; + } + ++ ++_INLINE_ struct ext2_dx_root_info* get_ext2_dx_root_info(ext2_filsys fs, char *buf) ++{ ++ struct ext2_dir_entry_2 * de = (struct ext2_dir_entry_2 *) buf; ++ ++ if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA)) ++ return (struct ext2_dx_root_info *)(buf + ++ __EXT2_DIR_REC_LEN(1) +__EXT2_DIR_REC_LEN(2)); ++ ++ /* get dotdot first */ ++ de = (struct ext2_dir_entry_2 *)((char *)de + de->rec_len); ++ ++ /* dx root info is after dotdot entry */ ++ de = (struct ext2_dir_entry_2 *)((char *)de + EXT2_DIR_REC_LEN(de)); ++ ++ return (struct ext2_dx_root_info*) de; ++} ++ + #undef _INLINE_ + #endif + +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -815,6 +815,7 @@ static __u32 ok_features[3] = { + EXT4_FEATURE_INCOMPAT_FLEX_BG| + EXT4_FEATURE_INCOMPAT_EA_INODE| + EXT4_FEATURE_INCOMPAT_MMP | ++ EXT4_FEATURE_INCOMPAT_DIRDATA| + EXT4_FEATURE_INCOMPAT_64BIT, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| +Index: e2fsprogs/misc/tune2fs.c +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.c ++++ e2fsprogs/misc/tune2fs.c +@@ -127,7 +127,8 @@ static __u32 ok_features[3] = { + EXT3_FEATURE_INCOMPAT_EXTENTS | + EXT4_FEATURE_INCOMPAT_FLEX_BG | + EXT4_FEATURE_INCOMPAT_EA_INODE| +- EXT4_FEATURE_INCOMPAT_MMP, ++ EXT4_FEATURE_INCOMPAT_MMP| ++ EXT4_FEATURE_INCOMPAT_DIRDATA, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT4_FEATURE_RO_COMPAT_HUGE_FILE| +@@ -146,7 +147,8 @@ static __u32 clear_ok_features[3] = { + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT4_FEATURE_INCOMPAT_FLEX_BG | + EXT4_FEATURE_INCOMPAT_EA_INODE| +- EXT4_FEATURE_INCOMPAT_MMP, ++ EXT4_FEATURE_INCOMPAT_MMP| ++ EXT4_FEATURE_INCOMPAT_DIRDATA, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT4_FEATURE_RO_COMPAT_HUGE_FILE| +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -2030,7 +2030,7 @@ static int handle_htree(e2fsck_t ctx, st + } + + /* XXX should check that beginning matches a directory */ +- root = (struct ext2_dx_root_info *) (block_buf + 24); ++ root = get_ext2_dx_root_info(fs, block_buf); + + if ((root->reserved_zero || root->info_length < 8) && + fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) +Index: e2fsprogs/e2fsck/pass2.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass2.c ++++ e2fsprogs/e2fsck/pass2.c +@@ -329,13 +329,82 @@ static EXT2_QSORT_TYPE special_dir_block + return (int) (db_a->blockcnt - db_b->blockcnt); + } + ++void ext2_fix_dirent_dirdata(struct ext2_dir_entry_2 *de) ++{ ++ int i = 0, dirdatalen, rlen; ++ __u8 flags = 0, new_flag = 0; ++ __u8 de_flags = de->file_type & ~EXT2_FT_MASK; ++ ++ while (i < 4) { ++ ++ flags = new_flag | (1 << i) << 4; ++ ++ if ((de_flags & flags) == flags) { ++ ++ dirdatalen = ext2_get_dirent_dirdata_size(de, flags); ++ rlen = __EXT2_DIR_REC_LEN(de->name_len + dirdatalen); ++ ++ if (rlen > de->rec_len) ++ break; ++ ++ new_flag |= flags; ++ } ++ i++; ++ } ++ ++ de->file_type = (de->file_type & EXT2_FT_MASK) | new_flag; ++} ++ ++ ++/* ++ * check for dirent data in ext3 dirent. ++ * return 0 if dirent data is ok. ++ * return 1 if dirent data does not exist. ++ * return 2 if dirent was modified due to error. ++ */ ++int e2fsck_check_dirent_data(e2fsck_t ctx, struct ext2_dir_entry_2 *de, ++ unsigned int offset, struct problem_context *pctx) ++{ ++ if (!(ctx->fs->super->s_feature_incompat & ++ EXT4_FEATURE_INCOMPAT_DIRDATA)) { ++ if (de->file_type & ~EXT2_FT_MASK) { ++ /* clear dirent extra data flags. */ ++ if (fix_problem(ctx, PR_2_CLEAR_DIRDATA, pctx)) { ++ de->file_type &= EXT2_FT_MASK; ++ return 2; ++ } ++ } ++ return 1; ++ } ++ if (de->file_type & ~EXT2_FT_MASK) { + ++ if (de->rec_len >= EXT2_DIR_REC_LEN(de) || ++ (de->rec_len + offset == EXT2_BLOCK_SIZE(ctx->fs->super))) { ++ if (ext2_get_dirent_dirdata_size(de, EXT2_DIRENT_LUFID) == ++ EXT2_DIRENT_LUFID_SIZE) ++ return 0; ++ } ++ /* just clear dirent data flags for now, we should fix FID data ++ * in lustre specific pass. ++ */ ++ if (fix_problem(ctx, PR_2_CLEAR_DIRDATA, pctx)) { ++ ext2_fix_dirent_dirdata(de); ++ if (ext2_get_dirent_dirdata_size(de, EXT2_DIRENT_LUFID) != ++ EXT2_DIRENT_LUFID_SIZE) { ++ de->file_type &= ~EXT2_DIRENT_LUFID; ++ } ++ ++ return 2; ++ } ++ } ++ return 1; ++} + /* + * Make sure the first entry in the directory is '.', and that the + * directory entry is sane. + */ + static int check_dot(e2fsck_t ctx, +- struct ext2_dir_entry *dirent, ++ struct ext2_dir_entry *dirent, unsigned int offset, + ext2_ino_t ino, struct problem_context *pctx) + { + struct ext2_dir_entry *nextdir; +@@ -343,6 +412,7 @@ static int check_dot(e2fsck_t ctx, + int status = 0; + int created = 0; + int problem = 0; ++ int dir_data_error; + + if (!dirent->inode) + problem = PR_2_MISSING_DOT; +@@ -352,10 +422,14 @@ static int check_dot(e2fsck_t ctx, + else if (dirent->name[1] != '\0') + problem = PR_2_DOT_NULL_TERM; + ++ dir_data_error = e2fsck_check_dirent_data(ctx, ++ (struct ext2_dir_entry_2 *)dirent, ++ offset, pctx); ++ + (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (problem) { + if (fix_problem(ctx, problem, pctx)) { +- if (rec_len < 12) ++ if (rec_len < 12 && dir_data_error) + rec_len = dirent->rec_len = 12; + dirent->inode = ino; + dirent->name_len = 1; +@@ -371,7 +445,7 @@ static int check_dot(e2fsck_t ctx, + status = 1; + } + } +- if (rec_len > 12) { ++ if (rec_len > 12 && dir_data_error) { + new_len = rec_len - 12; + if (new_len > 12) { + if (created || +@@ -396,11 +470,12 @@ static int check_dot(e2fsck_t ctx, + * here; this gets done in pass 3. + */ + static int check_dotdot(e2fsck_t ctx, +- struct ext2_dir_entry *dirent, ++ struct ext2_dir_entry *dirent, unsigned int offset, + ext2_ino_t ino, struct problem_context *pctx) + { + int problem = 0; + unsigned int rec_len; ++ int dir_data_error; + + if (!dirent->inode) + problem = PR_2_MISSING_DOT_DOT; +@@ -411,10 +486,14 @@ static int check_dotdot(e2fsck_t ctx, + else if (dirent->name[2] != '\0') + problem = PR_2_DOT_DOT_NULL_TERM; + ++ dir_data_error = e2fsck_check_dirent_data(ctx, ++ (struct ext2_dir_entry_2 *)dirent, ++ offset, pctx); ++ + (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (problem) { + if (fix_problem(ctx, problem, pctx)) { +- if (rec_len < 12) ++ if (rec_len < 12 && dir_data_error) + dirent->rec_len = 12; + /* + * Note: we don't have the parent inode just +@@ -476,6 +555,12 @@ static _INLINE_ int check_filetype(e2fsc + int should_be = EXT2_FT_UNKNOWN; + __u16 result; + struct ext2_inode inode; ++ __u8 dirdata = 0; ++ ++ if (ctx->fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) { ++ dirdata = filetype & ~EXT2_FT_MASK; ++ filetype = filetype & EXT2_FT_MASK; ++ } + + if (!(ctx->fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE)) { +@@ -510,7 +595,7 @@ static _INLINE_ int check_filetype(e2fsc + pctx) == 0) + return 0; + +- dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; ++ dirent->name_len = ((dirent->name_len & 0xFF) | (dirdata | should_be) << 8); + return 1; + } + +@@ -532,7 +617,7 @@ static void parse_int_node(ext2_filsys f + ext2_dirhash_t hash = 0, prev_hash; + + if (db->blockcnt == 0) { +- root = (struct ext2_dx_root_info *) (block_buf + 24); ++ root = get_ext2_dx_root_info(fs, block_buf); + + #ifdef DX_DEBUG + printf("Root node dump:\n"); +@@ -543,7 +628,7 @@ static void parse_int_node(ext2_filsys f + printf("\t Flags: %d\n", root->unused_flags); + #endif + +- ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); ++ ent = (struct ext2_dx_entry *) ((char *) root + root->info_length); + } else { + ent = (struct ext2_dx_entry *) (block_buf+8); + } +@@ -807,7 +892,7 @@ static int check_dir_block(ext2_filsys f + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + limit = (struct ext2_dx_countlimit *) (buf+8); + if (db->blockcnt == 0) { +- root = (struct ext2_dx_root_info *) (buf + 24); ++ root = get_ext2_dx_root_info(fs, buf); + dx_db->type = DX_DIRBLOCK_ROOT; + dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; + if ((root->reserved_zero || +@@ -864,10 +949,10 @@ out_htree: + } + + if (dot_state == 0) { +- if (check_dot(ctx, dirent, ino, &cd->pctx)) ++ if (check_dot(ctx, dirent, offset, ino, &cd->pctx)) + dir_modified++; + } else if (dot_state == 1) { +- ret = check_dotdot(ctx, dirent, ino, &cd->pctx); ++ ret = check_dotdot(ctx, dirent, offset, ino, &cd->pctx); + if (ret < 0) + goto abort_free_dict; + if (ret) +@@ -883,6 +968,11 @@ out_htree: + if (!dirent->inode) + goto next; + ++ ret = e2fsck_check_dirent_data(ctx, (struct ext2_dir_entry_2 *)dirent, ++ offset, &cd->pctx); ++ if (ret == 2) ++ dir_modified++; ++ + /* + * Make sure the inode listed is a legal one. + */ +Index: e2fsprogs/e2fsck/pass3.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass3.c ++++ e2fsprogs/e2fsck/pass3.c +@@ -606,6 +606,7 @@ static int fix_dotdot_proc(struct ext2_d + struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; + errcode_t retval; + struct problem_context pctx; ++ __u16 dirdata = 0; + + if ((dirent->name_len & 0xFF) != 2) + return 0; +@@ -625,6 +626,9 @@ static int fix_dotdot_proc(struct ext2_d + fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); + } + dirent->inode = fp->parent; ++ ++ dirdata = dirent->name_len & (~EXT2_FT_MASK << 8); ++ + if (fp->ctx->fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE) + dirent->name_len = (dirent->name_len & 0xFF) | +@@ -632,6 +636,9 @@ static int fix_dotdot_proc(struct ext2_d + else + dirent->name_len = dirent->name_len & 0xFF; + ++ if (fp->ctx->fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) ++ dirent->name_len |= dirdata; ++ + fp->done++; + return DIRENT_ABORT | DIRENT_CHANGED; + } +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -1427,6 +1427,11 @@ static struct e2fsck_problem problem_tab + N_("@i %i is badly corrupt (badness value = %N). "), + PROMPT_CLEAR, PR_PREEN_OK }, + ++ /* Directory entry dirdata length set incorrectly */ ++ { PR_2_CLEAR_DIRDATA, ++ N_("@E dirdata length set incorrectly.\n"), ++ PROMPT_CLEAR, PR_PREEN_OK }, ++ + /* Pass 3 errors */ + + /* Pass 3: Checking directory connectivity */ +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -858,6 +858,9 @@ struct problem_context { + /* Inode completely corrupt */ + #define PR_2_INODE_TOOBAD 0x020049 + ++/* Directory dirdata flag set */ ++#define PR_2_CLEAR_DIRDATA 0x02f000 ++ + /* + * Pass 3 errors + */ +Index: e2fsprogs/e2fsck/rehash.c +=================================================================== +--- e2fsprogs.orig/e2fsck/rehash.c ++++ e2fsprogs/e2fsck/rehash.c +@@ -148,7 +148,7 @@ static int fill_dir_block(ext2_filsys fs + } + ent = fd->harray + fd->num_array++; + ent->dir = dirent; +- fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); ++ fd->dir_size += __EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); + ent->ino = dirent->inode; + if (fd->compress) + ent->hash = ent->minor_hash = 0; +@@ -440,7 +440,7 @@ static errcode_t copy_dir_entries(e2fsck + ent = fd->harray + i; + if (ent->dir->inode == 0) + continue; +- rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF); ++ rec_len = __EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF); + if (rec_len > left) { + if (left) { + left += prev_rec_len; +Index: e2fsprogs/lib/ext2fs/link.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/link.c ++++ e2fsprogs/lib/ext2fs/link.c +@@ -41,7 +41,7 @@ static int link_proc(struct ext2_dir_ent + unsigned int rec_len, min_rec_len, curr_rec_len; + int ret = 0; + +- rec_len = EXT2_DIR_REC_LEN(ls->namelen); ++ rec_len = __EXT2_DIR_REC_LEN(ls->namelen); + + ls->err = ext2fs_get_rec_len(ls->fs, dirent, &curr_rec_len); + if (ls->err) +@@ -68,7 +68,7 @@ static int link_proc(struct ext2_dir_ent + * truncate it and return. + */ + if (dirent->inode) { +- min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); ++ min_rec_len = __EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); + if (curr_rec_len < (min_rec_len + rec_len)) + return ret; + rec_len = curr_rec_len - min_rec_len; +Index: e2fsprogs/lib/ext2fs/newdir.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/newdir.c ++++ e2fsprogs/lib/ext2fs/newdir.c +@@ -56,8 +56,8 @@ errcode_t ext2fs_new_dir_block(ext2_fils + dir->inode = dir_ino; + dir->name_len = 1 | filetype; + dir->name[0] = '.'; +- rec_len = fs->blocksize - EXT2_DIR_REC_LEN(1); +- dir->rec_len = EXT2_DIR_REC_LEN(1); ++ rec_len = fs->blocksize - __EXT2_DIR_REC_LEN(1); ++ dir->rec_len = __EXT2_DIR_REC_LEN(1); + + /* + * Set up entry for '..' +Index: e2fsprogs/lib/ext2fs/dirblock.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/dirblock.c ++++ e2fsprogs/lib/ext2fs/dirblock.c +@@ -58,6 +58,39 @@ errcode_t ext2fs_read_dir_block3(ext2_fi + return retval; + } + ++/* ++ * Compute the total directory entry data length. ++ * This includes the filename and an implicit NUL terminator (always present), ++ * and optional extensions. Each extension has a bit set in the high 4 bits of ++ * de->file_type, and the extension length is the first byte in each entry. ++ */ ++int ext2_get_dirent_size(struct ext2_dir_entry_2 *de) ++{ ++ return ext2_get_dirent_dirdata_size(de, ~EXT2_FT_MASK); ++} ++ ++int ext2_get_dirent_dirdata_size(struct ext2_dir_entry_2 *de, char dirdata_flags) ++{ ++ char *len = de->name + de->name_len + 1 /* NUL terminator */; ++ int dlen = 0; ++ __u8 extra_data_flags = (de->file_type & ~EXT2_FT_MASK) >> 4; ++ ++ dirdata_flags >>= 4; ++ while ((extra_data_flags & dirdata_flags) != 0) { ++ if (extra_data_flags & 1) { ++ if (dirdata_flags & 1) ++ dlen += *len; ++ ++ len += *len; ++ } ++ extra_data_flags >>= 1; ++ dirdata_flags >>= 1; ++ } ++ ++ /* add NUL terminator byte to dirdata length */ ++ return dlen + (dlen != 0); ++} ++ + errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags EXT2FS_ATTR((unused))) + { diff --git a/patches/e2fsprogs-dblist.patch b/patches/e2fsprogs-dblist.patch new file mode 100644 index 0000000..d6c6012 --- /dev/null +++ b/patches/e2fsprogs-dblist.patch @@ -0,0 +1,18 @@ +Fix dblist size accounting in the case where ext2fs_resize_mem() fails +to allocate a larger buffer. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/ext2fs/dblist.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/dblist.c ++++ e2fsprogs/lib/ext2fs/dblist.c +@@ -172,7 +172,7 @@ errcode_t ext2fs_add_dir_block2(ext2_dbl + sizeof(struct ext2_db_entry2), + &dblist->list); + if (retval) { +- dblist->size -= 100; ++ dblist->size = old_size / sizeof(struct ext2_db_entry2); + return retval; + } + } diff --git a/patches/e2fsprogs-discard.patch b/patches/e2fsprogs-discard.patch new file mode 100644 index 0000000..31f7975 --- /dev/null +++ b/patches/e2fsprogs-discard.patch @@ -0,0 +1,82 @@ +Allow mke2fs discard patches to pass regression tests. + +Index: e2fsprogs/lib/ext2fs/unix_io.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/unix_io.c ++++ e2fsprogs/lib/ext2fs/unix_io.c +@@ -870,8 +870,11 @@ static errcode_t unix_discard(io_channel + range[1] = (__uint64_t)(count) * channel->block_size; + + ret = ioctl(data->dev, BLKDISCARD, &range); +- if (ret < 0) ++ if (ret < 0) { ++ if (errno == ENOTTY) ++ return EXT2_ET_UNIMPLEMENTED; + return errno; ++ } + return 0; + #else + return EXT2_ET_UNIMPLEMENTED; +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -2010,29 +2010,37 @@ static int mke2fs_discard_device(ext2_fi + count *= (1024 * 1024); + count /= fs->blocksize; + +- ext2fs_numeric_progress_init(fs, &progress, +- _("Discarding device blocks: "), +- blocks); + while (cur < blocks) { +- ext2fs_numeric_progress_update(fs, &progress, cur); +- + if (cur + count > blocks) + count = blocks - cur; + + retval = io_channel_discard(fs->io, cur, count, fs->blocksize); ++ if (cur == 0) { ++ /* If discard is unimplemented skip the progress bar */ ++ if (retval == EXT2_ET_UNIMPLEMENTED) ++ return retval; ++ ++ ext2fs_numeric_progress_init(fs, &progress, ++ _("Discarding device blocks: "), ++ blocks); ++ } ++ ++ ext2fs_numeric_progress_update(fs, &progress, cur); ++ + if (retval) + break; ++ + cur += count; + } + + if (retval) { +- ext2fs_numeric_progress_close(fs, &progress, +- _("failed - ")); ++ ext2fs_numeric_progress_close(fs, &progress, _("failed - ")); + if (!quiet) + printf("%s\n",error_message(retval)); +- } else ++ } else { + ext2fs_numeric_progress_close(fs, &progress, + _("done \n")); ++ } + + return retval; + } +Index: e2fsprogs/lib/et/Makefile.in +=================================================================== +--- e2fsprogs.orig/lib/et/Makefile.in ++++ e2fsprogs/lib/et/Makefile.in +@@ -96,7 +96,7 @@ install:: compile_et libcom_err.a $(HFIL + echo " INSTALL_DATA $(includedir)/et/$$i"; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/et/$$i; \ + done +- $(Q) $(LN) $(LINK_INSTALL_FLAGS) $(includedir)/et/com_err.h $(DESTDIR)$(includedir) ++ $(Q) $(LN) $(LINK_INSTALL_FLAGS) -s $(includedir)/et/com_err.h $(DESTDIR)$(includedir) + $(Q) for i in $(SHARE_FILES); do \ + echo " INSTALL_DATA $(datadir)/et/$$i"; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(datadir)/et/$$i; \ diff --git a/patches/e2fsprogs-e2fsck_exclusive.patch b/patches/e2fsprogs-e2fsck_exclusive.patch new file mode 100644 index 0000000..9ab0fb3 --- /dev/null +++ b/patches/e2fsprogs-e2fsck_exclusive.patch @@ -0,0 +1,35 @@ +b=13698 +The checks done by e2fsck for mounted vs. read-only runs is confusing. + +On the one hand, if e2fsck is NOT run with the "-n" flag (i.e. it might +modify the filesystem), there is no guarantee that it will open the +filesystem with the EXCLUSIVE flag (i.e. O_EXCL) to prevent the block +device from being used (in most cases = mounted). + +On the other hand, if e2fsck is run with "-n" (i.e. read-only), +and the /etc/fstab or /proc/mounts does not report the same block +device to match the mountpoint (which happens for Lustre, and can +also happen if there is an overlay mount) then the e2fsck thinks +the filesystem is unmounted, but fails because the EXCLUSIVE flag +is set even though it is running read-only. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -1056,9 +1056,10 @@ restart: + if (!old_bitmaps) + flags |= EXT2_FLAG_64BITS; + if ((ctx->options & E2F_OPT_READONLY) == 0) +- flags |= EXT2_FLAG_RW; +- if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0) +- flags |= EXT2_FLAG_EXCLUSIVE; ++ flags |= EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE; ++ /* we would abort above in check_mount() unless user asks for this */ ++ if ((ctx->mount_flags & EXT2_MF_MOUNTED) != 0) ++ flags &= ~EXT2_FLAG_EXCLUSIVE; + + retval = try_open_fs(ctx, flags, io_ptr, &fs); + diff --git a/patches/e2fsprogs-e2scan.patch b/patches/e2fsprogs-e2scan.patch new file mode 100644 index 0000000..311c373 --- /dev/null +++ b/patches/e2fsprogs-e2scan.patch @@ -0,0 +1,1780 @@ +Index: e2fsprogs/configure.in +=================================================================== +--- e2fsprogs.orig/configure.in ++++ e2fsprogs/configure.in +@@ -589,6 +589,28 @@ DEBUGFS_CMT= + ) + AC_SUBST(DEBUGFS_CMT) + dnl ++dnl handle --enable-e2scan ++dnl ++AC_ARG_ENABLE([e2scan], ++[ --disable-e2scan disable support of e2scan program], ++if test "$enableval" = "no" ++then ++ echo "Disabling e2scan support" ++ E2SCAN_CMT="#" ++ E2SCAN_MAN=.\" ++else ++ E2SCAN_CMT= ++ E2SCAN_MAN= ++ echo "Enabling e2scan support" ++fi ++, ++echo "Enabling e2scan support by default" ++E2SCAN_CMT= ++E2SCAN_MAN= ++) ++AC_SUBST(E2SCAN_CMT) ++AC_SUBST(E2SCAN_MAN) ++dnl + dnl handle --enable-imager + dnl + AC_ARG_ENABLE([imager], +@@ -812,6 +834,10 @@ AC_CHECK_HEADERS(net/if.h,,, + #endif + ]]) + AC_CHECK_HEADERS(db.h) ++dnl do not check sqlite3.h if e2scan is disabled ++if test x"$E2SCAN_CMT" == x; then ++AC_CHECK_HEADERS(sqlite3.h) ++fi + AC_FUNC_VPRINTF + dnl Check to see if dirent has member d_reclen. On cygwin those d_reclen + dnl is not decleared. +@@ -954,6 +980,51 @@ AC_CHECK_LIB(db-4.8, db_env_create, + AC_DEFINE(HAVE_DB4)]) + AC_SUBST(DB4VERSION) + dnl ++dnl Check to see if static sqlite exists ++dnl ++AC_ARG_WITH( ++ [sqlite3], ++ [ --with-sqlite3=DIR location of sqlite3 library (default /usr/lib)],, ++ [with_sqlite3=/usr/lib]) ++ ++dnl do not check sqlite3 library if e2scan is disabled ++if test x"$E2SCAN_CMT" == x; then ++ ++CFLAGS_OLD=$CFLAGS ++SQLITE3_LIB='' ++dnl ++dnl check static sqlite3 first ++dnl ++CFLAGS="$CFLAGS_OLD -L$with_sqlite3 -static -pthread" ++AC_CHECK_LIB(sqlite3, sqlite3_open, ++ [ ++ SQLITE3_LIB="-L$with_sqlite3 -static -pthread -lsqlite3" ++ AC_DEFINE(HAVE_SQLITE3) ++ ]) ++ ++if test x"$SQLITE3_LIB" == x; then ++dnl ++dnl static sqlite3 is not found, check dynamic sqlite3 ++dnl ++ AC_MSG_WARN(no static sqlite3 - looking for dynamic one) ++ CFLAGS="$CFLAGS_OLD -L$with_sqlite3 -pthread" ++ AC_CHECK_LIB(sqlite3, sqlite3_close, ++ [ ++ SQLITE3_LIB="-L$with_sqlite3 -pthread -lsqlite3" ++ AC_DEFINE(HAVE_SQLITE3) ++ ]) ++fi ++ ++AC_SUBST(SQLITE3_LIB) ++CFLAGS=$CFLAGS_OLD ++ ++if test x"$SQLITE3_LIB" == x; then ++ AC_MSG_WARN(no sqlite3 - e2scan will not support database based scanning) ++fi ++ ++fi ++ ++dnl + dnl See if optreset exists + dnl + AC_MSG_CHECKING(for optreset) +@@ -1170,7 +1241,7 @@ for i in MCONFIG Makefile e2fsprogs.spec + lib/ss/ss.pc lib/uuid/uuid.pc lib/et/com_err.pc \ + lib/e2p/e2p.pc lib/blkid/blkid.pc lib/ext2fs/ext2fs.pc \ + misc/Makefile ext2ed/Makefile e2fsck/Makefile \ +- debugfs/Makefile tests/Makefile tests/progs/Makefile \ ++ debugfs/Makefile e2scan/Makefile tests/Makefile tests/progs/Makefile \ + resize/Makefile doc/Makefile intl/Makefile \ + intl/libgnuintl.h po/Makefile.in ; do + if test -d `dirname ${srcdir}/$i` ; then +Index: e2fsprogs/e2fsprogs.spec.in +=================================================================== +--- e2fsprogs.orig/e2fsprogs.spec.in ++++ e2fsprogs/e2fsprogs.spec.in +@@ -150,6 +150,7 @@ exit 0 + %{_sbindir}/e2freefrag + %{_sbindir}/e4defrag + @LFSCK_CMT@%{_sbindir}/lfsck ++@E2SCAN_CMT@%{_sbindir}/e2scan + + %{_root_libdir}/libblkid.so.* + %{_root_libdir}/libcom_err.so.* +@@ -183,6 +184,7 @@ exit 0 + %{_mandir}/man8/fsck.ext4dev.8* + %{_mandir}/man8/e2image.8* + %{_mandir}/man8/e2label.8* ++@E2SCAN_CMT@%{_mandir}/man8/e2scan.8* + %{_mandir}/man8/e2undo.8* + %{_mandir}/man8/fsck.8* + %{_mandir}/man8/logsave.8* +Index: e2fsprogs/e2scan/db.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2scan/db.c +@@ -0,0 +1,265 @@ ++#define _GNU_SOURCE ++#define _FILE_OFFSET_BITS 64 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(HAVE_SQLITE3) && defined(HAVE_SQLITE3_H) ++ ++#include ++ ++/* e2scan.c */ ++extern ext2_filsys fs; ++extern struct { ++ int mode; ++ int nr; ++ union { ++ struct { ++ int fd; ++ int nr_commands; ++ } db; ++ struct { ++ /* number of files newer than specified time */ ++ ext2_ino_t nr_files; ++ /* number of files reported */ ++ ext2_ino_t nr_reported; ++ time_t mtimestamp; ++ time_t ctimestamp; ++ } fl; ++ }; ++} scan_data; ++ ++int block_iterate_cb(ext2_filsys fs, blk_t *block_nr, ++ e2_blkcnt_t blockcnt, ++ blk_t ref_block EXT2FS_ATTR((unused)), ++ int ref_offset EXT2FS_ATTR((unused)), ++ void *priv_data); ++ ++ ++static long count = 10000; ++ ++static void exec_one_sql_noreturn(sqlite3 *db, char *sqls) ++{ ++ char *errmsg = NULL; ++ ++ if (sqlite3_exec(db, sqls, NULL, NULL, &errmsg) != SQLITE_OK) { ++ fprintf(stderr, "SQL error: %s;\nrequest: %s", errmsg, sqls); ++ sqlite3_free(errmsg); ++ exit(1); ++ } ++} ++ ++static void create_sql_table(sqlite3 *db, const char *table_name, ++ const char *columns) ++{ ++ char *sqls; ++ ++ if (asprintf(&sqls, "create table %s (%s)", table_name, columns) < 0) { ++ perror("asprintf failed"); ++ exit(1); ++ } ++ ++ exec_one_sql_noreturn(db, sqls); ++ free(sqls); ++} ++ ++static void begin_one_transaction(sqlite3 *db) ++{ ++ exec_one_sql_noreturn(db, "BEGIN;"); ++} ++ ++static void commit_one_transaction(sqlite3 *db) ++{ ++ exec_one_sql_noreturn(db, "COMMIT;"); ++} ++ ++static void batch_one_transaction(sqlite3 *db) ++{ ++ static long num = 0; ++ ++ num ++; ++ if (num % count == 0) { ++ commit_one_transaction(db); ++ begin_one_transaction(db); ++ } ++ /* else do nothing */ ++} ++ ++#define COLUMNS "ino, generation, parent, name, size, mtime, ctime, dtime" ++ ++static void create_full_db(const char *name, int fd) ++{ ++ sqlite3 *db; ++ int rd; ++ int nr; ++ char sqls[512]; ++ ++ if (sqlite3_open(name, &db) != SQLITE_OK) { ++ fprintf(stderr, "failed to sqlite3_open: %s\n", name); ++ sqlite3_close(db); ++ exit(1); ++ } ++ create_sql_table(db, "dirs", COLUMNS); ++ create_sql_table(db, "files", COLUMNS); ++ ++ begin_one_transaction(db); ++ ++ nr = 0; ++ while (1) { ++ rd = read(fd, sqls, 512); ++ if (rd == -1) { ++ perror("read failed\n"); ++ exit(1); ++ } ++ if (rd != 512) ++ break; ++ nr ++; ++ exec_one_sql_noreturn(db, sqls); ++ batch_one_transaction(db); ++ } ++ commit_one_transaction(db); ++ printf("database is created, %d records are inserted\n", nr); ++ sqlite3_close(db); ++} ++ ++/* write sql command to pipe */ ++#define PIPECMDLEN 512 ++static void write_sql_command(int fd, const char *sqls) ++{ ++ char buf[PIPECMDLEN]; ++ ++ if (strlen(sqls) + 1 > PIPECMDLEN) { ++ fprintf(stderr, "too long command"); ++ exit(1); ++ } ++ strcpy(buf, sqls); ++ if (write(fd, buf, PIPECMDLEN) != PIPECMDLEN) { ++ perror("failed to write to pipe"); ++ exit(1); ++ } ++ scan_data.db.nr_commands ++; ++} ++ ++pid_t fork_db_creation(const char *database) ++{ ++ int p[2]; ++ struct stat st; ++ pid_t pid; ++ ++ if (stat(database, &st) == 0) { ++ fprintf(stderr, "%s exists. remove it first\n", database); ++ exit(1); ++ } ++ if (pipe(p) == -1) { ++ fprintf(stderr, "failed to pipe"); ++ exit(1); ++ } ++ ++ pid = fork(); ++ if (pid == (pid_t)-1) { ++ fprintf(stderr, "failed to fork"); ++ exit(1); ++ } ++ if (pid == (pid_t)0) { ++ /* child, read data written by parent and write to ++ * database */ ++ close(p[1]); ++ create_full_db(database, p[0]); ++ close(p[0]); ++ exit(0); ++ } ++ ++ /* parent, read inodes and write them to pipe */ ++ close(p[0]); ++ scan_data.db.fd = p[1]; ++ return pid; ++} ++ ++void database_iscan_action(ext2_ino_t ino, struct ext2_inode *inode, ++ int fd, char *buf) ++{ ++ char *sqls; ++ ++ if (LINUX_S_ISDIR(inode->i_mode)) { ++ if (ino == EXT2_ROOT_INO) { ++ sqls = sqlite3_mprintf("%s (%u,%u,%u,'%q',%u,%u,%u,%u)", ++ "insert into dirs values", ++ ino, inode->i_generation, ino, "/", ++ inode->i_size, inode->i_mtime, ++ inode->i_ctime, inode->i_dtime); ++ write_sql_command(fd, sqls); ++ sqlite3_free(sqls); ++ } ++ ++ if (ext2fs_block_iterate2(fs, ino, 0, buf, ++ block_iterate_cb, &ino)) { ++ fprintf(stderr, "ext2fs_block_iterate2 failed\n"); ++ exit(1); ++ } ++ } ++} ++ ++/* ++ * callback for ext2fs_dblist_dir_iterate to be called for each ++ * directory entry ++ */ ++int database_dblist_iterate_cb(ext2_ino_t dir, struct ext2_dir_entry *dirent, ++ int namelen, int fd) ++{ ++ struct ext2_inode inode; ++ char *table; ++ char *sqls; ++ errcode_t retval; ++ char str[256]; ++ ++ if (!ext2fs_fast_test_inode_bitmap2(fs->inode_map, dirent->inode)) ++ /* entry of deleted file? can that ever happen */ ++ return 0; ++ ++ retval = ext2fs_read_inode(fs, dirent->inode, &inode); ++ if (retval) { ++ com_err("ext2fs_read_inode", retval, "while reading inode"); ++ exit(1); ++ } ++ ++ if (LINUX_S_ISDIR(inode.i_mode)) ++ table = "dirs"; ++ else ++ table = "files"; ++ ++ sprintf(str, "%.*s", namelen, dirent->name); ++ sqls = sqlite3_mprintf("%s %s %s (%u,%u,%u,'%q',%u,%u,%u,%u)", ++ "insert into", table, "values", ++ dirent->inode, inode.i_generation, dir, ++ str, ++ inode.i_size, inode.i_mtime, ++ inode.i_ctime, inode.i_dtime); ++ write_sql_command(fd, sqls); ++ sqlite3_free(sqls); ++ ++ return 0; ++} ++ ++#else ++ ++pid_t fork_db_creation(const char *database) ++{ ++ return 0; ++} ++ ++void database_iscan_action(ext2_ino_t ino, struct ext2_inode *inode, ++ int fd, char *buf) ++{ ++ return; ++} ++ ++int database_dblist_iterate_cb(ext2_ino_t dir, struct ext2_dir_entry *dirent, ++ int namelen, int fd) ++{ ++ return 0; ++} ++ ++#endif +Index: e2fsprogs/e2scan/e2scan.8.in +=================================================================== +--- /dev/null ++++ e2fsprogs/e2scan/e2scan.8.in +@@ -0,0 +1,116 @@ ++.TH e2scan 1 "2006 Sep 26" Lustre "backup utilities" ++.SH NAME ++e2scan \- scan an Ext2-type filesystem for modified inodes ++.SH SYNOPSIS ++.br ++.B e2scan ++@E2SCAN_MAN@{ ++.B -l ++@E2SCAN_MAN@| ++@E2SCAN_MAN@.B -f ++@E2SCAN_MAN@} ++[ ++.BI -a " groups" ++] [ ++.BI -b " blocks" ++] [ ++.BI -C " chdir" ++] [ ++@E2SCAN_MAN@.BI -d " database" ++@E2SCAN_MAN@] [ ++.BI -n " filename" ++] [ ++.BI -N " date" ++] [ ++.BI -o " outfile" ++] ++.I device ++.br ++.SH DESCRIPTION ++.BR e2scan , ++iterates all inodes on ++.IR device , ++find inodes modified since the specified time (default 1 day), and prints ++their pathnames relative to the root of the filesystem. This allows the ++pathnames to be used as input to a backup tool running in the mountpoint, like ++.BR "tar \-C" , ++as the filesystem may be mounted at an arbitrary mountpoint. ++ ++The ++.B e2scan ++program is optimized for scanning an entire filesystem for (modified) files, ++but is not efficient for smaller subdirectory scans. Use ++.BR find (1) ++for that purpose instead. ++.SH OPTIONS ++.TP ++.BI \-a " groups" ++Set readahead for inode table blocks to get better performance when scanning ++.IR device . ++Default is 1 group of readahead. ++.TP ++.BI \-b " inode_buffer_blocks" ++Set number of inode blocks to read from disk at a time. ++.TP ++.BI \-C " directory" ++Specify the working directory (relative to the root of the filesystem ++being scanned) for the output pathnames. Only directories underneath ++the root will be candidates for listing. For Lustre MDT filesystems the ++pathname must be prefixed with "/ROOT" to dump the client visible filesystem. ++@E2SCAN_MAN@.TP ++@E2SCAN_MAN@.BI \-d " database_file" ++@E2SCAN_MAN@Specify output file for database when running in ++@E2SCAN_MAN@.B \-f ++@E2SCAN_MAN@mode. ++.TP ++.B \-D ++Also include directories in the output. The default is to only list files, ++because tools like ++.BR tar (1) ++will recurse into directories and files that are also listed therein will be ++backed up twice. ++@E2SCAN_MAN@.TP ++@E2SCAN_MAN@.B \-f ++@E2SCAN_MAN@List files in the filesystem and insert them into the ++@E2SCAN_MAN@.BR sqlite3 (1) ++@E2SCAN_MAN@database named by the ++@E2SCAN_MAN@.B \-d ++@E2SCAN_MAN@option. ++.TP ++.B \-l ++List files in the filesystem to standard output, or to the file specified ++with the ++.B \-o ++option. This is the default mode. ++.TP ++.BI \-n " filename" ++Dump only files newer than the specified ++.IR filename . ++.TP ++.BI \-N " date" ++Dump only files newer than the specified date. This supports a wide ++variety of input formats like "YYYY-MM-DD HH:MM:SS". Use a date of ++.R 0 ++to dump all files. ++.TP ++.BI \-o " outfile" ++Record the files found into ++.I outfile ++instead of the default standard output. ++.SH EXAMPLES ++To dump all of the files in the filesystem into the file ++.IR myfilelist : ++.IP ++e2scan -N 0 -o myfilelist /dev/sdb1 ++.PP ++To list files and directories newer than Feb 6, 2007 in the /home directory: ++.IP ++e2scan -D -N "Feb 6 00:00:00 2007" -C /home /dev/sdb1 ++.PP ++.SH AUTHOR ++This version of ++.B e2scan ++was originally written by Vladimir Saviliev ++and Andreas Dilger . ++.SH SEE ALSO ++.BR find (1) +Index: e2fsprogs/e2scan/e2scan.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2scan/e2scan.c +@@ -0,0 +1,640 @@ ++#define _GNU_SOURCE ++#define _FILE_OFFSET_BITS 64 ++#define _XOPEN_SOURCE /* for getdate */ ++#define _XOPEN_SOURCE_EXTENDED /* for getdate */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ext2_filsys fs; ++const char *database = "e2scan.db"; ++int readahead_groups = 1; /* by default readahead one group inode table */ ++FILE *outfile; ++ ++void usage(char *prog) ++{ ++ fprintf(stderr, ++#if defined(HAVE_SQLITE3) && defined(HAVE_SQLITE3_H) ++ "\nUsage: %s {-l | -f} [ options ] device-filename\nModes:" ++ "\t-f: create file database\n" ++#else ++ "\nUsage: %s -l [ options ] device-filename\nModes:" ++#endif ++ "\t-l: list recently changed files\n" ++ "Options:\n" ++ "\t-a groups: readahead 'groups' inode tables (default %d)\n" ++ "\t-b blocks: buffer 'blocks' inode table blocks\n" ++ "\t-C chdir: list files relative to 'chdir' in filesystem\n" ++ "\t-d database: output database filename (default %s)\n" ++ "\t-D: list not only files, but directories as well\n" ++ "\t-n filename: list files newer than 'filename'\n" ++ "\t-N date: list files newer than 'date' (default 1 day, " ++ "0 for all files)\n" ++ "\t-o outfile: output file list to 'outfile'\n", ++ prog, readahead_groups, database); ++ exit(1); ++} ++ ++#define SM_NONE 0 ++#define SM_DATABASE 1 /* -f */ ++#define SM_FILELIST 2 /* -l */ ++ ++struct { ++ int mode; ++ int nr; ++ union { ++ struct { ++ int fd; ++ int nr_commands; ++ } db; ++ struct { ++ /* number of files newer than specified time */ ++ ext2_ino_t nr_files; ++ ext2_ino_t nr_dirs; ++ /* number of files reported */ ++ ext2_ino_t nr_reported; ++ time_t mtimestamp; ++ time_t ctimestamp; ++ int with_dirs; ++ } fl; ++ }; ++} scan_data = { .mode = SM_FILELIST, }; ++ ++/* db.c */ ++pid_t fork_db_creation(const char *database); ++void database_iscan_action(ext2_ino_t ino, ++ struct ext2_inode *inode, int fd, char *buf); ++int database_dblist_iterate_cb(ext2_ino_t dir, struct ext2_dir_entry *dirent, ++ int namelen, int fd); ++ ++/* filelist.c */ ++void filelist_iscan_action(ext2_ino_t ino, ++ struct ext2_inode *inode, char *buf); ++int filelist_dblist_iterate_cb(ext2_ino_t dirino, ++ struct ext2_dir_entry *dirent, ++ int namelen); ++int create_root_dentries(char *root); ++void report_root(void); ++ ++ ++static void get_timestamps(const char *filename) ++{ ++ struct stat st; ++ ++ if (stat(filename, &st) == -1) { ++ perror("failed to stat file"); ++ exit(1); ++ } ++ scan_data.fl.mtimestamp = st.st_mtime; ++ scan_data.fl.ctimestamp = st.st_ctime; ++} ++ ++/* ++ * callback for ext2fs_block_iterate2, it adds directory leaf blocks ++ * to dblist ++ */ ++int block_iterate_cb(ext2_filsys fs, blk_t *block_nr, ++ e2_blkcnt_t blockcnt, ++ blk_t ref_block EXT2FS_ATTR((unused)), ++ int ref_offset EXT2FS_ATTR((unused)), ++ void *priv_data) ++{ ++ int ret; ++ ext2_ino_t *ino; ++ ++ if ((int) blockcnt < 0) ++ /* skip indirect blocks */ ++ return 0; ++ ret = 0; ++ ino = priv_data; ++ if (ext2fs_add_dir_block(fs->dblist, *ino, *block_nr, (int) blockcnt)) ++ ret |= BLOCK_ABORT; ++ ++ return ret; ++} ++ ++/* ++ * done_group callback for inode scan. ++ * When i-th group of inodes is scanned over, readahead for i+2-th ++ * group is issued. Inode table readahead for two first groups is ++ * issued before scan begin. ++ */ ++errcode_t done_group_callback(ext2_filsys fs, ext2_inode_scan scan, ++ dgrp_t group, void *vp) ++{ ++ dgrp_t ra_group; ++ unsigned long ra_start; ++ int ra_size; ++ ++ if (readahead_groups <= 0) ++ return 0; ++ ++ if (((group + 1) % readahead_groups) != 0) ++ return 0; ++ ++ ra_group = group + 1 + readahead_groups; ++ if (ra_group >= fs->group_desc_count) ++ return 0; ++ ++ ra_start = ext2fs_inode_table_loc(fs, ra_group); ++ if (ra_group + readahead_groups > fs->group_desc_count) ++ ra_size = fs->group_desc_count - ra_group; ++ else ++ ra_size = readahead_groups; ++ ++ ra_size *= fs->inode_blocks_per_group; ++ io_channel_readahead(fs->io, ra_start, ra_size); ++ return 0; ++} ++ ++#define DEFAULT_CHUNK_SIZE 16 ++__u32 chunk_size; /* in blocks */ ++int nr_chunks; ++ ++struct chunk { ++ __u32 start; ++ __u32 covered; ++} *cur_chunk, *ra_chunk, *chunks; ++ ++/* callback for ext2fs_dblist_iterate */ ++static int fill_chunks(ext2_filsys fs, struct ext2_db_entry *db_info, ++ void *priv_data) ++{ ++ __u32 cur; ++ ++ cur = db_info->blk / chunk_size; ++ if (cur_chunk == NULL || cur != cur_chunk->start) { ++ /* new sweep starts */ ++ if (cur_chunk == NULL) ++ cur_chunk = chunks; ++ else ++ cur_chunk ++; ++ ++ cur_chunk->start = cur; ++ cur_chunk->covered = 1; ++ } else ++ cur_chunk->covered ++; ++ ++ return 0; ++} ++ ++/* callback for ext2fs_dblist_iterate */ ++static int count_chunks(ext2_filsys fs, struct ext2_db_entry *db_info, ++ void *priv_data) ++{ ++ __u32 cur; ++ static __u32 prev = (__u32)-1; ++ ++ cur = db_info->blk / chunk_size; ++ if (cur != prev) { ++ nr_chunks ++; ++ prev = cur; ++ } ++ return 0; ++} ++ ++/* create list of chunks, readahead two first of them */ ++static void make_chunk_list(ext2_dblist dblist) ++{ ++ chunk_size = readahead_groups * DEFAULT_CHUNK_SIZE; ++ if (chunk_size == 0) ++ return; ++ ++ ext2fs_dblist_iterate(dblist, count_chunks, NULL); ++ chunks = malloc(sizeof(struct chunk) * nr_chunks); ++ if (chunks == NULL) { ++ fprintf(stderr, "malloc failed\n"); ++ exit(1); ++ } ++ ext2fs_dblist_iterate(dblist, fill_chunks, NULL); ++ ++ /* start readahead for two first chunks */ ++ ra_chunk = chunks; ++ cur_chunk = NULL; ++ ++ io_channel_readahead(fs->io, ++ ra_chunk->start * chunk_size, ++ chunk_size); ++ ra_chunk ++; ++ if (ra_chunk < chunks + nr_chunks) ++ io_channel_readahead(fs->io, ++ ra_chunk->start * chunk_size, ++ chunk_size); ++} ++ ++/* ++ * this is called for each directory block when it is read by dblist ++ * iterator ++ */ ++static int dblist_readahead(void *vp) ++{ ++ if (chunk_size == 0) ++ return 0; ++ if (cur_chunk == NULL) ++ cur_chunk = chunks; ++ if (--cur_chunk->covered == 0) { ++ /* ++ * last block of current chunk is read, readahead ++ * chunk is under I/O, get new readahead chunk, move ++ * current chunk ++ */ ++ cur_chunk ++; ++ ra_chunk ++; ++ if (ra_chunk < chunks + nr_chunks) ++ io_channel_readahead(fs->io, ++ ra_chunk->start * chunk_size, ++ chunk_size); ++ } ++ return 0; ++} ++ ++/* ++ * callback for ext2fs_dblist_dir_iterate to be called for each ++ * directory entry, perform actions common for both database and ++ * filelist modes, call specific functions depending on the mode ++ */ ++static int dblist_iterate_cb(ext2_ino_t dirino, int entry, ++ struct ext2_dir_entry *dirent, ++ int offset EXT2FS_ATTR((unused)), ++ int blocksize EXT2FS_ATTR((unused)), ++ char *buf EXT2FS_ATTR((unused)), ++ void *private) ++{ ++ int namelen; ++ ++ if (offset == 0) { ++ /* new directory block is read */ ++ scan_data.nr ++; ++ dblist_readahead(NULL); ++ } ++ ++ if (dirent->inode == 0) ++ return 0; ++ ++ namelen = (dirent->name_len & 0xFF); ++ if (namelen == 2 && !strncmp(dirent->name, "..", 2)) ++ return 0; ++ ++ if (namelen == 1 && !strncmp(dirent->name, ".", 1)) ++ return 0; ++ ++ if (dirent->inode > fs->super->s_inodes_count) { ++ fprintf(stderr, "too big ino %u (%.*s)\n", ++ dirent->inode, namelen, dirent->name); ++ exit(1); ++ } ++ ++ if (scan_data.mode == SM_DATABASE) ++ return database_dblist_iterate_cb(dirino, dirent, namelen, ++ scan_data.db.fd); ++ ++ return filelist_dblist_iterate_cb(dirino, dirent, namelen); ++} ++ ++int main(int argc, char **argv) ++{ ++ char *root = "/"; ++ int inode_buffer_blocks = 0; ++ errcode_t retval; ++ char *block_buf; ++ ext2_inode_scan scan; ++ struct ext2_inode inode; ++ ext2_ino_t ino; ++ dgrp_t nr; ++ time_t t; ++ int c; ++ pid_t pid; ++ ++ /* ++ * by default find for files which are modified less than one ++ * day ago ++ */ ++ scan_data.fl.mtimestamp = time(NULL) - 60 * 60 * 24; ++ scan_data.fl.ctimestamp = scan_data.fl.mtimestamp; ++ outfile = stdout; ++ ++ opterr = 0; ++#if defined(HAVE_SQLITE3) && defined(HAVE_SQLITE3_H) ++#define OPTF "f" ++#else ++#define OPTF "" ++#endif ++ while ((c = getopt(argc, argv, "a:b:C:d:D"OPTF"hln:N:o:")) != EOF) { ++ char *end; ++ ++ switch (c) { ++ case 'a': ++ if (optarg == NULL) ++ usage(argv[0]); ++ readahead_groups = strtoul(optarg, &end, 0); ++ if (*end) { ++ fprintf(stderr, "%s: bad -a argument '%s'\n", ++ argv[0], optarg); ++ usage(argv[0]); ++ } ++ break; ++ case 'b': ++ inode_buffer_blocks = strtoul(optarg, &end, 0); ++ if (*end) { ++ fprintf(stderr, "%s: bad -b argument '%s'\n", ++ argv[0], optarg); ++ usage(argv[0]); ++ } ++ break; ++ case 'C': ++ root = optarg; ++ break; ++ case 'd': ++ database = optarg; ++ break; ++ case 'D': ++ scan_data.fl.with_dirs = 1; ++ break; ++ case 'f': ++#if !defined(HAVE_SQLITE3) || !defined(HAVE_SQLITE3_H) ++ fprintf(stderr, ++ "%s: sqlite3 was not detected on configure, " ++ "database creation is not supported\n",argv[0]); ++ return 1; ++#endif ++ scan_data.mode = SM_DATABASE; ++ break; ++ case 'l': ++ scan_data.mode = SM_FILELIST; ++ break; ++ case 'n': ++ get_timestamps(optarg); ++ break; ++ case 'N': { ++ const char *fmts[] = {"%c", /*date/time current locale*/ ++ "%Ec",/*date/time alt. locale*/ ++ "%a%t%b%t%d,%t%Y%t%H:%M:%S", ++ "%a,%t%d%t%b%t%Y%t%H:%M:%S", ++ "%a%t%b%t%d%t%H:%M:%S%t%Z%t%Y", ++ "%a%t%b%t%d%t%H:%M:%S%t%Y", ++ "%b%t%d%t%H:%M:%S%t%Z%t%Y", ++ "%b%t%d%t%H:%M:%S%t%Y", ++ "%x%t%X",/*date time*/ ++ "%Ex%t%EX",/*alternate date time*/ ++ "%F", /*ISO 8601 date*/ ++ "%+", /*`date` format*/ ++ "%s", /*seconds since epoch */ ++ NULL, ++ }; ++ const char **fmt; ++ char *ret; ++ struct tm tmptm, *tm = NULL; ++ time_t now = time(0); ++ ++ tmptm = *localtime(&now); ++ ++ for (fmt = &fmts[0]; *fmt != NULL; fmt++) { ++ if (strptime(optarg, *fmt, &tmptm) != NULL) { ++ tm = &tmptm; ++ break; ++ } ++ } ++ ++ if (tm == NULL) { ++ fprintf(stderr, "%s: bad -N argument '%s'\n", ++ argv[0], optarg); ++ usage(argv[0]); ++ } ++ scan_data.fl.mtimestamp = mktime(tm); ++ scan_data.fl.ctimestamp = scan_data.fl.mtimestamp; ++ break; ++ } ++ case 'o': ++ outfile = fopen(optarg, "w"); ++ if (outfile == NULL) { ++ fprintf(stderr, "%s: can't open '%s': %s\n", ++ argv[0], optarg, strerror(errno)); ++ usage(argv[0]); ++ } ++ break; ++ default: ++ fprintf(stderr, "%s: unknown option '-%c'\n", ++ argv[0], optopt); ++ case 'h': ++ usage(argv[0]); ++ } ++ } ++ ++ if (scan_data.mode == SM_NONE || argv[optind] == NULL) ++ usage(argv[0]); ++ ++ ++ fprintf(stderr, "generating list of files with\n" ++ "\tmtime newer than %s" ++ "\tctime newer than %s", ++ ctime(&scan_data.fl.mtimestamp), ++ ctime(&scan_data.fl.ctimestamp)); ++ ++ retval = ext2fs_open(argv[optind], EXT2_FLAG_SOFTSUPP_FEATURES, ++ 0, 0, unix_io_manager, &fs); ++ if (retval != 0) { ++ com_err("ext2fs_open", retval, "opening %s\n", argv[optind]); ++ return 1; ++ } ++ ++ t = time(NULL); ++ ++ for (nr = 0; nr < fs->group_desc_count; nr ++) ++ io_channel_readahead(fs->io, ++ ext2fs_inode_bitmap_loc(fs, nr), 1); ++ retval = ext2fs_read_inode_bitmap(fs); ++ if (retval) { ++ com_err("ext2fs_read_inode_bitmap", retval, ++ "opening inode bitmap on %s\n", argv[optind]); ++ exit(1); ++ } ++ fprintf(stderr, "inode bitmap is read, %ld seconds\n", time(NULL) - t); ++ ++ ++ if (inode_buffer_blocks == 0) ++ inode_buffer_blocks = fs->inode_blocks_per_group; ++ ++ retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan); ++ if (retval) { ++ com_err("ext2fs_open_inode_scan", retval, ++ "opening inode scan on %s\n", argv[optind]); ++ fprintf(stderr, "failed to open inode scan\n"); ++ exit(1); ++ } ++ ext2fs_set_inode_callback(scan, done_group_callback, NULL); ++ ++ retval = ext2fs_init_dblist(fs, NULL); ++ if (retval) { ++ com_err("ext2fs_init_dblist", retval, ++ "initializing dblist\n"); ++ exit(1); ++ } ++ ++ block_buf = (char *)malloc(fs->blocksize * 3); ++ if (block_buf == NULL) { ++ fprintf(stderr, "%s: failed to allocate memory for block_buf\n", ++ argv[0]); ++ exit(1); ++ } ++ memset(block_buf, 0, fs->blocksize * 3); ++ ++ switch (scan_data.mode) { ++ case SM_DATABASE: ++ pid = fork_db_creation(database); ++ break; ++ ++ case SM_FILELIST: ++ c = create_root_dentries(root); ++ if (c == ENOENT && strncmp(root, "/ROOT", 5) != 0) { ++ /* Try again with prepending "/ROOT" */ ++ char newroot[PATH_MAX]; ++ if (snprintf(newroot, PATH_MAX, "/ROOT/%s", root) >= ++ PATH_MAX) { ++ fprintf(stderr, "%s: root path '%s' too long\n", ++ argv[0], root); ++ exit(1); ++ } ++ if (create_root_dentries(newroot) == 0) ++ c = 0; ++ } ++ if (c == ENOENT) ++ fprintf(stderr, ++ "%s: visible filesystem root '%s' not found\n", ++ argv[0], root); ++ else if (c == EIO) ++ fprintf(stderr, ++ "%s: error reading visible root: '%s'\n", ++ argv[0], root); ++ else if (c == ENOTDIR) ++ fprintf(stderr, ++ "%s: visible root '%s' not a directory\n", ++ argv[0], root); ++ if (c) ++ exit(1); ++ break; ++ default: ++ break; ++ } ++ ++ t = time(NULL); ++ fprintf(stderr, "scanning inode tables .. "); ++ scan_data.nr = 0; ++ ++ done_group_callback(fs, scan, -readahead_groups * 2, NULL); ++ done_group_callback(fs, scan, -readahead_groups, NULL); ++ while (ext2fs_get_next_inode(scan, &ino, &inode) == 0) { ++ if (ino == 0) ++ break; ++ ++ scan_data.nr ++; ++ if (ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino) == 0) ++ /* deleted - always skip for now */ ++ continue; ++ switch (scan_data.mode) { ++ case SM_DATABASE: ++ database_iscan_action(ino, &inode, scan_data.db.fd, ++ block_buf); ++ break; ++ ++ case SM_FILELIST: ++ filelist_iscan_action(ino, &inode, block_buf); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ switch (scan_data.mode) { ++ case SM_DATABASE: ++ fprintf(stderr, ++ "done\n\t%d inodes, %ld seconds\n", ++ scan_data.nr, time(NULL) - t); ++ break; ++ ++ case SM_FILELIST: ++ fprintf(stderr, "done\n\t%d inodes, %ld seconds, %d files, " ++ "%d dirs to find\n", ++ scan_data.nr, time(NULL) - t, scan_data.fl.nr_files, ++ scan_data.fl.nr_dirs); ++ if (scan_data.fl.nr_files == 0 && scan_data.fl.nr_dirs == 0) { ++ ext2fs_close_inode_scan(scan); ++ ext2fs_close(fs); ++ free(block_buf); ++ return 0; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ t = time(NULL); ++ fprintf(stderr, "scanning directory blocks (%u).. ", ++ ext2fs_dblist_count(fs->dblist)); ++ ++ /* root directory does not have name, handle it separately */ ++ report_root(); ++ /* ++ * we have a list of directory leaf blocks, blocks are sorted, ++ * but can be not very sequential. If such blocks are close to ++ * each other, read throughput can be improved if blocks are ++ * read not sequentially, but all at once in a big ++ * chunk. Create list of those chunks, it will be then used to ++ * issue readahead ++ */ ++ make_chunk_list(fs->dblist); ++ ++ scan_data.nr = 0; ++ retval = ext2fs_dblist_dir_iterate(fs->dblist, ++ DIRENT_FLAG_INCLUDE_EMPTY, ++ block_buf, ++ dblist_iterate_cb, NULL); ++ if (retval) { ++ com_err("ext2fs_dblist_dir_iterate", retval, ++ "dir iterating dblist\n"); ++ exit(1); ++ } ++ if (chunk_size) ++ free(chunks); ++ ++ switch (scan_data.mode) { ++ case SM_DATABASE: ++ { ++ int status; ++ ++ fprintf(stderr, ++ "done\n\t%d blocks, %ld seconds, " ++ "%d records sent to database\n", ++ scan_data.nr, time(NULL) - t, scan_data.db.nr_commands); ++ close(scan_data.db.fd); ++ waitpid(pid, &status, 0); ++ if (WIFEXITED(status)) ++ fprintf(stderr, "database creation exited with %d\n", ++ WEXITSTATUS(status)); ++ break; ++ } ++ ++ case SM_FILELIST: ++ fprintf(stderr, ++ "done\n\t%d blocks, %ld seconds, %d files reported\n", ++ scan_data.nr, time(NULL) - t, scan_data.fl.nr_reported); ++ break; ++ ++ default: ++ break; ++ } ++ ++ ext2fs_close_inode_scan(scan); ++ ext2fs_close(fs); ++ free(block_buf); ++ ++ return 0; ++} +Index: e2fsprogs/e2scan/Makefile.in +=================================================================== +--- /dev/null ++++ e2fsprogs/e2scan/Makefile.in +@@ -0,0 +1,104 @@ ++# ++# Standard e2fsprogs prologue.... ++# ++ ++srcdir = @srcdir@ ++top_srcdir = @top_srcdir@ ++VPATH = @srcdir@ ++top_builddir = .. ++my_dir = e2scan ++INSTALL = @INSTALL@ ++SQLITE3_LIB = @SQLITE3_LIB@ ++ ++@MCONFIG@ ++ ++PROGS= e2scan ++MANPAGES= e2scan.8 ++ ++MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds ++ ++E2SCAN_OBJS=e2scan.o db.o filelist.o ++ ++SRCS=$(srcdir)/e2scan.c $(srcdir)/filelist.c $(srcdir)/db.c ++ ++LIBS=$(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \ ++ $(LIBUUID) $(SQLITE3_LIB) ++DEPLIBS=$(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(DEPLIBBLKID) $(DEPLIBUUID) ++ ++.c.o: ++ @echo " CC $<" ++ @$(CC) -c $(ALL_CFLAGS) $< -o $@ ++ ++all:: $(PROGS) $(MANPAGES) ++ ++e2scan: $(E2SCAN_OBJS) $(DEPLIBS) ++ @$(CC) $(ALL_LDFLAGS) -o e2scan $(E2SCAN_OBJS) $(LIBS) ++ ++e2scan.8: $(DEP_SUBSTITUTE) $(srcdir)/e2scan.8.in ++ @echo " SUBST $@" ++ @$(SUBSTITUTE_UPTIME) $(srcdir)/e2scan.8.in e2scan.8 ++ ++installdirs: ++ @echo " MKINSTALLDIRS $(sbindir) $(man8dir)" ++ @$(MKINSTALLDIRS) $(DESTDIR)$(sbindir) \ ++ $(DESTDIR)$(man8dir) ++ ++install: $(PROGS) $(MANPAGES) installdirs ++ @for i in $(PROGS); do \ ++ echo " INSTALL $(sbindir)/$$i"; \ ++ $(INSTALL_PROGRAM) $$i $(DESTDIR)$(sbindir)/$$i; \ ++ done ++ @for i in $(MANPAGES); do \ ++ for j in $(COMPRESS_EXT); do \ ++ $(RM) -f $(DESTDIR)$(man8dir)/$$i.$$j; \ ++ done; \ ++ echo " INSTALL_DATA $(man8dir)/$$i"; \ ++ $(INSTALL_DATA) $$i $(DESTDIR)$(man8dir)/$$i; \ ++ done ++ ++install-strip: install ++ @for i in $(PROGS); do \ ++ echo " STRIP $(sbindir)/$$i"; \ ++ $(STRIP) $(DESTDIR)$(sbindir)/$$i; \ ++ done ++ ++uninstall: ++ for i in $(PROGS); do \ ++ $(RM) -f $(DESTDIR)$(sbindir)/$$i; \ ++ done ++ for i in $(MANPAGES); do \ ++ $(RM) -f $(DESTDIR)$(man8dir)/$$i; \ ++ done ++ ++#check:: ++# ./correct_test1 Makefile out ++# ./correct_test2 ++ ++clean: ++ $(RM) -f e2scan correct_test1 correct_test2 e2scan.8 \#* *.s *.o *.a *~ core out ++ ++mostlyclean: clean ++distclean: clean ++ $(RM) -f debug_cmds.c .depend Makefile $(srcdir)/TAGS \ ++ $(srcdir)/Makefile.in.old ++ ++# +++ Dependency line eater +++ ++# ++# Makefile dependencies follow. This must be the last section in ++# the Makefile.in file ++# ++filelist.o: $(srcdir)/filelist.c $(top_srcdir)/lib/ext2fs/ext2_fs.h \ ++ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ ++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/et/com_err.h \ ++ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ ++ $(top_srcdir)/lib/ext2fs/bitops.h ++db.o: $(srcdir)/db.c $(top_srcdir)/lib/ext2fs/ext2_fs.h \ ++ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ ++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/et/com_err.h \ ++ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ ++ $(top_srcdir)/lib/ext2fs/bitops.h ++e2scan.o: $(srcdir)/e2scan.c \ ++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ ++ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ ++ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ ++ $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h +Index: e2fsprogs/Makefile.in +=================================================================== +--- e2fsprogs.orig/Makefile.in ++++ e2fsprogs/Makefile.in +@@ -13,9 +13,10 @@ INSTALL = @INSTALL@ + @DEBUGFS_CMT@DEBUGFS_DIR= debugfs + @UUID_CMT@UUID_LIB_SUBDIR= lib/uuid + @BLKID_CMT@BLKID_LIB_SUBDIR= lib/blkid ++@E2SCAN_CMT@E2SCAN_DIR= e2scan + + LIB_SUBDIRS=lib/et lib/ss lib/e2p $(UUID_LIB_SUBDIR) lib/ext2fs $(BLKID_LIB_SUBDIR) intl +-PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po ++PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po $(E2SCAN_DIR) + SUBDIRS=util $(LIB_SUBDIRS) $(PROG_SUBDIRS) tests + + SUBS= lib/ext2fs/ext2_types.h lib/blkid/blkid_types.h lib/uuid/uuid_types.h +@@ -60,7 +61,7 @@ distclean-doc: + + install: subs all-libs-recursive install-progs-recursive \ + install-shlibs-libs-recursive install-doc-libs +- if test ! -d e2fsck && test ! -d debugfs && test ! -d misc && test ! -d ext2ed ; then $(MAKE) install-libs ; fi ++ if test ! -d e2fsck && test ! -d debugfs && test ! -d e2scan && test ! -d misc && test ! -d ext2ed ; then $(MAKE) install-libs ; fi + + install-strip: subs all-libs-recursive install-strip-progs-recursive \ + install-shlibs-strip-libs-recursive install-doc-libs +Index: e2fsprogs/lib/ext2fs/dblist.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/dblist.c ++++ e2fsprogs/lib/ext2fs/dblist.c +@@ -152,7 +152,6 @@ errcode_t ext2fs_copy_dblist(ext2_dblist + * (moved to closefs.c) + */ + +- + /* + * Add a directory block to the directory block list + */ +Index: e2fsprogs/e2scan/filelist.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2scan/filelist.c +@@ -0,0 +1,455 @@ ++#define _GNU_SOURCE ++#define _FILE_OFFSET_BITS 64 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* e2scan.c */ ++extern ext2_filsys fs; ++extern FILE *outfile; ++extern struct { ++ int mode; ++ int nr; ++ union { ++ struct { ++ int fd; ++ int nr_commands; ++ } db; ++ struct { ++ /* number of files newer than specified time */ ++ ext2_ino_t nr_files; ++ ext2_ino_t nr_dirs; ++ /* number of files reported */ ++ ext2_ino_t nr_reported; ++ time_t mtimestamp; ++ time_t ctimestamp; ++ int with_dirs; ++ } fl; ++ }; ++} scan_data; ++ ++ext2_ino_t visible_root_ino; ++ ++int block_iterate_cb(ext2_filsys fs, blk_t *block_nr, ++ e2_blkcnt_t blockcnt, ++ blk_t ref_block EXT2FS_ATTR((unused)), ++ int ref_offset EXT2FS_ATTR((unused)), ++ void *priv_data); ++ ++ ++/* ++create root dentry ++ root->connected_to_root = 1 ++ root->d_path = "/" ++for each directory block: ++ if (directory is not in memory) ++ create new directory dentry ++ set directory->connected_to_root = 0 ++ for each entry found in directory block: ++ if (entry is a subdirectory) ++ if (subdir is in memory) ++ subdir->d_parent = directory ++ if (directory->connected_to_root) ++ recurse for each subsubdir ++ subsubdir->connected_to_root = 1 ++ subsubdir->d_parent = subdir ++ subsubdir->d_path = subdir->d_path + name ++ for each non-directory entry on subdir ++ generate full pathname and output ++ drop filename entry from RAM ++ else ++ create new subdir dentry ++ subdir->connected_to_root = directory->connected_to_root ++ subdir->d_parent = directory ++ if (directory->connected_to_root) ++ subdir->d_path = directory->d_path + name ++ else if (file is interesting) ++ if (directory->connected_to_root) ++ generate full pathname and output ++ else ++ create filename entry ++ attach filename to directory ++*/ ++ ++struct e2scan_dentry { ++ ext2_ino_t ino; ++ struct e2scan_dentry *d_parent; ++ char *name; ++ struct e2scan_dentry *d_child; /* pointer to first of subdirs */ ++ struct e2scan_dentry *d_next; /* pointer to next directory */ ++ unsigned connected_to_root:1; ++ unsigned is_file:1; ++ unsigned is_dir:1; ++ unsigned not_in_root:1; ++ unsigned is_printed:1; ++}; ++ ++static void *dentry_tree = NULL; ++ ++static int compare_ino(const void *a, const void *b) ++{ ++ const struct e2scan_dentry *d1; ++ const struct e2scan_dentry *d2; ++ ++ d1 = a; ++ d2 = b; ++ if (d1->ino > d2->ino) ++ return 1; ++ if (d1->ino < d2->ino) ++ return -1; ++ return 0; ++} ++ ++static struct e2scan_dentry *find_dentry(ext2_ino_t ino) ++{ ++ struct e2scan_dentry tmp, **pdentry; ++ ++ tmp.ino = ino; ++ pdentry = tfind(&tmp, &dentry_tree, compare_ino); ++ return (pdentry == NULL) ? NULL : *pdentry; ++} ++ ++static struct e2scan_dentry *find_or_create_dentry(ext2_ino_t ino, int *created) ++{ ++ struct e2scan_dentry **dentry, *new; ++ ++ new = calloc(1, sizeof(struct e2scan_dentry)); ++ if (new == NULL) { ++ fprintf(stderr, "malloc failed"); ++ exit(1); ++ } ++ new->ino = ino; ++ ++ dentry = tsearch(new, &dentry_tree, compare_ino); ++ if (dentry == NULL) { ++ fprintf(stderr, "tsearch failed"); ++ exit(1); ++ } ++ if (*dentry != new) { ++ *created = 0; ++ free(new); ++ } else { ++ *created = 1; ++ } ++ ++ return *dentry; ++} ++ ++static int is_file_interesting(ext2_ino_t ino) ++{ ++ return ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino); ++} ++ ++static void link_to_parent(struct e2scan_dentry *parent, ++ struct e2scan_dentry *child) ++{ ++ child->d_next = parent->d_child; ++ parent->d_child = child; ++ child->d_parent = parent; ++} ++ ++static void dentry_attach_name(struct e2scan_dentry *dentry, int namelen, ++ const char *name) ++{ ++ if (dentry->name) { ++ if (namelen == 1 && (!strcmp(name, ".") || !strcmp(name, "/"))) ++ return; ++ fprintf(stderr, "dentry name: %s, name %.*s\n", ++ dentry->name, namelen, name); ++ exit(1); ++ } ++ asprintf(&dentry->name, "%.*s", namelen, name); ++} ++ ++/* ++ - look up $ROOT in the filesystem ++ - build dentry for each component of the path, starting at / ++ - for each component of the path except the last, mark dentry "not_in_root" ++*/ ++int create_root_dentries(char *root) ++{ ++ int created; ++ char *name; ++ ext2_ino_t ino; ++ struct e2scan_dentry *child, *parent; ++ struct ext2_inode inode; ++ char *copy, *p; ++ ++ copy = p = strdup(root); ++ ++ ino = EXT2_ROOT_INO; ++ name = "/"; ++ parent = NULL; ++ do { ++ child = find_or_create_dentry(ino, &created); ++ dentry_attach_name(child, strlen(name), name); ++ child->connected_to_root = 1; ++ child->not_in_root = 1; ++ if (parent != NULL) ++ link_to_parent(parent, child); ++ parent = child; ++ ++ name = strtok(copy, "/"); ++ if (name == NULL) ++ break; ++ copy = NULL; ++ ++ if (ext2fs_lookup(fs, ino, name, strlen(name), NULL, &ino)) ++ return ENOENT; ++ } while (1); ++ ++ if (ext2fs_read_inode(fs, ino, &inode)) ++ return EIO; ++ ++ if (!LINUX_S_ISDIR(inode.i_mode)) { ++ return ENOTDIR; ++ } ++ child->not_in_root = 0; ++ visible_root_ino = ino; ++ fprintf(stderr, "visible root: \"%s\"\n", root); ++ ++ free(p); ++ ++ return 0; ++} ++ ++static inline void output_dot(void) ++{ ++ fprintf(outfile, "."); ++} ++ ++static inline void output_dot_newline(void) ++{ ++ fprintf(outfile, ".\n"); ++} ++ ++static inline void output_dir_name(const char *dirname) ++{ ++ fprintf(outfile, "/%s", dirname); ++} ++ ++static inline void output_file_name(const char *filename, int len) ++{ ++ fprintf(outfile, "/%.*s\n", len, filename); ++} ++ ++static int up_path(struct e2scan_dentry *dentry) ++{ ++ int len; ++ ++ len = 0; ++ while (dentry->ino != visible_root_ino) { ++ if (dentry->ino == EXT2_ROOT_INO) ++ return -1; ++ dentry = dentry->d_parent; ++ len ++; ++ } ++ return len; ++} ++ ++static void revert_dir_name(int path_length, struct e2scan_dentry *dentry) ++{ ++ if (path_length > 0) { ++ path_length --; ++ revert_dir_name(path_length, dentry->d_parent); ++ output_dir_name(dentry->name); ++ } ++ return; ++} ++ ++static void report_file_name(struct e2scan_dentry *dentry, ext2_ino_t ino, ++ const char *name, int namelen) ++{ ++ int path_up_length; ++ ++ ext2fs_fast_unmark_inode_bitmap2(fs->inode_map, ino); ++ ++ if (ino == visible_root_ino) { ++ /* visible root is to be reported */ ++ output_dot_newline(); ++ scan_data.fl.nr_reported ++; ++ return; ++ } ++ ++ path_up_length = up_path(dentry); ++ if (path_up_length == -1) ++ /* file is not in visible root */ ++ return; ++ ++ output_dot(); ++ revert_dir_name(path_up_length, dentry); ++ /* the file is under visible root */ ++ scan_data.fl.nr_reported ++; ++ output_file_name(name, namelen); ++} ++ ++void report_root(void) ++{ ++ if (EXT2_ROOT_INO == visible_root_ino && ++ is_file_interesting(EXT2_ROOT_INO)) { ++ output_dot_newline(); ++ scan_data.fl.nr_reported ++; ++ } ++} ++ ++static struct e2scan_dentry *connect_subtree_to_root(struct e2scan_dentry *dir, ++ int not_in_root) ++{ ++ struct e2scan_dentry *subdir, *prev, *p; ++ ++ assert(!dir->is_file); ++ dir->connected_to_root = 1; ++ dir->not_in_root = not_in_root; ++ ++ subdir = dir->d_child; ++ prev = NULL; ++ while (subdir) { ++ if (subdir->is_file) { ++ /* report filename and release dentry */ ++ report_file_name(dir, subdir->ino, subdir->name, ++ strlen(subdir->name)); ++ ++ if (prev == NULL) ++ dir->d_child = subdir->d_next; ++ else ++ prev->d_next = subdir->d_next; ++ ++ p = tdelete(subdir, &dentry_tree, compare_ino); ++ assert(p != NULL); ++ ++ free(subdir->name); ++ p = subdir->d_next; ++ free(subdir); ++ subdir = p; ++ continue; ++ } ++ if (subdir->is_dir && subdir->is_printed == 0) { ++ /* report directory name */ ++ report_file_name(dir, subdir->ino, subdir->name, ++ strlen(subdir->name)); ++ subdir->is_printed = 1; ++ } ++ connect_subtree_to_root(subdir, not_in_root); ++ prev = subdir; ++ subdir = subdir->d_next; ++ } ++ return NULL; ++} ++ ++void filelist_iscan_action(ext2_ino_t ino, ++ struct ext2_inode *inode, char *buf) ++{ ++ int created; ++ struct e2scan_dentry *dentry; ++ int to_be_listed; ++ ++ if (!LINUX_S_ISDIR(inode->i_mode) && ++ (inode->i_flags & EXT2_NODUMP_FL)) { ++ /* skip files which are not to be backuped */ ++ ext2fs_fast_unmark_inode_bitmap2(fs->inode_map, ino); ++ return; ++ } ++ ++ to_be_listed = (inode->i_ctime < scan_data.fl.ctimestamp && ++ inode->i_mtime < scan_data.fl.mtimestamp) ? 0 : 1; ++ if (LINUX_S_ISDIR(inode->i_mode)) { ++ dentry = find_or_create_dentry(ino, &created); ++ ++ if (ext2fs_block_iterate2(fs, ino, 0, buf, ++ block_iterate_cb, &ino)) { ++ fprintf(stderr, "ext2fs_block_iterate2 failed\n"); ++ exit(1); ++ } ++ dentry->is_dir = to_be_listed; ++ } ++ if (!to_be_listed) ++ /* too old files are not interesting */ ++ ext2fs_fast_unmark_inode_bitmap2(fs->inode_map, ino); ++ else { ++ /* files and directories to find names of */ ++ if (LINUX_S_ISDIR(inode->i_mode)) { ++ if (scan_data.fl.with_dirs) ++ scan_data.fl.nr_dirs++; ++ else ++ ext2fs_fast_unmark_inode_bitmap2(fs->inode_map, ++ ino); ++ } else ++ scan_data.fl.nr_files++; ++ } ++} ++ ++int filelist_dblist_iterate_cb(ext2_ino_t dirino, ++ struct ext2_dir_entry *dirent, ++ int namelen) ++{ ++ struct e2scan_dentry *dir, *subdir; ++ int created; ++ int ret; ++ struct ext2_dir_entry_2 *dirent2; ++ int is_dirname; ++ ++ dir = find_dentry(dirino); ++ assert(dir != NULL); ++ ++ dirent2 = (struct ext2_dir_entry_2 *)dirent; ++ is_dirname = (dirent2->file_type == EXT2_FT_DIR) ? 1 : 0; ++ if (is_dirname) { ++ subdir = find_dentry(dirent->inode); ++ if (subdir == NULL) ++ /* new name is encountered, skip it */ ++ return 0; ++ ++ if (subdir->d_parent == NULL) { ++ dentry_attach_name(subdir, namelen, dirent->name); ++ link_to_parent(dir, subdir); ++ ++ if (dir->connected_to_root) ++ /* ++ * go down and connect all subdirs to ++ * root recursively ++ */ ++ connect_subtree_to_root(subdir, ++ dir->not_in_root); ++ } ++ } ++ if (is_file_interesting(dirent->inode)) { ++ if (dir->connected_to_root) { ++ if (is_dirname && subdir->is_printed == 0) { ++ report_file_name(dir, dirent->inode, ++ dirent->name, namelen); ++ subdir->is_printed = 1; ++ } else ++ report_file_name(dir, dirent->inode, ++ dirent->name, namelen); ++ } else { ++ subdir = find_or_create_dentry(dirent->inode, &created); ++ if (created) { ++ dentry_attach_name(subdir,namelen,dirent->name); ++ ++ link_to_parent(dir, subdir); ++ subdir->is_file = 1; ++ } else { ++ /* ++ * dentry exists already, hard link ++ * encountered, nothing to do about it ++ */ ++ ; ++ } ++ } ++ } ++ ret = 0; ++ if (scan_data.fl.nr_reported == ++ (scan_data.fl.nr_files + scan_data.fl.nr_dirs)) ++ /* ++ * names of all recently modified files are ++ * generated, break dblist iteration ++ */ ++ ret |= DIRENT_ABORT; ++ return ret; ++} +Index: e2fsprogs/util/subst.conf.in +=================================================================== +--- e2fsprogs.orig/util/subst.conf.in ++++ e2fsprogs/util/subst.conf.in +@@ -5,6 +5,8 @@ SS_DIR @SS_DIR@ + E2FSPROGS_MONTH @E2FSPROGS_MONTH@ + E2FSPROGS_YEAR @E2FSPROGS_YEAR@ + E2FSPROGS_VERSION @E2FSPROGS_VERSION@ ++E2SCAN_CMT @E2SCAN_CMT@ ++E2SCAN_MAN @E2SCAN_MAN@ + LFSCK_CMT @LFSCK_CMT@ + LFSCK_MAN @LFSCK_MAN@ + SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ diff --git a/patches/e2fsprogs-expand-extra-isize.patch b/patches/e2fsprogs-expand-extra-isize.patch new file mode 100644 index 0000000..60397ee --- /dev/null +++ b/patches/e2fsprogs-expand-extra-isize.patch @@ -0,0 +1,1728 @@ +This patch adds a "-E expand_extra_isize" feature which makes sure that +_every_ used inode has i_extra_isize >= s_min_extra_isize if +s_min_extra_isize is set. Else it makes sure that i_extra_isize of every +inode is equal to sizeof(ext2_inode_large) - 128. + +This is useful for the case where nanosecond timestamps or 64-bit inode +version fields are required for all inodes in the filesystem. + +Signed-off-by: Kalpak Shah +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/ext2fs/ext_attr.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext_attr.c ++++ e2fsprogs/lib/ext2fs/ext_attr.c +@@ -17,6 +17,7 @@ + #endif + #include + #include ++#include + + #include "ext2_fs.h" + #include "ext2_ext_attr.h" +@@ -60,6 +61,34 @@ __u32 ext2fs_ext_attr_hash_entry(struct + #undef NAME_HASH_SHIFT + #undef VALUE_HASH_SHIFT + ++#define BLOCK_HASH_SHIFT 16 ++/* ++ * Re-compute the extended attribute hash value after an entry has changed. ++ */ ++static void ext2fs_attr_rehash(struct ext2_ext_attr_header *header, ++ struct ext2_ext_attr_entry *entry) ++{ ++ struct ext2_ext_attr_entry *here; ++ __u32 hash = 0; ++ ++ entry->e_hash = ext2fs_ext_attr_hash_entry(entry, (char *)header + ++ entry->e_value_offs); ++ ++ here = ENTRY(header+1); ++ while (!EXT2_EXT_IS_LAST_ENTRY(here)) { ++ if (!here->e_hash) { ++ /* Block is not shared if an entry's hash value == 0 */ ++ hash = 0; ++ break; ++ } ++ hash = (hash << BLOCK_HASH_SHIFT) ^ ++ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ ++ here->e_hash; ++ here = EXT2_EXT_ATTR_NEXT(here); ++ } ++ header->h_hash = hash; ++} ++ + errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf) + { + errcode_t retval; +@@ -132,7 +161,10 @@ errcode_t ext2fs_adjust_ea_refcount2(ext + if (retval) + goto errout; + +- header = (struct ext2_ext_attr_header *) block_buf; ++ header = BHDR(block_buf); ++ if (header->h_magic != EXT2_EXT_ATTR_MAGIC) ++ return EXT2_ET_EA_BAD_MAGIC; ++ + header->h_refcount += adjust; + if (newcount) + *newcount = header->h_refcount; +@@ -151,5 +183,903 @@ errcode_t ext2fs_adjust_ea_refcount(ext2 + char *block_buf, int adjust, + __u32 *newcount) + { +- return ext2fs_adjust_ea_refcount(fs, blk, block_buf, adjust, newcount); ++ return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust, newcount); ++} ++ ++struct ext2_attr_info { ++ int name_index; ++ const char *name; ++ const char *value; ++ int value_len; ++}; ++ ++struct ext2_attr_search { ++ struct ext2_ext_attr_entry *first; ++ char *base; ++ char *end; ++ struct ext2_ext_attr_entry *here; ++ int not_found; ++}; ++ ++struct ext2_attr_ibody_find { ++ ext2_ino_t ino; ++ struct ext2_attr_search s; ++}; ++ ++struct ext2_attr_block_find { ++ struct ext2_attr_search s; ++ char *block; ++}; ++ ++void ext2fs_attr_shift_entries(struct ext2_ext_attr_entry *entry, ++ int value_offs_shift, char *to, ++ char *from, int n) ++{ ++ struct ext2_ext_attr_entry *last = entry; ++ ++ /* Adjust the value offsets of the entries */ ++ for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) { ++ if (!last->e_value_block && last->e_value_size) { ++ last->e_value_offs = last->e_value_offs + ++ value_offs_shift; ++ } ++ } ++ /* Shift the entries by n bytes and zero freed space in inode */ ++ memmove(to, from, n); ++ if (to > from) ++ memset(from, 0, to - from); ++} ++ ++/* ++ * This function returns the free space present in the inode or the EA block. ++ * total is number of bytes taken up by the EA entries and is used to shift ++ * the EAs in ext2fs_expand_extra_isize(). ++ */ ++int ext2fs_attr_free_space(struct ext2_ext_attr_entry *last, ++ int *min_offs, char *base, int *total) ++{ ++ for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) { ++ *total += EXT2_EXT_ATTR_LEN(last->e_name_len); ++ if (!last->e_value_block && last->e_value_size) { ++ int offs = last->e_value_offs; ++ if (offs < *min_offs) ++ *min_offs = offs; ++ } ++ } ++ ++ return (*min_offs - ((char *)last - base) - sizeof(__u32)); ++} ++ ++static errcode_t ext2fs_attr_check_names(struct ext2_ext_attr_entry *entry, ++ char *end) ++{ ++ while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { ++ struct ext2_ext_attr_entry *next = EXT2_EXT_ATTR_NEXT(entry); ++ if ((char *)next >= end) ++ return EXT2_ET_EA_BAD_ENTRIES; ++ entry = next; ++ } ++ return 0; ++} ++ ++static errcode_t ext2fs_attr_find_entry(struct ext2_ext_attr_entry **pentry, ++ int name_index, const char *name, ++ int size, int sorted) ++{ ++ struct ext2_ext_attr_entry *entry; ++ int name_len; ++ int cmp = 1; ++ ++ if (name == NULL) ++ return EXT2_ET_EA_BAD_NAME; ++ ++ name_len = strlen(name); ++ entry = *pentry; ++ for (; !EXT2_EXT_IS_LAST_ENTRY(entry); ++ entry = EXT2_EXT_ATTR_NEXT(entry)) { ++ cmp = name_index - entry->e_name_index; ++ if (!cmp) ++ cmp = name_len - entry->e_name_len; ++ if (!cmp) ++ cmp = memcmp(name, entry->e_name, name_len); ++ if (cmp <= 0 && (sorted || cmp == 0)) ++ break; ++ } ++ *pentry = entry; ++ ++ return cmp ? EXT2_ET_EA_NAME_NOT_FOUND : 0; ++} ++ ++static errcode_t ext2fs_attr_block_find(ext2_filsys fs,struct ext2_inode *inode, ++ struct ext2_attr_info *i, ++ struct ext2_attr_block_find *bs) ++{ ++ struct ext2_ext_attr_header *header; ++ errcode_t error; ++ ++ if (inode->i_file_acl) { ++ /* The inode already has an extended attribute block. */ ++ error = ext2fs_get_mem(fs->blocksize, &bs->block); ++ if (error) ++ return error; ++ error = ext2fs_read_ext_attr(fs, inode->i_file_acl, bs->block); ++ if (error) ++ goto cleanup; ++ ++ header = BHDR(bs->block); ++ if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { ++ error = EXT2_ET_EA_BAD_MAGIC; ++ goto cleanup; ++ } ++ ++ /* Find the named attribute. */ ++ bs->s.base = bs->block; ++ bs->s.first = (struct ext2_ext_attr_entry *)(header + 1); ++ bs->s.end = bs->block + fs->blocksize; ++ bs->s.here = bs->s.first; ++ error = ext2fs_attr_find_entry(&bs->s.here, i->name_index, ++ i->name, fs->blocksize, 1); ++ if (error && error != EXT2_ET_EA_NAME_NOT_FOUND) ++ goto cleanup; ++ bs->s.not_found = error; ++ } ++ error = 0; ++ ++cleanup: ++ if (error && bs->block) ++ ext2fs_free_mem(&bs->block); ++ return error; ++} ++ ++static errcode_t ext2fs_attr_ibody_find(ext2_filsys fs, ++ struct ext2_inode_large *inode, ++ struct ext2_attr_info *i, ++ struct ext2_attr_ibody_find *is) ++{ ++ __u32 *eamagic; ++ char *start; ++ errcode_t error; ++ ++ if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE) ++ return 0; ++ ++ if (inode->i_extra_isize == 0) ++ return 0; ++ eamagic = IHDR(inode); ++ ++ start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + ++ inode->i_extra_isize + sizeof(__u32); ++ is->s.first = (struct ext2_ext_attr_entry *)start; ++ is->s.base = start; ++ is->s.here = is->s.first; ++ is->s.end = (char *)inode + EXT2_INODE_SIZE(fs->super); ++ if (*eamagic == EXT2_EXT_ATTR_MAGIC) { ++ error = ext2fs_attr_check_names((struct ext2_ext_attr_entry *) ++ start, is->s.end); ++ if (error) ++ return error; ++ /* Find the named attribute. */ ++ error = ext2fs_attr_find_entry(&is->s.here, i->name_index, ++ i->name, is->s.end - ++ (char *)is->s.base, 0); ++ if (error && error != EXT2_ET_EA_NAME_NOT_FOUND) ++ return error; ++ is->s.not_found = error; ++ } ++ ++ return 0; ++} ++ ++static errcode_t ext2fs_attr_set_entry(ext2_filsys fs, struct ext2_attr_info *i, ++ struct ext2_attr_search *s) ++{ ++ struct ext2_ext_attr_entry *last; ++ int free, min_offs = s->end - s->base, name_len = strlen(i->name); ++ ++ /* Compute min_offs and last. */ ++ for (last = s->first; !EXT2_EXT_IS_LAST_ENTRY(last); ++ last = EXT2_EXT_ATTR_NEXT(last)) { ++ if (!last->e_value_block && last->e_value_size) { ++ int offs = last->e_value_offs; ++ ++ if (offs < min_offs) ++ min_offs = offs; ++ } ++ } ++ free = min_offs - ((char *)last - s->base) - sizeof(__u32); ++ ++ if (!s->not_found) { ++ if (!s->here->e_value_block && s->here->e_value_size) { ++ int size = s->here->e_value_size; ++ free += EXT2_EXT_ATTR_SIZE(size); ++ } ++ free += EXT2_EXT_ATTR_LEN(name_len); ++ } ++ if (i->value) { ++ if (free < EXT2_EXT_ATTR_LEN(name_len) + ++ EXT2_EXT_ATTR_SIZE(i->value_len)) ++ return EXT2_ET_EA_NO_SPACE; ++ } ++ ++ if (i->value && s->not_found) { ++ /* Insert the new name. */ ++ int size = EXT2_EXT_ATTR_LEN(name_len); ++ int rest = (char *)last - (char *)s->here + sizeof(__u32); ++ ++ memmove((char *)s->here + size, s->here, rest); ++ memset(s->here, 0, size); ++ s->here->e_name_index = i->name_index; ++ s->here->e_name_len = name_len; ++ memcpy(s->here->e_name, i->name, name_len); ++ } else { ++ if (!s->here->e_value_block && s->here->e_value_size) { ++ char *first_val = s->base + min_offs; ++ int offs = s->here->e_value_offs; ++ char *val = s->base + offs; ++ int size = EXT2_EXT_ATTR_SIZE(s->here->e_value_size); ++ ++ if (i->value && ++ size == EXT2_EXT_ATTR_SIZE(i->value_len)) { ++ /* The old and the new value have the same ++ size. Just replace. */ ++ s->here->e_value_size = i->value_len; ++ memset(val + size - EXT2_EXT_ATTR_PAD, 0, ++ EXT2_EXT_ATTR_PAD); /* Clear pad bytes */ ++ memcpy(val, i->value, i->value_len); ++ return 0; ++ } ++ ++ /* Remove the old value. */ ++ memmove(first_val + size, first_val, val - first_val); ++ memset(first_val, 0, size); ++ s->here->e_value_size = 0; ++ s->here->e_value_offs = 0; ++ min_offs += size; ++ ++ /* Adjust all value offsets. */ ++ last = s->first; ++ while (!EXT2_EXT_IS_LAST_ENTRY(last)) { ++ int o = last->e_value_offs; ++ ++ if (!last->e_value_block && ++ last->e_value_size && o < offs) ++ last->e_value_offs = o + size; ++ last = EXT2_EXT_ATTR_NEXT(last); ++ } ++ } ++ if (!i->value) { ++ /* Remove the old name. */ ++ int size = EXT2_EXT_ATTR_LEN(name_len); ++ ++ last = ENTRY((char *)last - size); ++ memmove((char *)s->here, (char *)s->here + size, ++ (char *)last - (char *)s->here + sizeof(__u32)); ++ memset(last, 0, size); ++ } ++ } ++ ++ if (i->value) { ++ /* Insert the new value. */ ++ s->here->e_value_size = i->value_len; ++ if (i->value_len) { ++ int size = EXT2_EXT_ATTR_SIZE(i->value_len); ++ char *val = s->base + min_offs - size; ++ ++ s->here->e_value_offs = min_offs - size; ++ memset(val + size - EXT2_EXT_ATTR_PAD, 0, ++ EXT2_EXT_ATTR_PAD); /* Clear the pad bytes. */ ++ memcpy(val, i->value, i->value_len); ++ } ++ } ++ ++ return 0; ++} ++ ++static errcode_t ext2fs_attr_block_set(ext2_filsys fs, struct ext2_inode *inode, ++ struct ext2_attr_info *i, ++ struct ext2_attr_block_find *bs) ++{ ++ struct ext2_attr_search *s = &bs->s; ++ char *new_buf = NULL, *old_block = NULL; ++ blk_t blk; ++ int clear_flag = 0; ++ errcode_t error; ++ ++ if (i->value && i->value_len > fs->blocksize) ++ return EXT2_ET_EA_NO_SPACE; ++ ++ if (s->base) { ++ if (BHDR(s->base)->h_refcount != 1) { ++ int offset = (char *)s->here - bs->block; ++ ++ /* Decrement the refcount of the shared block */ ++ old_block = s->base; ++ BHDR(s->base)->h_refcount -= 1; ++ ++ error = ext2fs_get_mem(fs->blocksize, &s->base); ++ if (error) ++ goto cleanup; ++ clear_flag = 1; ++ memcpy(s->base, bs->block, fs->blocksize); ++ s->first = ENTRY(BHDR(s->base)+1); ++ BHDR(s->base)->h_refcount = 1; ++ s->here = ENTRY(s->base + offset); ++ s->end = s->base + fs->blocksize; ++ } ++ } else { ++ error = ext2fs_get_mem(fs->blocksize, &s->base); ++ if (error) ++ goto cleanup; ++ clear_flag = 1; ++ memset(s->base, 0, fs->blocksize); ++ BHDR(s->base)->h_magic = EXT2_EXT_ATTR_MAGIC; ++ BHDR(s->base)->h_blocks = 1; ++ BHDR(s->base)->h_refcount = 1; ++ s->first = ENTRY(BHDR(s->base)+1); ++ s->here = ENTRY(BHDR(s->base)+1); ++ s->end = s->base + fs->blocksize; ++ } ++ ++ error = ext2fs_attr_set_entry(fs, i, s); ++ if (error) ++ goto cleanup; ++ ++ if (!EXT2_EXT_IS_LAST_ENTRY(s->first)) ++ ext2fs_attr_rehash(BHDR(s->base), s->here); ++ ++ if (!EXT2_EXT_IS_LAST_ENTRY(s->first)) { ++ if (bs->block && bs->block == s->base) { ++ /* We are modifying this block in-place */ ++ new_buf = bs->block; ++ blk = inode->i_file_acl; ++ error = ext2fs_write_ext_attr(fs, blk, s->base); ++ if (error) ++ goto cleanup; ++ } else { ++ /* We need to allocate a new block */ ++ error = ext2fs_new_block(fs, 0, 0, &blk); ++ if (error) ++ goto cleanup; ++ ext2fs_block_alloc_stats(fs, blk, +1); ++ error = ext2fs_write_ext_attr(fs, blk, s->base); ++ if (error) ++ goto cleanup; ++ new_buf = s->base; ++ if (old_block) { ++ BHDR(s->base)->h_refcount -= 1; ++ error = ext2fs_write_ext_attr(fs, ++ inode->i_file_acl, ++ s->base); ++ if (error) ++ goto cleanup; ++ } ++ } ++ } ++ ++ /* Update the i_blocks if we added a new EA block */ ++ if (!inode->i_file_acl && new_buf) ++ inode->i_blocks += fs->blocksize / 512; ++ /* Update the inode. */ ++ inode->i_file_acl = new_buf ? blk : 0; ++ ++cleanup: ++ if (clear_flag) ++ ext2fs_free_mem(&s->base); ++ return 0; ++} ++ ++static errcode_t ext2fs_attr_ibody_set(ext2_filsys fs, ++ struct ext2_inode_large *inode, ++ struct ext2_attr_info *i, ++ struct ext2_attr_ibody_find *is) ++{ ++ __u32 *eamagic; ++ struct ext2_attr_search *s = &is->s; ++ errcode_t error; ++ ++ if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE) ++ return EXT2_ET_EA_NO_SPACE; ++ ++ error = ext2fs_attr_set_entry(fs, i, s); ++ if (error) ++ return error; ++ ++ eamagic = IHDR(inode); ++ if (!EXT2_EXT_IS_LAST_ENTRY(s->first)) ++ *eamagic = EXT2_EXT_ATTR_MAGIC; ++ else ++ *eamagic = 0; ++ ++ return ext2fs_write_inode_full(fs, is->ino, (struct ext2_inode *)inode, ++ EXT2_INODE_SIZE(fs->super)); ++} ++ ++static struct { ++ char str[28]; ++ int len; ++} ext2_attr_index_prefix[] = { ++ [EXT2_ATTR_INDEX_USER] = { EXT2_ATTR_INDEX_USER_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_USER_PREFIX) }, ++ [EXT2_ATTR_INDEX_POSIX_ACL_ACCESS] = ++ { EXT2_ATTR_INDEX_POSIX_ACL_ACCESS_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_POSIX_ACL_ACCESS_PREFIX) }, ++ [EXT2_ATTR_INDEX_POSIX_ACL_DEFAULT] = ++ { EXT2_ATTR_INDEX_POSIX_ACL_DEFAULT_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_POSIX_ACL_DEFAULT_PREFIX) }, ++ [EXT2_ATTR_INDEX_TRUSTED] = { EXT2_ATTR_INDEX_TRUSTED_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_TRUSTED_PREFIX) }, ++ [EXT2_ATTR_INDEX_LUSTRE] = { EXT2_ATTR_INDEX_LUSTRE_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_LUSTRE_PREFIX) }, ++ [EXT2_ATTR_INDEX_SECURITY] = { EXT2_ATTR_INDEX_SECURITY_PREFIX, ++ sizeof(EXT2_ATTR_INDEX_SECURITY_PREFIX)}, ++ { "", 0 } ++}; ++ ++errcode_t ext2fs_attr_set(ext2_filsys fs, ext2_ino_t ino, ++ struct ext2_inode *inode, ++ int name_index, const char *name, const char *value, ++ int value_len, int flags) ++{ ++ struct ext2_inode_large *inode_large = NULL; ++ struct ext2_attr_info i = { ++ .name_index = name_index, ++ .name = name, ++ .value = value, ++ .value_len = value_len, ++ }; ++ struct ext2_attr_ibody_find is = { ++ .ino = ino, ++ .s = { .not_found = -ENODATA, }, ++ }; ++ struct ext2_attr_block_find bs = { ++ .s = { .not_found = -ENODATA, }, ++ }; ++ errcode_t error; ++ ++ if (!name) ++ return EXT2_ET_EA_BAD_NAME; ++ if (strlen(name) > 255) ++ return EXT2_ET_EA_NAME_TOO_BIG; ++ ++ /* If the prefix is still present, skip it */ ++ if (strncmp(name, ext2_attr_index_prefix[name_index].str, ++ ext2_attr_index_prefix[name_index].len) == 0) ++ i.name += ext2_attr_index_prefix[name_index].len; ++ ++ if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) { ++ inode_large = (struct ext2_inode_large *)inode; ++ ++ error = ext2fs_attr_ibody_find(fs, inode_large, &i, &is); ++ if (error) ++ goto cleanup; ++ } ++ if (is.s.not_found) { ++ error = ext2fs_attr_block_find(fs, inode, &i, &bs); ++ if (error) ++ goto cleanup; ++ } ++ ++ if (is.s.not_found && bs.s.not_found) { ++ error = EXT2_ET_EA_NAME_NOT_FOUND; ++ if (flags & XATTR_REPLACE) ++ goto cleanup; ++ error = 0; ++ if (!value) ++ goto cleanup; ++ } else { ++ error = EXT2_ET_EA_NAME_EXISTS; ++ if (flags & XATTR_CREATE) ++ goto cleanup; ++ } ++ ++ if (!value) { ++ if (!is.s.not_found && ++ (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE)) ++ error = ext2fs_attr_ibody_set(fs, inode_large, &i, &is); ++ else if (!bs.s.not_found) ++ error = ext2fs_attr_block_set(fs, inode, &i, &bs); ++ } else { ++ if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) ++ error = ext2fs_attr_ibody_set(fs, inode_large, &i, &is); ++ if (!error && !bs.s.not_found) { ++ i.value = NULL; ++ error = ext2fs_attr_block_set(fs, inode, &i, &bs); ++ } else if (error == EXT2_ET_EA_NO_SPACE) { ++ error = ext2fs_attr_block_set(fs, inode, &i, &bs); ++ if (error) ++ goto cleanup; ++ if (!is.s.not_found) { ++ i.value = NULL; ++ if (EXT2_INODE_SIZE(fs->super) > ++ EXT2_GOOD_OLD_INODE_SIZE) ++ error = ext2fs_attr_ibody_set(fs, ++ inode_large, &i, &is); ++ } ++ } ++ } ++ ++cleanup: ++ return error; ++} ++ ++static errcode_t ext2fs_attr_check_block(ext2_filsys fs, char *buffer) ++{ ++ if (BHDR(buffer)->h_magic != (EXT2_EXT_ATTR_MAGIC) || ++ BHDR(buffer)->h_blocks != 1) ++ return EXT2_ET_EA_BAD_MAGIC; ++ ++ return ext2fs_attr_check_names((struct ext2_ext_attr_entry *) ++ (BHDR(buffer) + 1), ++ buffer + fs->blocksize); ++} ++ ++static errcode_t ext2fs_attr_block_get(ext2_filsys fs, struct ext2_inode *inode, ++ int name_index, const char *name, ++ void *buffer, size_t buffer_size, ++ int *easize) ++{ ++ struct ext2_ext_attr_header *header = NULL; ++ struct ext2_ext_attr_entry *entry; ++ char *block_buf = NULL; ++ errcode_t error; ++ ++ error = EXT2_ET_EA_NAME_NOT_FOUND; ++ if (!inode->i_file_acl) ++ goto cleanup; ++ ++ error = ext2fs_get_mem(fs->blocksize, &block_buf); ++ if (error) ++ return error; ++ error = ext2fs_read_ext_attr(fs, inode->i_file_acl, block_buf); ++ if (error) ++ goto cleanup; ++ ++ error = ext2fs_attr_check_block(fs, block_buf); ++ if (error) ++ goto cleanup; ++ ++ header = BHDR(block_buf); ++ entry = (struct ext2_ext_attr_entry *)(header+1); ++ error = ext2fs_attr_find_entry(&entry, name_index, name, ++ fs->blocksize, 1); ++ if (error) ++ goto cleanup; ++ if (easize) ++ *easize = entry->e_value_size; ++ if (buffer) { ++ error = EXT2_ET_EA_TOO_BIG; ++ if (entry->e_value_size > buffer_size) ++ goto cleanup; ++ memcpy(buffer, block_buf + entry->e_value_offs, ++ entry->e_value_size); ++ } ++ ++cleanup: ++ if (block_buf) ++ ext2fs_free_mem (&block_buf); ++ return error; ++} ++ ++static errcode_t ext2fs_attr_ibody_get(ext2_filsys fs, ++ struct ext2_inode_large *inode, ++ int name_index, const char *name, ++ void *buffer, size_t buffer_size, ++ int *easize) ++{ ++ struct ext2_ext_attr_entry *entry; ++ int error; ++ char *end, *start; ++ __u32 *eamagic; ++ ++ if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE) ++ return EXT2_ET_EA_NAME_NOT_FOUND; ++ ++ eamagic = IHDR(inode); ++ error = ext2fs_attr_check_block(fs, buffer); ++ if (error) ++ return error; ++ ++ start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + ++ inode->i_extra_isize + sizeof(__u32); ++ entry = (struct ext2_ext_attr_entry *)start; ++ end = (char *)inode + EXT2_INODE_SIZE(fs->super); ++ error = ext2fs_attr_check_names(entry, end); ++ if (error) ++ goto cleanup; ++ error = ext2fs_attr_find_entry(&entry, name_index, name, ++ end - (char *)entry, 0); ++ if (error) ++ goto cleanup; ++ if (easize) ++ *easize = entry->e_value_size; ++ if (buffer) { ++ error = EXT2_ET_EA_TOO_BIG; ++ if (entry->e_value_size > buffer_size) ++ goto cleanup; ++ memcpy(buffer, start + entry->e_value_offs,entry->e_value_size); ++ } ++ ++cleanup: ++ return error; ++} ++ ++ ++errcode_t ext2fs_attr_get(ext2_filsys fs, struct ext2_inode *inode, ++ int name_index, const char *name, char *buffer, ++ size_t buffer_size, int *easize) ++{ ++ errcode_t error; ++ ++ error = ext2fs_attr_ibody_get(fs, (struct ext2_inode_large *)inode, ++ name_index, name, buffer, buffer_size, ++ easize); ++ if (error == EXT2_ET_EA_NAME_NOT_FOUND) ++ error = ext2fs_attr_block_get(fs, inode, name_index, name, ++ buffer, buffer_size, easize); ++ ++ return error; ++} ++ ++int ext2fs_attr_get_next_attr(struct ext2_ext_attr_entry *entry, int name_index, ++ char *buffer, int buffer_size, int start) ++{ ++ const int prefix_len = ext2_attr_index_prefix[name_index].len; ++ int total_len; ++ ++ if (!start && !EXT2_EXT_IS_LAST_ENTRY(entry)) ++ entry = EXT2_EXT_ATTR_NEXT(entry); ++ ++ for (; !EXT2_EXT_IS_LAST_ENTRY(entry); ++ entry = EXT2_EXT_ATTR_NEXT(entry)) { ++ if (!name_index) ++ break; ++ if (name_index == entry->e_name_index) ++ break; ++ } ++ if (EXT2_EXT_IS_LAST_ENTRY(entry)) ++ return 0; ++ ++ total_len = prefix_len + entry->e_name_len + 1; ++ if (buffer && total_len <= buffer_size) { ++ memcpy(buffer, ext2_attr_index_prefix[name_index].str, ++ prefix_len); ++ memcpy(buffer + prefix_len, entry->e_name, entry->e_name_len); ++ buffer[prefix_len + entry->e_name_len] = '\0'; ++ } ++ ++ return total_len; ++} ++ ++errcode_t ext2fs_expand_extra_isize(ext2_filsys fs, ext2_ino_t ino, ++ struct ext2_inode_large *inode, ++ int new_extra_isize, int *ret, ++ int *needed_size) ++{ ++ struct ext2_inode *inode_buf = NULL; ++ __u32 *eamagic = NULL; ++ struct ext2_ext_attr_header *header = NULL; ++ struct ext2_ext_attr_entry *entry = NULL, *last = NULL; ++ struct ext2_attr_ibody_find is = { ++ .ino = ino, ++ .s = { .not_found = EXT2_ET_EA_NO_SPACE, }, ++ }; ++ struct ext2_attr_block_find bs = { ++ .s = { .not_found = EXT2_ET_EA_NO_SPACE, }, ++ }; ++ char *start, *end, *block_buf = NULL, *buffer =NULL, *b_entry_name=NULL; ++ int total_ino = 0, total_blk, free, offs, tried_min_extra_isize = 0; ++ int s_min_extra_isize = fs->super->s_min_extra_isize; ++ errcode_t error = 0; ++ ++ if (needed_size) ++ *needed_size = new_extra_isize; ++ error = ext2fs_get_mem(fs->blocksize, &block_buf); ++ if (error) ++ return error; ++ ++ if (inode == NULL) { ++ error = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode_buf); ++ if (error) ++ goto cleanup; ++ ++ error = ext2fs_read_inode_full(fs, ino, inode_buf, ++ EXT2_INODE_SIZE(fs->super)); ++ if (error) ++ goto cleanup; ++ ++ inode = (struct ext2_inode_large *)inode_buf; ++ } ++ ++retry: ++ if (inode->i_extra_isize >= new_extra_isize) ++ goto cleanup; ++ ++ eamagic = IHDR(inode); ++ start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize; ++ /* No extended attributes present */ ++ if (*eamagic != EXT2_EXT_ATTR_MAGIC) { ++ memset(start, 0, ++ EXT2_INODE_SIZE(fs->super) - EXT2_GOOD_OLD_INODE_SIZE - ++ inode->i_extra_isize); ++ inode->i_extra_isize = new_extra_isize; ++ if (needed_size) ++ *needed_size = 0; ++ goto write_inode; ++ } ++ ++ start += sizeof(__u32); ++ end = (char *)inode + EXT2_INODE_SIZE(fs->super); ++ last = entry = (struct ext2_ext_attr_entry *)start; ++ offs = end - start; ++ /* Consider space takenup by magic number */ ++ total_ino = sizeof(__u32); ++ free = ext2fs_attr_free_space(last, &offs, start, &total_ino); ++ ++ /* Enough free space available in the inode for expansion */ ++ if (free >= new_extra_isize) { ++ ext2fs_attr_shift_entries(entry, ++ inode->i_extra_isize - new_extra_isize, ++ (char *)inode +EXT2_GOOD_OLD_INODE_SIZE+ ++ new_extra_isize, ++ start - sizeof(__u32), total_ino); ++ inode->i_extra_isize = new_extra_isize; ++ if (needed_size) ++ *needed_size = 0; ++ goto write_inode; ++ } ++ ++ if (inode->i_file_acl) { ++ error = ext2fs_read_ext_attr(fs, inode->i_file_acl, block_buf); ++ if (error) ++ goto cleanup; ++ ++ header = BHDR(block_buf); ++ if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { ++ error = EXT2_ET_EA_BAD_MAGIC; ++ goto cleanup; ++ } ++ end = block_buf + fs->blocksize; ++ last = entry = (struct ext2_ext_attr_entry *)(header+1); ++ start = (char *)entry; ++ offs = end - start; ++ free = ext2fs_attr_free_space(last, &offs, start, &total_blk); ++ if (free < new_extra_isize) { ++ if (!tried_min_extra_isize && s_min_extra_isize) { ++ tried_min_extra_isize++; ++ new_extra_isize = s_min_extra_isize; ++ goto retry; ++ } ++ if (ret) ++ *ret = EXT2_EXPAND_EISIZE_NOSPC; ++ error = EXT2_ET_EA_NO_SPACE; ++ goto cleanup; ++ } ++ } else { ++ if (ret && *ret == EXT2_EXPAND_EISIZE_UNSAFE) { ++ *ret = EXT2_EXPAND_EISIZE_NEW_BLOCK; ++ error = 0; ++ goto cleanup; ++ } ++ free = fs->blocksize; ++ } ++ ++ while (new_extra_isize > 0) { ++ int offs, size, entry_size; ++ struct ext2_ext_attr_entry *small_entry = NULL; ++ struct ext2_attr_info i = { ++ .value = NULL, ++ .value_len = 0, ++ }; ++ unsigned int total_size, shift_bytes, temp = ~0U, extra_isize=0; ++ ++ start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + ++ inode->i_extra_isize + sizeof(__u32); ++ end = (char *)inode + EXT2_INODE_SIZE(fs->super); ++ last = (struct ext2_ext_attr_entry *)start; ++ ++ /* Find the entry best suited to be pushed into EA block */ ++ entry = NULL; ++ for (; !EXT2_EXT_IS_LAST_ENTRY(last); ++ last = EXT2_EXT_ATTR_NEXT(last)) { ++ total_size = EXT2_EXT_ATTR_SIZE(last->e_value_size) + ++ EXT2_EXT_ATTR_LEN(last->e_name_len); ++ if (total_size <= free && total_size < temp) { ++ if (total_size < new_extra_isize) { ++ small_entry = last; ++ } else { ++ entry = last; ++ temp = total_size; ++ } ++ } ++ } ++ ++ if (entry == NULL) { ++ if (small_entry) { ++ entry = small_entry; ++ } else { ++ if (!tried_min_extra_isize && ++ s_min_extra_isize) { ++ tried_min_extra_isize++; ++ new_extra_isize = s_min_extra_isize; ++ goto retry; ++ } ++ if (ret) ++ *ret = EXT2_EXPAND_EISIZE_NOSPC; ++ error = EXT2_ET_EA_NO_SPACE; ++ goto cleanup; ++ } ++ } ++ offs = entry->e_value_offs; ++ size = entry->e_value_size; ++ entry_size = EXT2_EXT_ATTR_LEN(entry->e_name_len); ++ i.name_index = entry->e_name_index; ++ error = ext2fs_get_mem(size, &buffer); ++ if (error) ++ goto cleanup; ++ error = ext2fs_get_mem(entry->e_name_len + 1, &b_entry_name); ++ if (error) ++ goto cleanup; ++ /* Save the entry name and the entry value */ ++ memcpy((char *)buffer, (char *)start + offs, ++ EXT2_EXT_ATTR_SIZE(size)); ++ memcpy((char *)b_entry_name, (char *)entry->e_name, ++ entry->e_name_len); ++ b_entry_name[entry->e_name_len] = '\0'; ++ i.name = b_entry_name; ++ ++ error = ext2fs_attr_ibody_find(fs, inode, &i, &is); ++ if (error) ++ goto cleanup; ++ ++ error = ext2fs_attr_set_entry(fs, &i, &is.s); ++ if (error) ++ goto cleanup; ++ ++ entry = (struct ext2_ext_attr_entry *)start; ++ if (entry_size + EXT2_EXT_ATTR_SIZE(size) >= new_extra_isize) ++ shift_bytes = new_extra_isize; ++ else ++ shift_bytes = entry_size + EXT2_EXT_ATTR_SIZE(size); ++ ext2fs_attr_shift_entries(entry, ++ inode->i_extra_isize - shift_bytes, ++ (char *)inode +EXT2_GOOD_OLD_INODE_SIZE+ ++ extra_isize + shift_bytes, ++ start - sizeof(__u32), ++ total_ino - entry_size); ++ ++ extra_isize += shift_bytes; ++ new_extra_isize -= shift_bytes; ++ if (needed_size) ++ *needed_size = new_extra_isize; ++ inode->i_extra_isize = extra_isize; ++ ++ i.name = b_entry_name; ++ i.value = buffer; ++ i.value_len = size; ++ error = ext2fs_attr_block_find(fs, (struct ext2_inode *)inode, ++ &i, &bs); ++ if (error) ++ goto cleanup; ++ ++ /* Add entry which was removed from the inode into the block */ ++ error = ext2fs_attr_block_set(fs, (struct ext2_inode *)inode, ++ &i, &bs); ++ if (error) ++ goto cleanup; ++ } ++ ++write_inode: ++ error = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)inode, ++ EXT2_INODE_SIZE(fs->super)); ++cleanup: ++ if (inode_buf) ++ ext2fs_free_mem(&inode_buf); ++ if (block_buf) ++ ext2fs_free_mem(&block_buf); ++ if (buffer) ++ ext2fs_free_mem(&buffer); ++ if (b_entry_name) ++ ext2fs_free_mem(&b_entry_name); ++ ++ return error; + } +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -670,6 +670,12 @@ static void parse_extended_opts(e2fsck_t + extended_usage++; + continue; + } ++ } else if (strcmp(token, "expand_extra_isize") == 0) { ++ ctx->flags |= E2F_FLAG_EXPAND_EISIZE; ++ if (arg) { ++ extended_usage++; ++ continue; ++ } + } else if (strcmp(token, "journal_only") == 0) { + if (arg) { + extended_usage++; +@@ -702,6 +708,7 @@ static void parse_extended_opts(e2fsck_t + fputs(("\tnodiscard\n"), stderr); + fputs(("\tshared=\n"), stderr); + fputs(("\tclone=\n"), stderr); ++ fputs(("\texpand_extra_isize\n"), stderr); + fputc('\n', stderr); + exit(1); + } +@@ -1420,6 +1427,54 @@ print_unsupp_features: + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + fatal_error(ctx, 0); + check_if_skip(ctx); ++ ++ if (EXT2_GOOD_OLD_INODE_SIZE + sb->s_want_extra_isize > ++ EXT2_INODE_SIZE(sb)) { ++ if (fix_problem(ctx, PR_0_WANT_EXTRA_ISIZE_INVALID, &pctx)) ++ sb->s_want_extra_isize = sizeof(struct ext2_inode_large) - ++ EXT2_GOOD_OLD_INODE_SIZE; ++ } ++ if (EXT2_GOOD_OLD_INODE_SIZE + sb->s_min_extra_isize > ++ EXT2_INODE_SIZE(sb)) { ++ if (fix_problem(ctx, PR_0_MIN_EXTRA_ISIZE_INVALID, &pctx)) ++ sb->s_min_extra_isize = 0; ++ } ++ if (EXT2_INODE_SIZE(sb) > EXT2_GOOD_OLD_INODE_SIZE) { ++ ctx->want_extra_isize = sizeof(struct ext2_inode_large) - ++ EXT2_GOOD_OLD_INODE_SIZE; ++ ctx->min_extra_isize = ~0L; ++ if (EXT2_HAS_RO_COMPAT_FEATURE(sb, ++ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) { ++ if (ctx->want_extra_isize < sb->s_want_extra_isize) ++ ctx->want_extra_isize = sb->s_want_extra_isize; ++ if (ctx->want_extra_isize < sb->s_min_extra_isize) ++ ctx->want_extra_isize = sb->s_min_extra_isize; ++ } ++ } ++ else { ++ if (sb->s_feature_ro_compat & ++ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) { ++ fix_problem(ctx, PR_0_CLEAR_EXTRA_ISIZE, &pctx); ++ sb->s_feature_ro_compat &= ++ ~EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE; ++ } ++ sb->s_want_extra_isize = 0; ++ sb->s_min_extra_isize = 0; ++ ctx->flags &= ~E2F_FLAG_EXPAND_EISIZE; ++ } ++ ++ if (ctx->options & E2F_OPT_READONLY) { ++ if (ctx->flags & (E2F_FLAG_EXPAND_EISIZE)) { ++ fprintf(stderr, _("Cannot enable EXTRA_ISIZE feature " ++ "on read-only filesystem\n")); ++ exit(1); ++ } ++ } else { ++ if (sb->s_want_extra_isize > sb->s_min_extra_isize && ++ (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) ++ ctx->flags |= E2F_FLAG_EXPAND_EISIZE; ++ } ++ + check_resize_inode(ctx); + if (bad_blocks_file) + read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks); +Index: e2fsprogs/lib/ext2fs/ext2_ext_attr.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_ext_attr.h ++++ e2fsprogs/lib/ext2fs/ext2_ext_attr.h +@@ -15,6 +15,9 @@ + /* Maximum number of references to one attribute block */ + #define EXT2_EXT_ATTR_REFCOUNT_MAX 1024 + ++#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ ++#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ ++ + struct ext2_ext_attr_header { + __u32 h_magic; /* magic number for identification */ + __u32 h_refcount; /* reference count */ +@@ -30,11 +33,35 @@ struct ext2_ext_attr_entry { + __u32 e_value_block; /* disk block attribute is stored on (n/i) */ + __u32 e_value_size; /* size of attribute value */ + __u32 e_hash; /* hash value of name and value */ +-#if 0 ++#if 1 + char e_name[0]; /* attribute name */ + #endif + }; + ++#define BHDR(block) ((struct ext2_ext_attr_header *)block) ++#define IHDR(inode) ((__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE + \ ++ (inode)->i_extra_isize)) ++#define ENTRY(ptr) ((struct ext2_ext_attr_entry *)(ptr)) ++ ++/* Name indexes */ ++#define EXT2_ATTR_INDEX_USER 1 ++#define EXT2_ATTR_INDEX_POSIX_ACL_ACCESS 2 ++#define EXT2_ATTR_INDEX_POSIX_ACL_DEFAULT 3 ++#define EXT2_ATTR_INDEX_TRUSTED 4 ++#define EXT2_ATTR_INDEX_LUSTRE 5 ++#define EXT2_ATTR_INDEX_SECURITY 6 ++#define EXT2_ATTR_INDEX_MAX 7 ++ ++#define EXT2_ATTR_INDEX_USER_PREFIX "user." ++#define EXT2_ATTR_INDEX_POSIX_ACL_ACCESS_PREFIX "system.posix_acl_access" ++#define EXT2_ATTR_INDEX_POSIX_ACL_DEFAULT_PREFIX "system.posix_acl_default" ++#define EXT2_ATTR_INDEX_TRUSTED_PREFIX "trusted." ++#define EXT2_ATTR_INDEX_LUSTRE_PREFIX "lustre." ++#define EXT2_ATTR_INDEX_SECURITY_PREFIX "security." ++ ++#define EXT2_ATTR_PREFIX(index) (index ## _PREFIX) ++#define EXT2_ATTR_PREFIX_LEN(index) (index ## _PRE_LEN) ++ + #define EXT2_EXT_ATTR_PAD_BITS 2 + #define EXT2_EXT_ATTR_PAD ((unsigned) 1<field)) <= \ ++ (EXT2_GOOD_OLD_INODE_SIZE + \ ++ (inode)->i_extra_isize)) \ ++ + #if defined(__KERNEL__) || defined(__linux__) + #define i_reserved1 osd1.linux1.l_i_reserved1 + #define i_frag osd2.linux2.l_i_frag +@@ -694,6 +700,7 @@ struct ext2_super_block { + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ ++ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) + + /* +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -23,6 +23,7 @@ + * - A bitmap of which inodes have bad fields. (inode_bad_map) + * - A bitmap of which inodes are in bad blocks. (inode_bb_map) + * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) ++ * - A bitmap of which inodes need to be expanded (expand_eisize_map) + * - A bitmap of which blocks are in use. (block_found_map) + * - A bitmap of which blocks are in use by two inodes (block_dup_map) + * - The data blocks of the directory inodes. (dir_map) +@@ -382,18 +383,30 @@ static void check_inode_extra_space(e2fs + (inode->i_extra_isize < min || inode->i_extra_isize > max)) { + if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx)) + return; +- inode->i_extra_isize = min; ++ inode->i_extra_isize = ctx->want_extra_isize; + e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, + EXT2_INODE_SIZE(sb), "pass1"); + return; + } + +- eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + +- inode->i_extra_isize); +- if (*eamagic == EXT2_EXT_ATTR_MAGIC) { +- /* it seems inode has an extended attribute(s) in body */ +- check_ea_in_inode(ctx, pctx); ++ eamagic = IHDR(inode); ++ if (*eamagic != EXT2_EXT_ATTR_MAGIC && ++ (ctx->flags & E2F_FLAG_EXPAND_EISIZE) && ++ (inode->i_extra_isize < ctx->want_extra_isize)) { ++ fix_problem(ctx, PR_1_EXPAND_EISIZE, pctx); ++ memset((char *)inode + EXT2_GOOD_OLD_INODE_SIZE, 0, ++ EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE); ++ inode->i_extra_isize = ctx->want_extra_isize; ++ e2fsck_write_inode_full(ctx, pctx->ino, ++ (struct ext2_inode *)inode, ++ EXT2_INODE_SIZE(sb), ++ "check_inode_extra_space"); ++ if (inode->i_extra_isize < ctx->min_extra_isize) ++ ctx->min_extra_isize = inode->i_extra_isize; + } ++ ++ if (*eamagic == EXT2_EXT_ATTR_MAGIC) ++ check_ea_in_inode(ctx, pctx); + } + + /* +@@ -547,6 +560,151 @@ extern void e2fsck_setup_tdb_icount(e2fs + *ret = 0; + } + ++int e2fsck_pass1_delete_attr(e2fsck_t ctx, struct ext2_inode_large *inode, ++ struct problem_context *pctx, int needed_size) ++{ ++ struct ext2_ext_attr_header *header; ++ struct ext2_ext_attr_entry *entry_ino, *entry_blk = NULL, *entry; ++ char *start, name[4096], block_buf[4096]; ++ int len, index = EXT2_ATTR_INDEX_USER, entry_size, ea_size; ++ int in_inode = 1, error; ++ unsigned int freed_bytes = inode->i_extra_isize; ++ ++ start = (char *)inode + EXT2_GOOD_OLD_INODE_SIZE + ++ inode->i_extra_isize + sizeof(__u32); ++ entry_ino = (struct ext2_ext_attr_entry *)start; ++ ++ if (inode->i_file_acl) { ++ error = ext2fs_read_ext_attr(ctx->fs, inode->i_file_acl, ++ block_buf); ++ /* We have already checked this block, shouldn't happen */ ++ if (error) { ++ fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, pctx); ++ return 0; ++ } ++ header = BHDR(block_buf); ++ if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { ++ fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, pctx); ++ return 0; ++ } ++ ++ entry_blk = (struct ext2_ext_attr_entry *)(header+1); ++ } ++ entry = entry_ino; ++ len = sizeof(entry->e_name); ++ entry_size = ext2fs_attr_get_next_attr(entry, index, name, len, 1); ++ ++ while (freed_bytes < needed_size) { ++ if (entry_size && name[0] != '\0') { ++ pctx->str = name; ++ if (fix_problem(ctx, PR_1_EISIZE_DELETE_EA, pctx)) { ++ ea_size = EXT2_EXT_ATTR_LEN(entry->e_name_len) + ++ EXT2_EXT_ATTR_SIZE(entry->e_value_size); ++ error = ext2fs_attr_set(ctx->fs, pctx->ino, ++ (struct ext2_inode *)inode, ++ index, name, 0,0,0); ++ if (!error) ++ freed_bytes += ea_size; ++ } ++ } ++ len = sizeof(entry->e_name); ++ entry_size = ext2fs_attr_get_next_attr(entry, index,name,len,0); ++ entry = EXT2_EXT_ATTR_NEXT(entry); ++ if (EXT2_EXT_IS_LAST_ENTRY(entry)) { ++ if (in_inode) { ++ entry = entry_blk; ++ len = sizeof(entry->e_name); ++ entry_size = ext2fs_attr_get_next_attr(entry, ++ index, name, len, 1); ++ in_inode = 0; ++ } else { ++ index += 1; ++ in_inode = 1; ++ if (!entry && index < EXT2_ATTR_INDEX_MAX) ++ entry = (struct ext2_ext_attr_entry *)start; ++ else ++ return freed_bytes; ++ } ++ } ++ } ++ ++ return freed_bytes; ++} ++ ++int e2fsck_pass1_expand_eisize(e2fsck_t ctx, struct ext2_inode_large *inode, ++ struct problem_context *pctx) ++{ ++ int needed_size = 0, retval, ret = EXT2_EXPAND_EISIZE_UNSAFE; ++ static int message; ++ ++retry: ++ retval = ext2fs_expand_extra_isize(ctx->fs, pctx->ino, inode, ++ ctx->want_extra_isize, &ret, ++ &needed_size); ++ if (ret & EXT2_EXPAND_EISIZE_NEW_BLOCK) ++ goto mark_expand_eisize_map; ++ if (!retval) { ++ e2fsck_write_inode_full(ctx, pctx->ino, ++ (struct ext2_inode *)inode, ++ EXT2_INODE_SIZE(ctx->fs->super), ++ "pass1"); ++ return 0; ++ } ++ ++ if (ret & EXT2_EXPAND_EISIZE_NOSPC) { ++ if (ctx->options & (E2F_OPT_PREEN | E2F_OPT_YES)) { ++ fix_problem(ctx, PR_1_EA_BLK_NOSPC, pctx); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -1; ++ } ++ ++ if (!message) { ++ pctx->num = ctx->fs->super->s_min_extra_isize; ++ fix_problem(ctx, PR_1_EXPAND_EISIZE_WARNING, pctx); ++ message = 1; ++ } ++delete_EA: ++ retval = e2fsck_pass1_delete_attr(ctx, inode, pctx, ++ needed_size); ++ if (retval >= ctx->want_extra_isize) ++ goto retry; ++ ++ needed_size -= retval; ++ ++ /* ++ * We loop here until either the user deletes EA(s) or ++ * EXTRA_ISIZE feature is disabled. ++ */ ++ if (fix_problem(ctx, PR_1_CLEAR_EXTRA_ISIZE, pctx)) { ++ ctx->fs->super->s_feature_ro_compat &= ++ ~EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE; ++ ext2fs_mark_super_dirty(ctx->fs); ++ } else { ++ goto delete_EA; ++ } ++ ctx->fs_unexpanded_inodes++; ++ ++ /* No EA was deleted, inode cannot be expanded */ ++ return -1; ++ } ++ ++mark_expand_eisize_map: ++ if (!ctx->expand_eisize_map) { ++ pctx->errcode = ext2fs_allocate_inode_bitmap(ctx->fs, ++ _("expand extrz isize map"), ++ &ctx->expand_eisize_map); ++ if (pctx->errcode) { ++ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, ++ pctx); ++ exit(1); ++ } ++ } ++ ++ /* Add this inode to the expand_eisize_map */ ++ ext2fs_mark_inode_bitmap2(ctx->expand_eisize_map, pctx->ino); ++ return 0; ++} ++ + void e2fsck_pass1(e2fsck_t ctx) + { + int i; +@@ -567,6 +725,8 @@ void e2fsck_pass1(e2fsck_t ctx) + int imagic_fs, extent_fs; + int busted_fs_time = 0; + int inode_size; ++ int inode_exp = 0; ++ + + init_resource_track(&rtrack, ctx->fs->io); + clear_problem_context(&pctx); +@@ -1085,6 +1245,22 @@ void e2fsck_pass1(e2fsck_t ctx) + } else + check_blocks(ctx, &pctx, block_buf); + ++ if (ctx->flags & E2F_FLAG_EXPAND_EISIZE) { ++ struct ext2_inode_large *inode_l; ++ ++ inode_l = (struct ext2_inode_large *)inode; ++ ++ if (inode_l->i_extra_isize < ctx->want_extra_isize) { ++ fix_problem(ctx, PR_1_EXPAND_EISIZE, &pctx); ++ inode_exp = e2fsck_pass1_expand_eisize(ctx, ++ inode_l, ++ &pctx); ++ } ++ if ((inode_l->i_extra_isize < ctx->min_extra_isize) && ++ inode_exp == 0) ++ ctx->min_extra_isize = inode_l->i_extra_isize; ++ } ++ + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + +@@ -1389,11 +1565,17 @@ static void adjust_extattr_refcount(e2fs + break; + pctx.blk = blk; + pctx.errcode = ext2fs_read_ext_attr2(fs, blk, block_buf); ++ /* We already checked this block, shouldn't happen */ + if (pctx.errcode) { + fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx); + return; + } +- header = (struct ext2_ext_attr_header *) block_buf; ++ header = BHDR(block_buf); ++ if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { ++ fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx); ++ return; ++ } ++ + pctx.blkcount = header->h_refcount; + should_be = header->h_refcount + adjust_sign * count; + pctx.num = should_be; +@@ -1500,7 +1682,7 @@ static int check_ext_attr(e2fsck_t ctx, + pctx->errcode = ext2fs_read_ext_attr2(fs, blk, block_buf); + if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx)) + goto clear_extattr; +- header = (struct ext2_ext_attr_header *) block_buf; ++ header = BHDR(block_buf); + pctx->blk = ext2fs_file_acl_block(inode); + if (((ctx->ext_attr_ver == 1) && + (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) || +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -509,6 +509,12 @@ typedef struct ext2_icount *ext2_icount_ + #define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + ++/* ++ * Flags for returning status of ext2fs_expand_extra_isize() ++ */ ++#define EXT2_EXPAND_EISIZE_UNSAFE 0x0001 ++#define EXT2_EXPAND_EISIZE_NEW_BLOCK 0x0002 ++#define EXT2_EXPAND_EISIZE_NOSPC 0x0004 + + /* + * For ext2 compression support +@@ -975,6 +981,16 @@ extern errcode_t ext2fs_expand_dir(ext2_ + /* ext_attr.c */ + extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, + void *data); ++int ext2fs_attr_get_next_attr(struct ext2_ext_attr_entry *entry, int name_index, ++ char *buffer, int buffer_size, int start); ++errcode_t ext2fs_attr_set(ext2_filsys fs, ext2_ino_t ino, ++ struct ext2_inode *inode, ++ int name_index, const char *name, const char *value, ++ int value_len, int flags); ++extern errcode_t ext2fs_expand_extra_isize(ext2_filsys fs, ext2_ino_t ino, ++ struct ext2_inode_large *inode, ++ int new_extra_isize, int *ret, ++ int *needed_size); + extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); + extern errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, + void *buf); +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -229,6 +229,16 @@ struct problem_context { + #define PR_0_GDT_CSUM_LATCH 0x00003E + + ++/* Invalid s_min_extra_isize */ ++#define PR_0_MIN_EXTRA_ISIZE_INVALID 0x000040 ++ ++/* Invalid s_want_extra_isize */ ++#define PR_0_WANT_EXTRA_ISIZE_INVALID 0x000041 ++ ++/* Clear EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE flag */ ++#define PR_0_CLEAR_EXTRA_ISIZE 0x000042 ++ ++ + /* + * Pass 1 errors + */ +@@ -533,6 +543,25 @@ struct problem_context { + /* eh_depth for in-inode header is bad */ + #define PR_1_EXTENT_EH_DEPTH_BAD 0x010064 + ++/* Warning for user that all inodes need to be expanded atleast by ++ * s_min_extra_isize ++ */ ++#define PR_1_EXPAND_EISIZE_WARNING 0x010068 ++ ++/* Expand the inode */ ++#define PR_1_EXPAND_EISIZE 0x010069 ++ ++/* Delete an EA so that EXTRA_ISIZE may be enabled */ ++#define PR_1_EISIZE_DELETE_EA 0x01006A ++ ++/* An EA needs to be deleted by e2fsck is being run with -p or -y */ ++#define PR_1_EA_BLK_NOSPC 0x01006B ++ ++/* Disable EXTRA_ISIZE feature as inode cannot be expanded ++ * without deletion of an EA ++ */ ++#define PR_1_CLEAR_EXTRA_ISIZE 0x01006C ++ + /* + * Pass 1b errors + */ +@@ -1003,6 +1032,9 @@ struct problem_context { + /* Inode in use but group is marked INODE_UNINIT */ + #define PR_5_INODE_UNINIT 0x050019 + ++/* Expand the inodes which need a new EA block */ ++#define PR_5_EXPAND_EISIZE 0x05001a ++ + /* + * Post-Pass 5 errors + */ +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -402,6 +402,19 @@ static struct e2fsck_problem problem_tab + N_("One or more @b @g descriptor checksums are invalid. "), + PROMPT_FIX, PR_PREEN_OK }, + ++ { PR_0_MIN_EXTRA_ISIZE_INVALID, ++ N_("@S has invalid s_min_extra_isize. "), ++ PROMPT_FIX, PR_PREEN_OK }, ++ ++ { PR_0_WANT_EXTRA_ISIZE_INVALID, ++ N_("@S has invalid s_want_extra_isize. "), ++ PROMPT_FIX, PR_PREEN_OK }, ++ ++ { PR_0_CLEAR_EXTRA_ISIZE, ++ N_("Disable extra_isize feature since @f has 128 byte inodes.\n"), ++ PROMPT_NONE, 0 }, ++ ++ + /* Pass 1 errors */ + + /* Pass 1: Checking inodes, blocks, and sizes */ +@@ -910,6 +923,38 @@ static struct e2fsck_problem problem_tab + N_("@i %i has extent header with incorrect eh_depth\n"), + PROMPT_FIX, 0 }, + ++ /* expand inode */ ++ { PR_1_EXPAND_EISIZE_WARNING, ++ N_("\ne2fsck is being run with \"expand_extra_isize\" option or\n" ++ "s_min_extra_isize of %d bytes has been set in the superblock.\n" ++ "Inode %i does not have enough free space. Either some EAs\n" ++ "need to be deleted from this inode or the RO_COMPAT_EXTRA_ISIZE\n" ++ "flag must be cleared.\n\n"), PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | ++ PR_PREEN_NOMSG }, ++ ++ /* expand inode */ ++ { PR_1_EXPAND_EISIZE, ++ N_("Expanding @i %i.\n"), ++ PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG }, ++ ++ /* delete an EA so that EXTRA_ISIZE feature may be enabled */ ++ { PR_1_EISIZE_DELETE_EA, ++ N_("Delete EA %s of @i %i so that EXTRA_ISIZE feature may be " ++ "enabled?\n"), PROMPT_FIX, PR_NO_OK | PR_PREEN_NO }, ++ ++ /* an EA needs to be deleted by e2fsck is being run with -p or -y */ ++ { PR_1_EA_BLK_NOSPC, ++ N_("An EA needs to be deleted for @i %i but e2fsck is being run\n" ++ "with -p or -y mode.\n"), ++ PROMPT_ABORT, 0 }, ++ ++ /* disable EXTRA_ISIZE feature since inode cannot be expanded */ ++ { PR_1_CLEAR_EXTRA_ISIZE, ++ N_("Disable EXTRA_ISIZE feature since @i %i cannot be expanded\n" ++ "without deletion of an EA.\n"), ++ PROMPT_FIX, 0 }, ++ ++ + /* Pass 1b errors */ + + /* Pass 1B: Rescan for duplicate/bad blocks */ +@@ -1657,6 +1702,11 @@ static struct e2fsck_problem problem_tab + N_("@g %g @i(s) in use but @g is marked INODE_UNINIT\n"), + PROMPT_FIX, PR_PREEN_OK }, + ++ /* Expand inode */ ++ { PR_5_EXPAND_EISIZE, ++ N_("Expanding @i %i.\n"), ++ PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG }, ++ + /* Post-Pass 5 errors */ + + /* Recreate journal if E2F_FLAG_JOURNAL_INODE flag is set */ +Index: e2fsprogs/e2fsck/e2fsck.c +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.c ++++ e2fsprogs/e2fsck/e2fsck.c +@@ -158,6 +158,7 @@ errcode_t e2fsck_reset_context(e2fsck_t + ctx->fs_fragmented = 0; + ctx->fs_fragmented_dir = 0; + ctx->large_files = 0; ++ ctx->fs_unexpanded_inodes = 0; + + for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++) + ctx->extent_depth_count[i] = 0; +Index: e2fsprogs/e2fsck/pass5.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass5.c ++++ e2fsprogs/e2fsck/pass5.c +@@ -70,6 +70,42 @@ void e2fsck_pass5(e2fsck_t ctx) + ext2fs_free_block_bitmap(ctx->block_found_map); + ctx->block_found_map = 0; + ++ if (ctx->flags & E2F_FLAG_EXPAND_EISIZE) { ++ int min_extra_isize; ++ ++ if (!ctx->expand_eisize_map) ++ goto set_min_extra_isize; ++ ++ for (pctx.ino = 1; pctx.ino < ctx->fs->super->s_inodes_count; ++ pctx.ino++) { ++ if (ext2fs_test_inode_bitmap2(ctx->expand_eisize_map, ++ pctx.ino)) { ++ fix_problem(ctx, PR_5_EXPAND_EISIZE, &pctx); ++ ext2fs_expand_extra_isize(ctx->fs, pctx.ino, 0, ++ ctx->want_extra_isize, ++ NULL, NULL); ++ } ++ } ++ ext2fs_free_inode_bitmap(ctx->expand_eisize_map); ++ ++set_min_extra_isize: ++ if (ctx->fs->super->s_min_extra_isize) ++ min_extra_isize = ctx->fs->super->s_min_extra_isize; ++ else ++ min_extra_isize = ctx->want_extra_isize; ++ if (ctx->min_extra_isize >= min_extra_isize && ++ !ctx->fs_unexpanded_inodes) { ++ ctx->fs->super->s_min_extra_isize =ctx->min_extra_isize; ++ ctx->fs->super->s_feature_ro_compat |= ++ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE; ++ } else { ++ ctx->fs->super->s_min_extra_isize = 0; ++ ctx->fs->super->s_feature_ro_compat &= ++ ~EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE; ++ } ++ ext2fs_mark_super_dirty(ctx->fs); ++ } ++ + print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io); + } + +@@ -707,10 +743,10 @@ static void check_inode_end(e2fsck_t ctx + + /* protect loop from wrap-around if end is maxed */ + for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) { +- if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { ++ if (!ext2fs_test_inode_bitmap2(fs->inode_map, i)) { + if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { + for (; i <= end; i++) +- ext2fs_mark_inode_bitmap(fs->inode_map, ++ ext2fs_mark_inode_bitmap2(fs->inode_map, + i); + ext2fs_mark_ib_dirty(fs); + } else +Index: e2fsprogs/lib/ext2fs/ext2_err.et.in +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_err.et.in ++++ e2fsprogs/lib/ext2fs/ext2_err.et.in +@@ -422,4 +422,28 @@ ec EXT2_NO_MTAB_FILE, + ec EXT2_ET_CANT_USE_LEGACY_BITMAPS, + "Filesystem too large to use legacy bitmaps" + ++ec EXT2_ET_EA_BAD_MAGIC, ++ "Extended attribute block has bad magic value" ++ ++ec EXT2_ET_EA_BAD_ENTRIES, ++ "Extended attribute block has bad entries" ++ ++ec EXT2_ET_EA_NO_SPACE, ++ "No free space for extended attribute" ++ ++ec EXT2_ET_EA_TOO_BIG, ++ "Extended attribute too big for buffer" ++ ++ec EXT2_ET_EA_NAME_TOO_BIG, ++ "Extended attribute name too big for header" ++ ++ec EXT2_ET_EA_BAD_NAME, ++ "Extended attribute name is bad" ++ ++ec EXT2_ET_EA_NAME_NOT_FOUND, ++ "Extended attribute name not found" ++ ++ec EXT2_ET_EA_NAME_EXISTS, ++ "Extended attribute name already exists" ++ + end +Index: e2fsprogs/tests/f_illitable_flexbg/expect.1 +=================================================================== +--- e2fsprogs.orig/tests/f_illitable_flexbg/expect.1 ++++ e2fsprogs/tests/f_illitable_flexbg/expect.1 +@@ -9,6 +9,7 @@ Relocate? yes + Group descriptor 1 checksum is invalid. FIXED. + Group descriptor 2 checksum is invalid. FIXED. + Group descriptor 3 checksum is invalid. FIXED. ++Disable extra_isize feature since filesystem has 128 byte inodes. + Pass 1: Checking inodes, blocks, and sizes + Relocating group 1's inode table to 142... + Restarting e2fsck from the beginning... +Index: e2fsprogs/tests/f_unused_itable/expect.1 +=================================================================== +--- e2fsprogs.orig/tests/f_unused_itable/expect.1 ++++ e2fsprogs/tests/f_unused_itable/expect.1 +@@ -1,3 +1,4 @@ ++Disable extra_isize feature since filesystem has 128 byte inodes. + Pass 1: Checking inodes, blocks, and sizes + Pass 2: Checking directory structure + Entry 'foo' in / (2) references inode 65 found in group 1's unused inodes area. +Index: e2fsprogs/e2fsck/emptydir.c +=================================================================== +--- e2fsprogs.orig/e2fsck/emptydir.c ++++ e2fsprogs/e2fsck/emptydir.c +@@ -98,9 +98,9 @@ void add_empty_dirblock(empty_dir_info e + db->blk, db->blockcnt, db->ino); + + ext2fs_mark_block_bitmap2(edi->empty_dir_blocks, db->blk); +- if (ext2fs_test_inode_bitmap(edi->dir_map, db->ino)) ++ if (ext2fs_test_inode_bitmap2(edi->dir_map, db->ino)) + return; +- ext2fs_mark_inode_bitmap(edi->dir_map, db->ino); ++ ext2fs_mark_inode_bitmap2(edi->dir_map, db->ino); + + ext2fs_add_dir_block2(edi->empty_dblist, db->ino, + db->blk, db->blockcnt); diff --git a/patches/e2fsprogs-extended_ops.patch b/patches/e2fsprogs-extended_ops.patch new file mode 100644 index 0000000..acc4e8a --- /dev/null +++ b/patches/e2fsprogs-extended_ops.patch @@ -0,0 +1,27 @@ +Minor reformatting patch to make applying later patches easier. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -587,14 +587,13 @@ static void parse_extended_opts(e2fsck_t + continue; + } + ea_ver = strtoul(arg, &p, 0); +- if (*p || +- ((ea_ver != 1) && (ea_ver != 2))) { +- fprintf(stderr, +- _("Invalid EA version.\n")); ++ if (*p == '\0' && (ea_ver == 1 || ea_ver == 2)) { ++ ctx->ext_attr_ver = ea_ver; ++ } else { ++ fprintf(stderr, _("Invalid EA version.\n")); + extended_usage++; + continue; + } +- ctx->ext_attr_ver = ea_ver; + } else if (strcmp(token, "fragcheck") == 0) { + ctx->options |= E2F_OPT_FRAGCHECK; + continue; diff --git a/patches/e2fsprogs-extents.patch b/patches/e2fsprogs-extents.patch new file mode 100644 index 0000000..f7fc3af --- /dev/null +++ b/patches/e2fsprogs-extents.patch @@ -0,0 +1,396 @@ +The e2fsck_ext2fs_extent_get() part of this patch is a workaround to +handle problems with old Lustre extents patches that didn't clear +the ee_start_hi or ei_leaf_hi fields. + +That has been fixed for long time and could be removed as soon as the +f_extent_* tests are fixed to clear these _hi fields. Otherwise the +extents are all marked as corrupt and it ruins those tests value. + +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -138,7 +138,7 @@ int e2fsck_pass1_check_device_inode(ext2 + * If the index flag is set, then this is a bogus + * device/fifo/socket + */ +- if (inode->i_flags & EXT2_INDEX_FL) ++ if (inode->i_flags & (EXT2_INDEX_FL | EXT4_EXTENTS_FL)) + return 0; + + /* +@@ -175,7 +175,7 @@ int e2fsck_pass1_check_symlink(ext2_fils + struct ext2fs_extent extent; + + if ((inode->i_size_high || inode->i_size == 0) || +- (inode->i_flags & EXT2_INDEX_FL)) ++ (inode->i_flags & (EXT2_INDEX_FL | EXT4_EXTENTS_FL))) + return 0; + + if (inode->i_flags & EXT4_EXTENTS_FL) { +@@ -1054,8 +1054,7 @@ void e2fsck_pass1(e2fsck_t ctx) + check_blocks(ctx, &pctx, block_buf); + continue; + } +- } +- else if (LINUX_S_ISFIFO (inode->i_mode) && ++ } else if (LINUX_S_ISFIFO (inode->i_mode) && + e2fsck_pass1_check_device_inode(fs, inode)) { + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); +@@ -1678,6 +1677,34 @@ void e2fsck_clear_inode(e2fsck_t ctx, ex + e2fsck_write_inode(ctx, ino, inode, source); + } + ++/* Workaround to handle problems with old Lustre extents patches that didn't ++ * clear the ee_start_hi or ei_leaf_hi fields. Could be removed as soon as ++ * the f_extent tests are fixed to clear these _hi fields. */ ++static errcode_t e2fsck_ext2fs_extent_get(e2fsck_t ctx, struct problem_context *pctx, ++ ext2_extent_handle_t ehandle, int flags, ++ struct ext2fs_extent *extent) ++{ ++ __u16 blk_hi; ++ int high_bits_ok = ext2fs_blocks_count(ctx->fs->super) > 0xffffffffULL; ++ int rc = 0; ++ ++ rc = ext2fs_extent_get(ehandle, flags, extent); ++ if (rc) ++ return rc; ++ ++ blk_hi = extent->e_pblk >> 32; ++ ++ if (blk_hi && !high_bits_ok && ++ fix_problem(ctx, PR_1_EXTENT_HI, pctx)) { ++ extent->e_pblk &= 0xFFFFFFFFULL; ++ rc = ext2fs_extent_replace(ehandle, 0, extent); ++ if (rc) ++ return rc; ++ } ++ ++ return rc; ++} ++ + static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, + struct process_block_struct *pb, + blk64_t start_block, +@@ -1695,8 +1722,8 @@ static void scan_extent_node(e2fsck_t ct + if (pctx->errcode) + return; + +- pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB, +- &extent); ++ pctx->errcode = e2fsck_ext2fs_extent_get(ctx, pctx, ehandle, ++ EXT2_EXTENT_FIRST_SIB, &extent); + while (!pctx->errcode && info.num_entries-- > 0) { + is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF; + is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); +@@ -1726,9 +1753,9 @@ static void scan_extent_node(e2fsck_t ct + pctx->str = "ext2fs_extent_delete"; + return; + } +- pctx->errcode = ext2fs_extent_get(ehandle, +- EXT2_EXTENT_CURRENT, +- &extent); ++ pctx->errcode = e2fsck_ext2fs_extent_get(ctx, ++ pctx, ehandle, ++ EXT2_EXTENT_CURRENT, &extent); + if (pctx->errcode == EXT2_ET_NO_CURRENT_NODE) { + pctx->errcode = 0; + break; +@@ -1740,8 +1767,8 @@ static void scan_extent_node(e2fsck_t ct + + if (!is_leaf) { + blk = extent.e_pblk; +- pctx->errcode = ext2fs_extent_get(ehandle, +- EXT2_EXTENT_DOWN, &extent); ++ pctx->errcode = e2fsck_ext2fs_extent_get(ctx, pctx, ++ ehandle, EXT2_EXTENT_DOWN, &extent); + if (pctx->errcode) { + pctx->str = "EXT2_EXTENT_DOWN"; + problem = PR_1_EXTENT_HEADER_INVALID; +@@ -1752,8 +1779,8 @@ static void scan_extent_node(e2fsck_t ct + scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle); + if (pctx->errcode) + return; +- pctx->errcode = ext2fs_extent_get(ehandle, +- EXT2_EXTENT_UP, &extent); ++ pctx->errcode = e2fsck_ext2fs_extent_get(ctx, pctx, ++ ehandle, EXT2_EXTENT_UP, &extent); + if (pctx->errcode) { + pctx->str = "EXT2_EXTENT_UP"; + return; +@@ -1818,9 +1845,9 @@ static void scan_extent_node(e2fsck_t ct + pb->previous_block = extent.e_pblk + extent.e_len - 1; + start_block = pb->last_block = extent.e_lblk + extent.e_len - 1; + next: +- pctx->errcode = ext2fs_extent_get(ehandle, +- EXT2_EXTENT_NEXT_SIB, +- &extent); ++ pctx->errcode = e2fsck_ext2fs_extent_get(ctx, pctx, ehandle, ++ EXT2_EXTENT_NEXT_SIB, ++ &extent); + } + if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT) + pctx->errcode = 0; +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -895,6 +895,21 @@ static struct e2fsck_problem problem_tab + N_("@a in @i %i is corrupt (@n value)."), + PROMPT_CLEAR, 0}, + ++ /* extent has high 16 bits set */ ++ { PR_1_EXTENT_HI, ++ N_("High 16 bits of extent/index @b set\n"), ++ PROMPT_CLEAR, PR_LATCH_EXTENT_HI|PR_PREEN_OK|PR_NO_OK|PR_PREEN_NOMSG}, ++ ++ /* extent has high 16 bits set header */ ++ { PR_1_EXTENT_HI_LATCH, ++ N_("@i %i has high 16 bits of extent/index @b set\n"), ++ PROMPT_CLEAR, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG }, ++ ++ /* eh_depth should be 0 */ ++ { PR_1_EXTENT_EH_DEPTH_BAD, ++ N_("@i %i has extent header with incorrect eh_depth\n"), ++ PROMPT_FIX, 0 }, ++ + /* Pass 1b errors */ + + /* Pass 1B: Rescan for duplicate/bad blocks */ +@@ -1661,6 +1676,7 @@ static struct latch_descr pr_latch_info[ + { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 }, + { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END }, + { PR_LATCH_BG_CHECKSUM, PR_0_GDT_CSUM_LATCH, 0 }, ++ { PR_LATCH_EXTENT_HI, PR_1_EXTENT_HI_LATCH, 0 }, + { -1, 0, 0 }, + }; + +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -39,6 +39,7 @@ struct problem_context { + #define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */ + #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */ + #define PR_LATCH_BG_CHECKSUM 0x00A0 /* Latch for block group checksums */ ++#define PR_LATCH_EXTENT_HI 0x00B0 /* Latch for extent high bits set */ + + #define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1) + +@@ -523,6 +524,15 @@ struct problem_context { + /* Bad extended attribute value in inode */ + #define PR_1_INODE_EA_BAD_VALUE 0x010061 + ++/* extent/index has high 16 bits set - header */ ++#define PR_1_EXTENT_HI 0x010062 ++ ++/* extent/index has high 16 bits set */ ++#define PR_1_EXTENT_HI_LATCH 0x010063 ++ ++/* eh_depth for in-inode header is bad */ ++#define PR_1_EXTENT_EH_DEPTH_BAD 0x010064 ++ + /* + * Pass 1b errors + */ +Index: e2fsprogs/lib/ext2fs/swapfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/swapfs.c ++++ e2fsprogs/lib/ext2fs/swapfs.c +@@ -266,11 +266,13 @@ void ext2fs_swap_inode_full(ext2_filsys + if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) + return; /* no i_extra_isize field */ + +- if (hostorder) ++ if (hostorder) { + extra_isize = f->i_extra_isize; +- t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); +- if (!hostorder) ++ t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); ++ } else { ++ t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); + extra_isize = t->i_extra_isize; ++ } + if (extra_isize > EXT2_INODE_SIZE(fs->super) - + sizeof(struct ext2_inode)) { + /* this is error case: i_extra_size is too large */ +Index: e2fsprogs/lib/ext2fs/valid_blk.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/valid_blk.c ++++ e2fsprogs/lib/ext2fs/valid_blk.c +@@ -18,6 +18,7 @@ + + #include "ext2_fs.h" + #include "ext2fs.h" ++#include "ext3_extents.h" + + /* + * This function returns 1 if the inode's block entries actually +@@ -40,12 +41,23 @@ int ext2fs_inode_has_valid_blocks(struct + if (LINUX_S_ISLNK (inode->i_mode)) { + if (ext2fs_file_acl_block(inode) == 0) { + /* With no EA block, we can rely on i_blocks */ +- if (inode->i_blocks == 0) +- return 0; ++ if (inode->i_flags & EXT4_EXTENTS_FL) { ++ struct ext3_extent_header *eh; ++ eh = (struct ext3_extent_header *)inode->i_block; ++ if (eh->eh_entries == 0) ++ return 0; ++ } else { ++ if (inode->i_blocks == 0) ++ return 0; ++ } + } else { + /* With an EA block, life gets more tricky */ + if (inode->i_size >= EXT2_N_BLOCKS*4) + return 1; /* definitely using i_block[] */ ++ /* ++ * we cannot have EA + extents, so assume we are not ++ * using extents ++ */ + if (inode->i_size > 4 && inode->i_block[1] == 0) + return 1; /* definitely using i_block[] */ + return 0; /* Probably a fast symlink */ +Index: e2fsprogs/tests/f_extents/expect.1 +=================================================================== +--- e2fsprogs.orig/tests/f_extents/expect.1 ++++ e2fsprogs/tests/f_extents/expect.1 +@@ -2,51 +2,68 @@ Pass 1: Checking inodes, blocks, and siz + Inode 12 is in extent format, but superblock is missing EXTENTS feature + Fix? yes + +-Inode 12 has an invalid extent +- (logical block 0, invalid physical block 21994527527949, len 17) ++Inode 12 has high 16 bits of extent/index block set + Clear? yes + +-Inode 12, i_blocks is 34, should be 0. Fix? yes +- ++High 16 bits of extent/index block set ++CLEARED. + Inode 13 missing EXTENT_FL, but is in extents format + Fix? yes + +-Inode 17 has an invalid extent +- (logical block 0, invalid physical block 22011707397135, len 15) +-Clear? yes +- +-Inode 17, i_blocks is 32, should be 0. Fix? yes +- ++High 16 bits of extent/index block set ++CLEARED. + Error while reading over extent tree in inode 18: Corrupt extent header + Clear inode? yes + + Inode 18, i_blocks is 2, should be 0. Fix? yes + ++ ++Running additional passes to resolve blocks claimed by more than one inode... ++Pass 1B: Rescanning for multiply-claimed blocks ++Multiply-claimed block(s) in inode 12: 5133 5124 5125 5129 5132 5133 5142 5143 5144 5145 ++Multiply-claimed block(s) in inode 17: 5124 5125 5129 5132 5142 5143 5144 5145 ++Pass 1C: Scanning directories for inodes with multiply-claimed blocks ++Pass 1D: Reconciling multiply-claimed blocks ++(There are 2 inodes containing multiply-claimed blocks.) ++ ++File /fdup1 (inode #12, mod time Wed Jul 5 21:55:26 2006) ++ has 10 multiply-claimed block(s), shared with 1 file(s): ++ /fdup2 (inode #17, mod time Wed Jul 5 21:55:27 2006) ++Clone multiply-claimed blocks? yes ++ ++File /fdup2 (inode #17, mod time Wed Jul 5 21:55:27 2006) ++ has 8 multiply-claimed block(s), shared with 1 file(s): ++ /fdup1 (inode #12, mod time Wed Jul 5 21:55:26 2006) ++Multiply-claimed blocks already reassigned or cloned. ++ + Pass 2: Checking directory structure + Entry 'fbad-flag' in / (2) has deleted/unused inode 18. Clear? yes + ++Inode 19 (/fbad-sock) is an illegal FIFO. ++Clear? yes ++ + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information +-Block bitmap differences: -1081 +4611 -(5121--5142) ++Block bitmap differences: +4611 -(5121--5122) +(5143--5146) + Fix? yes + +-Free blocks count wrong for group #0 (7081, counted=7098). ++Free blocks count wrong for group #0 (7081, counted=7065). + Fix? yes + +-Free blocks count wrong (7081, counted=7098). ++Free blocks count wrong (7081, counted=7065). + Fix? yes + + Inode bitmap differences: -18 + Fix? yes + +-Free inodes count wrong for group #0 (237, counted=238). ++Free inodes count wrong for group #0 (238, counted=239). + Fix? yes + +-Free inodes count wrong (237, counted=238). ++Free inodes count wrong (238, counted=239). + Fix? yes + + + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +-test_filesys: 18/256 files (0.0% non-contiguous), 1094/8192 blocks ++test_filesys: 17/256 files (11.8% non-contiguous), 1127/8192 blocks + Exit status is 1 +Index: e2fsprogs/tests/f_extents/expect.2 +=================================================================== +--- e2fsprogs.orig/tests/f_extents/expect.2 ++++ e2fsprogs/tests/f_extents/expect.2 +@@ -3,5 +3,5 @@ Pass 2: Checking directory structure + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information +-test_filesys: 18/256 files (0.0% non-contiguous), 1094/8192 blocks ++test_filesys: 17/256 files (11.8% non-contiguous), 1127/8192 blocks + Exit status is 0 +Index: e2fsprogs/tests/f_fast_symlink_extents/expect.1 +=================================================================== +--- e2fsprogs.orig/tests/f_fast_symlink_extents/expect.1 ++++ e2fsprogs/tests/f_fast_symlink_extents/expect.1 +@@ -1,11 +1,23 @@ + Pass 1: Checking inodes, blocks, and sizes +-Fast symlink 13 has EXTENT_FL set. Clear? yes ++Error while reading over extent tree in inode 13: Corrupt extent header ++Clear inode? yes + + Pass 2: Checking directory structure ++Entry 'bar' in / (2) has deleted/unused inode 13. Clear? yes ++ + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information ++Inode bitmap differences: -13 ++Fix? yes ++ ++Free inodes count wrong for group #0 (3, counted=4). ++Fix? yes ++ ++Free inodes count wrong (3, counted=4). ++Fix? yes ++ + + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +-test_filesys: 13/16 files (0.0% non-contiguous), 21/100 blocks ++test_filesys: 12/16 files (0.0% non-contiguous), 21/100 blocks + Exit status is 1 +Index: e2fsprogs/tests/f_fast_symlink_extents/expect.2 +=================================================================== +--- e2fsprogs.orig/tests/f_fast_symlink_extents/expect.2 ++++ e2fsprogs/tests/f_fast_symlink_extents/expect.2 +@@ -3,5 +3,5 @@ Pass 2: Checking directory structure + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information +-test_filesys: 13/16 files (0.0% non-contiguous), 21/100 blocks ++test_filesys: 12/16 files (0.0% non-contiguous), 21/100 blocks + Exit status is 0 diff --git a/patches/e2fsprogs-fiemap-lustre.patch b/patches/e2fsprogs-fiemap-lustre.patch new file mode 100644 index 0000000..0f8ee40 --- /dev/null +++ b/patches/e2fsprogs-fiemap-lustre.patch @@ -0,0 +1,651 @@ +Incremental improvements to filefrag FIEMAP handling: +* add support for multiple-device filesystems +* add -k option to print extents in kB-sized units (like df -k) +* add -b {blocksize} to print extents in blocksize units +* add -e option to use in extent format, even for non-extent files. +* add -X option to print extents in hexadecimal format + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/ext2fs/fiemap.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/fiemap.h ++++ e2fsprogs/lib/ext2fs/fiemap.h +@@ -19,7 +19,8 @@ struct fiemap_extent { + __u64 fe_length; /* length in bytes for this extent */ + __u64 fe_reserved64[2]; + __u32 fe_flags; /* FIEMAP_EXTENT_* flags for this extent */ +- __u32 fe_reserved[3]; ++ __u32 fe_device; /* device number (fs-specific if FIEMAP_EXTENT_NET)*/ ++ __u32 fe_reserved[2]; + }; + + struct fiemap { +@@ -42,6 +43,7 @@ struct fiemap { + + #define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */ + #define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute tree */ ++#define FIEMAP_FLAG_DEVICE_ORDER 0x40000000 /* return device ordered mapping */ + + #define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR) + +@@ -65,4 +67,9 @@ struct fiemap { + * support extents. Result + * merged for efficiency. */ + ++/* Network filesystem flags - use a high bit, don't conflict with upstream */ ++#define FIEMAP_EXTENT_NO_DIRECT 0x40000000 /* Data mapping undefined */ ++#define FIEMAP_EXTENT_NET 0x80000000 /* Data stored remotely. ++ * Sets NO_DIRECT flag */ ++ + #endif /* _LINUX_FIEMAP_H */ +Index: e2fsprogs/misc/filefrag.8.in +=================================================================== +--- e2fsprogs.orig/misc/filefrag.8.in ++++ e2fsprogs/misc/filefrag.8.in +@@ -5,7 +5,10 @@ filefrag \- report on file fragmentation + .SH SYNOPSIS + .B filefrag + [ +-.B \-Bbsvx ++.BI \-b blocksize ++] ++[ ++.B \-BeklsvxX + ] + [ + .I files... +@@ -27,8 +30,15 @@ If FIEMAP is not supported then filefrag + Force the use of the older FIBMAP ioctl instead of the FIEMAP ioctl for + testing purposes. + .TP +-.B \-b +-Use 1024 byte blocksize for the output. ++.BI \-b blocksize ++Use specified blocksize in bytes for the output instead of the filesystem ++.TP ++.B \-e ++Print output in extent format, even for non-extent files. ++.BI \-k ++Use 1024-byte blocksize for output. ++.B \-l ++Extents are displayed in device-logical offset order. + .TP + .B \-s + Sync the file before requesting the mapping. +@@ -38,6 +48,9 @@ Be verbose when checking for file fragme + .TP + .B \-x + Display mapping of extended attributes. ++.TP ++.B \-X ++Display extent block numbers in hexadecimal format. + .SH AUTHOR + .B filefrag + was written by Theodore Ts'o . +Index: e2fsprogs/misc/filefrag.c +=================================================================== +--- e2fsprogs.orig/misc/filefrag.c ++++ e2fsprogs/misc/filefrag.c +@@ -15,8 +15,8 @@ + #include + + int main(void) { +- fputs("This program is only supported on Linux!\n", stderr); +- exit(EXIT_FAILURE); ++ fputs("This program is only supported on Linux!\n", stderr); ++ exit(EXIT_FAILURE); + } + #else + #define _LARGEFILE64_SOURCE +@@ -43,22 +43,34 @@ extern int optind; + #include + + int verbose = 0; +-int no_bs = 0; /* Don't use the files blocksize, use 1K blocksize */ ++int blocksize = 0; /* Use specified blocksize (default 1kB) */ + int sync_file = 0; /* fsync file before getting the mapping */ + int xattr_map = 0; /* get xattr mapping */ +-int force_bmap = 0; +-int logical_width = 12; +-int physical_width = 14; +-unsigned long long filesize; ++int force_bmap = 0; /* force use of FIBMAP instead of FIEMAP */ ++int force_extent = 0; /* print output in extent format always */ ++int device_offset = 0; /* extents report device-relative offsets */ ++int logical_width = 8; ++int physical_width = 10; ++char *ext_fmt = "%4d: %*llu..%*llu: %*llu..%*llu: %6llu: %s\n"; ++char *hex_fmt = "%4d: %*llx..%*llx: %*llx..%*llx: %6llx: %s\n"; + +-#define FILEFRAG_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR) ++#define FILEFRAG_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR |\ ++ FIEMAP_FLAG_DEVICE_ORDER) + + #define FIBMAP _IO(0x00, 1) /* bmap access */ + #define FIGETBSZ _IO(0x00, 2) /* get the block size used for bmap */ + ++#define LUSTRE_SUPER_MAGIC 0x0BD00BD0 ++ + #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ + #define EXT3_IOC_GETFLAGS _IOR('f', 1, long) + ++#ifdef HAVE_FSTAT64 ++#define mystat stat64 ++#else ++#define mystat stat ++#endif ++ + static int int_log2(int arg) + { + int l = 0; +@@ -101,30 +113,41 @@ static int get_bmap(int fd, unsigned lon + if (errno == EPERM) { + fprintf(stderr, "No permission to use FIBMAP ioctl; " + "must have root privileges\n"); +- exit(1); + } +- perror("FIBMAP"); + } + *phy_blk = b; + + return ret; + } + ++static void print_extent_header(void) ++{ ++ printf(" ext: %*s %*s length: %sflags:\n", ++ logical_width * 2 + 3, ++ device_offset ? "device_logical:" : "logical_offset:", ++ physical_width * 2 + 3, "physical_offset:", ++ device_offset ? " dev: " : ""); ++} ++ + static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex, +- unsigned long long expected, int blk_shift) ++ int blk_shift, struct mystat *fileinfo) + { +- __u64 phy_blk; ++ unsigned long long physical_blk; + unsigned long long logical_blk; +- unsigned long ext_len; ++ unsigned long long ext_blks, ext_len; + char flags[256] = ""; + +- /* For inline data all offsets should be in terms of bytes, not blocks */ ++ /* For inline data all offsets should be in bytes, not blocks */ + if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE) + blk_shift = 0; + + ext_len = fm_extent->fe_length >> blk_shift; ++ ext_blks = (fm_extent->fe_length - 1) >> blk_shift; + logical_blk = fm_extent->fe_logical >> blk_shift; +- phy_blk = fm_extent->fe_physical >> blk_shift; ++ physical_blk = fm_extent->fe_physical >> blk_shift; ++ ++ if (device_offset) ++ sprintf(flags, "%04x: ", fm_extent->fe_device); + + if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN) + strcat(flags, "unknown,"); +@@ -142,45 +165,50 @@ static void print_extent_info(struct fie + strcat(flags, "unwritten,"); + if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED) + strcat(flags, "merged,"); ++ if (fm_extent->fe_flags & FIEMAP_EXTENT_NET) ++ strcat(flags, "network,"); ++ if (fm_extent->fe_flags & FIEMAP_EXTENT_NO_DIRECT) ++ strcat(flags, "no_direct,"); + +- if (fm_extent->fe_logical + fm_extent->fe_length >= filesize) ++ if (fm_extent->fe_logical + fm_extent->fe_length >= fileinfo->st_size) + strcat(flags, "eof,"); + + /* Remove trailing comma, if any */ + if (flags[0]) + flags[strlen(flags) - 1] = '\0'; + +- if (expected) +- printf("%4d %*llu %*llu %*llu %6lu %s\n", +- cur_ex, logical_width, logical_blk, +- physical_width, phy_blk, physical_width, expected, +- ext_len, flags); +- else +- printf("%4d %*llu %*llu %*s %6lu %s\n", +- cur_ex, logical_width, logical_blk, +- physical_width, phy_blk, physical_width, "", +- ext_len, flags); ++ printf(ext_fmt, cur_ex, logical_width, logical_blk, ++ logical_width, logical_blk + ext_blks, ++ physical_width, physical_blk, ++ physical_width, physical_blk + ext_blks, ++ ext_len, flags); + } + +-static int filefrag_fiemap(int fd, int blk_shift, int *num_extents) ++static int filefrag_fiemap(int fd, int blk_shift, int *num_extents, ++ struct mystat *fileinfo) + { + char buf[4096] = ""; + struct fiemap *fiemap = (struct fiemap *)buf; + struct fiemap_extent *fm_ext = &fiemap->fm_extents[0]; + int count = (sizeof(buf) - sizeof(*fiemap)) / + sizeof(struct fiemap_extent); +- unsigned long long last_blk = 0; ++ unsigned long long next_physical = 0; + unsigned long flags = 0; + unsigned int i; + static int fiemap_incompat_printed; + int fiemap_header_printed = 0; + int tot_extents = 1, n = 0; ++ int previous_device = 0; + int last = 0; + int rc; + +- memset(fiemap, 0, sizeof(struct fiemap)); ++ fiemap->fm_length = ~0ULL; + +- if (!verbose) ++ /* If extents are going to be device ordered, then we may need to use ++ * the first extent to pass the next starting offset and the device. */ ++ memset(fiemap, 0, sizeof(struct fiemap) + sizeof(struct fiemap_extent)); ++ ++ if (!verbose && !force_extent) + count = 0; + + if (sync_file) +@@ -189,6 +217,10 @@ static int filefrag_fiemap(int fd, int b + if (xattr_map) + flags |= FIEMAP_FLAG_XATTR; + ++ if (device_offset) ++ flags |= FIEMAP_FLAG_DEVICE_ORDER; ++ ++retry_wo_device_offset: + do { + fiemap->fm_length = ~0ULL; + fiemap->fm_flags = flags; +@@ -199,14 +231,16 @@ static int filefrag_fiemap(int fd, int b + printf("FIEMAP failed with unsupported " + "flags %x\n", fiemap->fm_flags); + fiemap_incompat_printed = 1; ++ } else if (rc == EBADR && (fiemap->fm_flags & ++ FIEMAP_FLAG_DEVICE_ORDER)) { ++ flags &= ~FIEMAP_FLAG_DEVICE_ORDER; ++ goto retry_wo_device_offset; + } + return rc; + } + + if (verbose && !fiemap_header_printed) { +- printf(" ext %*s %*s %*s length flags\n", logical_width, +- "logical", physical_width, "physical", +- physical_width, "expected"); ++ print_extent_header(); + fiemap_header_printed = 1; + } + +@@ -220,27 +254,40 @@ static int filefrag_fiemap(int fd, int b + break; + + for (i = 0; i < fiemap->fm_mapped_extents; i++) { +- __u64 phy_blk, logical_blk; +- unsigned long ext_len; ++ unsigned long long physical, logical; ++ ++ physical = fm_ext[i].fe_physical; ++ logical = fm_ext[i].fe_logical; + +- phy_blk = fm_ext[i].fe_physical >> blk_shift; +- ext_len = fm_ext[i].fe_length >> blk_shift; +- logical_blk = fm_ext[i].fe_logical >> blk_shift; ++ if (previous_device != fm_ext[i].fe_device) ++ previous_device = fm_ext[i].fe_device; + +- if (logical_blk && phy_blk != last_blk + 1) ++ if (logical && physical != next_physical) + tot_extents++; + else +- last_blk = 0; +- print_extent_info(&fm_ext[i], n, last_blk, blk_shift); ++ last = 0; ++ print_extent_info(&fm_ext[i], n, blk_shift, fileinfo); + +- last_blk = phy_blk + ext_len - 1; ++ next_physical = physical + fm_ext[i].fe_length; + if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST) + last = 1; + n++; + } + +- fiemap->fm_start = (fm_ext[i-1].fe_logical + +- fm_ext[i-1].fe_length); ++ /* For DEVICE_ORDER mappings, if EXTENT_LAST not yet found then ++ * fm_start needs to be the same as it was for earlier ioctl. ++ * The first extent is used to pass the end offset and device ++ * of the last FIEMAP call. Otherwise, we ask for extents ++ * starting from where the last mapping ended. */ ++ if (flags & FIEMAP_FLAG_DEVICE_ORDER) { ++ fm_ext[0].fe_logical = fm_ext[i - 1].fe_logical + ++ fm_ext[i - 1].fe_length; ++ fm_ext[0].fe_device = fm_ext[i - 1].fe_device; ++ fiemap->fm_start = 0; ++ } else { ++ fiemap->fm_start = fm_ext[i - 1].fe_logical + ++ fm_ext[i - 1].fe_length; ++ } + } while (last == 0); + + *num_extents = tot_extents; +@@ -250,24 +297,88 @@ out: + + #define EXT2_DIRECT 12 + ++static int filefrag_fibmap(int fd, int blk_shift, int *num_extents, ++ struct mystat *fileinfo, ++ unsigned long numblocks, int is_ext2) ++{ ++ struct fiemap_extent fm_ext; ++ unsigned long i, last_block; ++ unsigned long long logical; ++ /* Blocks per indirect block */ ++ const long bpib = fileinfo->st_blksize / 4; ++ int count; ++ ++ if (force_extent) { ++ memset(&fm_ext, 0, sizeof(fm_ext)); ++ fm_ext.fe_device = fileinfo->st_dev; ++ } ++ ++ for (i = 0, logical = 0, *num_extents = 0, count = last_block = 0; ++ i < numblocks; ++ i++, logical += fileinfo->st_blksize) { ++ unsigned long block = 0; ++ int rc; ++ ++ if (is_ext2 && last_block) { ++ if (((i - EXT2_DIRECT) % bpib) == 0) ++ last_block++; ++ if (((i - EXT2_DIRECT - bpib) % (bpib * bpib)) == 0) ++ last_block++; ++ if (((i - EXT2_DIRECT - bpib - bpib * bpib) % ++ (((unsigned long long)bpib )* bpib * bpib)) == 0) ++ last_block++; ++ } ++ rc = get_bmap(fd, i, &block); ++ if (rc < 0) ++ return rc; ++ if (block == 0) ++ continue; ++ if (!*num_extents) { ++ (*num_extents)++; ++ if (force_extent) { ++ print_extent_header(); ++ fm_ext.fe_physical = block*fileinfo->st_blksize; ++ } ++ } ++ count++; ++ if (force_extent && ++ (last_block && (block != last_block + 1) || ++ fm_ext.fe_logical + fm_ext.fe_length != logical)) { ++ print_extent_info(&fm_ext, *num_extents - 1, ++ blk_shift, fileinfo); ++ fm_ext.fe_logical = logical; ++ fm_ext.fe_physical = block*fileinfo->st_blksize; ++ fm_ext.fe_length = 0; ++ (*num_extents)++; ++ } else if (verbose && last_block && (block != last_block + 1)) { ++ printf("Discontinuity: Block %ld is at %lu (was %lu)\n", ++ i, block, last_block + 1); ++ (*num_extents)++; ++ } ++ fm_ext.fe_length += fileinfo->st_blksize; ++ last_block = block; ++ } ++ ++ if (force_extent) ++ print_extent_info(&fm_ext, *num_extents - 1, ++ blk_shift, fileinfo); ++ ++ return count; ++} ++ + static void frag_report(const char *filename) + { + struct statfs fsinfo; +-#ifdef HAVE_FSTAT64 +- struct stat64 fileinfo; +-#else +- struct stat fileinfo; +-#endif +- int bs; ++ struct mystat fileinfo; ++ int blk_shift; + long fd; +- unsigned long block, last_block = 0, numblocks, i, count; +- long bpib; /* Blocks per indirect block */ +- long cylgroups; +- int num_extents = 0, expected; ++ unsigned long numblocks; ++ int data_blocks_per_cyl = 1; ++ int num_extents = 1, expected; + int is_ext2 = 0; +- static int once = 1; ++ static int last_device; + unsigned int flags; +- int rc; ++ int width; + + #ifdef HAVE_OPEN64 + fd = open64(filename, O_RDONLY); +@@ -291,89 +402,91 @@ static void frag_report(const char *file + perror("stat"); + return; + } ++ fileinfo.st_blksize = fsinfo.f_bsize; + if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0) + flags = 0; + if (!(flags & EXT4_EXTENTS_FL) && + ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) || + (fsinfo.f_type == 0xef53))) + is_ext2++; +- if (verbose && once) ++ if (verbose && last_device != fileinfo.st_dev) + printf("Filesystem type is: %lx\n", + (unsigned long) fsinfo.f_type); + +- cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8); +- if (verbose && is_ext2 && once) +- printf("Filesystem cylinder groups is approximately %ld\n", +- cylgroups); +- +- physical_width = int_log10(fsinfo.f_blocks); +- if (physical_width < 8) +- physical_width = 8; +- +- if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ +- perror("FIGETBSZ"); +- close(fd); +- return; ++ /* Check if filesystem is Lustre. Always print in extent format ++ * with 1kB blocks, using the device-relative logical offsets. */ ++ if (fsinfo.f_type == LUSTRE_SUPER_MAGIC) { ++ is_ext2 = 0; ++ force_extent = 1; ++ device_offset = 1; ++ blocksize = blocksize ?: 1024; ++ } ++ ++ if (is_ext2) { ++ long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8); ++ ++ if (verbose && last_device != fileinfo.st_dev) ++ printf("Filesystem cylinder groups is approximately %ld\n", ++ cylgroups); ++ ++ data_blocks_per_cyl = fsinfo.f_bsize * 8 - ++ (fsinfo.f_files / 8 / cylgroups) - 3; + } ++ last_device = fileinfo.st_dev; + +- if (no_bs) +- bs = 1024; ++ width = int_log10(fsinfo.f_blocks); ++ if (width > physical_width) ++ physical_width = width; ++ ++ numblocks = (fileinfo.st_size + fsinfo.f_bsize - 1) / fsinfo.f_bsize; ++ if (blocksize != 0) ++ blk_shift = int_log2(blocksize); ++ else ++ blk_shift = int_log2(fsinfo.f_bsize); + +- bpib = bs / 4; +- numblocks = (fileinfo.st_size + (bs-1)) / bs; +- logical_width = int_log10(numblocks); +- if (logical_width < 7) +- logical_width = 7; +- filesize = (long long)fileinfo.st_size; ++ width = int_log10(numblocks); ++ if (width > logical_width) ++ logical_width = width; + if (verbose) +- printf("File size of %s is %lld (%ld block%s, blocksize %d)\n", +- filename, (long long) fileinfo.st_size, numblocks, +- numblocks == 1 ? "" : "s", bs); ++ printf("File size of %s is %llu (%lu block%s of %d bytes)\n", ++ filename, (unsigned long long)fileinfo.st_size, ++ numblocks * fsinfo.f_bsize >> blk_shift, ++ numblocks == 1 ? "" : "s", 1 << blk_shift); ++ + if (force_bmap || +- filefrag_fiemap(fd, int_log2(bs), &num_extents) != 0) { +- for (i = 0, count = 0; i < numblocks; i++) { +- if (is_ext2 && last_block) { +- if (((i-EXT2_DIRECT) % bpib) == 0) +- last_block++; +- if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) +- last_block++; +- if (((i-EXT2_DIRECT-bpib-bpib*bpib) % +- (((__u64) bpib)*bpib*bpib)) == 0) +- last_block++; +- } +- rc = get_bmap(fd, i, &block); +- if (block == 0) +- continue; +- if (!num_extents) +- num_extents++; +- count++; +- if (last_block && (block != last_block+1) ) { +- if (verbose) +- printf("Discontinuity: Block %ld is at " +- "%lu (was %lu)\n", +- i, block, last_block+1); +- num_extents++; ++ filefrag_fiemap(fd, blk_shift, &num_extents, &fileinfo) != 0) { ++ expected = filefrag_fibmap(fd, blk_shift, &num_extents, ++ &fileinfo, numblocks, is_ext2); ++ if (expected < 0) { ++ if (errno == EINVAL || errno == ENOTTY) { ++ fprintf(stderr, "%s: FIBMAP unsupported\n", ++ filename); ++ } else if (errno != EPERM) { ++ fprintf(stderr, "%s: FIBMAP error: %s", ++ filename, strerror(errno)); + } +- last_block = block; ++ goto out_close; + } ++ expected = expected / data_blocks_per_cyl + 1; + } ++ + if (num_extents == 1) + printf("%s: 1 extent found", filename); + else + printf("%s: %d extents found", filename, num_extents); +- expected = (count/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1; + if (is_ext2 && expected < num_extents) + printf(", perfection would be %d extent%s\n", expected, +- (expected>1) ? "s" : ""); ++ (expected > 1) ? "s" : ""); + else + fputc('\n', stdout); ++out_close: + close(fd); +- once = 0; + } + + static void usage(const char *progname) + { +- fprintf(stderr, "Usage: %s [-Bbvsx] file ...\n", progname); ++ fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeklsvxX] file ...\n", ++ progname); + exit(1); + } + +@@ -382,23 +495,61 @@ int main(int argc, char**argv) + char **cpp; + int c; + +- while ((c = getopt(argc, argv, "Bbsvx")) != EOF) ++ while ((c = getopt(argc, argv, "Bb::eklsvxX")) != EOF) + switch (c) { + case 'B': + force_bmap++; ++ force_extent = 0; + break; + case 'b': +- no_bs++; ++ if (optarg) { ++ char *end; ++ blocksize = strtoul(optarg, &end, 0); ++ if (end) { ++ switch (end[0]) { ++ case 'g': ++ case 'G': blocksize *= 1024; ++ /* no break */ ++ case 'm': ++ case 'M': blocksize *= 1024; ++ /* no break */ ++ case 'k': ++ case 'K': blocksize *= 1024; ++ break; ++ default: break; ++ } ++ } ++ } else { /* allow -b without argument, for compat */ ++ fprintf(stderr, "%s: -b needs a blocksize " ++ "option, assuming 1024-byte blocks.\n", ++ argv[0]); ++ blocksize = 1024; ++ } + break; +- case 'v': +- verbose++; ++ case 'e': ++ force_extent++; ++ if (!verbose) ++ verbose++; ++ force_bmap = 0; ++ break; ++ case 'k': ++ blocksize = 1024; ++ break; ++ case 'l': ++ device_offset++; + break; + case 's': + sync_file++; + break; ++ case 'v': ++ verbose++; ++ break; + case 'x': + xattr_map++; + break; ++ case 'X': ++ ext_fmt = hex_fmt; ++ break; + default: + usage(argv[0]); + break; diff --git a/patches/e2fsprogs-i_size-corruption.patch b/patches/e2fsprogs-i_size-corruption.patch new file mode 100644 index 0000000..85f9ce8 --- /dev/null +++ b/patches/e2fsprogs-i_size-corruption.patch @@ -0,0 +1,21 @@ +Fix handling of block preallocation support in cases where the kernel +PAGE_SIZE is larger than the filesystem blocksize. + +Signed-off-by: Kalpak Shah +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -2273,8 +2273,8 @@ static void check_blocks(e2fsck_t ctx, s + if ((pb.last_block >= 0) && + /* allow allocated blocks to end of PAGE_SIZE */ + (size < (__u64)pb.last_block * fs->blocksize) && +- (pb.last_block / blkpg * blkpg != pb.last_block || +- size < (__u64)(pb.last_block & ~(blkpg-1)) *fs->blocksize) && ++ ((pb.last_block + 1) / blkpg * blkpg != (pb.last_block+1) || ++ size < (__u64)(pb.last_block & ~(blkpg-1))*fs->blocksize)&& + !(inode->i_flags & EXT4_EOFBLOCKS_FL)) + bad_size = 3; + else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) && diff --git a/patches/e2fsprogs-ibadness-counter.patch b/patches/e2fsprogs-ibadness-counter.patch new file mode 100644 index 0000000..6f0e6bb --- /dev/null +++ b/patches/e2fsprogs-ibadness-counter.patch @@ -0,0 +1,937 @@ +The present e2fsck code checks the inode, per field basis. It doesn't +take into consideration to total sanity of the inode. This may cause +e2fsck turning a garbage inode into an apparently sane inode ("It is a +vessel of fertilizer, and none may abide its strength."). + +The following patch adds a heuristics to detect the degree of badness of +an inode. icount mechanism is used to keep track of the badness of every +inode. The badness is increased as various fields in inode are found to +be corrupt. Badness above a certain threshold value results in deletion +of the inode. The default threshold value is 7, it can be specified to +e2fsck using "-E inode_badness_threshold=" + +This can avoid lengthy pass1b shared block processing, where a corrupt +chunk of the inode table has resulted in a bunch of garbage inodes +suddenly having shared blocks with a lot of good inodes (or each other). + +Signed-off-by: Girish Shilamkar +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsck/e2fsck.h +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.h ++++ e2fsprogs/e2fsck/e2fsck.h +@@ -11,6 +11,7 @@ + + #include + #include ++#include + #ifdef HAVE_UNISTD_H + #include + #endif +@@ -204,6 +205,24 @@ typedef enum { + E2F_CLONE_ZERO + } clone_opt_t; + ++#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \ ++ ((offsetof(typeof(*ext4_inode), field) + \ ++ sizeof(ext4_inode->field)) <= \ ++ (EXT2_GOOD_OLD_INODE_SIZE + \ ++ (einode)->i_extra_isize)) \ ++ ++#define EXT4_XTIME_FUTURE(ctx, sb, xtime, margin) \ ++ (!((ctx)->flags & E2F_FLAG_TIME_INSANE) && \ ++ (xtime) > (ctx)->now + (margin)) ++#define EXT4_XTIME_ANCIENT(ctx, sb, xtime, margin) \ ++ ((xtime) < (sb)->s_mkfs_time - (margin)) ++ ++#define BADNESS_NORMAL 1 ++#define BADNESS_HIGH 2 ++#define BADNESS_THRESHOLD 8 ++#define BADNESS_BAD_MODE 100 ++#define BADNESS_LARGE_FILE 2199023255552ULL ++ + /* + * Define the extended attribute refcount structure + */ +@@ -240,7 +259,6 @@ struct e2fsck_struct { + unsigned long max); + + ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */ +- ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */ + ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */ + ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */ + ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */ +@@ -255,6 +273,8 @@ struct e2fsck_struct { + */ + ext2_icount_t inode_count; + ext2_icount_t inode_link_info; ++ ext2_icount_t inode_badness; ++ int inode_badness_threshold; + + ext2_refcount_t refcount; + ext2_refcount_t refcount_extra; +@@ -473,6 +493,11 @@ extern int e2fsck_pass1_check_symlink(ex + extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, + struct ext2_inode *inode, int restart_flag, + const char *source); ++#define e2fsck_mark_inode_bad(ctx,ino,count) \ ++ e2fsck_mark_inode_bad_loc(ctx, ino, count, __func__, __LINE__) ++extern void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, ino_t ino, int count, ++ const char *func, const int line); ++extern int is_inode_bad(e2fsck_t ctx, ino_t ino); + + /* pass2.c */ + extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -20,7 +20,8 @@ + * - A bitmap of which inodes are in use. (inode_used_map) + * - A bitmap of which inodes are directories. (inode_dir_map) + * - A bitmap of which inodes are regular files. (inode_reg_map) +- * - A bitmap of which inodes have bad fields. (inode_bad_map) ++ * - An icount mechanism is used to keep track of ++ * inodes with bad fields and its badness (ctx->inode_badness) + * - A bitmap of which inodes are in bad blocks. (inode_bb_map) + * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) + * - A bitmap of which inodes need to be expanded (expand_eisize_map) +@@ -67,7 +68,6 @@ static void check_blocks(e2fsck_t ctx, s + static void mark_table_blocks(e2fsck_t ctx); + static void alloc_bb_map(e2fsck_t ctx); + static void alloc_imagic_map(e2fsck_t ctx); +-static void mark_inode_bad(e2fsck_t ctx, ino_t ino); + static void handle_fs_bad_blocks(e2fsck_t ctx); + static void process_inodes(e2fsck_t ctx, char *block_buf); + static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b); +@@ -242,6 +242,7 @@ static void check_immutable(e2fsck_t ctx + if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS)) + return; + ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL); + if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx)) + return; + +@@ -260,6 +261,7 @@ static void check_size(e2fsck_t ctx, str + if ((inode->i_size == 0) && (inode->i_size_high == 0)) + return; + ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL); + if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx)) + return; + +@@ -360,7 +362,7 @@ static void check_inode_extra_space(e2fs + struct ext2_super_block *sb = ctx->fs->super; + struct ext2_inode_large *inode; + __u32 *eamagic; +- int min, max; ++ int min, max, dirty = 0; + + inode = (struct ext2_inode_large *) pctx->inode; + if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) { +@@ -381,12 +383,24 @@ static void check_inode_extra_space(e2fs + */ + if (inode->i_extra_isize && + (inode->i_extra_isize < min || inode->i_extra_isize > max)) { ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL); + if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx)) + return; + inode->i_extra_isize = ctx->want_extra_isize; +- e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, +- EXT2_INODE_SIZE(sb), "pass1"); +- return; ++ dirty = 1; ++ ++ goto out; ++ } ++ ++ if (EXT4_FITS_IN_INODE(inode, inode,i_crtime) && inode->i_crtime != 0 && ++ (EXT4_XTIME_FUTURE(ctx, sb, inode->i_crtime, 2 * ctx->time_fudge) || ++ EXT4_XTIME_ANCIENT(ctx, sb, inode->i_crtime, 2*ctx->time_fudge))) { ++ pctx->num = inode->i_crtime; ++ if (fix_problem(ctx, PR_1_CRTIME_BAD, pctx)) { ++ inode->i_crtime = 0; ++ dirty = 1; ++ } ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_HIGH); + } + + eamagic = IHDR(inode); +@@ -397,16 +411,17 @@ static void check_inode_extra_space(e2fs + memset((char *)inode + EXT2_GOOD_OLD_INODE_SIZE, 0, + EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE); + inode->i_extra_isize = ctx->want_extra_isize; +- e2fsck_write_inode_full(ctx, pctx->ino, +- (struct ext2_inode *)inode, +- EXT2_INODE_SIZE(sb), +- "check_inode_extra_space"); ++ dirty = 1; + if (inode->i_extra_isize < ctx->min_extra_isize) + ctx->min_extra_isize = inode->i_extra_isize; + } + + if (*eamagic == EXT2_EXT_ATTR_MAGIC) + check_ea_in_inode(ctx, pctx); ++out: ++ if (dirty) ++ e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, ++ EXT2_INODE_SIZE(sb), "pass1"); + } + + /* +@@ -521,6 +536,7 @@ static void check_is_really_dir(e2fsck_t + (rec_len % 4)) + return; + ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_TREAT_AS_DIRECTORY, pctx)) { + inode->i_mode = (inode->i_mode & 07777) | LINUX_S_IFDIR; + e2fsck_write_inode_full(ctx, pctx->ino, inode, +@@ -955,14 +971,16 @@ void e2fsck_pass1(e2fsck_t ctx) + ehp = inode->i_block; + #endif + if ((ext2fs_extent_header_verify(ehp, +- sizeof(inode->i_block)) == 0) && +- (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) { +- inode->i_flags |= EXT4_EXTENTS_FL; ++ sizeof(inode->i_block)) == 0)) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ if (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx)) { ++ inode->i_flags |= EXT4_EXTENTS_FL; + #ifdef WORDS_BIGENDIAN +- memcpy(inode->i_block, tmp_block, +- sizeof(inode->i_block)); ++ memcpy(inode->i_block, tmp_block, ++ sizeof(inode->i_block)); + #endif +- e2fsck_write_inode(ctx, ino, inode, "pass1"); ++ e2fsck_write_inode(ctx, ino, inode, "pass1"); ++ } + } + } + +@@ -1022,6 +1040,7 @@ void e2fsck_pass1(e2fsck_t ctx) + * as a special case. + */ + if (inode->i_dtime && inode->i_links_count) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) { + inode->i_dtime = 0; + e2fsck_write_inode(ctx, ino, inode, +@@ -1129,6 +1148,7 @@ void e2fsck_pass1(e2fsck_t ctx) + * + */ + if (inode->i_dtime) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) { + inode->i_dtime = 0; + e2fsck_write_inode(ctx, ino, inode, "pass1"); +@@ -1145,18 +1165,19 @@ void e2fsck_pass1(e2fsck_t ctx) + frag = fsize = 0; + } + ++ /* Fixed in pass2, e2fsck_process_bad_inode(). */ + if (inode->i_faddr || frag || fsize || + (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl)) +- mark_inode_bad(ctx, ino); +- if (!(fs->super->s_feature_incompat & ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ if (!(fs->super->s_feature_incompat & + EXT4_FEATURE_INCOMPAT_64BIT) && + inode->osd2.linux2.l_i_file_acl_high != 0) +- mark_inode_bad(ctx, ino); ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode->osd2.linux2.l_i_blocks_hi != 0)) +- mark_inode_bad(ctx, ino); ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (inode->i_flags & EXT2_IMAGIC_FL) { + if (imagic_fs) { + if (!ctx->inode_imagic_map) +@@ -1164,6 +1185,7 @@ void e2fsck_pass1(e2fsck_t ctx) + ext2fs_mark_inode_bitmap2(ctx->inode_imagic_map, + ino); + } else { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) { + inode->i_flags &= ~EXT2_IMAGIC_FL; + e2fsck_write_inode(ctx, ino, +@@ -1224,8 +1246,20 @@ void e2fsck_pass1(e2fsck_t ctx) + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); + ctx->fs_sockets_count++; +- } else +- mark_inode_bad(ctx, ino); ++ } else { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ } ++ ++ if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_atime,ctx->time_fudge)|| ++ EXT4_XTIME_FUTURE(ctx, sb, inode->i_mtime,ctx->time_fudge)) ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ ++ if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_ctime,ctx->time_fudge)|| ++ EXT4_XTIME_ANCIENT(ctx, sb, inode->i_ctime,ctx->time_fudge)) ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_HIGH); ++ ++ /* i_crtime is checked in check_inode_extra_space() */ ++ + if (!(inode->i_flags & EXT4_EXTENTS_FL)) { + if (inode->i_block[EXT2_IND_BLOCK]) + ctx->fs_ind_count++; +@@ -1444,26 +1478,31 @@ static EXT2_QSORT_TYPE process_inode_cmp + } + + /* +- * Mark an inode as being bad in some what ++ * Mark an inode as being bad and increment its badness counter. + */ +-static void mark_inode_bad(e2fsck_t ctx, ino_t ino) ++void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, ino_t ino, int count, ++ const char *func, const int line) + { + struct problem_context pctx; ++ __u16 result; + +- if (!ctx->inode_bad_map) { ++ if (!ctx->inode_badness) { + clear_problem_context(&pctx); + +- pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, +- _("bad inode map"), &ctx->inode_bad_map); ++ pctx.errcode = ext2fs_create_icount2(ctx->fs, 0, 0, NULL, ++ &ctx->inode_badness); + if (pctx.errcode) { +- pctx.num = 3; +- fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); +- /* Should never get here */ ++ fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + } +- ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino); ++ ext2fs_icount_fetch(ctx->inode_badness, ino, &result); ++ ext2fs_icount_store(ctx->inode_badness, ino, count + result); ++ ++ if (ctx->options & E2F_OPT_DEBUG) ++ fprintf(stderr, "%s:%d: increase inode %lu badness %u to %u\n", ++ func, line, (unsigned long)ino, result, count + result); + } + + +@@ -1622,7 +1661,8 @@ static int check_ext_attr(e2fsck_t ctx, + if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) || + (blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { +- mark_inode_bad(ctx, ino); ++ /* Fixed in pass2, e2fsck_process_bad_inode(). */ ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + return 0; + } + +@@ -1788,9 +1828,11 @@ static int handle_htree(e2fsck_t ctx, st + + if ((!LINUX_S_ISDIR(inode->i_mode) && + fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) || +- (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && +- fix_problem(ctx, PR_1_HTREE_SET, pctx))) +- return 1; ++ (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX))) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ if (fix_problem(ctx, PR_1_HTREE_SET, pctx)) ++ return 1; ++ } + + pctx->errcode = ext2fs_bmap2(fs, ino, inode, 0, 0, 0, 0, &blk); + +@@ -1798,6 +1840,7 @@ static int handle_htree(e2fsck_t ctx, st + (blk == 0) || + (blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + else +@@ -1805,8 +1848,11 @@ static int handle_htree(e2fsck_t ctx, st + } + + retval = io_channel_read_blk64(fs->io, blk, 1, block_buf); +- if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) +- return 1; ++ if (retval) { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); ++ if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) ++ return 1; ++ } + + /* XXX should check that beginning matches a directory */ + root = (struct ext2_dx_root_info *) (block_buf + 24); +@@ -1847,8 +1893,8 @@ void e2fsck_clear_inode(e2fsck_t ctx, ex + ext2fs_unmark_inode_bitmap2(ctx->inode_used_map, ino); + if (ctx->inode_reg_map) + ext2fs_unmark_inode_bitmap2(ctx->inode_reg_map, ino); +- if (ctx->inode_bad_map) +- ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); ++ if (ctx->inode_badness) ++ ext2fs_icount_store(ctx->inode_badness, ino, 0); + + /* + * If the inode was partially accounted for before processing +@@ -1923,6 +1969,11 @@ static void scan_extent_node(e2fsck_t ct + problem = PR_1_EXTENT_ENDS_BEYOND; + + if (problem) { ++ /* To ensure that extent is in inode */ ++ if (info.curr_level == 0) ++ e2fsck_mark_inode_bad(ctx, pctx->ino, ++ BADNESS_HIGH); ++ + report_problem: + pctx->blk = extent.e_pblk; + pctx->blk2 = extent.e_lblk; +@@ -2115,6 +2166,7 @@ static void check_blocks(e2fsck_t ctx, s + EXT2_FEATURE_INCOMPAT_COMPRESSION) + pb.compressed = 1; + else { ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) { + inode->i_flags &= ~EXT2_COMPRBLK_FL; + dirty_inode++; +@@ -2169,6 +2221,11 @@ static void check_blocks(e2fsck_t ctx, s + } + + if (!pb.num_blocks && pb.is_dir) { ++ /* ++ * The mode might be in-correct. Increasing the badness by ++ * small amount won't hurt much. ++ */ ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { + e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks"); + ctx->fs_directory_count--; +@@ -2234,6 +2291,7 @@ static void check_blocks(e2fsck_t ctx, s + if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) { + pctx->num = (pb.last_block+1) * fs->blocksize; + pctx->group = bad_size; ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { + inode->i_size = pctx->num; + if (!LINUX_S_ISDIR(inode->i_mode)) +@@ -2250,6 +2308,7 @@ static void check_blocks(e2fsck_t ctx, s + (inode->i_flags & EXT4_HUGE_FILE_FL) && + (inode->osd2.linux2.l_i_blocks_hi != 0))) { + pctx->num = pb.num_blocks; ++ e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { + inode->i_blocks = pb.num_blocks; + inode->osd2.linux2.l_i_blocks_hi = pb.num_blocks >> 32; +@@ -2406,8 +2465,10 @@ static int process_block(ext2_filsys fs, + problem = PR_1_TOOBIG_SYMLINK; + + if (blk < fs->super->s_first_data_block || +- blk >= ext2fs_blocks_count(fs->super)) ++ blk >= ext2fs_blocks_count(fs->super)) { + problem = PR_1_ILLEGAL_BLOCK_NUM; ++ e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL); ++ } + + if (problem) { + p->num_illegal_blocks++; +Index: e2fsprogs/e2fsck/pass1b.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1b.c ++++ e2fsprogs/e2fsck/pass1b.c +@@ -629,8 +629,8 @@ static void delete_file(e2fsck_t ctx, ex + block_buf, delete_file_block, &pb); + if (pctx.errcode) + fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); +- if (ctx->inode_bad_map) +- ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); ++ if (ctx->inode_badness) ++ e2fsck_mark_inode_bad(ctx, ino, 0); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); + + /* Inode may have changed by block_iterate, so reread it */ +Index: e2fsprogs/e2fsck/pass2.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass2.c ++++ e2fsprogs/e2fsck/pass2.c +@@ -33,11 +33,10 @@ + * Pass 2 relies on the following information from previous passes: + * - The directory information collected in pass 1. + * - The inode_used_map bitmap +- * - The inode_bad_map bitmap ++ * - The inode_badness bitmap + * - The inode_dir_map bitmap + * + * Pass 2 frees the following data structures +- * - The inode_bad_map bitmap + * - The inode_reg_map bitmap + */ + +@@ -248,10 +247,6 @@ void e2fsck_pass2(e2fsck_t ctx) + ext2fs_free_mem(&buf); + ext2fs_free_dblist(fs->dblist); + +- if (ctx->inode_bad_map) { +- ext2fs_free_inode_bitmap(ctx->inode_bad_map); +- ctx->inode_bad_map = 0; +- } + if (ctx->inode_reg_map) { + ext2fs_free_inode_bitmap(ctx->inode_reg_map); + ctx->inode_reg_map = 0; +@@ -479,6 +474,7 @@ static _INLINE_ int check_filetype(e2fsc + { + int filetype = dirent->name_len >> 8; + int should_be = EXT2_FT_UNKNOWN; ++ __u16 result; + struct ext2_inode inode; + + if (!(ctx->fs->super->s_feature_incompat & +@@ -490,16 +486,18 @@ static _INLINE_ int check_filetype(e2fsc + return 1; + } + ++ if (ctx->inode_badness) ++ ext2fs_icount_fetch(ctx->inode_badness, dirent->inode, ++ &result); ++ + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) { + should_be = EXT2_FT_DIR; + } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, + dirent->inode)) { + should_be = EXT2_FT_REG_FILE; +- } else if (ctx->inode_bad_map && +- ext2fs_test_inode_bitmap2(ctx->inode_bad_map, +- dirent->inode)) ++ } else if (ctx->inode_badness && result >= BADNESS_BAD_MODE) { + should_be = 0; +- else { ++ } else { + e2fsck_read_inode(ctx, dirent->inode, &inode, + "check_filetype"); + should_be = ext2_file_type(inode.i_mode); +@@ -954,12 +952,10 @@ out_htree: + * (We wait until now so that we can display the + * pathname to the user.) + */ +- if (ctx->inode_bad_map && +- ext2fs_test_inode_bitmap2(ctx->inode_bad_map, +- dirent->inode)) { +- if (e2fsck_process_bad_inode(ctx, ino, +- dirent->inode, +- buf + fs->blocksize)) { ++ if (ctx->inode_badness && ++ ext2fs_icount_is_set(ctx->inode_badness, dirent->inode)) { ++ if (e2fsck_process_bad_inode(ctx, ino, dirent->inode, ++ buf + fs->blocksize)) { + dirent->inode = 0; + dir_modified++; + goto next; +@@ -1181,9 +1177,17 @@ static void deallocate_inode(e2fsck_t ct + struct ext2_inode inode; + struct problem_context pctx; + __u32 count; ++ int extent_fs = 0; + + e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); ++ /* ext2fs_block_iterate2() depends on the extents flags */ ++ if (inode.i_flags & EXT4_EXTENTS_FL) ++ extent_fs = 1; + e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); ++ if (extent_fs) { ++ inode.i_flags |= EXT4_EXTENTS_FL; ++ e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); ++ } + clear_problem_context(&pctx); + pctx.ino = ino; + +@@ -1210,6 +1214,8 @@ static void deallocate_inode(e2fsck_t ct + if (count == 0) { + ext2fs_unmark_block_bitmap2(ctx->block_found_map, + ext2fs_file_acl_block(&inode)); ++ if (ctx->inode_badness) ++ ext2fs_icount_store(ctx->inode_badness, ino, 0); + ext2fs_block_alloc_stats2(fs, + ext2fs_file_acl_block(&inode), + -1); +@@ -1256,8 +1262,11 @@ extern int e2fsck_process_bad_inode(e2fs + int not_fixed = 0; + unsigned char *frag, *fsize; + struct problem_context pctx; +- int problem = 0; ++ int problem = 0; ++ __u16 badness; + ++ if (ctx->inode_badness) ++ ext2fs_icount_fetch(ctx->inode_badness, ino, &badness); + e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); + + clear_problem_context(&pctx); +@@ -1272,6 +1281,7 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + } + + if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && +@@ -1305,6 +1315,11 @@ extern int e2fsck_process_bad_inode(e2fs + } else + not_fixed++; + problem = 0; ++ /* ++ * A high value is associated with bad mode in order to detect ++ * that mode was corrupt in check_filetype() ++ */ ++ badness += BADNESS_BAD_MODE; + } + + if (inode.i_faddr) { +@@ -1313,6 +1328,7 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + } + + switch (fs->super->s_creator_os) { +@@ -1330,6 +1346,7 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + pctx.num = 0; + } + if (fsize && *fsize) { +@@ -1339,9 +1356,26 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + pctx.num = 0; + } + ++ /* In pass1 these conditions were used to mark inode bad so that ++ * it calls e2fsck_process_bad_inode and make an extensive check ++ * plus prompt for action to be taken. To compensate for badness ++ * incremented in pass1 by this condition, decrease it. ++ */ ++ if ((inode.i_faddr || frag || fsize || ++ (LINUX_S_ISDIR(inode.i_mode) && inode.i_dir_acl)) || ++ (inode.i_file_acl && ++ (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) || ++ (inode.i_file_acl < fs->super->s_first_data_block) || ++ (inode.i_file_acl >= fs->super->s_blocks_count)))) { ++ /* badness can be 0 if called from pass4. */ ++ if (badness) ++ badness -= BADNESS_NORMAL; ++ } ++ + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && +@@ -1351,6 +1385,8 @@ extern int e2fsck_process_bad_inode(e2fs + inode.osd2.linux2.l_i_blocks_hi = 0; + inode_modified++; + } ++ /* Badness was increased in pass1 for this condition */ ++ /* badness += BADNESS_NORMAL; */ + } + + if (!(fs->super->s_feature_incompat & +@@ -1362,6 +1398,7 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + } + + if (ext2fs_file_acl_block(&inode) && +@@ -1372,6 +1409,7 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; + } + if (inode.i_dir_acl && + LINUX_S_ISDIR(inode.i_mode)) { +@@ -1380,12 +1418,29 @@ extern int e2fsck_process_bad_inode(e2fs + inode_modified++; + } else + not_fixed++; ++ badness += BADNESS_NORMAL; ++ } ++ ++ /* ++ * The high value due to BADNESS_BAD_MODE should not delete the inode. ++ */ ++ if (ctx->inode_badness && ++ (badness - ((badness >= BADNESS_BAD_MODE) ? BADNESS_BAD_MODE : 0))>= ++ ctx->inode_badness_threshold) { ++ pctx.num = badness; ++ if (fix_problem(ctx, PR_2_INODE_TOOBAD, &pctx)) { ++ deallocate_inode(ctx, ino, 0); ++ if (ctx->flags & E2F_FLAG_SIGNAL_MASK) ++ return 0; ++ return 1; ++ } ++ not_fixed++; + } + + if (inode_modified) + e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); +- if (!not_fixed && ctx->inode_bad_map) +- ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); ++ if (ctx->inode_badness) ++ ext2fs_icount_store(ctx->inode_badness, ino, 0); + return 0; + } + +Index: e2fsprogs/e2fsck/pass4.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass4.c ++++ e2fsprogs/e2fsck/pass4.c +@@ -181,6 +181,7 @@ void e2fsck_pass4(e2fsck_t ctx) + } + ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; + ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; ++ ext2fs_free_icount(ctx->inode_badness); ctx->inode_badness = 0; + ext2fs_free_inode_bitmap(ctx->inode_bb_map); + ctx->inode_bb_map = 0; + ext2fs_free_inode_bitmap(ctx->inode_imagic_map); +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -923,6 +923,11 @@ static struct e2fsck_problem problem_tab + N_("@i %i has extent header with incorrect eh_depth\n"), + PROMPT_FIX, 0 }, + ++ /* invalid inode creation time */ ++ { PR_1_CRTIME_BAD, ++ N_("@i %i creation time (%t) invalid.\n"), ++ PROMPT_CLEAR, PR_PREEN_OK | PR_NO_OK }, ++ + /* expand inode */ + { PR_1_EXPAND_EISIZE_WARNING, + N_("\ne2fsck is being run with \"expand_extra_isize\" option or\n" +@@ -1386,6 +1391,11 @@ static struct e2fsck_problem problem_tab + N_("i_file_acl_hi @F %N, @s zero.\n"), + PROMPT_CLEAR, PR_PREEN_OK }, + ++ /* Inode too bad */ ++ { PR_2_INODE_TOOBAD, ++ N_("@i %i is badly corrupt (badness value = %N). "), ++ PROMPT_CLEAR, PR_PREEN_OK }, ++ + /* Pass 3 errors */ + + /* Pass 3: Checking directory connectivity */ +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -543,6 +543,9 @@ struct problem_context { + /* eh_depth for in-inode header is bad */ + #define PR_1_EXTENT_EH_DEPTH_BAD 0x010064 + ++/* invalid inode creation time */ ++#define PR_1_CRTIME_BAD 0x010067 ++ + /* Warning for user that all inodes need to be expanded atleast by + * s_min_extra_isize + */ +@@ -834,6 +837,9 @@ struct problem_context { + /* i_file_acl_hi should be zero */ + #define PR_2_I_FILE_ACL_HI_ZERO 0x020048 + ++/* Inode completely corrupt */ ++#define PR_2_INODE_TOOBAD 0x020049 ++ + /* + * Pass 3 errors + */ +Index: e2fsprogs/e2fsck/super.c +=================================================================== +--- e2fsprogs.orig/e2fsck/super.c ++++ e2fsprogs/e2fsck/super.c +@@ -834,8 +834,7 @@ void check_super_block(e2fsck_t ctx) + * write time is in the future. + */ + if (!broken_system_clock && +- !(ctx->flags & E2F_FLAG_TIME_INSANE) && +- fs->super->s_mtime > (__u32) ctx->now) { ++ EXT4_XTIME_FUTURE(ctx, fs->super, fs->super->s_mtime, 0)) { + pctx.num = fs->super->s_mtime; + problem = PR_0_FUTURE_SB_LAST_MOUNT; + if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge) +@@ -846,8 +845,7 @@ void check_super_block(e2fsck_t ctx) + } + } + if (!broken_system_clock && +- !(ctx->flags & E2F_FLAG_TIME_INSANE) && +- fs->super->s_wtime > (__u32) ctx->now) { ++ EXT4_XTIME_FUTURE(ctx, fs->super, fs->super->s_wtime, 0)) { + pctx.num = fs->super->s_wtime; + problem = PR_0_FUTURE_SB_LAST_WRITE; + if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge) +Index: e2fsprogs/lib/ext2fs/icount.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/icount.c ++++ e2fsprogs/lib/ext2fs/icount.c +@@ -467,6 +467,23 @@ static errcode_t get_inode_count(ext2_ic + return 0; + } + ++int ext2fs_icount_is_set(ext2_icount_t icount, ext2_ino_t ino) ++{ ++ __u16 result; ++ ++ if (ext2fs_test_inode_bitmap2(icount->single, ino)) ++ return 1; ++ else if (icount->multiple) { ++ if (ext2fs_test_inode_bitmap2(icount->multiple, ino)) ++ return 1; ++ return 0; ++ } ++ ext2fs_icount_fetch(icount, ino, &result); ++ if (result) ++ return 1; ++ return 0; ++} ++ + errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) + { + errcode_t ret = 0; +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -676,6 +676,18 @@ static void parse_extended_opts(e2fsck_t + extended_usage++; + continue; + } ++ /* -E inode_badness_threshold= */ ++ } else if (strcmp(token, "inode_badness_threshold") == 0) { ++ if (!arg) { ++ extended_usage++; ++ continue; ++ } ++ ctx->inode_badness_threshold = strtoul(arg, &p, 0); ++ if (*p != '\0' || (ctx->inode_badness_threshold > 200)){ ++ fprintf(stderr, _("Invalid badness value.\n")); ++ extended_usage++; ++ continue; ++ } + } else if (strcmp(token, "journal_only") == 0) { + if (arg) { + extended_usage++; +@@ -709,6 +721,7 @@ static void parse_extended_opts(e2fsck_t + fputs(("\tshared=\n"), stderr); + fputs(("\tclone=\n"), stderr); + fputs(("\texpand_extra_isize\n"), stderr); ++ fputs(("\tinode_badness_threhold=(value)\n"), stderr); + fputc('\n', stderr); + exit(1); + } +@@ -774,6 +787,8 @@ static errcode_t PRS(int argc, char *arg + + initialize_profile_options(ctx); + ++ ctx->inode_badness_threshold = BADNESS_THRESHOLD; ++ + while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF) + switch (c) { + case 'C': +Index: e2fsprogs/e2fsck/e2fsck.c +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.c ++++ e2fsprogs/e2fsck/e2fsck.c +@@ -111,10 +111,6 @@ errcode_t e2fsck_reset_context(e2fsck_t + ext2fs_free_inode_bitmap(ctx->inode_bb_map); + ctx->inode_bb_map = 0; + } +- if (ctx->inode_bad_map) { +- ext2fs_free_inode_bitmap(ctx->inode_bad_map); +- ctx->inode_bad_map = 0; +- } + if (ctx->inode_imagic_map) { + ext2fs_free_inode_bitmap(ctx->inode_imagic_map); + ctx->inode_imagic_map = 0; +Index: e2fsprogs/e2fsck/e2fsck.8.in +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.8.in ++++ e2fsprogs/e2fsck/e2fsck.8.in +@@ -203,6 +203,15 @@ be 1 or 2. The default extended attribu + Only replay the journal if required, but do not perform any further checks + or repairs. + .TP ++.BI inode_badness_threshold= threshold_value ++A badness counter is associated with every inode, which determines the degree ++of inode corruption. Each error found in the inode will increase the badness by ++1 or 2, and inodes with a badness at or above ++.I threshold_value ++will be prompted for deletion. The default ++.I threshold_value ++is 7. ++.TP + .BI fragcheck + During pass 1, print a detailed report of any discontiguous blocks for + files in the filesystem. +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -1163,6 +1163,7 @@ extern errcode_t ext2fs_initialize(const + + /* icount.c */ + extern void ext2fs_free_icount(ext2_icount_t icount); ++extern int ext2fs_icount_is_set(ext2_icount_t icount, ext2_ino_t ino); + extern errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, + int flags, ext2_icount_t *ret); + extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, +Index: e2fsprogs/tests/f_messy_inode/expect.1 +=================================================================== +--- e2fsprogs.orig/tests/f_messy_inode/expect.1 ++++ e2fsprogs/tests/f_messy_inode/expect.1 +@@ -20,19 +20,21 @@ Pass 2: Checking directory structure + i_file_acl for inode 14 (/MAKEDEV) is 4294901760, should be zero. + Clear? yes + ++Inode 14 is badly corrupt (badness value = 13). Clear? yes ++ + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information + Block bitmap differences: -(43--49) + Fix? yes + +-Free blocks count wrong for group #0 (68, counted=75). ++Free blocks count wrong for group #0 (70, counted=77). + Fix? yes + +-Free blocks count wrong (68, counted=75). ++Free blocks count wrong (70, counted=77). + Fix? yes + + + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +-test_filesys: 29/32 files (3.4% non-contiguous), 25/100 blocks ++test_filesys: 28/32 files (3.6% non-contiguous), 23/100 blocks + Exit status is 1 +Index: e2fsprogs/tests/f_messy_inode/expect.2 +=================================================================== +--- e2fsprogs.orig/tests/f_messy_inode/expect.2 ++++ e2fsprogs/tests/f_messy_inode/expect.2 +@@ -3,5 +3,5 @@ Pass 2: Checking directory structure + Pass 3: Checking directory connectivity + Pass 4: Checking reference counts + Pass 5: Checking group summary information +-test_filesys: 29/32 files (0.0% non-contiguous), 25/100 blocks ++test_filesys: 28/32 files (0.0% non-contiguous), 23/100 blocks + Exit status is 0 diff --git a/patches/e2fsprogs-large-ea.patch b/patches/e2fsprogs-large-ea.patch new file mode 100644 index 0000000..e3ad594 --- /dev/null +++ b/patches/e2fsprogs-large-ea.patch @@ -0,0 +1,604 @@ +Index: e2fsprogs/e2fsck/e2fsck.h +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.h ++++ e2fsprogs/e2fsck/e2fsck.h +@@ -263,6 +263,7 @@ struct e2fsck_struct { + ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */ + ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */ + ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/ ++ ext2fs_inode_bitmap inode_ea_map; /* EA inodes which are non-orphan */ + + ext2fs_block_bitmap block_found_map; /* Blocks which are in use */ + ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */ +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -28,6 +28,7 @@ + * - A bitmap of which blocks are in use. (block_found_map) + * - A bitmap of which blocks are in use by two inodes (block_dup_map) + * - The data blocks of the directory inodes. (dir_map) ++ * - A bitmap of EA inodes. (inode_ea_map) + * + * Pass 1 is designed to stash away enough information so that the + * other passes should not need to read in the inode information +@@ -270,6 +271,118 @@ static void check_size(e2fsck_t ctx, str + e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); + } + ++static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse) ++{ ++ e2fsck_t ctx = (e2fsck_t) fs->priv_data; ++ ++ if (ctx->block_found_map) { ++ if (inuse > 0) ++ ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); ++ else ++ ext2fs_unmark_block_bitmap2(ctx->block_found_map, blk); ++ } ++} ++ ++static void mark_inode_ea_map(e2fsck_t ctx, struct problem_context *pctx, ++ ext2_ino_t ino) ++{ ++ if (!ctx->inode_ea_map) { ++ pctx->errcode = ext2fs_allocate_inode_bitmap(ctx->fs, ++ _("EA inode map"), ++ &ctx->inode_ea_map); ++ if (pctx->errcode) { ++ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, ++ pctx); ++ exit(1); ++ } ++ } ++ ++ ext2fs_mark_inode_bitmap2(ctx->inode_ea_map, ino); ++} ++ ++/* ++ * Delete an EA entry. If this is the last entry to be deleted, then i_file_acl ++ * must have been freed, so we must update e2fsck block statistics and set ++ * i_file_acl_deleted. ++ * When we delete the entry successfully, this function returns 0, else ++ * non-zero value. ++ */ ++ ++static int e2fsck_ea_entry_delete(e2fsck_t ctx, struct ext2_ext_attr_entry *entry, ++ struct problem_context *pctx, ++ int *i_file_acl_deleted, problem_t prob) ++{ ++ blk_t i_file_acl = pctx->inode->i_file_acl; ++ int err = 1; ++ ++ pctx->num = entry->e_value_inum; ++ ++ if (fix_problem(ctx, prob, pctx)) { ++ /* Delete corrupt EA entry */ ++ err = ext2fs_attr_set(ctx->fs, pctx->ino, pctx->inode, ++ entry->e_name_index, entry->e_name, ++ 0, 0, 0); ++ if (err == 0) { ++ if (i_file_acl && pctx->inode->i_file_acl == 0) { ++ e2fsck_block_alloc_stats(ctx->fs, i_file_acl, -1); ++ *i_file_acl_deleted = 1; ++ } ++ return 0; ++ } ++ } ++ ++ return err; ++} ++ ++/* ++ * Check validity of EA inode. Return 0 if EA inode is valid, nonzero otherwise. ++ */ ++static int check_large_ea_inode(e2fsck_t ctx, struct ext2_ext_attr_entry *entry, ++ struct problem_context *pctx, ++ int *i_file_acl_deleted) ++{ ++ struct ext2_inode inode; ++ int ret = 0; ++ ++ /* Check if inode is within valid range */ ++ if ((entry->e_value_inum < EXT2_FIRST_INODE(ctx->fs->super)) || ++ (entry->e_value_inum > ctx->fs->super->s_inodes_count)) { ++ ret = e2fsck_ea_entry_delete(ctx, entry, pctx, ++ i_file_acl_deleted, ++ PR_1_ATTR_VALUE_EA_INODE); ++ /* If user refuses to delete this entry, caller may try to set ++ * the bit for this out-of-bound inode in inode_ea_map, so ++ * always return failure */ ++ return 1; ++ } ++ ++ e2fsck_read_inode(ctx, entry->e_value_inum, &inode, "pass1"); ++ if (!(inode.i_flags & EXT4_EA_INODE_FL)) { ++ /* If EXT4_EA_INODE_FL flag is not present but back-pointer ++ * matches then we should set this flag */ ++ if (inode.i_mtime == pctx->ino && ++ inode.i_generation == pctx->inode->i_generation && ++ fix_problem(ctx, PR_1_ATTR_SET_EA_INODE_FL, pctx)) { ++ inode.i_flags |= EXT4_EA_INODE_FL; ++ ext2fs_write_inode(ctx->fs, entry->e_value_inum, &inode); ++ } else { ++ ret = e2fsck_ea_entry_delete(ctx, entry, pctx, ++ i_file_acl_deleted, ++ PR_1_ATTR_NO_EA_INODE_FL); ++ goto out; ++ } ++ } else if (inode.i_mtime != pctx->ino || ++ inode.i_generation != pctx->inode->i_generation) { ++ ret = e2fsck_ea_entry_delete(ctx, entry, pctx, ++ i_file_acl_deleted, ++ PR_1_ATTR_INVAL_EA_INODE); ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ + static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx) + { + struct ext2_super_block *sb = ctx->fs->super; +@@ -307,18 +420,25 @@ static void check_ea_in_inode(e2fsck_t c + /* attribute len eats this space */ + remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); + +- /* check value size */ +- if (entry->e_value_size == 0 || entry->e_value_size > remain) { ++ if (entry->e_value_size == 0) { + pctx->num = entry->e_value_size; + problem = PR_1_ATTR_VALUE_SIZE; + goto fix; + } + +- /* e_value_block must be 0 in inode's ea */ +- if (entry->e_value_block != 0) { +- pctx->num = entry->e_value_block; +- problem = PR_1_ATTR_VALUE_BLOCK; +- goto fix; ++ if (entry->e_value_inum == 0) { ++ /* check value size */ ++ if (entry->e_value_size > remain) { ++ pctx->num = entry->e_value_size; ++ problem = PR_1_ATTR_VALUE_SIZE; ++ goto fix; ++ } ++ } else { ++ int ret, tmp; ++ ++ ret = check_large_ea_inode(ctx, entry, pctx, &tmp); ++ if (ret == 0) ++ mark_inode_ea_map(ctx, pctx, entry->e_value_inum); + } + + /* Value size cannot be larger than EA space in inode */ +@@ -338,7 +458,10 @@ static void check_ea_in_inode(e2fsck_t c + goto fix; + } + +- remain -= entry->e_value_size; ++ /* If EA value is stored in external inode then it does not ++ * consume space here */ ++ if (entry->e_value_inum == 0) ++ remain -= entry->e_value_size; + + entry = EXT2_EXT_ATTR_NEXT(entry); + } +@@ -627,7 +750,7 @@ int e2fsck_pass1_delete_attr(e2fsck_t ct + if (EXT2_EXT_IS_LAST_ENTRY(entry)) { + if (in_inode) { + entry = entry_blk; +- len = sizeof(entry->e_name); ++ len = sizeof(entry->e_name); + entry_size = ext2fs_attr_get_next_attr(entry, + index, name, len, 1); + in_inode = 0; +@@ -1657,6 +1780,7 @@ static int check_ext_attr(e2fsck_t ctx, + struct ext2_ext_attr_entry *entry; + int count; + region_t region = 0; ++ int ret; + + blk = ext2fs_file_acl_block(inode); + if (blk == 0) +@@ -1778,19 +1902,27 @@ static int check_ext_attr(e2fsck_t ctx, + goto clear_extattr; + break; + } +- if (entry->e_value_block != 0) { +- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) +- goto clear_extattr; +- } +- if (entry->e_value_offs + entry->e_value_size > fs->blocksize) { +- if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) +- goto clear_extattr; +- break; +- } +- if (entry->e_value_size && +- region_allocate(region, entry->e_value_offs, +- EXT2_EXT_ATTR_SIZE(entry->e_value_size))) { +- if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) ++ if (entry->e_value_inum == 0) { ++ if (entry->e_value_offs + entry->e_value_size > fs->blocksize) { ++ if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) ++ goto clear_extattr; ++ break; ++ } ++ if (entry->e_value_size && ++ region_allocate(region, entry->e_value_offs, ++ EXT2_EXT_ATTR_SIZE(entry->e_value_size))) { ++ if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) ++ goto clear_extattr; ++ } ++ } else { ++ int i_file_acl_deleted = 0; ++ ++ ret = check_large_ea_inode(ctx, entry, pctx, ++ &i_file_acl_deleted); ++ if (ret == 0) ++ mark_inode_ea_map(ctx, pctx, entry->e_value_inum); ++ ++ if (i_file_acl_deleted) + goto clear_extattr; + } + +@@ -2998,18 +3130,6 @@ static errcode_t e2fsck_get_alloc_block( + return (0); + } + +-static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse) +-{ +- e2fsck_t ctx = (e2fsck_t) fs->priv_data; +- +- if (ctx->block_found_map) { +- if (inuse > 0) +- ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); +- else +- ext2fs_unmark_block_bitmap2(ctx->block_found_map, blk); +- } +-} +- + void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool) + { + ext2_filsys fs = ctx->fs; +Index: e2fsprogs/e2fsck/pass4.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass4.c ++++ e2fsprogs/e2fsck/pass4.c +@@ -11,6 +11,7 @@ + * Pass 4 frees the following data structures: + * - A bitmap of which inodes are in bad blocks. (inode_bb_map) + * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) ++ * - A bitmap of EA inodes. (inode_ea_map) + */ + + #include "e2fsck.h" +@@ -39,6 +40,20 @@ static int disconnect_inode(e2fsck_t ctx + } else { + e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode"); + } ++ ++ if (inode->i_flags & EXT4_EA_INODE_FL) { ++ if (ext2fs_test_inode_bitmap2(ctx->inode_ea_map, i)) { ++ ext2fs_icount_store(ctx->inode_count, i, 1); ++ return 0; ++ } else { ++ /* Zero the link count so that when inode is linked to ++ * lost+found it has correct link count */ ++ inode->i_links_count = 0; ++ e2fsck_write_inode(ctx, i, inode, "disconnect_inode"); ++ ext2fs_icount_store(ctx->inode_link_info, i, 0); ++ } ++ } ++ + clear_problem_context(&pctx); + pctx.ino = i; + pctx.inode = inode; +@@ -182,6 +197,8 @@ void e2fsck_pass4(e2fsck_t ctx) + ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; + ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; + ext2fs_free_icount(ctx->inode_badness); ctx->inode_badness = 0; ++ ext2fs_free_inode_bitmap(ctx->inode_ea_map); ++ ctx->inode_ea_map = 0; + ext2fs_free_inode_bitmap(ctx->inode_bb_map); + ctx->inode_bb_map = 0; + ext2fs_free_inode_bitmap(ctx->inode_imagic_map); +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -969,6 +969,27 @@ static struct e2fsck_problem problem_tab + "without deletion of an EA.\n"), + PROMPT_FIX, 0 }, + ++ /* Inode has illegal extended attribute value inode */ ++ { PR_1_ATTR_VALUE_EA_INODE, ++ N_("@i %i has @I @a value @i %N.\n"), ++ PROMPT_FIX, PR_PREEN_OK }, ++ ++ /* Invalid backpointer from extended attribute inode to parent inode */ ++ { PR_1_ATTR_INVAL_EA_INODE, ++ N_("@n backpointer from @a @i %N to parent @i %i.\n"), ++ PROMPT_CLEAR, PR_PREEN_OK }, ++ ++ /* Inode has invalid extended attribute. EA inode missing ++ * EA_INODE flag. */ ++ { PR_1_ATTR_NO_EA_INODE_FL, ++ N_("@i %i has @n @a. EA @i %N missing EA_INODE flag.\n"), ++ PROMPT_CLEAR, PR_PREEN_OK }, ++ ++ /* EA inode for parent inode missing EA_INODE flag. */ ++ { PR_1_ATTR_SET_EA_INODE_FL, ++ N_("EA @i %N for parent @i %i missing EA_INODE flag.\n "), ++ PROMPT_FIX, PR_PREEN_OK }, ++ + + /* Pass 1b errors */ + +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -570,6 +570,19 @@ struct problem_context { + */ + #define PR_1_CLEAR_EXTRA_ISIZE 0x01006C + ++/* Inode has illegal EA value inode */ ++#define PR_1_ATTR_VALUE_EA_INODE 0x01006D ++ ++/* Invalid backpointer from EA inode to parent inode */ ++#define PR_1_ATTR_INVAL_EA_INODE 0x01006E ++ ++/* Parent inode has invalid EA entry. EA inode does not have ++ * EXT4_EA_INODE_FL flag. Delete EA entry? */ ++#define PR_1_ATTR_NO_EA_INODE_FL 0x01006F ++ ++/* EA inode for parent inode does not have EXT4_EA_INODE_FL flag */ ++#define PR_1_ATTR_SET_EA_INODE_FL 0x010070 ++ + /* + * Pass 1b errors + */ +Index: e2fsprogs/lib/blkid/probe.h +=================================================================== +--- e2fsprogs.orig/lib/blkid/probe.h ++++ e2fsprogs/lib/blkid/probe.h +@@ -119,6 +119,7 @@ struct ext2_super_block { + #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 + #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 + #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 ++#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 + + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ +Index: e2fsprogs/lib/e2p/feature.c +=================================================================== +--- e2fsprogs.orig/lib/e2p/feature.c ++++ e2fsprogs/lib/e2p/feature.c +@@ -76,6 +76,8 @@ static struct feature feature_list[] = { + "flex_bg"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP, + "mmp" }, ++ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE, ++ "large_xattr" }, + { 0, 0, 0 }, + }; + +Index: e2fsprogs/lib/ext2fs/ext2_ext_attr.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_ext_attr.h ++++ e2fsprogs/lib/ext2fs/ext2_ext_attr.h +@@ -30,7 +30,7 @@ struct ext2_ext_attr_entry { + __u8 e_name_len; /* length of name */ + __u8 e_name_index; /* attribute name index */ + __u16 e_value_offs; /* offset in disk block of value */ +- __u32 e_value_block; /* disk block attribute is stored on (n/i) */ ++ __u32 e_value_inum; /* inode in which the value is stored */ + __u32 e_value_size; /* size of attribute value */ + __u32 e_hash; /* hash value of name and value */ + #if 1 +@@ -48,6 +48,9 @@ struct ext2_xattr_ibody_header { + EXT2_GOOD_OLD_INODE_SIZE + (inode)->i_extra_isize)) + #define ENTRY(ptr) ((struct ext2_ext_attr_entry *)(ptr)) + ++#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) ((b) >> 1) ++#define EXT4_XATTR_MAX_LARGE_EA_SIZE (1024 * 1024) ++ + /* Name indexes */ + #define EXT2_ATTR_INDEX_USER 1 + #define EXT2_ATTR_INDEX_POSIX_ACL_ACCESS 2 +Index: e2fsprogs/lib/ext2fs/ext2_fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_fs.h ++++ e2fsprogs/lib/ext2fs/ext2_fs.h +@@ -697,7 +697,8 @@ struct ext2_super_block { + + #define EXT2_FEATURE_COMPAT_SUPP 0 + #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ +- EXT4_FEATURE_INCOMPAT_MMP) ++ EXT4_FEATURE_INCOMPAT_MMP|\ ++ EXT4_FEATURE_INCOMPAT_EA_INODE) + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -571,6 +571,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT3_FEATURE_INCOMPAT_EXTENTS|\ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ + EXT4_FEATURE_INCOMPAT_MMP|\ ++ EXT4_FEATURE_INCOMPAT_EA_INODE|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #else + #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ +@@ -580,6 +581,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT3_FEATURE_INCOMPAT_EXTENTS|\ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ + EXT4_FEATURE_INCOMPAT_MMP|\ ++ EXT4_FEATURE_INCOMPAT_EA_INODE|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #endif + #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ +Index: e2fsprogs/lib/ext2fs/ext_attr.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext_attr.c ++++ e2fsprogs/lib/ext2fs/ext_attr.c +@@ -45,7 +45,7 @@ __u32 ext2fs_ext_attr_hash_entry(struct + } + + /* The hash needs to be calculated on the data in little-endian. */ +- if (entry->e_value_block == 0 && entry->e_value_size != 0) { ++ if (entry->e_value_inum == 0 && entry->e_value_size != 0) { + __u32 *value = (__u32 *)data; + for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >> + EXT2_EXT_ATTR_PAD_BITS; n; n--) { +@@ -207,6 +207,7 @@ struct ext2_attr_ibody_find { + }; + + struct ext2_attr_block_find { ++ ext2_ino_t ino; + struct ext2_attr_search s; + char *block; + }; +@@ -219,7 +220,7 @@ void ext2fs_attr_shift_entries(struct ex + + /* Adjust the value offsets of the entries */ + for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) { +- if (!last->e_value_block && last->e_value_size) { ++ if (last->e_value_inum == 0 && last->e_value_size) { + last->e_value_offs = last->e_value_offs + + value_offs_shift; + } +@@ -240,7 +241,7 @@ int ext2fs_attr_free_space(struct ext2_e + { + for (; !EXT2_EXT_IS_LAST_ENTRY(last); last = EXT2_EXT_ATTR_NEXT(last)) { + *total += EXT2_EXT_ATTR_LEN(last->e_name_len); +- if (!last->e_value_block && last->e_value_size) { ++ if (last->e_value_inum == 0 && last->e_value_size) { + int offs = last->e_value_offs; + if (offs < *min_offs) + *min_offs = offs; +@@ -376,7 +377,7 @@ static errcode_t ext2fs_attr_set_entry(e + /* Compute min_offs and last. */ + for (last = s->first; !EXT2_EXT_IS_LAST_ENTRY(last); + last = EXT2_EXT_ATTR_NEXT(last)) { +- if (!last->e_value_block && last->e_value_size) { ++ if (last->e_value_inum == 0 && last->e_value_size) { + int offs = last->e_value_offs; + + if (offs < min_offs) +@@ -386,7 +387,7 @@ static errcode_t ext2fs_attr_set_entry(e + free = min_offs - ((char *)last - s->base) - sizeof(__u32); + + if (!s->not_found) { +- if (!s->here->e_value_block && s->here->e_value_size) { ++ if (s->here->e_value_inum == 0 && s->here->e_value_size) { + int size = s->here->e_value_size; + free += EXT2_EXT_ATTR_SIZE(size); + } +@@ -409,7 +410,7 @@ static errcode_t ext2fs_attr_set_entry(e + s->here->e_name_len = name_len; + memcpy(s->here->e_name, i->name, name_len); + } else { +- if (!s->here->e_value_block && s->here->e_value_size) { ++ if (s->here->e_value_inum == 0 && s->here->e_value_size) { + char *first_val = s->base + min_offs; + int offs = s->here->e_value_offs; + char *val = s->base + offs; +@@ -438,7 +439,7 @@ static errcode_t ext2fs_attr_set_entry(e + while (!EXT2_EXT_IS_LAST_ENTRY(last)) { + int o = last->e_value_offs; + +- if (!last->e_value_block && ++ if (last->e_value_inum == 0 && + last->e_value_size && o < offs) + last->e_value_offs = o + size; + last = EXT2_EXT_ATTR_NEXT(last); +@@ -556,9 +557,20 @@ static errcode_t ext2fs_attr_block_set(e + /* Update the i_blocks if we added a new EA block */ + if (!inode->i_file_acl && new_buf) + inode->i_blocks += fs->blocksize / 512; ++ ++ /* Drop the previous xattr block. */ ++ if (!new_buf) { ++ if (!fs->block_map) ++ ext2fs_read_block_bitmap(fs); ++ ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1); ++ inode->i_blocks -= fs->blocksize / 512; ++ } ++ + /* Update the inode. */ + inode->i_file_acl = new_buf ? blk : 0; + ++ ext2fs_write_inode(fs, bs->ino, inode); ++ + cleanup: + if (clear_flag) + ext2fs_free_mem(&s->base); +@@ -866,6 +878,7 @@ errcode_t ext2fs_expand_extra_isize(ext2 + .s = { .not_found = EXT2_ET_EA_NO_SPACE, }, + }; + struct ext2_attr_block_find bs = { ++ .ino = ino, + .s = { .not_found = EXT2_ET_EA_NO_SPACE, }, + }; + char *start, *end, *block_buf = NULL, *buffer =NULL, *b_entry_name=NULL; +Index: e2fsprogs/lib/ext2fs/swapfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/swapfs.c ++++ e2fsprogs/lib/ext2fs/swapfs.c +@@ -151,7 +151,7 @@ void ext2fs_swap_ext_attr_entry(struct e + struct ext2_ext_attr_entry *from_entry) + { + to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs); +- to_entry->e_value_block = ext2fs_swab32(from_entry->e_value_block); ++ to_entry->e_value_inum = ext2fs_swab32(from_entry->e_value_inum); + to_entry->e_value_size = ext2fs_swab32(from_entry->e_value_size); + to_entry->e_hash = ext2fs_swab32(from_entry->e_hash); + } +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -813,6 +813,7 @@ static __u32 ok_features[3] = { + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| + EXT2_FEATURE_INCOMPAT_META_BG| + EXT4_FEATURE_INCOMPAT_FLEX_BG| ++ EXT4_FEATURE_INCOMPAT_EA_INODE| + EXT4_FEATURE_INCOMPAT_MMP | + EXT4_FEATURE_INCOMPAT_64BIT, + /* R/O compat */ +Index: e2fsprogs/misc/tune2fs.c +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.c ++++ e2fsprogs/misc/tune2fs.c +@@ -126,6 +126,7 @@ static __u32 ok_features[3] = { + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT3_FEATURE_INCOMPAT_EXTENTS | + EXT4_FEATURE_INCOMPAT_FLEX_BG | ++ EXT4_FEATURE_INCOMPAT_EA_INODE| + EXT4_FEATURE_INCOMPAT_MMP, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | +@@ -144,6 +145,7 @@ static __u32 clear_ok_features[3] = { + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT4_FEATURE_INCOMPAT_FLEX_BG | ++ EXT4_FEATURE_INCOMPAT_EA_INODE| + EXT4_FEATURE_INCOMPAT_MMP, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | +@@ -484,6 +486,9 @@ mmp_error: + sb->s_mmp_update_interval = 0; + } + ++ if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE)) ++ sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_EA_INODE; ++ + if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { + /* + * If adding a journal flag, let the create journal diff --git a/patches/e2fsprogs-lazy_journal_init.patch b/patches/e2fsprogs-lazy_journal_init.patch new file mode 100644 index 0000000..9882bba --- /dev/null +++ b/patches/e2fsprogs-lazy_journal_init.patch @@ -0,0 +1,186 @@ +This patch adds the ability to skip zeroing the journal on disk. This can +significantly speed up mke2fs with large journals. At worst the uninitialized +journal is only a very short-term risk (if at all), because the journal will +be overwritten on any new filesystem as soon as any significant amount of data +is written to disk, unlike lazy_itable_init which can leave uninitialized +itable blocks indefinitely (in the absence of the kernel init thread). + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -197,10 +197,9 @@ typedef struct ext2_file *ext2_file_t; + + /* + * Flags for mkjournal +- * +- * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock + */ +-#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 ++#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 /* create V1 superblock (deprecated) */ ++#define EXT2_MKJOURNAL_LAZYINIT 0x0000002 /* don't zero journal inode before use*/ + + struct opaque_ext2_group_desc; + +Index: e2fsprogs/lib/ext2fs/mkjournal.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/mkjournal.c ++++ e2fsprogs/lib/ext2fs/mkjournal.c +@@ -103,7 +103,7 @@ static errcode_t write_journal_file(ext2 + /* Open the device or journal file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + retval = errno; +- goto errout; ++ goto errfree; + } + + /* Write the superblock out */ +@@ -117,6 +117,9 @@ static errcode_t write_journal_file(ext2 + goto errout; + memset(buf, 0, fs->blocksize); + ++ if (flags & EXT2_MKJOURNAL_LAZYINIT) ++ goto success; ++ + for (i = 1; i < blocks; i++) { + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { +@@ -126,10 +129,12 @@ static errcode_t write_journal_file(ext2 + if (ret_size != (int) fs->blocksize) + goto errout; + } +- close(fd); + ++success: + retval = 0; + errout: ++ close(fd); ++errfree: + ext2fs_free_mem(&buf); + return retval; + } +@@ -213,6 +218,7 @@ struct mkjournal_struct { + blk64_t goal; + blk64_t blk_to_zero; + int zero_count; ++ int flags; + char *buf; + errcode_t err; + }; +@@ -244,7 +250,7 @@ static int mkjournal_proc(ext2_filsys fs + retval = 0; + if (blockcnt <= 0) + retval = io_channel_write_blk64(fs->io, new_blk, 1, es->buf); +- else { ++ else if (!(es->flags & EXT2_MKJOURNAL_LAZYINIT)) { + if (es->zero_count) { + if ((es->blk_to_zero + es->zero_count == new_blk) && + (es->zero_count < 1024)) +@@ -309,6 +315,7 @@ static errcode_t write_journal_inode(ext + es.newblocks = 0; + es.buf = buf; + es.err = 0; ++ es.flags = flags; + es.zero_count = 0; + + if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { +@@ -511,6 +518,13 @@ errcode_t ext2fs_add_journal_inode(ext2_ + if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) + return errno; + ++ /* Note that we can't do lazy journal initialization for mounted ++ * filesystems, since the zero writing is also allocating the ++ * journal blocks. We could use fallocate, but not all kernels ++ * support that, and creating a journal on a mounted ext2 ++ * filesystems is extremely rare these days... Skip it. */ ++ flags &= ~EXT2_MKJOURNAL_LAZYINIT; ++ + if ((retval = write_journal_file(fs, jfile, blocks, flags))) + goto errout; + +Index: e2fsprogs/misc/mke2fs.8.in +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.8.in ++++ e2fsprogs/misc/mke2fs.8.in +@@ -232,7 +232,15 @@ This speeds up filesystem + initialization noticeably, but it requires the kernel to finish + initializing the filesystem in the background when the filesystem is + first mounted. If the option value is omitted, it defaults to 1 to +-enable lazy inode table initialization. ++enable lazy inode table zeroing. ++.TP ++.B lazy_journal_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR] ++If enabled, the journal inode will not be fully zeroed out by ++.BR mke2fs . ++This speeds up filesystem initialization noticeably, but carries some ++small risk if the system crashes before the journal has been overwritten ++entirely one time. If the option value is omitted, it defaults to 1 to ++enable lazy journal inode zeroing. + .TP + .B test_fs + Set a flag in the filesystem superblock indicating that it may be +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -503,6 +503,10 @@ static void create_journal_dev(ext2_fils + _("while initializing journal superblock")); + exit(1); + } ++ ++ if (journal_flags & EXT2_MKJOURNAL_LAZYINIT) ++ goto write_superblock; ++ + ext2fs_numeric_progress_init(fs, &progress, + _("Zeroing journal device: "), + ext2fs_blocks_count(fs->super)); +@@ -527,6 +531,8 @@ static void create_journal_dev(ext2_fils + } + ext2fs_zero_blocks2(0, 0, 0, 0, 0); + ++ ext2fs_numeric_progress_close(fs, &progress, NULL); ++write_superblock: + retval = io_channel_write_blk64(fs->io, + fs->super->s_first_data_block+1, + 1, buf); +@@ -535,7 +541,6 @@ static void create_journal_dev(ext2_fils + _("while writing journal superblock")); + exit(1); + } +- ext2fs_numeric_progress_close(fs, &progress, NULL); + } + + static void show_stats(ext2_filsys fs) +@@ -746,6 +751,12 @@ static void parse_extended_opts(struct e + } + } else if (!strcmp(token, "test_fs")) { + param->s_flags |= EXT2_FLAGS_TEST_FILESYS; ++ } else if (!strcmp(token, "lazy_journal_init")) { ++ if (arg) ++ journal_flags |= strtoul(arg, &p, 0) ? ++ EXT2_MKJOURNAL_LAZYINIT : 0; ++ else ++ journal_flags |= EXT2_MKJOURNAL_LAZYINIT; + } else if (!strcmp(token, "lazy_itable_init")) { + if (arg) + lazy_itable_init = strtoul(arg, &p, 0); +@@ -770,6 +781,7 @@ static void parse_extended_opts(struct e + "\tstripe-width=\n" + "\tresize=\n" + "\tlazy_itable_init=<0 to disable, 1 to enable>\n" ++ "\tlazy_journal_init=<0 to disable, 1 to enable>\n" + "\ttest_fs\n" + "\tdiscard\n" + "\tnodiscard\n\n"), +@@ -1778,6 +1790,9 @@ profile_error: + "lazy_itable_init", + lazy_itable_init); + discard = get_bool_from_profile(fs_types, "discard" , discard); ++ journal_flags |= get_bool_from_profile(fs_types, ++ "lazy_journal_init", 0) ? ++ EXT2_MKJOURNAL_LAZYINIT : 0; + + /* Get options from profile */ + for (cpp = fs_types; *cpp; cpp++) { diff --git a/patches/e2fsprogs-lfsck.patch b/patches/e2fsprogs-lfsck.patch new file mode 100644 index 0000000..43743cd --- /dev/null +++ b/patches/e2fsprogs-lfsck.patch @@ -0,0 +1,5213 @@ +add support for lustre lfsck tool + +Index: e2fsprogs/MCONFIG.in +=================================================================== +--- e2fsprogs.orig/MCONFIG.in ++++ e2fsprogs/MCONFIG.in +@@ -97,6 +97,9 @@ DEPLIBSS = $(LIB)/libss@LIB_EXT@ + DEPLIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@ + DEPLIBUUID = @DEPLIBUUID@ + DEPLIBBLKID = @DEPLIBBLKID@ @PRIVATE_LIBS_CMT@ $(DEPLIBUUID) ++#Version of libdb lib found by configure ++LIBDB = @libdb@ ++ + + STATIC_LIBSS = $(LIB)/libss@STATIC_LIB_EXT@ @DLOPEN_LIB@ + STATIC_LIBCOM_ERR = $(LIB)/libcom_err@STATIC_LIB_EXT@ @SEM_INIT_LIB@ +@@ -202,8 +205,8 @@ Makefile: $(srcdir)/Makefile.in $(top_bu + $(DEP_MAKEFILE) $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=$(my_dir)/Makefile ./config.status + +-@MAINTAINER_CMT@$(top_srcdir)/configure: $(top_srcdir)/configure.in +-@MAINTAINER_CMT@ cd $(top_srcdir) && autoconf ++$(top_srcdir)/configure: $(top_srcdir)/configure.in ++ cd $(top_srcdir) && autoconf + + # + # Make depend magic... +Index: e2fsprogs/configure.in +=================================================================== +--- e2fsprogs.orig/configure.in ++++ e2fsprogs/configure.in +@@ -212,6 +212,54 @@ Q=@ + AC_SUBST(E) + AC_SUBST(Q) + dnl ++dnl handle --enable-lfsck ++dnl ++AC_ARG_ENABLE([lfsck], ++[ --disable-lfsck disable EXPERIMENTAL Lustre lfsck support], ++if test "$enableval" = "no" ++then ++ LFSCK_CMT=# ++ LFSCK_MAN=.\" ++ echo "Disabling Lustre lfsck support" ++else ++ LFSCK_CMT= ++ LFSCK_MAN= ++ AC_DEFINE(ENABLE_LFSCK) ++ echo "Enabling Lustre lfsck support" ++fi ++, ++LFSCK_CMT= ++LFSCK_MAN= ++AC_DEFINE(ENABLE_LFSCK) ++echo "Enabling Lustre lfsck support by default" ++) ++AC_SUBST(LFSCK_CMT) ++AC_SUBST(LFSCK_MAN) ++dnl ++dnl set lustre include path and build lfsck ++dnl ++AC_ARG_WITH([lustre], ++[ --with-lustre=LUSTRE path to Lustre sources for lfsck (default=/usr for RPM)], ++AC_MSG_RESULT(LUSTRE is $withval) ++LUSTRE="$withval", ++LUSTRE="/usr")dnl ++AC_SUBST(LUSTRE) ++dnl ++AS_IF([test "x$enable_lfsck" != "xno"], ++[ ++ AC_CHECK_FILE($LUSTRE/include/lustre/liblustreapi.h,, ++ AC_CHECK_FILE($LUSTRE/lustre/include/lustre/liblustreapi.h,, ++ AC_MSG_ERROR([No lustre includes found.])) ++ ) ++dnl # Disable for old autoconf that doesn't check header usability. ++dnl # Supposed to check if lustre_idl.h is usable from userspace. ++dnl AC_CHECK_HEADER($LUSTRE/lustre/include/lustre/lustre_idl.h, ++dnl AC_DEFINE(HAVE_LUSTRE_LUSTRE_IDL_H), ++dnl AC_CHECK_HEADER($LUSTRE/include/lustre/lustre_idl.h, ++dnl AC_DEFINE(HAVE_LUSTRE_LUSTRE_IDL_H),) ++dnl ) ++]) ++dnl + dnl handle --enable-compression + dnl + AC_ARG_ENABLE([compression], +@@ -763,6 +811,7 @@ AC_CHECK_HEADERS(net/if.h,,, + #include + #endif + ]]) ++AC_CHECK_HEADERS(db.h) + AC_FUNC_VPRINTF + dnl Check to see if dirent has member d_reclen. On cygwin those d_reclen + dnl is not decleared. +@@ -880,6 +929,31 @@ SOCKET_LIB='' + AC_CHECK_LIB(socket, socket, [SOCKET_LIB=-lsocket]) + AC_SUBST(SOCKET_LIB) + dnl ++dnl Check to see if libdb exists for the sake of lfsck ++dnl ++AC_CHECK_LIB(db-4.1, db_env_create, ++[DB4VERSION=4.1 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.2, db_env_create, ++[DB4VERSION=4.2 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.3, db_env_create, ++[DB4VERSION=4.3 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.5, db_env_create, ++[DB4VERSION=4.5 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.6, db_env_create, ++[DB4VERSION=4.6 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.7, db_env_create, ++[DB4VERSION=4.7 ++AC_DEFINE(HAVE_DB4)]) ++AC_CHECK_LIB(db-4.8, db_env_create, ++[DB4VERSION=4.8 ++AC_DEFINE(HAVE_DB4)]) ++AC_SUBST(DB4VERSION) ++dnl + dnl See if optreset exists + dnl + AC_MSG_CHECKING(for optreset) +Index: e2fsprogs/e2fsck/Makefile.in +=================================================================== +--- e2fsprogs.orig/e2fsck/Makefile.in ++++ e2fsprogs/e2fsck/Makefile.in +@@ -12,30 +12,35 @@ INSTALL = @INSTALL@ + @MCONFIG@ + + PROGS= e2fsck ++@LFSCK_CMT@USPROGS= lfsck + MANPAGES= e2fsck.8 + FMANPAGES= e2fsck.conf.5 ++@LFSCK_CMT@MANPAGES += lfsck.8 + XTRA_CFLAGS= -DRESOURCE_TRACK -I. + +-LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) $(LIBINTL) $(LIBE2P) ++@LFSCK_CMT@LFSCK_LIBS=-ldb-@DB4VERSION@ ++@LFSCK_CMT@LUSTRE_INC=-I @LUSTRE@/lustre/include -I @LUSTRE@/include -Wall ++@LFSCK_CMT@LUSTRE_LIB=-L @LUSTRE@/lustre/utils -L @LUSTRE@/lib64 -L @LUSTRE@/lib ++LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) $(LIBINTL) $(LIBE2P) $(LFSCK_LIBS) + DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR) $(DEPLIBBLKID) $(DEPLIBUUID) \ +- $(DEPLIBE2P) ++ $(DEPLIBE2P) $(LFSCK_LIBS) + + STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(STATIC_LIBBLKID) \ +- $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P) ++ $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P) $(LFSCK_LIBS) + STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR) \ +- $(DEPSTATIC_LIBBLKID) $(DEPSTATIC_LIBUUID) $(DEPSTATIC_LIBE2P) ++ $(DEPSTATIC_LIBBLKID) $(DEPSTATIC_LIBUUID) $(DEPSTATIC_LIBE2P) $(LFSCK_LIBS) + + PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) \ +- $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) $(PROFILED_LIBE2P) $(LIBINTL) ++ $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) $(PROFILED_LIBE2P) $(LIBINTL) $(LFSCK_LIBS) + PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(DEPPROFILED_LIBCOM_ERR) \ +- $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P) ++ $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P) $(LFSCK_LIBS) + + COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree + + .c.o: + $(E) " CC $<" +- $(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@ +-@PROFILE_CMT@ $(Q) $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $< ++ $(Q) $(CC) -c $(ALL_CFLAGS) $(LUSTRE_INC) $< -o $@ ++@PROFILE_CMT@ $(Q) $(CC) $(ALL_CFLAGS) $(LUSTRE_INC) -g -pg -o profiled/$*.o -c $< + + # + # Flags for using Checker +@@ -64,7 +69,10 @@ COMPILE_ET=$(top_builddir)/lib/et/compil + OBJS= crc32.o dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \ + pass3.o pass4.o pass5.o journal.o badblocks.o util.o dirinfo.o \ + dx_dirinfo.o ehandler.o problem.o message.o recovery.o region.o \ +- revoke.o ea_refcount.o rehash.o profile.o prof_err.o $(MTRACE_OBJ) ++ revoke.o ea_refcount.o rehash.o profile.o prof_err.o pass6.o $(MTRACE_OBJ) ++@LFSCK_CMT@OBJS += lfsck_common.o ++ ++@LFSCK_CMT@LFSCK_OBJS = lfsck_common.o lfsck.o + + PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \ + profiled/super.o profiled/pass1.o profiled/pass1b.o \ +@@ -74,7 +82,8 @@ PROFILED_OBJS= profiled/dict.o profiled/ + profiled/message.o profiled/problem.o \ + profiled/recovery.o profiled/region.o profiled/revoke.o \ + profiled/ea_refcount.o profiled/rehash.o profiled/profile.o \ +- profiled/crc32.o profiled/prof_err.o ++ profiled/crc32.o profiled/prof_err.o profiled/pass6.o ++@LFSCK_CMT@PROFILED_OBJS += profiled/lfsck_common.o + + SRCS= $(srcdir)/e2fsck.c \ + $(srcdir)/crc32.c \ +@@ -87,6 +96,7 @@ SRCS= $(srcdir)/e2fsck.c \ + $(srcdir)/pass3.c \ + $(srcdir)/pass4.c \ + $(srcdir)/pass5.c \ ++ $(srcdir)/pass6.c \ + $(srcdir)/journal.c \ + $(srcdir)/recovery.c \ + $(srcdir)/revoke.c \ +@@ -105,7 +115,10 @@ SRCS= $(srcdir)/e2fsck.c \ + prof_err.c \ + $(MTRACE_SRC) + +-all:: profiled $(PROGS) e2fsck $(MANPAGES) $(FMANPAGES) ++@LFSCK_CMT@SRCS += $(srcdir)/lfsck_common.c ++ ++@LFSCK_CMT@LFSCK_SRCS = $(srcdir)/lfsck_common.c $(srcdir)/lfsck.c ++all:: profiled $(PROGS) $(USPROGS) e2fsck $(MANPAGES) $(FMANPAGES) + + @PROFILE_CMT@all:: e2fsck.profiled + +@@ -161,6 +174,10 @@ check:: tst_refcount tst_region tst_crc3 + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_crc32 + LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_problem + ++@LFSCK_CMT@lfsck: $(LFSCK_OBJS) ++@LFSCK_CMT@ @echo " LD $@" ++@LFSCK_CMT@ $(LD) -pthread $(ALL_LDFLAGS) $(LUSTRE_INC) $(LFSCK_OBJS) -o lfsck $(LUSTRE_LIB) -llustreapi $(DEPLIBS) ++ + extend: extend.o + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) -o extend extend.o $(CHECKLIB) +@@ -184,6 +201,9 @@ profiled: + @PROFILE_CMT@ $(E) " MKDIR $@" + @PROFILE_CMT@ $(Q) mkdir profiled + ++lfsck.8: $(DEP_SUBSTITUTE) $(srcdir)/lfsck.8.in ++ $(SUBSTITUTE_UPTIME) $(srcdir)/lfsck.8.in lfsck.8 ++ + e2fsck.8: $(DEP_SUBSTITUTE) $(srcdir)/e2fsck.8.in + $(E) " SUBST $@" + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2fsck.8.in e2fsck.8 +@@ -193,15 +213,19 @@ e2fsck.conf.5: $(DEP_SUBSTITUTE) $(srcdi + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2fsck.conf.5.in e2fsck.conf.5 + + installdirs: +- $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir)" ++ $(E) " MKINSTALLDIRS $(root_sbindir) $(sbindir) $(man8dir)" + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(root_sbindir) \ +- $(DESTDIR)$(man8dir) $(DESTDIR)$(man5dir) ++ $(DESTDIR)$(man8dir) $(DESTDIR)$(man5dir) $(DESTDIR)$(sbindir) + +-install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs ++install: $(PROGS) $(USPROGS) $(MANPAGES) $(FMANPAGES) installdirs + $(Q) for i in $(PROGS); do \ + echo " INSTALL $(root_sbindir)/$$i"; \ + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(root_sbindir)/$$i; \ + done ++ @for i in $(USPROGS); do \ ++ echo " INSTALL $(sbindir)/$$i"; \ ++ $(INSTALL_PROGRAM) $$i $(DESTDIR)$(sbindir)/$$i; \ ++ done + $(Q) for i in ext2 ext3 ext4 ext4dev; do \ + echo " LINK $(root_sbindir)/fsck.$$i"; \ + (cd $(DESTDIR)$(root_sbindir); \ +@@ -237,6 +261,9 @@ uninstall: + for i in $(PROGS); do \ + $(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \ + done ++ for i in $(USPROGS); do \ ++ $(RM) -f $(DESTDIR)$(sbindir)/$$i; \ ++ done + $(RM) -f $(DESTDIR)$(root_sbindir)/fsck.ext2 \ + $(DESTDIR)$(root_sbindir)/fsck.ext3 \ + $(DESTDIR)$(root_sbindir)/fsck.ext4 \ +@@ -253,7 +280,7 @@ uninstall: + $(DESTDIR)$(root_sbindir)/fsck.ext4dev + + clean: +- $(RM) -f $(PROGS) \#* *\# *.s *.o *.a *~ core e2fsck.static \ ++ $(RM) -f $(PROGS) $(USPROGS) \#* *\# *.s *.o *.a *~ core e2fsck.static \ + e2fsck.shared e2fsck.profiled flushb e2fsck.8 \ + tst_problem tst_crc32 tst_region tst_refcount gen_crc32table \ + crc32table.h e2fsck.conf.5 prof_err.c prof_err.h \ +@@ -334,6 +361,12 @@ pass5.o: $(srcdir)/pass5.c $(srcdir)/e2f + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(srcdir)/problem.h ++pass6.o: $(srcdir)/pass6.c $(srcdir)/e2fsck.h \ ++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ ++ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ ++ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ ++ $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \ ++ $(srcdir)/problem.h $(top_srcdir)/lib/ext2fs/lfsck.h + journal.o: $(srcdir)/journal.c $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ +@@ -436,6 +469,9 @@ region.o: $(srcdir)/region.c $(srcdir)/e + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h ++lfsck.o: $(srcdir)/lfsck.c $(top_srcdir)/lib/ext2fs/lfsck.h $(srcdir)/lfsck_common.c \ ++ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ ++ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h + profile.o: $(srcdir)/profile.c $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/profile.h prof_err.h + prof_err.o: prof_err.c +Index: e2fsprogs/e2fsck/e2fsck.8.in +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.8.in ++++ e2fsprogs/e2fsck/e2fsck.8.in +@@ -333,6 +333,20 @@ may not be specified at the same time as + or + .B \-p + options. ++@LFSCK_MAN@.TP ++@LFSCK_MAN@.BI \-\-mdsdb " mds_database_filename" ++@LFSCK_MAN@Specify which file to use for an MDS database on a Lustre filesystem. ++@LFSCK_MAN@The mdsdb also needs to be specified when creating an OST database with ++@LFSCK_MAN@.B \-\-ostdb ++@LFSCK_MAN@but the mdsdb file used in a read-only manner. ++@LFSCK_MAN@.TP ++@LFSCK_MAN@.BI \-\-ostdb " ostN_database_filename" ++@LFSCK_MAN@Specify which file to use for an OST database on a Lustre filesystem. ++@LFSCK_MAN@A separate database file should be specified for each OST device in ++@LFSCK_MAN@the filesystem. For convenience a stub ++@LFSCK_MAN@.BR mdsdb .hdr ++@LFSCK_MAN@file is generated for use by the OST e2fsck to avoid the need to ++@LFSCK_MAN@wait for the MDS e2fsck to finish or copy the full mdsdb to the OSTs. + .SH EXIT CODE + The exit code returned by + .B e2fsck +Index: e2fsprogs/e2fsck/e2fsck.c +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.c ++++ e2fsprogs/e2fsck/e2fsck.c +@@ -193,8 +193,11 @@ void e2fsck_free_context(e2fsck_t ctx) + typedef void (*pass_t)(e2fsck_t ctx); + + pass_t e2fsck_passes[] = { +- e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4, +- e2fsck_pass5, 0 }; ++ e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4, e2fsck_pass5, ++#ifdef ENABLE_LFSCK ++ e2fsck_pass6, ++#endif ++ 0 }; + + #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART) + +Index: e2fsprogs/e2fsck/e2fsck.h +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.h ++++ e2fsprogs/e2fsck/e2fsck.h +@@ -158,6 +158,7 @@ struct resource_track { + #define E2F_OPT_FRAGCHECK 0x0800 + #define E2F_OPT_JOURNAL_ONLY 0x1000 /* only replay the journal */ + #define E2F_OPT_DISCARD 0x2000 ++#define E2F_OPT_VERBOSE 0x4000 + + /* + * E2fsck flags +@@ -184,6 +185,13 @@ struct resource_track { + + #define E2F_RESET_FLAGS (E2F_FLAG_TIME_INSANE) + ++/* Defines for Lustre */ ++#define LUSTRE_NULL 0x0000 ++#define LUSTRE_MDS 0x0001 ++#define LUSTRE_OST 0x0002 ++#define LUSTRE_TYPE 0x000f ++#define LUSTRE_ONLY 0x1000 ++ + /* + * Defines for indicating the e2fsck pass number + */ +@@ -336,6 +344,12 @@ struct e2fsck_struct { + io_channel journal_io; + char *journal_name; + ++ /* lustre support */ ++ int lustre_devtype; ++ char *lustre_mdsdb; ++ char *lustre_ostdb; ++ struct lfsck_outdb_info *lfsck_oinfo; ++ + #ifdef RESOURCE_TRACK + /* + * For timing purposes +@@ -419,6 +433,7 @@ extern void e2fsck_pass2(e2fsck_t ctx); + extern void e2fsck_pass3(e2fsck_t ctx); + extern void e2fsck_pass4(e2fsck_t ctx); + extern void e2fsck_pass5(e2fsck_t ctx); ++extern void e2fsck_pass6(e2fsck_t ctx); + + /* e2fsck.c */ + extern errcode_t e2fsck_allocate_context(e2fsck_t *ret); +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -49,6 +49,7 @@ + + #include "e2fsck.h" + #include ++#include "ext2fs/lfsck.h" + + #include "problem.h" + +@@ -390,6 +391,8 @@ static void check_ea_in_inode(e2fsck_t c + struct ext2_ext_attr_entry *entry; + char *start, *end; + unsigned int storage_size, remain; ++ struct lov_user_md_v1 *lmm = NULL; ++ struct lustre_mdt_attrs *lma = NULL; + int problem = 0; + + inode = (struct ext2_inode_large *) pctx->inode; +@@ -458,6 +461,9 @@ static void check_ea_in_inode(e2fsck_t c + goto fix; + } + ++ e2fsck_lfsck_find_ea(ctx, inode, entry, ++ start + entry->e_value_offs, &lmm, &lma); ++ + /* If EA value is stored in external inode then it does not + * consume space here */ + if (entry->e_value_inum == 0) +@@ -465,6 +471,10 @@ static void check_ea_in_inode(e2fsck_t c + + entry = EXT2_EXT_ATTR_NEXT(entry); + } ++ ++ if (lmm) ++ e2fsck_lfsck_save_ea(ctx, pctx->ino, inode->i_generation, ++ lmm, lma); + fix: + /* + * it seems like a corruption. it's very unlikely we could repair +@@ -1005,6 +1015,12 @@ void e2fsck_pass1(e2fsck_t ctx) + ext2fs_mark_block_bitmap2(ctx->block_found_map, + fs->super->s_mmp_block); + ++ if (!(ctx->options & E2F_OPT_READONLY) && ++ (ctx->lustre_devtype & LUSTRE_TYPE) == LUSTRE_MDS) { ++ if (e2fsck_lfsck_remove_pending(ctx, NULL)) ++ return; ++ } ++ + while (1) { + if (ino % EXT2_MMP_INODE_INTERVAL == 0) { + errcode_t error; +@@ -1513,6 +1529,9 @@ void e2fsck_pass1(e2fsck_t ctx) + } + e2fsck_pass1_dupblocks(ctx, block_buf); + } ++ ++ e2fsck_lfsck_flush_ea(ctx); ++ + ext2fs_free_mem(&inodes_to_process); + endit: + e2fsck_use_inode_shortcuts(ctx, 0); +@@ -1780,6 +1799,8 @@ static int check_ext_attr(e2fsck_t ctx, + struct ext2_ext_attr_entry *entry; + int count; + region_t region = 0; ++ struct lov_user_md_v1 *lmm = NULL; ++ struct lustre_mdt_attrs *lma = NULL; + int ret; + + blk = ext2fs_file_acl_block(inode); +@@ -1936,8 +1957,19 @@ static int check_ext_attr(e2fsck_t ctx, + entry->e_hash = hash; + } + ++ if (e2fsck_lfsck_find_ea(ctx, (struct ext2_inode_large *)inode, ++ entry, block_buf +entry->e_value_offs, ++ &lmm, &lma) != 0) { ++ if (ctx->flags & E2F_FLAG_SIGNAL_MASK) ++ return 0; ++ } ++ + entry = EXT2_EXT_ATTR_NEXT(entry); + } ++ ++ if (lmm) ++ e2fsck_lfsck_save_ea(ctx, ino, inode->i_generation, lmm, lma); ++ + if (region_allocate(region, (char *)entry - (char *)header, 4)) { + if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) + goto clear_extattr; +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -10,6 +10,7 @@ + */ + + #define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */ ++#define _GNU_SOURCE + + #include + #ifdef HAVE_STDLIB_H +@@ -47,6 +48,9 @@ extern int optind; + #ifdef HAVE_DIRENT_H + #include + #endif ++#ifdef HAVE_LIMITS_H ++#include ++#endif + + #include "e2p/e2p.h" + #include "et/com_err.h" +@@ -55,6 +59,17 @@ extern int optind; + #include "problem.h" + #include "../version.h" + ++#include "ext2fs/lfsck.h" ++ ++static struct option long_options[] = { ++#ifdef ENABLE_LFSCK ++ { "mdsdb", 1, NULL, 1 }, ++ { "mdtdb", 1, NULL, 1 }, ++ { "ostdb", 1, NULL, 2 }, ++#endif ++ { 0, 0, 0, 0 } ++}; ++ + /* Command line options */ + static int cflag; /* check disk */ + static int show_version_only; +@@ -343,6 +358,15 @@ static void check_if_skip(e2fsck_t ctx) + fs->super->s_checkinterval*2)) + reason = 0; + } ++#ifdef ENABLE_LFSCK ++ if (ctx->lustre_devtype & LUSTRE_TYPE) { ++ if (!reason || ctx->options & E2F_OPT_READONLY) ++ ctx->lustre_devtype |= LUSTRE_ONLY; ++ if (!reason) ++ reason = _(" lustre database creation"); ++ } ++#endif ++ + if (reason) { + fputs(ctx->device_name, stdout); + printf(reason, reason_arg); +@@ -378,6 +402,15 @@ static void check_if_skip(e2fsck_t ctx) + skip: + ext2fs_close(fs); + ctx->fs = NULL; ++#ifdef ENABLE_LFSCK ++ if (ctx->lustre_mdsdb) ++ free(ctx->lustre_mdsdb); ++ if (ctx->lustre_ostdb) ++ free(ctx->lustre_ostdb); ++ if (ctx->lfsck_oinfo) ++ e2fsck_lfsck_cleanupdb(ctx); ++#endif /* ENABLE_LFSCK */ ++ + e2fsck_free_context(ctx); + exit(FSCK_OK); + } +@@ -741,6 +774,7 @@ static errcode_t PRS(int argc, char *arg + { + int flush = 0; + int c, fd; ++ int option_index; + #ifdef MTRACE + extern void *mallwatch; + #endif +@@ -789,8 +823,75 @@ static errcode_t PRS(int argc, char *arg + + ctx->inode_badness_threshold = BADNESS_THRESHOLD; + +- while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF) ++ ctx->lustre_devtype = LUSTRE_NULL; ++ ++ while ((c = getopt_long(argc, argv, ++ "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk", ++ long_options, &option_index)) != EOF) + switch (c) { ++#ifdef ENABLE_LFSCK ++ case 1: { ++ char *dbpath, *tmp; ++ ++ if (!optarg) ++ usage(ctx); ++ ++ dbpath = malloc(PATH_MAX); ++ if (dbpath == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ exit(1); ++ } ++ tmp = malloc(PATH_MAX); ++ if (tmp == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ exit(1); ++ } ++ ++ strcpy(tmp, optarg); ++ if (realpath(my_dirname(tmp), dbpath) == NULL) { ++ fprintf(stderr, "Failure to resolve path %s\n", ++ optarg); ++ exit(1); ++ } ++ ++ strcpy(tmp, optarg); ++ sprintf(dbpath+strlen(dbpath), "/%s", my_basename(tmp)); ++ ctx->lustre_mdsdb = dbpath; ++ ctx->lustre_devtype |= LUSTRE_MDS; ++ ++ free(tmp); ++ break; ++ } ++ case 2: { ++ char *dbpath, *tmp; ++ ++ dbpath = malloc(PATH_MAX); ++ if (dbpath == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ exit(1); ++ } ++ tmp = malloc(PATH_MAX); ++ if (tmp == NULL) { ++ fprintf(stderr, "Out of memory\n"); ++ exit(1); ++ } ++ ++ strcpy(tmp, optarg); ++ if (realpath(my_dirname(tmp), dbpath) == NULL) { ++ fprintf(stderr, "Failure to resolve path %s\n", ++ optarg); ++ exit(1); ++ } ++ ++ strcpy(tmp, optarg); ++ sprintf(dbpath+strlen(dbpath), "/%s", my_basename(tmp)); ++ ctx->lustre_ostdb = dbpath; ++ ctx->lustre_devtype |= LUSTRE_OST; ++ ++ free(tmp); ++ break; ++ } ++#endif /* ENABLE_LFSCK */ + case 'C': + ctx->progress = e2fsck_update_progress; + res = sscanf(optarg, "%d", &ctx->progress_fd); +@@ -904,6 +1005,7 @@ static errcode_t PRS(int argc, char *arg + break; + case 'v': + verbose = 1; ++ ctx->options |= E2F_OPT_VERBOSE; + break; + case 'V': + show_version_only = 1; +@@ -922,6 +1024,16 @@ static errcode_t PRS(int argc, char *arg + default: + usage(ctx); + } ++#ifdef ENABLE_LFSCK ++ if (ctx->lustre_devtype) { ++ if ((ctx->lustre_devtype != LUSTRE_MDS) && ++ ctx->lustre_devtype != (LUSTRE_MDS | LUSTRE_OST)) { ++ com_err(ctx->program_name, 0, ++ _("must specify --mdsdb with --ostdb")); ++ usage(ctx); ++ } ++ } ++#endif /* ENABLE_LFSCK */ + if (show_version_only) + return 0; + if (optind != argc - 1) +@@ -1728,6 +1840,14 @@ no_journal: + ext2fs_close(fs); + ctx->fs = NULL; + free(ctx->journal_name); ++#ifdef ENABLE_LFSCK ++ if (ctx->lfsck_oinfo) ++ e2fsck_lfsck_cleanupdb(ctx); ++ if (ctx->lustre_mdsdb) ++ free(ctx->lustre_mdsdb); ++ if (ctx->lustre_ostdb) ++ free(ctx->lustre_ostdb); ++#endif /* ENABLE_LFSCK */ + + e2fsck_free_context(ctx); + remove_error_table(&et_ext2_error_table); +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -1398,7 +1398,7 @@ profile_error: + } + break; + case 'v': +- verbose = 1; ++ verbose++; + break; + case 'F': + force++; +Index: e2fsprogs/util/subst.conf.in +=================================================================== +--- e2fsprogs.orig/util/subst.conf.in ++++ e2fsprogs/util/subst.conf.in +@@ -5,6 +5,8 @@ SS_DIR @SS_DIR@ + E2FSPROGS_MONTH @E2FSPROGS_MONTH@ + E2FSPROGS_YEAR @E2FSPROGS_YEAR@ + E2FSPROGS_VERSION @E2FSPROGS_VERSION@ ++LFSCK_CMT @LFSCK_CMT@ ++LFSCK_MAN @LFSCK_MAN@ + SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ + SIZEOF_LONG @SIZEOF_LONG@ + SIZEOF_INT @SIZEOF_INT@ +Index: e2fsprogs/e2fsprogs.spec.in +=================================================================== +--- e2fsprogs.orig/e2fsprogs.spec.in ++++ e2fsprogs/e2fsprogs.spec.in +@@ -15,10 +15,14 @@ Prereq: /sbin/ldconfig + BuildRoot: %{_tmppath}/%{name}-root + %if %{_vendor} == "suse" + Group: System/Filesystems ++@LFSCK_CMT@Requires: db >= @DB4VERSION@ ++@LFSCK_CMT@BuildRequires: db-devel >= 4.1 texinfo + Provides: e2fsbn ext2fs libcom_err = %{version} ldiskfsprogs = %{version} + Obsoletes: ext2fs libcom_err < %{version} + %else + Group: System Environment/Base ++@LFSCK_CMT@Requires: db4 >= @DB4VERSION@ ++@LFSCK_CMT@BuildRequires: db4-devel >= 4.1 texinfo + Provides: e2fsprogs-libs = %{version} ldiskfsprogs = %{version} + Obsoletes: e4fsprogs e2fsprogs-libs < %{version} + %endif +@@ -71,8 +75,8 @@ SMP systems. + %setup + + %build +-%configure --enable-elf-shlibs --enable-nls \ +- %{?extra_config_flags:%extra_config_flags} ++%configure --enable-elf-shlibs --enable-nls --with-lustre=@LUSTRE@ \ ++ %{?extra_config_flags:%extra_config_flags} @LFSCK_CMT@ --enable-lfsck + make + make check + +@@ -145,6 +149,7 @@ exit 0 + %{_sbindir}/mklost+found + %{_sbindir}/e2freefrag + %{_sbindir}/e4defrag ++@LFSCK_CMT@%{_sbindir}/lfsck + + %{_root_libdir}/libblkid.so.* + %{_root_libdir}/libcom_err.so.* +@@ -170,6 +175,7 @@ exit 0 + %{_mandir}/man8/debugfs.8* + %{_mandir}/man8/dumpe2fs.8* + %{_mandir}/man8/e2fsck.8* ++@LFSCK_CMT@%{_mandir}/man8/lfsck.8* + %{_mandir}/man8/findfs.8* + %{_mandir}/man8/fsck.ext2.8* + %{_mandir}/man8/fsck.ext3.8* +Index: e2fsprogs/e2fsck/lfsck.8.in +=================================================================== +--- /dev/null ++++ e2fsprogs/e2fsck/lfsck.8.in +@@ -0,0 +1,78 @@ ++.\" -*- nroff -*- ++.\" Copyright 2004 by Andreas Dilger. All Rights Reserved. ++.\" This file may be copied under the terms of the GNU Public License. ++.\" ++.TH LFSCK 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" ++.SH NAME ++lfsck \- check a Lustre distributed filesystem ++.SH SYNOPSIS ++.B lfsck ++[ ++.B \-cdfhlnv ++] ++.B \--mdsdb ++.I mds_database_file ++.B \--ostdb ++.IR "ost1_database_file " [ "ost2_database_file " ...] ++.I filesystem ++.SH DESCRIPTION ++.B lfsck ++is used to check and repair the distributed coherency of a Lustre filesystem. ++.PP ++.I filesystem ++is the mountpoint of the Lustre filesystem to be checked. e.g. ++.IR /mnt/lustre ). ++.SH DESCRIPTION ++Lfsck is used to do the distributed coherency checking of a Lustre filesystem ++after ++.B e2fsck ++has been run on each of the local MDS and OST device filesystems. ++.B Lfsck ++will ensure that objects are not referenced by multiple MDS files, that there ++are no orphan objects on the OSTs (objects that do not have any file on the ++MDS which references them), and that all of the objects referenced by the ++MDS exist. Under normal circumstances Lustre will maintain such coherency ++by distributed logging mechanisms, but under exceptional circumstances that ++may fail (e.g. disk failure, filesystem corruption leading to e2fsck repair). ++.SH OPTIONS ++.TP ++.B \-c ++Create (empty) missing OST objects referenced by MDS inodes. ++.TP ++.B \-d ++Delete orphaned objects from the filesystem. Since objects on the OST are ++often only one of several stripes of a file it can be difficult to put ++multiple objects back together into a single usable file. ++.TP ++.B \-h ++Print a brief help message. ++.TP ++.B \-l ++Put orphaned objects into a lost+found directory in the root of the filesystem. ++.TP ++.B \-n ++Do not repair the filesystem, just perform a read-only check (default). ++.TP ++.B \-v ++Verbose operation - more verbosity by specifing option multiple times. ++.TP ++.BI \-\-mdsdb " mds_database_file" ++The MDS database file created by running ++.B e2fsck --mdsdb mds_database_file device ++on the MDS backing device. This is required. ++.TP ++.BI \-\-ostdb " ost1_database_file " [ "ost2_database_file " ...] ++The OST database files created by running ++.B e2fsck --ostdb ost_database_file device ++on each of the OST backing devices. These are required, unless an OST is ++unavailable, in which case all objects thereon will be considered missing. ++.SH REPORTING BUGS ++Bugs should be reported to Sun Microsystems, Inc. via Bugzilla: ++http://bugzilla.lustre.org/ ++.SH AUTHOR ++This version of ++.B lfsck ++was originally written by Liam Kelleher ++and maintained by Andreas Dilger ++.SH SEE ALSO ++.BR e2fsck (8) +Index: e2fsprogs/e2fsck/lfsck.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2fsck/lfsck.c +@@ -0,0 +1,2088 @@ ++/* -*- mode: c; c-basic-offset: 8; -*- ++ * vim:shiftwidth=8:tabstop=8: ++ * ++ * GPL HEADER START ++ * ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 only, ++ * as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License version 2 for more details (a copy is included ++ * in the LICENSE file that accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License ++ * version 2 along with this program; If not, see ++ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf ++ * ++ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, ++ * CA 95054 USA or visit www.sun.com if you need additional information or ++ * have any questions. ++ * ++ * GPL HEADER END ++ */ ++/* ++ * Copyright (c) 2004 Hewlett-Packard Co. ++ * Copyright 2004, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Use is subject to license terms. ++ */ ++/*********************************************************************** ++ * This program takes as input files generated by running e2fsck on ++ * the mds and ost filesystems. The file generated for each ost ++ * contains a table including the object id and size for each object ++ * extant on the ost in each entry. ++ * The file generated from scanning the mds filesystem with e2fsck ++ * contains multiple tables one for each ost. In each table an entry ++ * contains the mds fid as well as the object id on the appropriate ++ * ost. In addition there is an additional table that holds the mds_fid ++ * and the containing directory fid for each entry. This is used for ++ * name lookup. ++ * There are three basic checks ++ * 1) Make sure that multiple mds entries do not reference the same object ++ * 2) Cross reference each object on each ost to make sure a "containing" ++ * file for this exists on the mds ++ * 3) For each file on the mds make sure that the associated objects exist ++ * on the osts ++ * These checks and potential correction for errors found are run from ++ * run_pass* ++ * Each of these checks is just iterate through the appropriate table and ++ * cross check against another table and if errors are found repair. ++ ***************************************************************************/ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_SYS_IOCTL_H ++#include ++#endif ++#include "../version.h" ++#include "e2fsck.h" ++#include "ext2fs/lfsck.h" ++#include "ext2fs/ext2fs.h" ++ ++struct lfsck_fids { ++ int depth; ++ struct lu_fid *fids; ++}; ++ ++struct lfsck_thread_info { ++ struct lfsck_mds_hdr *mds_hdr; ++ DB *mds_direntdb; ++ DB *mds_sizeinfodb; ++ __u32 start_ost_idx; ++ __u32 end_ost_idx; ++ int status; ++}; ++ ++struct lfsck_saved_duplicates { ++ struct lu_fid ld_mds_fid; ++ struct ost_id ld_oi; ++ __u32 ld_ost_idx; ++ char *ld_link; ++}; ++ ++#ifndef O_LARGEFILE ++#define O_LARGEFILE 0 ++#endif ++ ++#define LOG_PATH "/var/log/lfsck.log" ++#define RLIMIT 1024 ++ ++/* Procedure declarations */ ++ ++char *progname = "lfsck"; ++FILE *logfile; ++ ++int lfsck_help; ++int lfsck_save; ++int lfsck_delete; ++int lfsck_create; ++int lfsck_force; ++int lfsck_verbose; ++int lfsck_yes; ++ ++int num_threads = 1; ++ ++char mnt_path[PATH_MAX]; ++char *mds_file; ++char lostandfounddir[PATH_MAX]; ++char dupedir[PATH_MAX]; ++char *ost_files[LOV_MAX_OSTS]; ++int num_ost_files; ++ ++struct obd_uuid lfsck_uuid[LOV_MAX_OSTS]; ++int lov_tgt_count = LOV_MAX_OSTS; ++ ++struct lfsck_saved_duplicates *lfsck_duplicates; ++int lfsck_dup_saved; ++int fixed; ++int fix_failed; ++ ++pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER; ++pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; ++pthread_mutex_t phase_lock = PTHREAD_MUTEX_INITIALIZER; ++pthread_mutex_t size_lock = PTHREAD_MUTEX_INITIALIZER; ++int all_started; ++ ++int lfsck_path2fid(const char *path, struct lu_fid *fid) ++{ ++ struct stat st; ++ long generation; ++ int fd; ++ int rc = 0; ++ ++#ifdef LL_IOC_PATH2FID ++ rc = llapi_path2fid(path, fid); ++ if (rc == 0 || rc != -ENOTTY) ++ return rc; ++#endif ++ /* LL_IOC_PATH2FID was landed in 1.8.2. If it doesn't exist at compile ++ * time, or it fails at runtime with a return ENOTTY indicating that ++ * the ioctl is unimplemented, emulate it here for the older clients. ++ * Assume the server is running Lustre 1.x and create an IGIF FID, ++ * since < 1.8.4 will not work properly with 2.x servers anyway. */ ++ fd = open(path, O_RDONLY); ++ if (fd < 0) ++ return -errno; ++ ++ rc = fstat(fd, &st); ++ if (rc < 0) { ++ rc = -errno; ++ goto out; ++ } ++ fid->f_seq = st.st_ino; ++ ++ rc = ioctl(fd, FSFILT_IOC_GETVERSION, &generation); ++ if (rc < 0) { ++ rc = -errno; ++ goto out; ++ } ++ fid->f_oid = generation; ++ fid->f_ver = 0; ++ ++out: ++ close(fd); ++ return rc; ++} ++ ++#define VERBOSE(lvl, fmt, args...) \ ++do { if (lfsck_verbose >= lvl) printf(fmt, ## args); } while (0) ++ ++int log_open() ++{ ++ time_t tm; ++ ++ if ((logfile = fopen(LOG_PATH, "a")) == NULL) { ++ fprintf(stderr, "%s: Failed to open log file %s\n", ++ progname, LOG_PATH); ++ return (-EPERM); ++ } ++ ++ time(&tm); ++ fprintf(logfile, "===============================================\n\n"); ++ fprintf(logfile, "Starting lfsck %s\n", ctime(&tm)); ++ return(0); ++} ++ ++int log_close(int status) ++{ ++ time_t tm; ++ ++ if (logfile == NULL) ++ return(0); ++ ++ time(&tm); ++ if (status < 0) { ++ fprintf(logfile, "ERROR: lfsck aborted\n"); ++ } else { ++ fprintf(logfile, "lfsck run completed: %s\n",ctime(&tm)); ++ } ++ fprintf(logfile, "===============================================\n\n"); ++ ++ fclose(logfile); ++ return(0); ++} ++ ++void log_write(char *fmt, ...) ++{ ++ va_list args; ++ ++ if (logfile) { ++ va_start(args, fmt); ++ vfprintf(logfile, fmt, args); ++ va_end(args); ++ } ++ va_start(args, fmt); ++ vfprintf(stderr, fmt, args); ++ va_end(args); ++} ++ ++void usage() ++{ ++ printf("\n"); ++ printf("usage: lfsck [-cdfhlnv] --mdsdb mdsdb " ++ "--ostdb ostdb1 [ostdb2 ...] filesystem\n\n"); ++ printf("\t-m|--mdsdb mdsdb MDS database from e2fsck --mdsdb\n"); ++ printf("\t-o|--ostdb ostdb OST databases from e2fsck --ostdb\n"); ++ printf("\tfilesytem full path of lustre mountpoint\n"); ++ printf("\t[-c|--create] create missing objects\n"); ++ printf("\t[-d|--delete] delete orphan objects\n"); ++ printf("\t[-f|--force] force running if fs appears unmounted\n"); ++ printf("\t[-h|--help] print this message\n"); ++ printf("\t[-l|--lostfound] save orphans objects to lost+found\n"); ++ printf("\t[-n|--nofix] do not fix filesystem errors (default)\n"); ++ printf("\t[-v|--verbose] print verbose runtime messages\n"); ++ //printf("\t[-y|--yes] do all cleanup automatically\n"); ++ printf("\n"); ++} ++ ++/* ++ * Get the lov config for the filesystem - this is primarily used to correlate ++ * each ost db file with its index in the lov configuration. Obviously this is ++ * critical. ++ */ ++int get_lov_config() ++{ ++ int fd, rc; ++ ++ fd = open(mnt_path, O_RDONLY); ++ if (fd < 0) { ++ log_write("Error: opening %s\n", mnt_path); ++ return (-errno); ++ } ++ ++ rc = llapi_lov_get_uuids(fd, lfsck_uuid, &lov_tgt_count); ++ ++ close(fd); ++ return rc; ++} ++ ++int parse_args(int argc, char *argv[]) ++{ ++ int option_index = 0; ++ char *path_name = NULL; ++ struct option long_options[] = { ++ { "create", 1, NULL, 'c' }, ++ { "delete", 0, NULL, 'd' }, ++ { "force", 0, NULL, 'f' }, ++ { "help", 0, NULL, 'h' }, ++ { "lostfound", 0, NULL, 'l' }, ++ { "mdsdb", 1, NULL, 'm' }, ++ { "mdtdb", 1, NULL, 'm' }, ++ { "nofix", 0, NULL, 'n' }, ++ { "ostdb", 1, NULL, 'o' }, ++ { "threads", 1, NULL, 't' }, ++ { "verbose", 0, NULL, 'v' }, ++ //{ "yes", 0, NULL, 'y' }, ++ { 0, 0, 0, 0 } ++ }; ++ struct mntent *mnt_info; ++ char tmp[PATH_MAX]; ++ char *dbpath; ++ int c, found; ++ char *p1; ++ FILE *fp; ++ ++ if (argc < 6 ) { ++ return(-EINVAL); ++ } ++ ++ while ((c = getopt_long(argc, argv, "-cdfhlm:no:t:vy", ++ long_options, &option_index)) != -1) { ++ switch (c) { ++ case 'c': ++ lfsck_create++; ++ break; ++ case 'd': ++ lfsck_delete++; ++ break; ++ case 'f': ++ lfsck_force++; ++ break; ++ case 'h': ++ lfsck_help++; ++ break; ++ case 'l': ++ lfsck_save++; ++ break; ++ case 'm': ++ VERBOSE(1, "MDSDB: %s\n", optarg); ++ dbpath = malloc(PATH_MAX); ++ if (dbpath == NULL) { ++ fprintf(stderr, "error allocating dbpath\n"); ++ return -ENOMEM; ++ } ++ strcpy(tmp, optarg); ++ if (realpath(my_dirname(tmp), dbpath) == NULL) { ++ fprintf(stderr, "Failure to resolve path %s\n", ++ optarg); ++ free(dbpath); ++ exit(1); ++ } ++ ++ strcpy(tmp, optarg); ++ sprintf(dbpath+strlen(dbpath), "/%s", my_basename(tmp)); ++ mds_file = dbpath; ++ break; ++ case 'n': ++ lfsck_create = 0; ++ lfsck_delete = 0; ++ lfsck_save = 0; ++ break; ++ case 1: ++ if (optind == argc) { /* last one is mountpoint */ ++ VERBOSE(1, "MOUNTPOINT: %s\n", optarg); ++ path_name = optarg; ++ break; ++ } ++ /* Otherwise it is another ostdb file */ ++ case 'o': ++ { ++ char *ost_path; ++ ++ VERBOSE(1, "OSTDB[%u]: %s\n", num_ost_files, optarg); ++ p1 = optarg; ++ do { ++ dbpath = malloc(PATH_MAX); ++ if (dbpath == NULL) { ++ fprintf(stderr, ++ "error allocate ost_files[%d]\n", ++ num_ost_files); ++ return -ENOMEM; ++ } ++ ++ /* Old-style arguments are comma separated */ ++ ost_path = strsep(&p1, ","); ++ strcpy(tmp, ost_path); ++ if (realpath(my_dirname(tmp), dbpath) == NULL) { ++ fprintf(stderr, "Failure to resolve " ++ "path %s\n", optarg); ++ for (c = 0; c < num_ost_files; c++) ++ free(ost_files[c]); ++ free(dbpath); ++ exit(1); ++ } ++ ++ strcpy(tmp, ost_path); ++ sprintf(dbpath+strlen(dbpath), "/%s", ++ my_basename(tmp)); ++ ost_files[num_ost_files] = dbpath; ++ num_ost_files++; ++ } while (p1 != NULL); ++ break; ++ } ++ case 't': ++ num_threads = strtol(optarg, NULL, 0); ++ if (num_threads == ULONG_MAX) ++ return (-EINVAL); ++ ++ if (num_threads > 128) ++ num_threads = 128; ++ if (num_threads == 0) ++ num_threads = 1; ++ break; ++ case 'v': ++ lfsck_verbose++; ++ break; ++ case 'y': ++ lfsck_yes++; ++ break; ++ default: ++ fprintf(stderr, "unknown option %c\n", c); ++ return(-EINVAL); ++ } ++ } ++ ++ if (path_name == NULL) ++ path_name = argv[optind]; ++ ++ if (lfsck_yes && !lfsck_save && !lfsck_delete && !lfsck_create) { ++ fprintf(stderr, "--yes requires either --save or --delete, or" ++ "--create\n"); ++ return(-EINVAL); ++ } ++ ++ if (realpath(path_name, mnt_path) == NULL) { ++ fprintf(stderr, "error getting real mount path_name\n"); ++ return (-EINVAL); ++ } ++ fp = setmntent(MOUNTED, "r"); ++ if (fp == NULL) { ++ fprintf(stderr, "error opening /etc/mtab\n"); ++ return (-EINVAL); ++ } ++ ++ found = 0; ++ while ((mnt_info = getmntent(fp)) != NULL) { ++ if (strcmp(mnt_info->mnt_dir, mnt_path) == 0 && ++ llapi_is_lustre_mnttype(mnt_info->mnt_type)) { ++ found = 1; ++ break; ++ } ++ } ++ endmntent(fp); ++ ++ if (!found) { ++ if (lfsck_force) { ++ fprintf(stderr, "lfsck: %s unmounted? forcing\n", ++ mnt_path); ++ } else { ++ fprintf(stderr, "lfsck: %s not mounted\n", mnt_path); ++ return(-EINVAL); ++ } ++ } ++ ++ if (mds_file == NULL || ost_files[0] == NULL) { ++ fprintf(stderr, "--mdsdb or --ostdb unspecified\n"); ++ return(-EINVAL); ++ } ++ ++ return(0); ++} ++ ++/* ++ * This is called from lfsck_get_path and also recursively. ++ * This function is used on error paths when the name of an mds fid has ++ * to be determined. It relies on the order of directory search that was ++ * run in e2fsck when generating the mds_fid + containing dir table. ++ * It searches through the table for the correct mds_fid. When this ++ * is found a list of fids which are the fids of the directory tree up ++ * to the containing directory of the sought for fid is returned. ++ * When called recursively it continues search from the current point and ++ * when the recursive call returns the search is continued from the ++ * current search point as well. Basically is just traverses the list once. ++ * For a file like /aaa/ccc/ddd the fids of aaa ccc and the fid ++ * for ddd would also be returned. ++ */ ++static int lfsck_get_fids(struct lu_fid *mds_fid, DB *mds_direntdb, ++ int depth, struct lfsck_fids *lfidp) ++{ ++ struct lfsck_mds_dirent mds_dirent; ++ int rc = 0; ++ DBT key, data; ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = mds_fid; ++ key.size = sizeof(*mds_fid); ++ data.data = &mds_dirent; ++ data.size = data.ulen = sizeof(mds_dirent); ++ data.flags = DB_DBT_USERMEM; ++ ++ rc = mds_direntdb->get(mds_direntdb, NULL, &key, &data, 0); ++ if (rc && !lfsck_is_dirfid_root(mds_fid)) { ++ log_write("Failed to find fid "DFID": %s\n", PFID(mds_fid), ++ db_strerror(rc)); ++ return (-ENOENT); ++ } ++ letocpu_mds_dirent(&mds_dirent); ++ if (lfsck_is_dirfid_root(&mds_dirent.mds_dirfid)) { ++ lfidp->fids = malloc(sizeof(*lfidp->fids) * (depth + 1)); ++ if (lfidp->fids == NULL) { ++ return (-ENOMEM); ++ } ++ lfidp->depth = depth; ++ lfidp->fids[depth] = mds_dirent.mds_fid; ++ return (0); ++ } ++ rc = lfsck_get_fids(&mds_dirent.mds_dirfid, mds_direntdb, ++ depth + 1, lfidp); ++ if (rc) { ++ return(rc); ++ } ++ ++ lfidp->fids[depth] = mds_dirent.mds_fid; ++ return(0); ++} ++ ++/* This function determines a path to a file given an mds fid. ++ * The workhorse function is lfsck_get_fids which once given a ++ * fid return a list of directory fids from the "root" directory to ++ * the fid in question. Using these fids we can construct the path to ++ * the file by using readir() ++ */ ++static int lfsck_get_path(struct lu_fid *mds_fid, DB *mds_direntdb, ++ char *path, int path_len) ++{ ++ struct lfsck_fids lfids; ++ DIR *dir; ++ struct dirent *dent; ++ int rc, i; ++ int cur_len = 0; ++ ++ VERBOSE(2, "lookup path for FID "DFID"\n", PFID(mds_fid)); ++ ++ lfids.fids = NULL; ++ lfids.depth = 0; ++ ++ rc = lfsck_get_fids(mds_fid, mds_direntdb, 0, &lfids); ++ if (rc != 0) { ++ rc = -ENOENT; ++ goto out; ++ } ++ ++ if (strlen(mnt_path) + 1 > path_len) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ cur_len = strlen(mnt_path); ++ path[strlen(mnt_path)] = 0; ++ memcpy(path, mnt_path, strlen(mnt_path)); ++ /* Skip the first dir since this would be "ROOT" */ ++ rc = 0; ++ for (i = lfids.depth - 1; i >= 0; i--) { ++ dir = opendir(path); ++ if (dir == NULL) { ++ rc = -errno; ++ goto out; ++ } ++ while (1) { ++ char path_tmp[PATH_MAX]; ++ struct lu_fid fid; ++ ++ dent = readdir(dir); ++ if (dent == NULL) { ++ closedir(dir); ++ rc = -ENOENT; ++ goto out; ++ } ++ ++ if (strlen(path) + strlen(dent->d_name) +2 >= PATH_MAX){ ++ closedir(dir); ++ rc = -ENAMETOOLONG; ++ goto out; ++ } ++ ++ sprintf(path_tmp, "%s/%s", path, dent->d_name); ++ rc = lfsck_path2fid(path_tmp, &fid); ++ if (rc) ++ continue; ++ ++ rc = 0; ++ if (lfsck_fidcmp(&fid, &lfids.fids[i]) == 0) { ++ if (cur_len + 1 + strlen(dent->d_name) > ++ path_len) { ++ rc = -ENOMEM; ++ closedir(dir); ++ goto out; ++ } ++ path[cur_len] = '/'; ++ cur_len++; ++ memcpy(&path[cur_len], dent->d_name, ++ strlen(dent->d_name)); ++ cur_len += strlen(dent->d_name); ++ path[cur_len] = 0; ++ closedir(dir); ++ break; ++ } ++ } ++ } ++out: ++ if (lfids.fids) ++ free(lfids.fids); ++ return(rc); ++} ++ ++/* ++ * Used by pass1 to save the ids of files which reference the same ++ * objects. This is then used by pass4 to repair these files ++ */ ++static int lfsck_save_duplicate(const struct lfsck_mds_objent *mds_obj) ++{ ++ VERBOSE(2, "save duplicate object %u:"DOIF" FID "DFID"\n", ++ mds_obj->mds_ostidx, POIF(&mds_obj->mds_oi), ++ PFID(&mds_obj->mds_fid)); ++ ++ pthread_mutex_lock(&phase_lock); ++ if (lfsck_duplicates == NULL) { ++ lfsck_duplicates = malloc(sizeof(*lfsck_duplicates) * ++ RLIMIT); ++ if (lfsck_duplicates == NULL) ++ return (-EINVAL); ++ ++ } else if (!((lfsck_dup_saved + 1) % RLIMIT)) { ++ size_t size = (((lfsck_dup_saved + 1) / RLIMIT) + 1 ) * ++ sizeof(*lfsck_duplicates) * RLIMIT; ++ void *tmp = realloc(lfsck_duplicates, size); ++ ++ if (tmp == NULL) ++ return (-ENOMEM); ++ ++ lfsck_duplicates = tmp; ++ } ++ lfsck_duplicates[lfsck_dup_saved].ld_mds_fid = mds_obj->mds_fid; ++ lfsck_duplicates[lfsck_dup_saved].ld_oi = mds_obj->mds_oi; ++ lfsck_duplicates[lfsck_dup_saved].ld_ost_idx = mds_obj->mds_ostidx; ++ lfsck_duplicates[lfsck_dup_saved].ld_link = NULL; ++ lfsck_dup_saved++; ++ pthread_mutex_unlock(&phase_lock); ++ return(0); ++} ++ ++/* ++ * Check for duplicate ost objects on mds. Run through the table of ++ * mds_fid/ost object to make sure that each ost object is only ++ * refrenced by one mds entry. If a duplicate is found save the information ++ * for repair in pass4 ++ */ ++int lfsck_run_pass1(__u32 ost_idx, DB *mds_ostdb, DB *ost_db, DB *mds_direntdb) ++{ ++ int i = 0; ++ int error = 0; ++ int rc = 0; ++ struct lfsck_mds_objent mds_obj, mds_obj2; ++ unsigned long count = 0; ++ DBT key, data; ++ DBC *dbcp = NULL; ++ ++ log_write("%s: ost_idx %d: pass1: check for duplicate objects\n", ++ progname, ost_idx); ++ ++ if ((rc = mds_ostdb->cursor(mds_ostdb, NULL, &dbcp, 0)) != 0) { ++ log_write("%s: error acquiring cursor for database: %s\n", ++ progname, db_strerror(rc)); ++ goto out; ++ } ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ data.data = &mds_obj; ++ data.size = data.ulen = sizeof(mds_obj); ++ data.flags = DB_DBT_USERMEM; ++ ++ while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ DBT data_dup; ++ db_recno_t num_dup; ++ ++ count++; ++ if ((rc = dbcp->c_count(dbcp, &num_dup, 0)) != 0) { ++ log_write("%s: [%u] getting object refcount: %s\n", ++ progname, ost_idx, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ if (num_dup <= 1) ++ continue; ++ ++ letocpu_mds_objent(&mds_obj); ++ ++ if (lfsck_save_duplicate(&mds_obj)) ++ fix_failed++; ++ ++ for (i = 1; i < num_dup; i++) { ++ memset(&data_dup, 0, sizeof(data_dup)); ++ data_dup.data = &mds_obj2; ++ data_dup.size = data_dup.ulen = sizeof(mds_obj2); ++ data_dup.flags = DB_DBT_USERMEM; ++ rc = dbcp->c_get(dbcp, &key,&data_dup,DB_NEXT); ++ if (rc != 0) { ++ log_write("%s: acquiring duplicate info: %s\n", ++ progname, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ letocpu_mds_objent(&mds_obj2); ++ ++ if (!lfsck_fidcmp(&mds_obj.mds_fid,&mds_obj2.mds_fid)) { ++ log_write("%s: [%u] hard link on FID "DFID" is" ++ " not a duplicate object "DOIF"\n", ++ progname, PFID(&mds_obj.mds_fid), ++ ost_idx, POIF(&mds_obj.mds_oi)); ++ continue; ++ } ++ ++ if (lfsck_save_duplicate(&mds_obj2)) ++ fix_failed++; ++ } ++ } ++ ++ if (rc != DB_NOTFOUND) { ++ log_write("%s: error reading from inode database: %s\n", ++ progname, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ rc = 0; ++ if (error == 0) { ++ log_write("%s: ost_idx %d: pass1 OK (%lu files total)\n", ++ progname, ost_idx, count); ++ } else { ++ log_write("%s: ost_idx %d: pass1 ERROR: %d duplicate " ++ "entries found (fixed in pass4) (%lu files total)\n", ++ progname, ost_idx, error, count); ++ } ++out: ++ if (dbcp) ++ dbcp->c_close(dbcp); ++ ++ return(rc); ++} ++ ++#ifndef LL_IOC_RECREATE_OBJ ++#define LL_IOC_RECREATE_OBJ _IOW ('f', 157, long) /* 1.x object IDs */ ++#endif ++#ifndef LL_IOC_RECREATE_FID ++#define LL_IOC_RECREATE_FID _IOW ('f', 157, struct lu_fid) /* 2.x FIDs */ ++#endif ++ ++/* If an MDS file is missing an object recreate object using an ioctl call */ ++static int lfsck_recreate_obj(int cmd, void *creat, struct ost_id *oi, ++ __u32 ost_idx, char *path) ++{ ++ ++ int fd; ++ int rc; ++ ++ if (!lfsck_create) { ++ log_write("[%u]: %s object %s "DOIF" not created\n", ost_idx, ++ path,cmd == LL_IOC_RECREATE_FID? "FID":"ID",POIF(oi)); ++ return 0; ++ } ++ ++ fd = open(path, O_LARGEFILE | O_RDONLY, 0); ++ if (fd < 0) { ++ rc = -errno; ++ log_write("[%u]: FAILED to open %s missing obj "DOIF"\n", ++ ost_idx, path, POIF(oi)); ++ fix_failed++; ++ return rc; ++ } ++ ++ rc = ioctl(fd, cmd, &creat); ++ if (rc) { ++ rc = -errno; ++ log_write("[%u]: failed to recreate %s missing obj "DOIF"\n", ++ ost_idx, path, POIF(oi)); ++ fix_failed++; ++ } else { ++ log_write("[%u]: recreated %s missing obj "DOIF"\n", ++ ost_idx, path, POIF(oi)); ++ fixed++; ++ } ++ close(fd); ++ ++ return(rc); ++} ++ ++/* ++ * If size checking is enabled see if this ost is "adding" to the file size ++ * if it is then just calculate the new size and save. ++ */ ++static int lfsck_calc_size(struct lfsck_mds_objent *mds_obj, ++ struct lfsck_ost_objent *ost_obj, ++ DB *mds_sizeinfodb) ++{ ++ int rc = 0; ++#ifdef LFSCK_CHECK_SIZE ++ struct lfsck_mds_szinfo mds_szinfo1; ++ __u64 calc_size; ++ DBT key, data; ++ __u64 chunks, rem; ++ ++ if (ost_obj->ost_size == 0) ++ return(0); ++ ++ pthread_mutex_lock(&size_lock); ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_obj->mds_fid; ++ key.size = sizeof(mds_obj->mds_fid); ++ data.data = &mds_szinfo1; ++ data.size = data.ulen = sizeof(mds_szinfo1); ++ data.flags = DB_DBT_USERMEM; ++ if ((rc = mds_sizeinfodb->get(mds_sizeinfodb, NULL, &key, &data, 0))) { ++ log_write("Failure to get sizeinfo "LPU64"\n",mds_obj->mds_fid); ++ pthread_mutex_unlock(&size_lock); ++ return (-ENOENT); ++ } ++ letocpu_mds_szinfo(&mds_szinfo1); ++ assert (mds_szinfo1.mds_stripe_pattern == LOV_PATTERN_RAID0); ++ chunks = ost_obj->ost_size / mds_szinfo1.mds_stripe_size; ++ rem = ost_obj->ost_size % mds_szinfo1.mds_stripe_size; ++ if (rem == 0) { ++ calc_size = (((chunks - 1 )* mds_szinfo1.mds_stripe_size) ++ * mds_szinfo1.mds_stripe_count); ++ calc_size += mds_szinfo1.mds_stripe_size * ++ (mds_obj->mds_ostoffset + 1); ++ } else { ++ calc_size = ((chunks * mds_szinfo1.mds_stripe_size) ++ * mds_szinfo1.mds_stripe_count); ++ if (mds_obj->mds_ostoffset == 0) { ++ calc_size += rem; ++ } else { ++ calc_size += mds_szinfo1.mds_stripe_size * ++ mds_obj->mds_ostoffset; ++ calc_size += rem; ++ } ++ } ++ if (calc_size > mds_szinfo1.mds_calc_size) { ++ mds_szinfo1.mds_calc_size = calc_size; ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_obj->mds_fid; ++ key.size = sizeof(mds_obj->mds_fid); ++ data.data = &mds_szinfo1; ++ data.size = sizeof(mds_szinfo1); ++ cputole_mds_szinfo(&mds_szinfo1); ++ /* Make sure we overwrite */ ++ if ((rc = mds_sizeinfodb->put(mds_sizeinfodb, ++ NULL, &key, &data, 0)) != 0) { ++ log_write("Failure to update sizeinfo data\n"); ++ pthread_mutex_unlock(&size_lock); ++ return (-EIO); ++ } ++ } ++ pthread_mutex_unlock(&size_lock); ++#endif /* LFSCK_CHECK_SIZE */ ++ return(rc); ++} ++ ++/* ++ * Check for dangling inode. ++ * pass runs through the mds table for an ost and checks again the ost table ++ * that the object refrenced on the mds exists on the ost ++ */ ++int lfsck_run_pass2(__u32 ost_idx, struct lfsck_mds_hdr *mds_hdr, ++ DB *mds_ostdb, DB *ostdb, ++ DB *mds_direntdb, DB *mds_sizeinfodb) ++{ ++ struct lfsck_mds_objent mds_obj; ++ struct lfsck_ost_objent ost_obj; ++ int error = 0, rc = 0; ++ unsigned long count = 0; ++ char *path; ++ DBC *dbcp = NULL; ++ DBT key, data; ++ __u64 max_objid = mds_hdr->mds_max_ost_id[ost_idx]; ++ __u64 mds_connect_flags = 0; ++ ++ rc = llapi_get_connect_flags(mnt_path, &mds_connect_flags); ++ /* Ignore the error here, and assume it is an older 1.8.x without ++ * LL_IOC_GET_CONNECT_FLAGS. We only use this for 2.x detection. */ ++ ++ log_write("lfsck: ost_idx %d: pass2: check for missing inode objects\n", ++ ost_idx); ++ ++ path = malloc(PATH_MAX); ++ if (path == NULL) { ++ log_write("lfsck: [%u]: pass2 ERROR: out of memory\n", ++ ost_idx); ++ return (-ENOMEM); ++ } ++ ++ rc = mds_ostdb->cursor(mds_ostdb, NULL, &dbcp, 0); ++ if (rc != 0) { ++ log_write("[%u]: error acquiring cursor for mds table: %s\n", ++ ost_idx, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ data.data = &mds_obj; ++ data.size = data.ulen = sizeof(mds_obj); ++ data.flags = DB_DBT_USERMEM; ++ while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ DBT key_ost, data_ost; ++ ++ count++; ++ letocpu_mds_objent(&mds_obj); ++ ++ if (mds_hdr->mds_flags & E2F_OPT_READONLY && ++ mds_obj.mds_oi.oi_id > max_objid) { ++ VERBOSE(2, "[%u] skipping MDS FID "DFID": object "DOIF ++ " > max "LPU64"\n", ost_idx, ++ PFID(&mds_obj.mds_fid), POIF(&mds_obj.mds_oi), ++ max_objid); ++ continue; ++ } ++ ++ memset(&key_ost, 0, sizeof(key_ost)); ++ memset(&data_ost, 0, sizeof(data_ost)); ++ key_ost.data = &mds_obj.mds_oi; ++ key_ost.size = sizeof(mds_obj.mds_oi); ++ data_ost.data = &ost_obj; ++ data_ost.size = data_ost.ulen = sizeof(ost_obj); ++ data_ost.flags = DB_DBT_USERMEM; ++ rc = ostdb->get(ostdb, NULL, &key_ost, &data_ost, 0); ++ if (rc != 0) { ++ letocpu_ost_objent(&ost_obj); ++ if (rc == DB_NOTFOUND) { ++ struct lu_fid fid; ++ struct create18 { ++ __u64 lrc_id; ++ __u32 lrc_ost_idx; ++ } create18; ++ void *create; ++ int cmd; ++ ++ if (lfsck_get_path(&mds_obj.mds_fid, ++ mds_direntdb,path,PATH_MAX)){ ++ VERBOSE(1,"[%u]: MDS FID "DFID" object " ++ DOIF" deleted?\n", ost_idx, ++ PFID(&mds_obj.mds_fid), ++ POIF(&mds_obj.mds_oi)); ++ continue; ++ } ++ error++; ++ if (mds_connect_flags & OBD_CONNECT_FID) { ++ ostid_idif_unpack(&mds_obj.mds_oi, ++ &fid, ost_idx); ++ create = &fid; ++ cmd = LL_IOC_RECREATE_FID; ++ } else { ++ create18.lrc_id = mds_obj.mds_oi.oi_id; ++ create18.lrc_ost_idx = ost_idx; ++ create = &create18; ++ cmd = LL_IOC_RECREATE_OBJ; ++ } ++ ++ lfsck_recreate_obj(cmd, create,&mds_obj.mds_oi, ++ ost_idx, path); ++ } else { ++ log_write("[%u]: error looking up object "DOIF ++ ": %s\n", ost_idx, ++ POIF(&mds_obj.mds_oi), ++ db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ } ++ if (lfsck_calc_size(&mds_obj, &ost_obj, mds_sizeinfodb)) { ++ log_write("[%u]: error updating file size for object " ++ DOIF": %s\n", ost_idx, POIF(&mds_obj.mds_oi), ++ strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ } ++ if (rc != DB_NOTFOUND) { ++ log_write("[%u]: error getting next inode: %s\n", ++ ost_idx, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ rc = 0; ++ if (error == 0) { ++ log_write("lfsck: ost_idx %d: pass2 OK (%lu objects)\n", ++ ost_idx, count); ++ } else { ++ log_write("lfsck: ost_idx %d: pass2 ERROR: %d dangling inodes " ++ "found (%lu files total)\n", ost_idx, error, count); ++ } ++ ++out: ++ dbcp->c_close(dbcp); ++ free(path); ++ return(0); ++} ++ ++/* ++ * If an object exists on an ost but is not referenced by an entry on the mds ++ * then create a lost+found entry and set the EA on the file so that the ++ * orphaned object is picked up. If the object is requested to be deleted ++ * an unlink on this lost+found file will now delete same ++ */ ++int lfsck_fix_orphan(__u32 ost_idx, struct ost_id *oi, ++ struct obd_uuid *uuid, int delete) ++{ ++ struct lov_user_md *lum; ++ char file[PATH_MAX]; ++ int fd, lum_size, rc = 0; ++ struct utimbuf utimbuf = { 0, 0 }; ++ ++ lum_size = LOV_EA_SIZE(lum, 1); ++ ++ lum = malloc(lum_size); ++ if (lum == NULL) { ++ log_write("%s: out of memory on EA (%u) orphan %u:"DOIF"\n", ++ progname, lum_size, ost_idx, POIF(oi)); ++ return(-ENOMEM); ++ } ++ ++ memset(file, 0, PATH_MAX); ++ sprintf(file, "%s/%s-"DOIF, lostandfounddir, uuid->uuid, POIF(oi)); ++ ++ fd = open(file, O_CREAT|O_EXCL|O_LOV_DELAY_CREATE, 0600); ++ if (fd < 0) { ++ rc = -errno; ++ log_write("%s: unable to open %s for orphan %u:"DOIF": %s\n", ++ progname, file, ost_idx, POIF(oi), strerror(-rc)); ++ goto out_free; ++ } ++ lum->lmm_magic = LOV_USER_MAGIC; ++ lum->lmm_pattern = LOV_PATTERN_RAID0; ++ lum->lmm_stripe_size = 1048576; ++ lum->lmm_stripe_offset = 0; ++ lum->lmm_stripe_count = 1; ++ lum->lmm_objects[0].l_object_id = oi->oi_id; ++ lum->lmm_objects[0].l_object_seq = oi->oi_seq; ++ lum->lmm_objects[0].l_ost_gen = 0; ++ lum->lmm_objects[0].l_ost_idx = ost_idx; ++ ++ /* reset the MDS timestamps so we can see the OST timestamps */ ++ utime(file, &utimbuf); ++ ++ if (ioctl(fd, LL_IOC_LOV_SETEA, lum) < 0) { ++ rc = -errno; ++ log_write("%s: unable to open %s for orphan %u:"DOIF": %s\n", ++ progname, file, ost_idx, POIF(oi), strerror(-rc)); ++ } ++ ++ close(fd); ++ if (rc != 0 || delete) { ++ int err = unlink(file); ++ if (err != 0 && errno != ENOENT) { ++ rc = rc ? rc : -errno; ++ log_write("%s: failed to unlink %s for orphan %u:"DOIF ++ ": %s\n", progname, file, ost_idx, ++ POIF(oi), strerror(-rc)); ++ } ++ } ++out_free: ++ free(lum); ++ return(rc); ++} ++ ++/* ++ * Check for orphans ++ * Run through each entry in ost table and check the mds ost table for ++ * a corresponding entry. If not found report and repair. ++ */ ++int lfsck_run_pass3(__u32 ost_idx, DB *mds_ostdb, DB *ostdb, ++ struct obd_uuid *uuid, __u64 last_id) ++{ ++ int error = 0, rc = 0; ++ struct lfsck_mds_objent mds_obj; ++ struct lfsck_ost_objent ost_obj; ++ unsigned long count = 0; ++ DBT key, data; ++ DBC *dbcp = NULL; ++ __u64 bytes = 0; ++ ++ log_write("lfsck: ost_idx %d: pass3: check for orphan objects\n", ++ ost_idx); ++ ++ VERBOSE(1, "[%u] uuid %s\n", ost_idx, uuid->uuid); ++ VERBOSE(1, "[%u] last_id "LPU64"\n", ost_idx, last_id); ++ ++ rc = ostdb->cursor(ostdb, NULL, &dbcp, 0); ++ if (rc != 0) { ++ log_write("[%u]: error acquiring cursor for mds table: %s\n", ++ ost_idx, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ data.data = &ost_obj; ++ data.size = data.ulen = sizeof(ost_obj); ++ data.flags = DB_DBT_USERMEM; ++ ++ while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ DBT key_mdt, data_mdt; ++ struct ost_id *oi; ++ ++ count++; ++ letocpu_ost_objent(&ost_obj); ++ oi = &ost_obj.ost_oi; ++ ++ if (oi->oi_id > last_id) { ++ VERBOSE(2, "[%u] skipping objid "DOIF" > "LPU64"\n", ++ ost_idx, POIF(oi), last_id); ++ continue; ++ } ++ VERBOSE(2, "[%u] processing objid "DOIF"\n", ost_idx, POIF(oi)); ++ ++ memset(&key_mdt, 0, sizeof(key_mdt)); ++ memset(&data_mdt, 0, sizeof(data_mdt)); ++ key_mdt.data = oi; ++ key_mdt.size = sizeof(*oi); ++ data_mdt.data = &mds_obj; ++ data_mdt.size = data_mdt.ulen = sizeof(mds_obj); ++ data_mdt.flags = DB_DBT_USERMEM; ++ rc = mds_ostdb->get(mds_ostdb, NULL, &key_mdt, &data_mdt, 0); ++ if (rc == 0) { ++ VERBOSE(2, "[%u] found object "DOIF" reference\n", ++ ost_idx, POIF(oi)); ++ continue; ++ } ++ ++ letocpu_mds_objent(&mds_obj); ++ if (rc != DB_NOTFOUND) { ++ log_write("Failed to check mds db for entry\n"); ++ rc = -EINVAL; ++ goto out; ++ } ++ if (ost_obj.ost_size == 0) { ++ /* don't report errors for normal orphan recovery */ ++ VERBOSE(1, "[%u] zero-length orphan objid "DOIF"\n", ++ ost_idx, POIF(oi)); ++ if (lfsck_save || lfsck_delete) { ++ /* No reason to save just delete*/ ++ rc = lfsck_fix_orphan(ost_idx, oi, uuid, 1); ++ if (rc) { ++ log_write("lfsck: [%u]: pass3 " ++ "error fixing zero-length " ++ "orphan objid "DOIF"\n", ++ ost_idx, POIF(oi)); ++ fix_failed++; ++ } else { ++ fixed++; ++ } ++ } ++ continue; ++ } ++ ++ error++; ++ bytes += ost_obj.ost_bytes; ++ if (lfsck_save || lfsck_delete) { ++ rc = lfsck_fix_orphan(ost_idx, oi, uuid, lfsck_delete); ++ if (rc) { ++ log_write("lfsck: [%u]: failed to fix orphan " ++ "object "DOIF", "LPU64" bytes\n", ++ ost_idx, POIF(oi),ost_obj.ost_bytes); ++ fix_failed++; ++ } else { ++ log_write("lfsck: [%u]: pass3 %s orphan object " ++ DOIF", "LPU64" bytes\n", ost_idx, ++ lfsck_save ? "saved" : "unlinked", ++ POIF(oi), ost_obj.ost_bytes); ++ fixed++; ++ } ++ } else { ++ error++; ++ log_write("lfsck: [%u]: pass3 orphan found objid " ++ DOIF", "LPU64" bytes\n", ost_idx, ++ POIF(oi), ost_obj.ost_bytes); ++ } ++ } ++ if (rc != DB_NOTFOUND) { ++ log_write("[%u]: error getting next object in db %d\n", ++ ost_idx, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (error == 0) { ++ log_write("lfsck: ost_idx %d: pass3 OK (%lu files total)\n", ++ ost_idx, count); ++ } else { ++ log_write("lfsck: ost_idx %d: pass3 %s: %4gMB of orphan " ++ "data (%lu of %lu files total)\n", ost_idx, ++ (lfsck_save | lfsck_delete) ? "FIXED" : "ERROR", ++ (double)bytes / (1024 * 1024), error, count); ++ } ++out: ++ if (dbcp) ++ dbcp->c_close(dbcp); ++ return (0); ++} ++ ++/* Missing ost information report affected file names */ ++int lfsck_list_affected_files(char *mds_file, struct lfsck_mds_hdr *mds_hdr, ++ DB *mds_direntdb, __u32 ost_idx) ++{ ++ struct lfsck_mds_objent mds_obj; ++ char dbname[256]; ++ char *path; ++ DB *mds_db = NULL; ++ DBT key,data; ++ DBC *dbcp = NULL; ++ int rc = 0; ++ ++ path = malloc(PATH_MAX); ++ if (path == NULL) { ++ return (-ENOMEM); ++ } ++ ++ sprintf(dbname, "%s.%d", MDS_OSTDB, ost_idx); ++ if ((rc = lfsck_opendb(mds_file, dbname, &mds_db, 1, 0, 0)) != 0) { ++ log_write("failed to open mds db file %s\n", mds_file); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if ((rc = mds_db->cursor(mds_db, NULL, &dbcp, 0)) != 0) { ++ log_write("Failed to acquire cursor for mds table\n"); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ data.data = &mds_obj; ++ data.size = data.ulen = sizeof(mds_obj); ++ data.flags = DB_DBT_USERMEM; ++ ++ log_write("Files affected by missing ost info are : -\n"); ++ while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ letocpu_mds_objent(&mds_obj); ++ ++ if (lfsck_get_path(&mds_obj.mds_fid, mds_direntdb, ++ path, PATH_MAX)) { ++ log_write("Failed to get path for fid "LPU64"\n", ++ mds_obj.mds_fid); ++ fix_failed++; ++ } else { ++ log_write("%s\n",path); ++ } ++ } ++ if (rc != DB_NOTFOUND) { ++ log_write("Error getting next element in db %d\n", rc); ++ rc = -EINVAL; ++ goto out; ++ } ++ rc = 0; ++ ++out: ++ if (dbcp) ++ dbcp->c_close(dbcp); ++ if (mds_db) ++ mds_db->close(mds_db, 0); ++ return(rc); ++} ++ ++/* ++ * For each ost index run checks 1 2 and 3. ++ * 1) Check for object referenced by more than one file ++ * 2) Check that objects exist on ost ++ * 3) Check that containg mds entry exists for an object ++ */ ++int run_test(__u32 ost_idx, struct lfsck_mds_hdr *mds_hdr, ++ DB *mds_direntdb, DB *mds_sizeinfodb ) ++{ ++ struct lfsck_ost_hdr *ost_hdr = NULL; ++ char dbname[256]; ++ DB *mds_ostdb = NULL; ++ DB *ost_db = NULL; ++ DBT key, data; ++ __u64 last_id; ++ int i, rc; ++ ++ sprintf(dbname, "%s.%d", MDS_OSTDB, ost_idx); ++ ++ VERBOSE(2, "testing ost_idx %d\n", ost_idx); ++ ++ rc = lfsck_opendb(mds_file, dbname, &mds_ostdb, 1, 0, 0); ++ if (rc != 0) { ++ log_write("failed to open mds db file %s: %s\n", ++ mds_file, db_strerror(rc)); ++ goto out; ++ } ++ ++ ost_hdr = malloc(sizeof(*ost_hdr)); ++ if (ost_hdr == NULL) { ++ log_write("Failure to alloc memory\n"); ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ ++ VERBOSE(2, "looking for index %u UUID %s\n", ost_idx, ++ lfsck_uuid[ost_idx].uuid); ++ ++ for (i = 0; i < num_ost_files; i++) { ++ VERBOSE(2, "checking file %s\n", ost_files[i]); ++ rc = lfsck_opendb(ost_files[i], OST_HDR, &ost_db, 0, 0, 0); ++ if (rc != 0) { ++ log_write("Error opening ost_data_file %s: rc %d\n", ++ ost_files[i], rc); ++ goto out; ++ } ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ ost_hdr->ost_magic = OST_MAGIC; ++ key.data = &ost_hdr->ost_magic; ++ key.size = sizeof(ost_hdr->ost_magic); ++ data.size = data.ulen = sizeof(*ost_hdr); ++ data.data = ost_hdr; ++ data.flags = DB_DBT_USERMEM; ++ ++ rc = ost_db->get(ost_db, NULL, &key, &data, 0); ++ ost_db->close(ost_db, 0); ++ ost_db = NULL; ++ if (rc != 0) { ++ log_write("Invalid ost magic on file %s: rc %s\n", ++ ost_files[i], db_strerror(rc)); ++ continue; ++ } ++ ++ letocpu_ost_hdr(ost_hdr); ++ VERBOSE(2, "%s has ost UUID %s\n", ost_files[i], ++ ost_hdr->ost_uuid.uuid); ++ ++ if (obd_uuid_equals(&lfsck_uuid[ost_idx], &ost_hdr->ost_uuid)) { ++ if (ost_hdr->ost_index != ost_idx) { ++ log_write("Requested ost_idx %u doesn't match " ++ "index %u found in %s\n", ost_idx, ++ ost_hdr->ost_index, ost_files[i]); ++ continue; ++ } ++ ++ break; ++ } ++ } ++ ++ if (i == num_ost_files) { ++ log_write("lfsck: can't find file for ost_idx %d\n", ost_idx); ++ rc = lfsck_list_affected_files(mds_file, mds_hdr, ++ mds_direntdb, ost_idx); ++ goto out; ++ } ++ rc = lfsck_opendb(ost_files[i], OST_OSTDB, &ost_db, 0, 0, 0); ++ if (rc != 0) { ++ log_write("error opening ost_data_file %s: rc %d\n", ++ ost_files[i], rc); ++ goto out; ++ } ++ ++ VERBOSE(1, "MDS: max_id "LPU64" OST: max_id "LPU64"\n", ++ mds_hdr->mds_max_ost_id[ost_idx], ost_hdr->ost_last_id); ++ ++ rc = lfsck_run_pass1(ost_idx, mds_ostdb, ost_db, mds_direntdb); ++ if (rc != 0) { ++ log_write("error in running pass1\n"); ++ goto out; ++ } ++ ++ rc = lfsck_run_pass2(ost_idx, mds_hdr, mds_ostdb, ost_db, mds_direntdb, ++ mds_sizeinfodb); ++ if (rc != 0) { ++ log_write("error in running pass2\n"); ++ goto out; ++ } ++ ++ last_id = (ost_hdr->ost_flags & E2F_OPT_READONLY || ++ mds_hdr->mds_flags & E2F_OPT_READONLY) ? ++ mds_hdr->mds_max_ost_id[ost_idx] : ost_hdr->ost_last_id; ++ ++ rc = lfsck_run_pass3(ost_idx, mds_ostdb, ost_db, &ost_hdr->ost_uuid, ++ last_id); ++ if (rc != 0) { ++ log_write("error in running pass3\n"); ++ goto out; ++ } ++ rc = 0; ++ ++out: ++ if (ost_hdr) ++ free(ost_hdr); ++ if (mds_ostdb) ++ mds_ostdb->close(mds_ostdb, 0); ++ if (ost_db) ++ ost_db->close(ost_db, 0); ++ ++ return(rc); ++} ++ ++static int lfsck_validate_duplicate(struct lfsck_saved_duplicates *dup, ++ const char *path) ++{ ++ struct lov_user_md *lum; ++ struct lov_user_ost_data_v1 *loi; ++ struct stat64 st; ++ struct lu_fid fid; ++ int rc, i; ++ ++ VERBOSE(2,"[%u] check duplicate FID "DFID" object "DOIF"\n for\t%s\n", ++ dup->ld_ost_idx, PFID(&dup->ld_mds_fid),POIF(&dup->ld_oi),path); ++ ++ /* first, validate that the paths are still valid */ ++ if (stat64(path, &st) < 0) { ++ rc = -errno; ++ log_write("%s: duplicate file %s error: %s\n", ++ progname, path, strerror(-rc)); ++ return rc; ++ } ++ ++ rc = lfsck_path2fid(path, &fid); ++ if (rc < 0) { ++ log_write("%s: unable to get LMA EA on %s: %s\n", ++ progname, path, strerror(-rc)); ++ return rc; ++ } ++ if (lfsck_fidcmp(&dup->ld_mds_fid, &fid)) { ++ log_write("%s: duplicate file %s is no longer FID "DFID"\n", ++ progname, path, PFID(&dup->ld_mds_fid)); ++ return -EBADF; ++ } ++ ++ lum = malloc(LOV_EA_MAX(lum)); ++ if (lum == NULL) { ++ log_write("%s: out of memory allocating LOV EA (%u)\n", ++ progname, LOV_EA_MAX(lum)); ++ return -ENOMEM; ++ } ++ ++ rc = llapi_file_get_stripe(path, lum); ++ if (rc < 0) { ++ log_write("%s: unable to get LOV EA on %s: %s\n", ++ progname, path, strerror(-rc)); ++ goto out; ++ } ++ ++ if (lum->lmm_pattern != LOV_PATTERN_RAID0) { ++ log_write("%s: unknown LOV stripe pattern %#08x\n", ++ progname, lum->lmm_pattern); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ if (lum->lmm_magic == LOV_USER_MAGIC_V1) { ++ loi = lum->lmm_objects; ++ } else if (lum->lmm_magic == LOV_USER_MAGIC_V3) { ++ loi = ((struct lov_user_md_v3 *)lum)->lmm_objects; ++ } else { ++ log_write("%s: unknown LOV magic %#08x\n", ++ progname, lum->lmm_magic); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ /* Verify that the object in question is still in the file */ ++ for (i = 0; i < lum->lmm_stripe_count; i++, loi++) { ++ if (loi->l_ost_idx == dup->ld_ost_idx && ++ loi->l_object_id == dup->ld_oi.oi_id && ++ loi->l_object_seq == dup->ld_oi.oi_seq) ++ break; ++ } ++ ++ if (i == lum->lmm_stripe_count) { ++ log_write("%s: cannot find object %u:"DOIF" in\n\t%s\n", ++ progname, dup->ld_ost_idx, POIF(&dup->ld_oi), path); ++ rc = -EBADF; ++ goto out; ++ } ++ ++out: ++ free(lum); ++ return rc; ++} ++ ++#ifndef HAVE_LLAPI_CANCEL_OSC_LOCKS ++#define NAMESPACES "/proc/fs/lustre/ldlm/namespaces" ++void llapi_cancel_osc_locks(const char *mnt_path) ++{ ++ DIR *namespaces; ++ char path[PATH_MAX]; ++ struct dirent *dent; ++ int rc, fd; ++ ++ namespaces = opendir(NAMESPACES); ++ if (namespaces == NULL) { ++ rc = -errno; ++ log_write("%s: error opening %s: %s\n", ++ progname, NAMESPACES, strerror(-rc)); ++ return; ++ } ++ ++ while ((dent = readdir(namespaces)) != NULL) { ++ if (strcmp(dent->d_name, ".") == 0 || ++ strcmp(dent->d_name, "..") == 0) ++ continue; ++ ++ if (strstr(dent->d_name, "osc") == NULL && ++ strstr(dent->d_name, "OSC") == NULL) ++ continue; ++ ++ snprintf(path, sizeof(path) - 1, "%s/%s/lru_size", ++ NAMESPACES, dent->d_name); ++ ++ fd = open(path, O_WRONLY); ++ if (fd < 0) { ++ log_write("%s: error opening %s to cancel locks: %s\n", ++ progname, path, strerror(errno)); ++ continue; ++ } ++ VERBOSE(3, "clearning locks in %s\n", path); ++ write(fd, "clear", 6); ++ close(fd); ++ } ++ ++ closedir(namespaces); ++} ++#endif ++ ++/* Remove inodes from the client cache to avoid hitting an LASSERTF() on ++ * the client if it tries to attach two inodes to the same object */ ++static void lfsck_drop_caches(void) ++{ ++ sync(); ++ llapi_cancel_osc_locks(mnt_path); ++ system("echo 3 > /proc/sys/vm/drop_caches"); ++} ++ ++/* Duplicate an object that is referenced by multiple files and point one ++ * of the files to use the duplicated object */ ++static int lfsck_fix_duplicate(struct lfsck_saved_duplicates *dup, ++ DB *mds_direntdb, const char *path) ++{ ++ char path_tmp[PATH_MAX] = { 0 }; ++ char tmp[PATH_MAX * 2 + 10] = { 0 }; ++ const char *base; ++ int rc; ++ ++ lfsck_drop_caches(); ++ ++ if (!lfsck_create) { ++ VERBOSE(1, "%s: [%u]: not duplicating FID "DFID ++ " object "DOIF" by request\n on\t%s\n", ++ progname, dup->ld_ost_idx, PFID(&dup->ld_mds_fid), ++ POIF(&dup->ld_oi), path); ++ return 0; ++ } ++ ++ rc = lfsck_validate_duplicate(dup, path); ++ if (rc < 0) ++ goto out; ++ ++ snprintf(path_tmp, sizeof(path_tmp) - 1, "%s.lfsck_tmp", path); ++ snprintf(tmp, sizeof(tmp) - 1, "cp -p '%s' '%s'", path, path_tmp); ++ VERBOSE(2, "%s\n", tmp); ++ rc = system(tmp); ++ if (rc) { ++ rc = -errno; ++ log_write("%s: duplicating object for %u:"DOIF" %s: %s\n", ++ progname, dup->ld_ost_idx, POIF(&dup->ld_oi), ++ path, strerror(-rc)); ++ goto out; ++ } ++ ++ base = strrchr(path, '/'); ++ if (base == NULL) ++ base = path; ++ else ++ base++; ++ ++ rc = asprintf(&dup->ld_link, "%s/%u-"DOIF"-"DFID":%s", dupedir, ++ dup->ld_ost_idx, POIF(&dup->ld_oi), ++ PFID(&dup->ld_mds_fid), base); ++ if (rc < 0) { ++ rc = -errno; ++ goto out; ++ } ++ ++ VERBOSE(2, "ln %s %s\n", path, dup->ld_link); ++ rc = link(path, dup->ld_link); ++ if (rc) { ++ rc = -errno; ++ log_write("%s: error linking %s to %s: %s\n", ++ progname, path, dup->ld_link, strerror(-rc)); ++ free(dup->ld_link); ++ dup->ld_link = NULL; ++ goto out; ++ } ++ ++ VERBOSE(2, "rename %s %s\n", path_tmp, path); ++ rc = rename(path_tmp, path); ++ if (rc) { ++ rc = -errno; ++ log_write("%s: error renaming %s to %s: %s\n", ++ progname, path_tmp, path, strerror(-rc)); ++ free(dup->ld_link); ++ dup->ld_link = NULL; ++ } else { ++ log_write("%s: [%u]: fixed duplicate FID "DFID" object " ++ DOIF":\n\t%s\n", progname, dup->ld_ost_idx, ++ PFID(&dup->ld_mds_fid), POIF(&dup->ld_oi), path); ++ } ++out: ++ if (rc) { ++ VERBOSE(2, "unlink %s\n", path_tmp); ++ if (unlink(path_tmp)) ++ log_write("%s: unlink %s failed: %s\n", progname, ++ path_tmp, strerror(errno)); ++ } ++ ++ return rc; ++} ++ ++/* ++ * Check for files found that reference the same ost objects ++ * (found in pass1) and repair now if necessary ++ */ ++int lfsck_run_pass4(DB *mds_direntdb) ++{ ++ char tmp[PATH_MAX + 512]; ++ char path[PATH_MAX]; ++ int failed_get_path, fixed_dup; ++ int i, j; ++ ++ log_write("lfsck: pass4: check for %u duplicate object references\n", ++ lfsck_dup_saved); ++ if (lfsck_dup_saved == 0) { ++ log_write("lfsck: pass4 OK (no duplicates)\n"); ++ return(0); ++ } ++ ++ do { ++ struct lu_fid *mds_fid; ++ ++ failed_get_path = 0; ++ fixed_dup = 0; ++ ++ lfsck_drop_caches(); ++ ++ for (i = 0; i < lfsck_dup_saved; i++) { ++ mds_fid = &lfsck_duplicates[i].ld_mds_fid; ++ if (mds_fid->f_oid == 0) ++ continue; ++ ++ if (lfsck_get_path(mds_fid, mds_direntdb, path, ++ sizeof(path))) { ++ failed_get_path++; ++ continue; ++ } ++ if (lfsck_fix_duplicate(&lfsck_duplicates[i], ++ mds_direntdb, path)) { ++ fix_failed++; ++ continue; ++ } ++ ++ fixed++; ++ fixed_dup++; ++ ++ /* don't duplicate a file multiple times even if it has ++ * multiple shared objects */ ++ for (j = i + 1; j < lfsck_dup_saved; j++) { ++ if (lfsck_fidcmp(&lfsck_duplicates[j].ld_mds_fid, ++ mds_fid) == 0) ++ lfsck_duplicates[j].ld_mds_fid.f_oid =0; ++ } ++ lfsck_duplicates[i].ld_mds_fid.f_oid = 0; ++ } ++ } while (failed_get_path && fixed_dup); ++ ++ for (i = 0; i < lfsck_dup_saved; i++) { ++ lfsck_drop_caches(); ++ ++ if (!lfsck_duplicates[i].ld_link) ++ continue; ++ ++ if (unlink(lfsck_duplicates[i].ld_link)) ++ log_write("%s: failed to unlink %s: %s\n", progname, ++ lfsck_duplicates[i].ld_link, strerror(errno)); ++ else ++ log_write("%s: %s unlinked\n", progname, ++ lfsck_duplicates[i].ld_link); ++ free(lfsck_duplicates[i].ld_link); ++ lfsck_duplicates[i].ld_link = NULL; ++ } ++ ++ snprintf(tmp, sizeof(tmp) - 1, "rm -rvf '%s'", dupedir); ++ VERBOSE(1, "%s\n", tmp); ++ system(tmp); ++ ++ log_write("lfsck: pass4 finished\n"); ++ ++ return(0); ++} ++ ++/* ++ * This is a placeholder to check for filesize correctness no fixup is in ++ * place right now since file size is still obtained from osts ++ */ ++int lfsck_run_pass5(DB *mds_direntdb, DB *mds_sizeinfodb) ++{ ++ int rc = 0; ++#ifdef LFSCK_CHECK_SIZE ++ struct lfsck_mds_szinfo mds_szinfo1; ++ char path[PATH_MAX]; ++ struct stat64 statbuf; ++ DBT key,data; ++ DBC *dbcp; ++ ++ log_write("lfsck: pass5: file size correctness\n"); ++ ++ if ((rc = mds_sizeinfodb->cursor(mds_sizeinfodb, NULL, &dbcp, 0)) != 0){ ++ log_write("%s: error acquiring cursor for database: %s\n", ++ progname, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ data.data = &mds_szinfo1; ++ data.size = data.ulen = sizeof(mds_szinfo1); ++ data.flags = DB_DBT_USERMEM; ++ while ((rc = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ letocpu_mds_szinfo(&mds_szinfo1); ++ ++ if (mds_szinfo1.mds_size != mds_szinfo1.mds_calc_size) { ++ if (lfsck_get_path(mds_szinfo1.mds_fid, mds_direntdb, ++ path, sizeof(path))) { ++ log_write("%s: failed to get path and update " ++ "size for fid "LPU64"\n", ++ mds_szinfo1.mds_fid); ++ fix_failed++; ++ continue; ++ } ++ ++ if (stat64(path, &statbuf)) { ++ log_write("%s: pass5: failed to stat %s\n", ++ progname, path); ++ fix_failed++; ++ continue; ++ } ++ if (statbuf.st_size == mds_szinfo1.mds_calc_size) { ++ VERBOSE(2, "%s: %s really has right size\n", ++ progname, path); ++ } else { ++ log_write("%s: %s size "LPU64" != "LPU64"\n", ++ progname, path, statbuf.st_size, ++ mds_szinfo1.mds_calc_size); ++ fixed++; ++ } ++ } ++ } ++ if (rc != DB_NOTFOUND) { ++ log_write("%s: error getting next element in db: %s\n", ++ progname, db_strerror(rc)); ++ rc = -EINVAL; ++ goto out; ++ } ++ rc = 0; ++ log_write("%s: pass5 finished\n", progname); ++out: ++ dbcp->c_close(dbcp); ++#endif /* LFSCK_CHECK_SIZE */ ++ return rc; ++} ++ ++int get_response() ++{ ++ char yes[] = "Yy"; ++ char no[] = "Nn"; ++ char c; ++ int rc = -1; ++ ++ while (1) { ++ c = getchar(); ++ if ( c == EOF) ++ break; ++ ++ if (strchr(yes, c)) { ++ rc = 1; ++ break; ++ } ++ ++ if (strchr(no, c)) { ++ rc = 0; ++ break; ++ } ++ } ++ return(rc); ++} ++ ++/* Starting point for each thread */ ++void *lfsck_start_thread(void *arg) ++{ ++ struct lfsck_thread_info *tinfo = (struct lfsck_thread_info *)arg; ++ int i,rc; ++ ++ tinfo->status = 0; ++ pthread_mutex_lock(&init_mutex); ++ if (all_started) ++ pthread_mutex_unlock(&init_mutex); ++ else ++ pthread_cond_wait(&init_cond, &init_mutex); ++ ++ if (!all_started) ++ pthread_exit(NULL); ++ for (i = tinfo->start_ost_idx; i < tinfo->end_ost_idx; i++) { ++ rc = run_test(i, tinfo->mds_hdr, tinfo->mds_direntdb, ++ tinfo->mds_sizeinfodb); ++ if (rc) { ++ log_write("lfsck: ost_idx %d: error running check\n",i); ++ tinfo->status = rc; ++ } ++ } ++ pthread_exit(NULL); ++} ++ ++/* Start threads and run filesystem checks and repair */ ++int lfsck_run_checks() ++{ ++ struct lfsck_mds_hdr *mds_hdr = NULL; ++ struct lfsck_thread_info *tinfo = NULL; ++ pthread_t *threads = NULL; ++ int rc, i; ++ DB *mds_direntdb = NULL; ++ DB *mds_hdrdb = NULL; ++ DB *mds_sizeinfodb = NULL; ++ DBT key, data; ++ int num_osts; ++ ++ rc = lfsck_opendb(mds_file, MDS_HDR, &mds_hdrdb, 0, 0, 0); ++ if (rc != 0) { ++ log_write("%s: error opening mds_hdr in %s: rc %d\n", ++ mds_file, rc); ++ return(-EINVAL); ++ } ++ mds_hdr = malloc(sizeof(*mds_hdr)); ++ if (mds_hdr == NULL) { ++ log_write("%s: out of memory allocating DB header (%u)\n", ++ progname, sizeof(*mds_hdr)); ++ rc = -ENOMEM; ++ goto out; ++ } ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ mds_hdr->mds_magic = MDS_MAGIC; ++ key.data = &mds_hdr->mds_magic; ++ key.size = sizeof(mds_hdr->mds_magic); ++ data.data = mds_hdr; ++ data.size = sizeof(*mds_hdr); ++ data.ulen = sizeof(*mds_hdr); ++ data.flags = DB_DBT_USERMEM; ++ rc = mds_hdrdb->get(mds_hdrdb, NULL, &key, &data, 0); ++ if (rc != 0) { ++ log_write("%s: error getting mds_hdr info %s: %s\n", ++ progname, mds_file, db_strerror(rc)); ++ goto out; ++ } ++ letocpu_mds_hdr(mds_hdr); ++ ++ rc = lfsck_opendb(mds_file, MDS_DIRINFO, &mds_direntdb, 0, 0, 0); ++ if (rc != 0) { ++ log_write("%s: error opening dirinfo db %s\n", ++ progname, mds_file); ++ goto out; ++ } ++ ++ rc = lfsck_opendb(mds_file, MDS_SIZEINFO, &mds_sizeinfodb, 0, 0, 0); ++ if (rc != 0) { ++ log_write("%s: error opening sizeinfo db %s\n", ++ progname, mds_file); ++ goto out; ++ } ++ ++ if (lov_tgt_count > mds_hdr->mds_num_osts) { ++ fprintf(stderr, "%s: number of osts in lov (%u) > " ++ "num referenced in mds (%u) (new ost or " ++ "empty filesystem?)\n", progname, ++ lov_tgt_count, mds_hdr->mds_num_osts); ++ fprintf(stderr, "Do you wish to continue? (y/n)\n"); ++ if ((rc = get_response()) != 1) { ++ log_write("%s: exiting \n", progname); ++ goto out; ++ } ++ fprintf(stderr, "\n"); ++ ++ num_osts = lov_tgt_count; ++ } else { ++ num_osts = mds_hdr->mds_num_osts; ++ } ++ if (num_threads > num_osts) ++ num_threads = num_osts; ++ ++ tinfo = calloc(num_threads, sizeof(*tinfo)); ++ if (tinfo == NULL) { ++ log_write("%s: out of memory for thread info\n", progname); ++ rc = -ENOMEM; ++ goto out; ++ } ++ threads = calloc(num_threads, sizeof(pthread_t)); ++ if (threads == NULL) { ++ log_write("%s: out of memory for threads\n", progname); ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ all_started = 0; ++ for (i = 0; i < num_threads; i++) { ++ __u32 end_ost_idx; ++ __u32 chunk; ++ ++ chunk = num_osts / num_threads; ++ if (num_osts % num_threads) ++ chunk++; ++ tinfo[i].mds_hdr = mds_hdr; ++ tinfo[i].mds_direntdb = mds_direntdb; ++ tinfo[i].mds_sizeinfodb = mds_sizeinfodb; ++ tinfo[i].status = 0; ++ tinfo[i].start_ost_idx = (chunk) * i; ++ end_ost_idx = (chunk) * (i + 1); ++ end_ost_idx = end_ost_idx > num_osts ? ++ num_osts : end_ost_idx; ++ tinfo[i].end_ost_idx = end_ost_idx; ++ rc = pthread_create(&threads[i], NULL, lfsck_start_thread, ++ &tinfo[i]); ++ if (rc) { ++ log_write("%s: error starting thread waiting for other" ++ " threads to exit\n", progname); ++ pthread_mutex_lock(&init_mutex); ++ pthread_cond_broadcast(&init_cond); ++ pthread_mutex_unlock(&init_mutex); ++ for (--i; i >= 0; i--) { ++ pthread_cancel(threads[i]); ++ } ++ rc = -ENOMEM; ++ goto out; ++ } ++ } ++ pthread_mutex_lock(&init_mutex); ++ all_started = 1; ++ pthread_cond_broadcast(&init_cond); ++ pthread_mutex_unlock(&init_mutex); ++ for (i = 0; i < num_threads; i++) { ++ rc = pthread_join(threads[i], NULL); ++ if (tinfo[i].status) { ++ log_write("%s: error running thread %u\n", progname, i); ++ rc = -EINVAL; ++ } ++ } ++ ++ rc = lfsck_run_pass4(mds_direntdb); ++ if (rc != 0) ++ goto out; ++ ++ rc = lfsck_run_pass5(mds_direntdb, mds_sizeinfodb); ++ ++out: ++ if (threads) ++ free(threads); ++ if (tinfo) ++ free(tinfo); ++ if (mds_hdr) ++ free(mds_hdr); ++ if (mds_direntdb) ++ mds_direntdb->close(mds_direntdb, 0); ++ if (mds_hdrdb) ++ mds_hdrdb->close(mds_hdrdb, 0); ++ if (mds_sizeinfodb) ++ mds_sizeinfodb->close(mds_sizeinfodb, 0); ++ ++ return(rc); ++} ++ ++int create_lostandfound() ++{ ++ struct stat statbuf; ++ ++ snprintf(lostandfounddir, PATH_MAX - 1, "%s/lost+found", mnt_path); ++ lostandfounddir[PATH_MAX - 1] = '\0'; ++ ++ VERBOSE(2, "%s: creating %s\n", progname, lostandfounddir); ++ if (mkdir(lostandfounddir, 0700)) { ++ if (errno != EEXIST) { ++ fprintf(stderr, "%s: error creating %s: %s\n", ++ progname, lostandfounddir, strerror(errno)); ++ return(-errno); ++ } ++ ++ if (stat(lostandfounddir, &statbuf)) { ++ fprintf(stderr, "%s: error stat %s: %s\n", ++ progname, lostandfounddir, strerror(errno)); ++ return(-errno); ++ } ++ ++ if (!S_ISDIR(statbuf.st_mode)) { ++ fprintf(stderr, "%s: error %s is not a directory\n", ++ progname, lostandfounddir); ++ return(-EINVAL); ++ } ++ } ++ ++ snprintf(dupedir, sizeof(dupedir), "%s/duplicates", lostandfounddir); ++ dupedir[PATH_MAX - 1] = '\0'; ++ ++ VERBOSE(2, "%s: creating %s\n", progname, dupedir); ++ if (mkdir(dupedir, 0700)) { ++ if (errno != EEXIST) { ++ fprintf(stderr, "%s: error creating %s: %s\n", ++ progname, dupedir, strerror(errno)); ++ return(-errno); ++ } ++ ++ if (stat(lostandfounddir, &statbuf)) { ++ fprintf(stderr, "%s: error stat %s: %s\n", ++ progname, dupedir, strerror(errno)); ++ return(-errno); ++ } ++ ++ if (!S_ISDIR(statbuf.st_mode)) { ++ fprintf(stderr, "%s: error %s is not a directory\n", ++ progname, dupedir); ++ return(-EINVAL); ++ } ++ } ++ ++ return(0); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ uid_t myuid; ++ int i; ++ ++ fprintf(stderr, "lfsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); ++ ++ if (parse_args(argc, argv)) { ++ usage(); ++ exit(16); ++ } ++ ++ myuid = getuid(); ++ if (myuid != 0 && !lfsck_force) { ++ fprintf(stderr, "%s: can only be run by root user\n", progname); ++ exit(16); ++ } ++ ++ log_open(); ++ ++ if ((lfsck_save || lfsck_delete) && create_lostandfound() != 0) { ++ log_write("%s: failed to create lost+found directory\n", ++ progname); ++ log_close(-1); ++ exit(8); ++ } ++ ++ if (get_lov_config()) { ++ log_close(-1); ++ exit(8); ++ } ++ ++ if (lfsck_run_checks()) ++ log_close(-1); ++ ++ if (mds_file) ++ free(mds_file); ++ for (i = 0; i < LOV_MAX_OSTS; i++) { ++ if (ost_files[i]) ++ free(ost_files[i]); ++ } ++ if (lfsck_duplicates) ++ free(lfsck_duplicates); ++ ++ log_close(0); ++ if (fix_failed) { ++ fprintf(stderr, "%s: exit with %u unfixed errors\n", ++ progname, fix_failed); ++ return 2; ++ } else { ++ printf("%s: fixed %u errors\n", progname, fixed); ++ return !!fixed; ++ } ++} +Index: e2fsprogs/lib/ext2fs/lfsck.h +=================================================================== +--- /dev/null ++++ e2fsprogs/lib/ext2fs/lfsck.h +@@ -0,0 +1,322 @@ ++#undef PACKAGE ++#undef VERSION ++#ifndef LFSCK_H ++#define LFSCK_H ++ ++#ifdef ENABLE_LFSCK ++/* These are unfortunately needed for lustre_user.h to be usable */ ++#define CLASSERT(cond) ({ switch(42) { case (cond): case 0: break; } }) ++#define LASSERT(cond) do { } while (0) ++#define LASSERTF(cond, fmt, a) do { } while (0) ++ ++#include "../lib/ext2fs/ext2fsP.h" ++#include ++#include ++ ++#ifdef HAVE_LIMITS_H ++#include ++#endif ++ ++#include ++ ++#ifndef LPU64 ++#if (__WORDSIZE == 32) || defined(__x86_64__) ++# define LPU64 "%llu" ++# define LPD64 "%lld" ++# define LPX64 "%#llx" ++# define LPSZ "%u" ++# define LPSSZ "%d" ++#elif (__WORDSIZE == 64) ++# define LPU64 "%lu" ++# define LPD64 "%ld" ++# define LPX64 "%#lx" ++# define LPSZ "%lu" ++# define LPSSZ "%ld" ++#endif ++#endif /* !LPU64 */ ++ ++/* Compatibility to allow 1.x lustre_user.h to be used with 2.x fields. ++ * There are also structures from lustre_idl.h below that are defined in ++ * terms of the 2.x field names that would have to be handled for 1.x if ++ * that lustre_idl.h was ever fixed to allow inclusion from userspace. */ ++#ifndef IDENTITY_DOWNCALL_MAGIC ++#define l_object_seq l_object_gr /* for lov_ost_data_v1 */ ++#define lmm_object_seq lmm_object_gr /* for lov_mds_md_v1/3 */ ++#endif /* IDENTITY_DOWNCALL_MAGIC */ ++ ++/* Unfortunately, neither the 1.8 or 2.x lustre_idl.h file is suitable ++ * for inclusion by userspace programs because of external dependencies. ++ * Define the minimum set of replacement functions here until that is fixed. */ ++#ifndef HAVE_LUSTRE_LUSTRE_IDL_H ++#define fid_seq(fid) ((fid)->f_seq) ++#define fid_oid(fid) ((fid)->f_oid) ++#define fid_ver(fid) ((fid)->f_ver) ++ ++#ifndef LL_IOC_PATH2FID ++#define DFID "["LPX64":0x%x:0x%x]" ++#define PFID(fid) \ ++ fid_seq(fid), \ ++ fid_oid(fid), \ ++ fid_ver(fid) ++#define llapi_get_connect_flags(mnt, flags) (0) ++struct lu_fid { ++ __u64 f_seq; ++ __u32 f_oid; ++ __u32 f_ver; ++}; ++#endif ++ ++#define OBD_CONNECT_FID 0x40000000ULL ++ ++struct lustre_mdt_attrs { ++ __u32 lma_compat; ++ __u32 lma_incompat; ++ struct lu_fid lma_self_fid; ++ __u64 lma_flags; ++ __u64 lma_ioepoch; ++ __u64 lma_som_size; ++ __u64 lma_som_blocks; ++ __u64 lma_som_mountid; ++}; ++ ++struct ost_id { ++ __u64 oi_id; ++ __u64 oi_seq; ++}; ++ ++enum fid_seq { ++ FID_SEQ_IGIF = 12ULL, ++ FID_SEQ_IGIF_MAX = 0x0ffffffffULL, ++ FID_SEQ_IDIF = 0x100000000ULL, ++}; ++ ++static inline int fid_seq_is_igif(const __u64 seq) ++{ ++ return seq >= FID_SEQ_IGIF && seq <= FID_SEQ_IGIF_MAX; ++} ++ ++static inline int fid_is_igif(const struct lu_fid *fid) ++{ ++ return fid_seq_is_igif(fid_seq(fid)); ++} ++ ++/* convert an OST objid + index into an IDIF FID SEQ number */ ++static inline __u64 fid_idif_seq(__u64 id, __u32 ost_idx) ++{ ++ return FID_SEQ_IDIF | (ost_idx << 16) | ((id >> 32) & 0xffff); ++} ++ ++/* convert ost_id from 1.x compatible OST protocol into FID for future usage */ ++static inline void ostid_idif_unpack(struct ost_id *oi, struct lu_fid *fid, ++ __u32 idx) ++{ ++ fid->f_seq = fid_idif_seq(oi->oi_id, idx); ++ fid->f_oid = oi->oi_id; /* truncate to 32 bits by assignment */ ++ fid->f_ver = oi->oi_id >> 48; /* in theory, not currently used */ ++} ++#endif /* HAVE_LUSTRE_LUSTRE_IDL_H */ ++ ++#ifndef DOIF ++#define DOIF LPU64":"LPU64 ++#define POIF(oi) (oi)->oi_seq, (oi)->oi_id ++#endif ++ ++/* Get O/R or O/0 dir */ ++#define OBJECT_DIR "O" ++#define OBJECT_DIR_V1 "R" ++#define OBJECT_DIR_V2 "0" ++#define LOG_DIR "1" ++#define PENDING_DIR "PENDING" ++#define OBJECTS "OBJECTS" ++#define CATLIST "CATALOGS" ++#define LAST_ID "LAST_ID" ++#define LAST_RCVD "last_rcvd" ++#define LOV_OBJID "lov_objid" ++ ++#ifndef EXT3_XATTR_INDEX_TRUSTED /* temporary until we hit l28 kernel */ ++#define EXT3_XATTR_INDEX_TRUSTED 4 ++#endif ++#ifndef EXT3_XATTR_INDEX_LUSTRE ++#define EXT3_XATTR_INDEX_LUSTRE 5 ++#endif ++#define XATTR_LUSTRE_MDS_LOV_EA "lov" ++#define XATTR_LUSTRE_MDT_LMA_EA "lma" ++ ++/* Database names */ ++#define MDS_HDR "mdshdr" ++#define MDS_DIRINFO "mds_dirinfo" ++#define MDS_SIZEINFO "mds_sizeinfo" ++#define MDS_OSTDB "mds_ostdb" ++#define OST_HDR "osthdr" ++#define OST_OSTDB "ost_db" ++ ++#define MDS_MAGIC 0xDBABCD01 ++#define OST_MAGIC 0xDB123402 ++ ++#define OBD_COMPAT_OST 0x00000002 /* this is an OST (1.6+) */ ++#define OBD_COMPAT_MDT 0x00000004 /* this is an MDT (1.6+) */ ++ ++#define OBD_INCOMPAT_OST 0x00000002 /* this is an OST (1.8+) */ ++#define OBD_INCOMPAT_MDT 0x00000004 /* this is an MDS (1.8+) */ ++ ++#define LOV_MAX_OSTS 2048 /* Arbitrary limit, can be increased */ ++#define LOV_EA_SIZE(lum, num) (sizeof(*lum) + num * sizeof(*lum->lmm_objects)) ++#define LOV_EA_MAX(lum) LOV_EA_SIZE(lum, LOV_MAX_OSTS) ++ ++/*XXX*/ ++#define STRTOUL strtoul ++#define STRTOUL_MAX ULONG_MAX ++ ++#define HASH_SIZE 131072 ++ ++struct lustre_server_data { ++ __u8 lsd_uuid[40]; /* server UUID */ ++ __u64 lsd_last_transno; /* last completed transaction ID */ ++ __u64 lsd_compat14; /* reserved - compat with old last_rcvd */ ++ __u64 lsd_mount_count; /* incarnation number */ ++ __u32 lsd_feature_compat; /* compatible feature flags */ ++ __u32 lsd_feature_rocompat;/* read-only compatible feature flags */ ++ __u32 lsd_feature_incompat;/* incompatible feature flags */ ++ __u32 lsd_server_size; /* size of server data area */ ++ __u32 lsd_client_start; /* start of per-client data area */ ++ __u16 lsd_client_size; /* size of per-client data area */ ++ __u16 lsd_subdir_count; /* number of subdirectories for objects */ ++ __u64 lsd_catalog_oid; /* recovery catalog object id */ ++ __u32 lsd_catalog_ogen; /* recovery catalog inode generation */ ++ __u8 lsd_peeruuid[40]; /* UUID of LOV/OSC associated with MDS */ ++ __u32 lsd_ost_index; /* index number of OST in LOV */ ++ __u32 lsd_mdt_index; /* index number of MDT in LMV */ ++}; ++ ++struct lfsck_mds_hdr { ++ __u64 mds_magic; ++ __u64 mds_flags; ++ __u64 mds_max_files; ++ __u32 mds_num_osts; ++ __u32 mds_unused; ++ __u64 mds_max_ost_id[LOV_MAX_OSTS]; ++ struct obd_uuid mds_uuid; ++ struct obd_uuid mds_ost_info[LOV_MAX_OSTS]; ++}; ++ ++struct lfsck_ost_hdr { ++ __u64 ost_magic; ++ __u64 ost_flags; ++ __u64 ost_num_files; ++ __u64 ost_last_id; ++ __u32 ost_index; ++ __u32 ost_unused; ++ struct obd_uuid ost_mds_uuid; ++ struct obd_uuid ost_uuid; ++}; ++ ++struct lfsck_mds_dirent { ++ struct lu_fid mds_dirfid; ++ struct lu_fid mds_fid; ++}; ++ ++struct lfsck_mds_szinfo { ++ __u64 mds_fid; ++ __u64 mds_seq; ++ __u64 mds_size; ++ __u64 mds_calc_size; ++ __u32 mds_stripe_size; ++ __u32 mds_stripe_pattern; ++ __u16 mds_stripe_count; ++ __u16 mds_stripe_start; ++}; ++ ++struct lfsck_mds_objent { ++ struct lu_fid mds_fid; ++ struct ost_id mds_oi; ++ __u32 mds_ostidx; ++ __u32 mds_ostoffset; ++}; ++ ++struct lfsck_ost_objent { ++ struct ost_id ost_oi; ++ __u64 ost_size; ++ __u64 ost_bytes; ++}; ++ ++struct lfsck_ofile_ctx { ++ DB *dbp; ++ __u64 max_id; ++ int have_max_id; ++}; ++ ++struct lfsck_outdb_info { ++ __u32 ost_count; ++ int have_ost_count; ++ DB *mds_sizeinfo_dbp; ++ struct lfsck_ofile_ctx *ofile_ctx; ++}; ++ ++/* pass6.c */ ++#ifdef FSCK_OK /* compiling for e2fsck or lfsck */ ++extern int e2fsck_lfsck_find_ea(e2fsck_t ctx, struct ext2_inode_large *inode, ++ struct ext2_ext_attr_entry *entry, void *value, ++ struct lov_user_md_v1 **lmm, ++ struct lustre_mdt_attrs **lma); ++extern int e2fsck_lfsck_save_ea(e2fsck_t ctx, ext2_ino_t ino, __u32 generation, ++ struct lov_user_md_v1 *lmm, ++ struct lustre_mdt_attrs *lma); ++extern int e2fsck_lfsck_flush_ea(e2fsck_t ctx); ++extern int e2fsck_lfsck_cleanupdb(e2fsck_t ctx); ++extern int e2fsck_lfsck_remove_pending(e2fsck_t ctx, char *block_buf); ++ ++/* lfsck_common.c */ ++extern char *my_dirname(char *path); ++extern const char *my_basename(const char *path); ++extern int lfsck_create_dbenv(const char *progname); ++extern int lfsck_opendb(const char *fname, const char *dbname, DB **dbpp, ++ int allow_dup, int keydata_size, int num_files); ++extern void cputole_mds_hdr(struct lfsck_mds_hdr *mds_hdr); ++extern void letocpu_mds_hdr(struct lfsck_mds_hdr *mds_hdr); ++extern void cputole_ost_hdr(struct lfsck_ost_hdr *ost_hdr); ++extern void letocpu_ost_hdr(struct lfsck_ost_hdr *ost_hdr); ++extern void cputole_fid(struct lu_fid *fid); ++extern void letocpu_fid(struct lu_fid *fid); ++extern void cputole_mds_dirent(struct lfsck_mds_dirent *mds_dirent); ++extern void letocpu_mds_dirent(struct lfsck_mds_dirent *mds_dirent); ++extern void cputole_mds_szinfo(struct lfsck_mds_szinfo *mds_szinfo); ++extern void letocpu_mds_szinfo(struct lfsck_mds_szinfo *mds_szinfo); ++extern void cputole_mds_objent(struct lfsck_mds_objent *mds_objent); ++extern void letocpu_mds_objent(struct lfsck_mds_objent *mds_objent); ++extern void cputole_ost_objent(struct lfsck_ost_objent *ost_objent); ++extern void letocpu_ost_objent(struct lfsck_ost_objent *ost_objent); ++extern void letocpu_lov_user_md(struct lov_user_md *lmm); ++ ++int lfsck_get_fid(ext2_filsys fs, ino_t ino, struct lu_fid *fid); ++int lfsck_is_dirfid_root(const struct lu_fid *dirfid); ++int lfsck_fidcmp(const struct lu_fid *fid1, const struct lu_fid *fid2); ++#endif /* FSCK_ON */ ++ ++#define MDS_START_DIRENT_TABLE sizeof(struct lfsck_mds_hdr) ++ ++#define MDS_START_SZINFO_TABLE(numfiles) \ ++sizeof(struct lfsck_mds_hdr) + (sizeof(struct lfsck_mds_dirent) * numfiles) ++ ++#define MDS_START_OST_TABLE_OFFSET(idx, numfiles) \ ++sizeof(struct lfsck_mds_hdr) + (sizeof(struct lfsck_mds_dirent) * numfiles) +\ ++(sizeof(struct lfsck_mds_szinfo) * numfiles) +\ ++(sizeof(struct lfsck_mds_objent_hdr) + \ ++((sizeof(struct lfsck_mds_objent) * numfiles)) * (idx)) + \ ++sizeof(struct lfsck_mds_objent_hdr) ++ ++#define MDS_START_OST_HDR_OFFSET(idx, numfiles) \ ++sizeof(struct lfsck_mds_hdr) + (sizeof(struct lfsck_mds_dirent) * numfiles) +\ ++(sizeof(struct lfsck_mds_szinfo) * numfiles) +\ ++(sizeof(struct lfsck_mds_objent_hdr) + \ ++((sizeof(struct lfsck_mds_objent) * numfiles)) * (idx)) ++ ++#define OST_START_OFFSET sizeof(struct lfsck_ost_hdr) ++ ++#else /* !ENABLE_LFSCK */ ++#define e2fsck_lfsck_found_ea(ctx, ino, inode, entry, value) (0) ++#define e2fsck_lfsck_flush_ea(ctx) (0) ++#define e2fsck_lfsck_cleanupdb(ctx) (0) ++#define e2fsck_lfsck_remove_pending(ctx, block_buf) (0) ++#endif /* ENABLE_LFSCK */ ++ ++#endif /* LFSCK_H */ +Index: e2fsprogs/e2fsck/lfsck_common.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2fsck/lfsck_common.c +@@ -0,0 +1,434 @@ ++/* ++ * Copyright (c) 2004 Hewlett-Packard Co. ++ */ ++/***************************************************************************** ++ * e2fsck extentions: code for gathering data from the OST & MDT filesystems ++ * when e2fsck is run against them. The best description and knowledge of ++ * the layout and information gathered is in lfsck.h where the structures ++ * defining each entry in the tables are declared. Basically the ost file ++ * contains one table with each entry holding the object id and size. ++ * In addition there is header information at the start of the file. ++ * The MDT file contains multiple tables, one per OST. Each MDT/OST table ++ * contains an entry describing the MDT FID and the OST object associated ++ * with this FID on an OST. In addition the MDT also contains a table ++ * with the mds_fid and the FID of the containg directory. Header information ++ * for each table is also included. ++ * lfsck is run afterwards where the data gathered and stored here is cross ++ * checked to ensure consistency and correctness ++ * ++ *****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ext2fs/lfsck.h" ++ ++#ifdef ENABLE_LFSCK ++char *my_dirname(char *path) ++{ ++ ++ if (path != NULL) { ++ char *tmp = strrchr(path, '/'); ++ if (tmp != NULL) { ++ *tmp = '\0'; ++ return path; ++ } ++ } ++ ++ return "."; ++} ++ ++const char *my_basename(const char *path) ++{ ++ if (path != NULL) { ++ char *tmp = strrchr(path, '/'); ++ if (tmp != NULL) ++ return tmp + 1; ++ } ++ ++ return path; ++} ++ ++DB_ENV *dbenv; ++ ++u_int32_t lfsck_hash_raw_fn(const void *p) ++{ ++ u_int32_t *c = (u_int32_t *)p; ++ u_int32_t rc = 0; ++ ++ rc = (*c >> 7) & (HASH_SIZE - 1) ; ++ ++ return rc; ++} ++ ++ ++u_int32_t lfsck_hash_fn(DB *dbp, const void *p, u_int32_t len) ++{ ++ u_int32_t rc = 0 ; ++ ++ if (len < sizeof(u_int32_t)) { ++ printf("Hash size error"); ++ exit(128); ++ } ++ rc = lfsck_hash_raw_fn(p); ++ ++ return (rc); ++} ++ ++int lfsck_create_dbenv(const char *progname) ++{ ++ int rc; ++ size_t pagesize; ++ long pages; ++ unsigned long cachesize; ++ ++ pagesize = getpagesize(); ++ pages = sysconf(_SC_AVPHYS_PAGES); ++ ++ cachesize = ((pagesize * 3) / 4) * pages; ++ if (cachesize > 500UL * 1024 * 1024) { ++ cachesize = 500UL * 1024 * 1024; ++ } else if (cachesize < 10 * 1024 * 1024) { ++ cachesize = 10 * 1024 * 1024; ++ } ++ ++ if ((rc = db_env_create(&dbenv, 0)) != 0) { ++ fprintf(stderr, "%s: error creating dbenv: %s\n", ++ progname, db_strerror(rc)); ++ return (-EINVAL); ++ } ++ if ((rc = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) { ++ dbenv->err(dbenv, rc, "set_cachesize"); ++ dbenv->close(dbenv, 0); ++ return (-EINVAL); ++ } ++ if ((rc = dbenv->set_data_dir(dbenv, "/")) != 0) { ++ dbenv->err(dbenv, rc, "set_data_dir"); ++ dbenv->close(dbenv, 0); ++ return (-EINVAL); ++ } ++ ++ /* Open the environment with full transactional support. */ ++ if ((rc = dbenv->open(dbenv, "/tmp", DB_CREATE | DB_PRIVATE | ++ DB_INIT_MPOOL|DB_INIT_LOCK|DB_THREAD, 0)) != 0) { ++ dbenv->err(dbenv, rc, "environment open: "); ++ dbenv->close(dbenv, 0); ++ return (-EINVAL); ++ } ++ return (0); ++} ++ ++int lfsck_opendb(const char *fname, const char *dbname, DB **dbpp, ++ int allow_dup, int keydata_size, int num_files) ++{ ++ static int dbenv_set = 0; ++ DB *dbp; ++ int rc; ++ int pagesize = 512; ++ int h_ffactor = 0; ++ ++ if (!dbenv_set) { ++ if (lfsck_create_dbenv(dbname)) ++ return(-EIO); ++ dbenv_set = 1; ++ } ++ ++ rc = db_create(&dbp, dbenv, 0); ++ if (rc) { ++ fprintf(stderr, "%s: error db_create: %s\n", ++ dbname, db_strerror(rc)); ++ return(EIO); ++ } ++ ++ if ((rc = dbp->set_pagesize(dbp, pagesize)) != 0) { ++ dbp->err(dbp, rc, "set_pagesize"); ++ dbp->close(dbp, 0); ++ return(EIO); ++ } ++ ++ if ((rc = dbp->set_lorder(dbp, 1234)) != 0 ) { ++ dbp->err(dbp, rc, "set_lorder"); ++ dbp->close(dbp, 0); ++ return (EIO); ++ } ++ ++ if (keydata_size && num_files) { ++ h_ffactor = (pagesize - 32) / (keydata_size + 8); ++ if ((rc = dbp->set_h_ffactor(dbp, h_ffactor)) != 0) { ++ dbp->err(dbp, rc, "set_h_ffactor"); ++ } ++ if ((rc = dbp->set_h_nelem(dbp, num_files)) != 0 ) { ++ dbp->err(dbp, rc, "set_h_nelem"); ++ } ++ } ++ ++ if ((rc = dbp->set_h_hash(dbp, lfsck_hash_fn)) != 0 ) { ++ dbp->err(dbp, rc, "set_h_hash"); ++ dbp->close(dbp, 0); ++ return (EIO); ++ } ++ ++ if (allow_dup) { ++ if ((rc = dbp->set_flags(dbp, DB_DUPSORT)) != 0) { ++ fprintf(stderr, "Failure to allow duplicates\n"); ++ dbp->close(dbp, 0); ++ return (EIO); ++ } ++ } ++ ++#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) || (DB_VERSION_MAJOR > 4) ++ if ((rc = dbp->open(dbp, NULL, fname, dbname, DB_HASH, ++ DB_CREATE | DB_INIT_LOCK | DB_THREAD, 0664)) != 0) ++#else ++ if ((rc = dbp->open(dbp, fname, dbname, DB_HASH, ++ DB_CREATE | DB_INIT_LOCK | DB_THREAD, 0664)) != 0) ++#endif ++ { ++ dbp->err(dbp, rc, "%s:%s\n", fname, dbname); ++ dbp->close(dbp, 0); ++ return (EIO); ++ } ++ *dbpp = dbp; ++ return (0); ++} ++ ++void cputole_mds_hdr(struct lfsck_mds_hdr *mds_hdr) ++{ ++ int i, num_osts = mds_hdr->mds_num_osts; ++ mds_hdr->mds_magic = ext2fs_cpu_to_le64(mds_hdr->mds_magic); ++ mds_hdr->mds_flags = ext2fs_cpu_to_le64(mds_hdr->mds_flags); ++ mds_hdr->mds_max_files = ext2fs_cpu_to_le64(mds_hdr->mds_max_files); ++ mds_hdr->mds_num_osts = ext2fs_cpu_to_le64(mds_hdr->mds_num_osts); ++ for (i = 0; i < num_osts; i++) { ++ mds_hdr->mds_max_ost_id[i] = ++ ext2fs_cpu_to_le64(mds_hdr->mds_max_ost_id[i]); ++ } ++ ++} ++ ++void letocpu_mds_hdr(struct lfsck_mds_hdr *mds_hdr) ++{ ++ int i; ++ mds_hdr->mds_magic = ext2fs_le64_to_cpu(mds_hdr->mds_magic); ++ mds_hdr->mds_flags = ext2fs_le64_to_cpu(mds_hdr->mds_flags); ++ mds_hdr->mds_max_files = ext2fs_le64_to_cpu(mds_hdr->mds_max_files); ++ mds_hdr->mds_num_osts = ext2fs_le64_to_cpu(mds_hdr->mds_num_osts); ++ for (i = 0; i < mds_hdr->mds_num_osts; i ++) { ++ mds_hdr->mds_max_ost_id[i] = ++ ext2fs_le64_to_cpu(mds_hdr->mds_max_ost_id[i]); ++ } ++} ++ ++void cputole_ost_hdr(struct lfsck_ost_hdr *ost_hdr) ++{ ++ ost_hdr->ost_magic = ext2fs_cpu_to_le64(ost_hdr->ost_magic); ++ ost_hdr->ost_flags = ext2fs_cpu_to_le64(ost_hdr->ost_flags); ++ ost_hdr->ost_num_files = ext2fs_cpu_to_le64(ost_hdr->ost_num_files); ++ ost_hdr->ost_last_id = ext2fs_cpu_to_le64(ost_hdr->ost_last_id); ++} ++ ++void letocpu_ost_hdr(struct lfsck_ost_hdr *ost_hdr) ++{ ++ ost_hdr->ost_magic = ext2fs_le64_to_cpu(ost_hdr->ost_magic); ++ ost_hdr->ost_flags = ext2fs_le64_to_cpu(ost_hdr->ost_flags); ++ ost_hdr->ost_num_files = ext2fs_le64_to_cpu(ost_hdr->ost_num_files); ++ ost_hdr->ost_last_id = ext2fs_le64_to_cpu(ost_hdr->ost_last_id); ++} ++ ++void cputole_fid(struct lu_fid *fid) ++{ ++ fid->f_seq = ext2fs_cpu_to_le64(fid->f_seq); ++ fid->f_oid = ext2fs_cpu_to_le32(fid->f_oid); ++ fid->f_ver = ext2fs_cpu_to_le32(fid->f_ver); ++} ++ ++void letocpu_fid(struct lu_fid *fid) ++{ ++ fid->f_seq = ext2fs_le64_to_cpu(fid->f_seq); ++ fid->f_oid = ext2fs_le32_to_cpu(fid->f_oid); ++ fid->f_ver = ext2fs_le32_to_cpu(fid->f_ver); ++} ++ ++void cputole_oi(struct ost_id *oi) ++{ ++ oi->oi_id = ext2fs_cpu_to_le64(oi->oi_id); ++ oi->oi_seq = ext2fs_cpu_to_le64(oi->oi_seq); ++} ++ ++void letocpu_oi(struct ost_id *oi) ++{ ++ oi->oi_id = ext2fs_le64_to_cpu(oi->oi_id); ++ oi->oi_seq = ext2fs_le64_to_cpu(oi->oi_seq); ++} ++ ++void cputole_mds_dirent(struct lfsck_mds_dirent *mds_dirent) ++{ ++ cputole_fid(&mds_dirent->mds_dirfid); ++ cputole_fid(&mds_dirent->mds_fid); ++} ++ ++void letocpu_mds_dirent(struct lfsck_mds_dirent *mds_dirent) ++{ ++ letocpu_fid(&mds_dirent->mds_dirfid); ++ letocpu_fid(&mds_dirent->mds_fid); ++} ++ ++void cputole_mds_szinfo(struct lfsck_mds_szinfo *mds_szinfo) ++{ ++ mds_szinfo->mds_fid = ext2fs_cpu_to_le64(mds_szinfo->mds_fid); ++ mds_szinfo->mds_seq = ext2fs_cpu_to_le64(mds_szinfo->mds_seq); ++ mds_szinfo->mds_size = ext2fs_cpu_to_le64(mds_szinfo->mds_size); ++ mds_szinfo->mds_calc_size = ++ ext2fs_cpu_to_le64(mds_szinfo->mds_calc_size); ++ mds_szinfo->mds_stripe_size = ++ ext2fs_cpu_to_le32(mds_szinfo->mds_stripe_size); ++ mds_szinfo->mds_stripe_pattern = ++ ext2fs_cpu_to_le32(mds_szinfo->mds_stripe_pattern); ++ mds_szinfo->mds_stripe_count = ++ ext2fs_cpu_to_le16(mds_szinfo->mds_stripe_count); ++ mds_szinfo->mds_stripe_start = ++ ext2fs_cpu_to_le16(mds_szinfo->mds_stripe_start); ++} ++ ++void letocpu_mds_szinfo(struct lfsck_mds_szinfo *mds_szinfo) ++{ ++ mds_szinfo->mds_fid = ext2fs_le64_to_cpu(mds_szinfo->mds_fid); ++ mds_szinfo->mds_seq = ext2fs_le64_to_cpu(mds_szinfo->mds_seq); ++ mds_szinfo->mds_size = ext2fs_le64_to_cpu(mds_szinfo->mds_size); ++ mds_szinfo->mds_calc_size = ++ ext2fs_le64_to_cpu(mds_szinfo->mds_calc_size); ++ mds_szinfo->mds_stripe_size = ++ ext2fs_le32_to_cpu(mds_szinfo->mds_stripe_size); ++ mds_szinfo->mds_stripe_pattern = ++ ext2fs_le32_to_cpu(mds_szinfo->mds_stripe_pattern); ++ mds_szinfo->mds_stripe_count = ++ ext2fs_le16_to_cpu(mds_szinfo->mds_stripe_count); ++ mds_szinfo->mds_stripe_start = ++ ext2fs_le16_to_cpu(mds_szinfo->mds_stripe_start); ++} ++ ++void cputole_mds_objent(struct lfsck_mds_objent *mds_objent) ++{ ++ cputole_fid(&mds_objent->mds_fid); ++ cputole_oi(&mds_objent->mds_oi); ++ mds_objent->mds_ostidx = ext2fs_cpu_to_le32(mds_objent->mds_ostidx); ++ mds_objent->mds_ostoffset=ext2fs_cpu_to_le32(mds_objent->mds_ostoffset); ++} ++ ++void letocpu_mds_objent(struct lfsck_mds_objent *mds_objent) ++{ ++ letocpu_fid(&mds_objent->mds_fid); ++ letocpu_oi(&mds_objent->mds_oi); ++ mds_objent->mds_ostidx = ext2fs_le32_to_cpu(mds_objent->mds_ostidx); ++ mds_objent->mds_ostoffset=ext2fs_le32_to_cpu(mds_objent->mds_ostoffset); ++} ++ ++void cputole_ost_objent(struct lfsck_ost_objent *ost_objent) ++{ ++ cputole_oi(&ost_objent->ost_oi); ++ ost_objent->ost_size = ext2fs_cpu_to_le64(ost_objent->ost_size); ++ ost_objent->ost_bytes = ext2fs_cpu_to_le64(ost_objent->ost_bytes); ++} ++ ++void letocpu_ost_objent(struct lfsck_ost_objent *ost_objent) ++{ ++ letocpu_oi(&ost_objent->ost_oi); ++ ost_objent->ost_oi.oi_id = ext2fs_le64_to_cpu(ost_objent->ost_oi.oi_id); ++ ost_objent->ost_oi.oi_seq=ext2fs_le64_to_cpu(ost_objent->ost_oi.oi_seq); ++ ost_objent->ost_size = ext2fs_le64_to_cpu(ost_objent->ost_size); ++ ost_objent->ost_bytes = ext2fs_le64_to_cpu(ost_objent->ost_bytes); ++} ++ ++void letocpu_lov_user_md(struct lov_user_md *lmm) ++{ ++ struct lov_user_ost_data_v1 *loi; ++ int i; ++ ++ lmm->lmm_magic = ext2fs_le32_to_cpu(lmm->lmm_magic); ++ lmm->lmm_pattern = ext2fs_le32_to_cpu(lmm->lmm_pattern); ++ letocpu_oi((struct ost_id *)&lmm->lmm_object_id); ++ lmm->lmm_stripe_size = ext2fs_le32_to_cpu(lmm->lmm_stripe_size); ++ lmm->lmm_stripe_count = ext2fs_le16_to_cpu(lmm->lmm_stripe_count); ++ /* No swabbing needed for the lov_user_md_v3 lmm_pool_name */ ++ ++ if (lmm->lmm_magic == LOV_USER_MAGIC_V3) ++ loi = ((struct lov_user_md_v3 *)lmm)->lmm_objects; ++ else /* if (lmm->lmm_magic == LOV_USER_MAGIC_V1) */ ++ loi = lmm->lmm_objects; ++ /* If there is a bad magic, this will be found immediately in the ++ * call to lfsck_check_lov_ea() following this function. */ ++ ++ for (i = 0; i < lmm->lmm_stripe_count; i++, loi++) { ++ letocpu_oi((struct ost_id *)&loi->l_object_id); ++ loi->l_ost_gen = ext2fs_le32_to_cpu(loi->l_ost_gen); ++ loi->l_ost_idx = ext2fs_le32_to_cpu(loi->l_ost_idx); ++ } ++} ++ ++int lfsck_get_fid(ext2_filsys fs, ino_t ino, struct lu_fid *fid) ++{ ++ struct ext2_inode *inode; ++ errcode_t rc; ++ int size; ++ struct lustre_mdt_attrs lma; ++ ++ rc = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode); ++ if (rc) { ++ com_err("ext2fs_get_mem", rc, "allocating %d bytes\n", ++ EXT2_INODE_SIZE(fs->super)); ++ return rc; ++ } ++ rc = ext2fs_read_inode_full(fs, ino, inode, EXT2_INODE_SIZE(fs->super)); ++ if (rc) { ++ com_err("ext2fs_read_inode_full", rc, ++ "reading inode %lu\n", ino); ++ ext2fs_free_mem(&inode); ++ return rc; ++ } ++ rc = ext2fs_attr_get(fs, inode, EXT2_ATTR_INDEX_TRUSTED, "lma", ++ (char *)&lma, sizeof(lma), &size); ++ if (rc) { ++ if (rc != EXT2_ET_EA_NAME_NOT_FOUND && ++ rc != EXT2_ET_EA_BAD_MAGIC) { ++ ext2fs_free_mem(&inode); ++ return rc; ++ } ++ /* compose igif */ ++ fid->f_seq = ino; ++ fid->f_oid = inode->i_generation; ++ fid->f_ver = 0; ++ } else { ++ *fid = lma.lma_self_fid; ++ } ++ ext2fs_free_mem(&inode); ++ return 0; ++} ++ ++int lfsck_is_dirfid_root(const struct lu_fid *dirfid) ++{ ++ if (dirfid->f_seq == EXT2_ROOT_INO && ++ dirfid->f_oid == 0 && dirfid->f_ver == 0) ++ return 1; ++ return 0; ++} ++ ++int lfsck_fidcmp(const struct lu_fid *fid1, const struct lu_fid *fid2) ++{ ++ if (fid_is_igif(fid1) && fid_is_igif(fid2)) { ++ /* do not compare f_ver for comparing igif-s */ ++ if (fid1->f_seq == fid2->f_seq && fid1->f_oid == fid2->f_oid) ++ return 0; ++ return 1; ++ } ++ if (!fid_is_igif(fid1) && !fid_is_igif(fid2)) { ++ if (fid1->f_seq == fid2->f_seq && fid1->f_oid == fid2->f_oid && ++ fid1->f_ver == fid2->f_ver) ++ return 0; ++ return 1; ++ } ++ return 1; ++} ++#endif +Index: e2fsprogs/e2fsck/pass6.c +=================================================================== +--- /dev/null ++++ e2fsprogs/e2fsck/pass6.c +@@ -0,0 +1,1511 @@ ++/* -*- mode: c; c-basic-offset: 8; -*- ++ * vim:shiftwidth=8:tabstop=8: ++ * ++ * GPL HEADER START ++ * ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 only, ++ * as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License version 2 for more details (a copy is included ++ * in the LICENSE file that accompanied this code). ++ * ++ * ++ * Copyright (c) 2004 Hewlett-Packard Co. ++ */ ++/***************************************************************************** ++ * e2fsck extentions: code for gathering data from the ost & mds filesystems ++ * when e2fsck is run against them. The best description and knowledge of the ++ * layout and information gathered is in lfsck.h where the structures ++ * defining each entry in the tables are declared. Basically the ost file ++ * contains one table with each entry holding the object id and size. ++ * In addition there is header information at the start of the file. ++ * The mds file contains multiple tables one per ost. Each mds/ost table ++ * contains an entry describing the mds fid and the ost object associated ++ * with this fid on an ost. In addition the mds also contains a table ++ * with the mds_fid and the fid of the containg directory. Header information ++ * for each table is also included. ++ * lfsck is run afterwards where the data gathered and stored here is cross ++ * checked to ensure consistency and correctness ++ * ++ *****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include "ext2fs/ext2_fs.h" ++#include "ext2fs/ext2fs.h" ++ ++#ifdef ENABLE_LFSCK ++#include "e2fsck.h" ++#include "ext2fs/lfsck.h" ++#include "problem.h" ++//#define LOG_REMOVAL ++ ++#define VERBOSE(ctx, fmt, args...) \ ++do { if (ctx->options & E2F_OPT_VERBOSE) printf(fmt, ##args); } while (0) ++ ++#define DEBUG(ctx, fmt, args...) \ ++do { if (ctx->options & E2F_OPT_DEBUG) printf(fmt, ##args); } while (0) ++ ++struct lfsck_mds_ctx { ++ e2fsck_t ctx; ++ DB *outdb; ++ ext2_ino_t dot; ++ ext2_ino_t dotdot; ++ struct lu_fid dotfid; ++ int numfiles; ++}; ++ ++struct lfsck_ost_ctx { ++ e2fsck_t ctx; ++ DB *outdb; ++ ext2_ino_t dirinode; ++ int numfiles; ++ int status; ++ __u64 max_objid; ++}; ++ ++int e2fsck_lfsck_cleanupdb(e2fsck_t ctx) ++{ ++ int i; ++ int rc = 0; ++ DB *dbp; ++ ++ if (ctx->lfsck_oinfo == NULL) { ++ return (0); ++ } ++ ++ for (i = 0; i < ctx->lfsck_oinfo->ost_count; i++) { ++ if (ctx->lfsck_oinfo->ofile_ctx[i].dbp != NULL) { ++ dbp = ctx->lfsck_oinfo->ofile_ctx[i].dbp; ++ rc += dbp->close(dbp, 0); ++ ctx->lfsck_oinfo->ofile_ctx[i].dbp = NULL; ++ } ++ } ++ if (ctx->lfsck_oinfo->mds_sizeinfo_dbp != NULL) { ++ dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp; ++ rc += dbp->close(dbp, 0); ++ ctx->lfsck_oinfo->mds_sizeinfo_dbp = NULL; ++ } ++ if (ctx->lfsck_oinfo->ofile_ctx) ++ ext2fs_free_mem(ctx->lfsck_oinfo->ofile_ctx); ++ ext2fs_free_mem(&ctx->lfsck_oinfo); ++ ++ return(rc); ++} ++ ++/* What is the last object id for the OST on the MDS */ ++int e2fsck_get_lov_objids(e2fsck_t ctx, struct lfsck_outdb_info *outdb) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t inode; ++ ext2_file_t e2_file; ++ __u64 *lov_objids = NULL; ++ unsigned int got; ++ char *block_buf; ++ int i, rc = 0; ++ ++ block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3, ++ "block iterate buffer"); ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LOV_OBJID, ++ strlen(LOV_OBJID), block_buf, &inode); ++ if (rc) ++ goto out; ++ ++ lov_objids = e2fsck_allocate_memory(ctx, ++ sizeof(*lov_objids) * LOV_MAX_OSTS, ++ "lov_objids array"); ++ if (lov_objids == NULL) { ++ rc = ENOMEM; ++ goto out; ++ } ++ ++ rc = ext2fs_file_open(fs, inode, 0, &e2_file); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_file_read(e2_file, lov_objids, ++ sizeof(*lov_objids) * LOV_MAX_OSTS, &got); ++ rc = ext2fs_file_close(e2_file); ++ ++ outdb->ost_count = got / sizeof(*lov_objids); ++ for (i = 0; i < outdb->ost_count; i++) { ++ VERBOSE(ctx,"MDS: ost_idx %d max_id "LPU64"\n",i,lov_objids[i]); ++ outdb->ofile_ctx[i].max_id = lov_objids[i]; ++ outdb->ofile_ctx[i].have_max_id = 1; ++ outdb->have_ost_count = 1; ++ } ++ ++out: ++ ext2fs_free_mem(&block_buf); ++ if (lov_objids) ++ ext2fs_free_mem(&lov_objids); ++ if (rc) ++ VERBOSE(ctx, "MDS: unable to read lov_objids: rc %d\n", rc); ++ else ++ VERBOSE(ctx, "MDS: got %d bytes = %d entries in lov_objids\n", ++ got, outdb->ost_count); ++ return (rc); ++} ++ ++static int lfsck_write_mds_hdrinfo(e2fsck_t ctx, struct lfsck_outdb_info *outdb) ++{ ++ struct lfsck_mds_hdr mds_hdr; ++ ext2_filsys fs = ctx->fs; ++ char *mds_hdrname; ++ DB *mds_hdrdb = NULL; ++ DBT key, data; ++ int rc = 0; ++ int i; ++ ++ mds_hdrname = e2fsck_allocate_memory(ctx, PATH_MAX, ++ "mds_hdr filename"); ++ sprintf(mds_hdrname, "%s.mdshdr",ctx->lustre_mdsdb); ++ ++ if (unlink(mds_hdrname)) { ++ if (errno != ENOENT) { ++ fprintf(stderr, "Failure to remove old db file %s\n", ++ mds_hdrname); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -EINVAL; ++ } ++ } ++ ++ rc = lfsck_opendb(mds_hdrname, MDS_HDR, &mds_hdrdb, 0, 0, 0); ++ if (rc != 0) { ++ fprintf(stderr, "failure to open database for mdsdhr " ++ "info%s: %s\n", MDS_HDR, db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ ext2fs_free_mem(&mds_hdrname); ++ return(rc); ++ } ++ ++ /* read in e2fsck_lfsck_save_ea() already if we opened read/write */ ++ if (ctx->lfsck_oinfo->ost_count == 0) ++ e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo); ++ ++ memset(&mds_hdr, 0, sizeof(mds_hdr)); ++ mds_hdr.mds_magic = MDS_MAGIC; ++ mds_hdr.mds_flags = ctx->options & E2F_OPT_READONLY; ++ mds_hdr.mds_max_files = fs->super->s_inodes_count - ++ fs->super->s_free_inodes_count; ++ VERBOSE(ctx, "MDS: max_files = "LPU64"\n", mds_hdr.mds_max_files); ++ mds_hdr.mds_num_osts = ctx->lfsck_oinfo->ost_count; ++ VERBOSE(ctx, "MDS: num_osts = %u\n", mds_hdr.mds_num_osts); ++ for (i = 0; i < mds_hdr.mds_num_osts; i++) { ++ mds_hdr.mds_max_ost_id[i] = ++ ctx->lfsck_oinfo->ofile_ctx[i].max_id; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_hdr.mds_magic; ++ key.size = sizeof(mds_hdr.mds_magic); ++ cputole_mds_hdr(&mds_hdr); ++ data.data = &mds_hdr; ++ data.size = sizeof(mds_hdr); ++ rc = mds_hdrdb->put(mds_hdrdb, NULL, &key, &data, 0); ++ if (rc != 0) { ++ fprintf(stderr, "error: db put %s: %s\n", MDS_HDR, ++ db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++out: ++ mds_hdrdb->close(mds_hdrdb, 0); ++ ext2fs_free_mem(&mds_hdrname); ++ if (rc == 0) { ++ printf("mds info db file written \n"); ++ fflush(stdout); ++ ++ } ++ return (rc); ++} ++ ++int e2fsck_lfsck_save_ea(e2fsck_t ctx, ext2_ino_t ino, __u32 generation, ++ struct lov_user_md *lmm, struct lustre_mdt_attrs *lma) ++{ ++ ext2_filsys fs = ctx->fs; ++#ifdef LFSCK_CHECK_SIZE ++ struct lfsck_mds_szinfo szinfo; ++#endif /* LFSCK_CHECK_SIZE */ ++ struct lov_user_ost_data_v1 *loi; ++ int rc, i; ++ DBT key, data; ++ DB *dbp; ++ __u32 numfiles = fs->super->s_inodes_count - ++ fs->super->s_free_inodes_count; ++ ++ if (!ctx->lfsck_oinfo) { ++ /* remove old db file */ ++ if (unlink(ctx->lustre_mdsdb)) { ++ rc = errno; ++ if (rc != ENOENT) { ++ fprintf(stderr,"Error removing old db %s: %s\n", ++ ctx->lustre_mdsdb, strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return rc; ++ } ++ } ++ ++ rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info), ++ &ctx->lfsck_oinfo); ++ if (rc) { ++ ctx->lfsck_oinfo = NULL; ++ ctx->flags |= E2F_FLAG_ABORT; ++ return rc; ++ } ++ memset(ctx->lfsck_oinfo, 0, sizeof(struct lfsck_outdb_info)); ++ rc = ext2fs_get_mem(sizeof(struct lfsck_ofile_ctx)*LOV_MAX_OSTS, ++ &ctx->lfsck_oinfo->ofile_ctx); ++ if (rc) { ++ ext2fs_free_mem(&ctx->lfsck_oinfo); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return rc; ++ } ++ memset(ctx->lfsck_oinfo->ofile_ctx, 0, ++ sizeof(struct lfsck_ofile_ctx) * LOV_MAX_OSTS); ++#ifdef LFSCK_CHECK_SIZE ++ if (lfsck_opendb(ctx->lustre_mdsdb, MDS_SIZEINFO, ++ &ctx->lfsck_oinfo->mds_sizeinfo_dbp, 0, ++ sizeof(szinfo.mds_fid) + sizeof(szinfo), ++ numfiles)) { ++ fprintf(stderr, "Failed to open db file %s\n", ++ MDS_SIZEINFO); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (EIO); ++ } ++#endif /* LFSCK_CHECK_SIZE */ ++ ++ if (ctx->options & E2F_OPT_READONLY) { ++ e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo); ++ lfsck_write_mds_hdrinfo(ctx, ctx->lfsck_oinfo); ++ } ++ } ++ if (lmm->lmm_magic == LOV_USER_MAGIC_V3) ++ loi = ((struct lov_user_md_v3 *)lmm)->lmm_objects; ++ else /* if (lmm->lmm_magic == LOV_USER_MAGIC_V1) */ ++ loi = lmm->lmm_objects; ++ ++#ifdef LFSCK_CHECK_SIZE ++ /* XXX: We don't save the layout type here. This doesn't matter for ++ * now, we don't really need the pool information for lfsck, but ++ * in the future we may need it for RAID-1 and other layouts. */ ++ memset(&szinfo, 0, sizeof(szinfo)); ++ szinfo.mds_fid = ino; ++ szinfo.mds_seq = lmm->lmm_object_seq; ++ szinfo.mds_stripe_size = lmm->lmm_stripe_size; ++ szinfo.mds_stripe_start = loi->l_ost_idx; ++ szinfo.mds_calc_size = 0; ++ szinfo.mds_stripe_pattern = lmm->lmm_pattern; ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &szinfo.mds_fid; ++ key.size = sizeof(szinfo.mds_fid); ++ cputole_mds_szinfo(&szinfo); ++ data.data = &szinfo; ++ data.size = sizeof(szinfo); ++ dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp; ++ if ((rc = dbp->put(dbp, NULL, &key, &data, 0)) != 0) { ++ dbp->err(ctx->lfsck_oinfo->mds_sizeinfo_dbp, rc, ++ "db->put failed\n"); ++ e2fsck_lfsck_cleanupdb(ctx); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (EIO); ++ } ++#endif /* LFSCK_CHECK_SIZE */ ++ for (i = 0; i < lmm->lmm_stripe_count; i++, loi++) { ++ int ost_idx = loi->l_ost_idx; ++ struct lfsck_mds_objent mds_ent; ++ struct lfsck_ofile_ctx *ofile_ctx = ++ &ctx->lfsck_oinfo->ofile_ctx[ost_idx]; ++ ++ if (ost_idx >= LOV_MAX_OSTS) { ++ fprintf(stderr, "invalid OST index %u ino %u[%d]\n", ++ ost_idx, ino, i); ++ continue; ++ } ++ ++ if (ost_idx + 1 > ctx->lfsck_oinfo->ost_count) { ++ if (ctx->lfsck_oinfo->have_ost_count) { ++ fprintf(stderr, "bad OST index %u ino %u[%d]\n", ++ ost_idx, ino, i); ++ continue; ++ } ++ ctx->lfsck_oinfo->ost_count = ost_idx + 1; ++ } ++ ++ if (ofile_ctx->dbp == NULL) { ++ char dbname[256]; ++ ++ sprintf(dbname, "%s.%d", MDS_OSTDB, ost_idx); ++ rc = lfsck_opendb(ctx->lustre_mdsdb, dbname, ++ &ofile_ctx->dbp, 1, ++ sizeof(mds_ent), numfiles); ++ if (rc) { ++ e2fsck_lfsck_cleanupdb(ctx); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (EIO); ++ } ++ } ++ ++ memset(&mds_ent, 0, sizeof(mds_ent)); ++ if (lma) { ++ mds_ent.mds_fid = lma->lma_self_fid; ++ } else { ++ mds_ent.mds_fid.f_seq = ino; ++ mds_ent.mds_fid.f_oid = generation; ++ mds_ent.mds_fid.f_ver = 0; ++ } ++ mds_ent.mds_oi = *(struct ost_id *)&loi->l_object_id; ++ mds_ent.mds_ostidx = ost_idx; ++ mds_ent.mds_ostoffset = i; ++ ++ if (mds_ent.mds_oi.oi_id > ofile_ctx->max_id) { ++ if (ofile_ctx->have_max_id) { ++ DEBUG(ctx, ++ "[%d] skip obj "LPU64" > max "LPU64"\n", ++ ost_idx, mds_ent.mds_oi.oi_id, ++ ofile_ctx->max_id); ++ continue; ++ } ++ ofile_ctx->max_id = mds_ent.mds_oi.oi_id; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_ent.mds_oi; ++ key.size = sizeof(mds_ent.mds_oi); ++ cputole_mds_objent(&mds_ent); ++ data.data = &mds_ent; ++ data.size = sizeof(mds_ent); ++ dbp = ofile_ctx->dbp; ++#if 0 ++ DEBUG(ctx, "OST[%u]: inode FID "DFID" oi "DOIF"\n", ost_idx, ++ PFID(&mds_ent.mds_fid), POIF(&mds_ent.mds_oi)); ++#endif ++ if ((rc = dbp->put(dbp, NULL, &key, &data, 0)) != 0) { ++ dbp->err(dbp, rc, "db->put failed\n"); ++ e2fsck_lfsck_cleanupdb(ctx); ++ ctx->flags |= E2F_FLAG_ABORT; ++ /* XXX - Free lctx memory */ ++ return (EIO); ++ } ++ } ++ return (0); ++} ++ ++static int lfsck_check_lov_ea(e2fsck_t ctx, struct lov_user_md *lmm) ++{ ++ if (lmm->lmm_magic != LOV_USER_MAGIC_V1 && ++ lmm->lmm_magic != LOV_USER_MAGIC_V3) { ++ VERBOSE(ctx, "error: only handle v1/v3 LOV EAs, not %08x\n", ++ lmm->lmm_magic); ++ return(-EINVAL); ++ } ++ ++ return 0; ++} ++ ++static int lfsck_check_lma_ea(e2fsck_t ctx, struct lustre_mdt_attrs *lma) ++{ ++ return 0; ++} ++ ++/* ++ * e2fsck pass1 has found a file with an EA let's save the information in ++ * the correct table(s). This is only called for an MDS search. ++ */ ++int e2fsck_lfsck_find_ea(e2fsck_t ctx, struct ext2_inode_large *inode, ++ struct ext2_ext_attr_entry *entry, void *value, ++ struct lov_user_md **lmm, ++ struct lustre_mdt_attrs **lma) ++{ ++ /* This ensures that we don't open the file here if traversing an OST */ ++ if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS) ++ return 0; ++ ++ if (!LINUX_S_ISREG(inode->i_mode)) ++ return 0; ++ ++ if (entry->e_name_index == EXT3_XATTR_INDEX_TRUSTED && ++ entry->e_name_index == EXT3_XATTR_INDEX_LUSTRE) ++ return 0; ++ ++ if (strncmp(entry->e_name, XATTR_LUSTRE_MDS_LOV_EA, ++ entry->e_name_len) == 0) { ++ *lmm = value; ++ letocpu_lov_user_md(*lmm); ++ ++ if (lfsck_check_lov_ea(ctx, *lmm)) { ++ *lmm = NULL; ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -EINVAL; ++ } ++ } else if (strncmp(entry->e_name, XATTR_LUSTRE_MDT_LMA_EA, ++ entry->e_name_len) == 0) { ++ *lma = value; ++ if (lfsck_check_lma_ea(ctx, *lma)) { ++ *lma = NULL; ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++/* make sure that the mds data is on file */ ++int e2fsck_lfsck_flush_ea(e2fsck_t ctx) ++{ ++ int i, rc = 0; ++ DB *dbp; ++ ++ if ((ctx->lustre_devtype & LUSTRE_TYPE) != LUSTRE_MDS) ++ return (0); ++ ++ if (ctx->lfsck_oinfo == 0) ++ return (0); ++ ++ for (i = 0; i < ctx->lfsck_oinfo->ost_count; i++) { ++ if (ctx->lfsck_oinfo->ofile_ctx == NULL) ++ break; ++ ++ if (ctx->lfsck_oinfo->ofile_ctx[i].dbp != NULL) { ++ dbp = ctx->lfsck_oinfo->ofile_ctx[i].dbp; ++ rc += dbp->close(dbp, 0); ++ ctx->lfsck_oinfo->ofile_ctx[i].dbp = NULL; ++ } ++ } ++ if (ctx->lfsck_oinfo->mds_sizeinfo_dbp != NULL) { ++ dbp = ctx->lfsck_oinfo->mds_sizeinfo_dbp; ++ rc += dbp->close(dbp, 0); ++ ctx->lfsck_oinfo->mds_sizeinfo_dbp = NULL; ++ } ++ ++ if (rc) ++ ctx->flags |= E2F_FLAG_ABORT; ++ ++ return(rc); ++} ++ ++/* From debugfs.c for file removal */ ++static int lfsck_release_blocks_proc(ext2_filsys fs, blk_t *blocknr, ++ int blockcnt, void *private) ++{ ++ blk_t block; ++ ++ block = *blocknr; ++ ext2fs_block_alloc_stats(fs, block, -1); ++ return 0; ++} ++ ++static void lfsck_kill_file_by_inode(ext2_filsys fs, ext2_ino_t inode) ++{ ++ struct ext2_inode inode_buf; ++ ++ if (ext2fs_read_inode(fs, inode, &inode_buf)) ++ return; ++ ++ inode_buf.i_dtime = time(NULL); ++ if (ext2fs_write_inode(fs, inode, &inode_buf)) ++ return; ++ ++ ext2fs_block_iterate(fs, inode, 0, NULL, ++ lfsck_release_blocks_proc, NULL); ++ ext2fs_inode_alloc_stats2(fs, inode, -1, ++ LINUX_S_ISDIR(inode_buf.i_mode)); ++} ++ ++/* ++ * remove a file. Currently this removes the lov_objids file ++ * since otherwise the automatic deletion of precreated objects on ++ * mds/ost connection could potentially remove objects with ++ * data - this would be especially the case if the mds has being ++ * restored from backup ++ */ ++static int lfsck_rm_file(e2fsck_t ctx, ext2_ino_t dir, char *name) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t ino; ++ struct ext2_inode inode; ++ int rc; ++ ++ rc = ext2fs_lookup(fs, dir, name, strlen(name), ++ NULL, &ino); ++ if (rc) ++ return (0); ++ ++ if (ext2fs_read_inode(fs, ino, &inode)) ++ return(-EINVAL); ++ ++ --inode.i_links_count; ++ ++ if (ext2fs_write_inode(fs, ino, &inode)) ++ return (-EINVAL); ++ ++ if (ext2fs_unlink(fs, dir, name, ino, 0)) ++ return (-EIO); ++ ++ if (inode.i_links_count == 0) ++ lfsck_kill_file_by_inode(fs, ino); ++ ++ return(0); ++} ++ ++/* called for each ost object - save the object id and size */ ++static int lfsck_list_objs(ext2_ino_t dir, int entry, ++ struct ext2_dir_entry *dirent, int offset, ++ int blocksize, char *buf, void *priv_data) ++{ ++ struct lfsck_ost_ctx *lctx = priv_data; ++ struct lfsck_ost_objent objent; ++ struct ext2_inode inode; ++ DBT key, data; ++ DB *dbp; ++ char name[32]; /* same as filter_fid2dentry() */ ++ ++ if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode)) ++ return (0); ++ ++ memset(name, 0, sizeof(name)); ++ strncpy(name, dirent->name, dirent->name_len & 0xFF); ++ memset(&objent, 0, sizeof(objent)); ++ objent.ost_oi.oi_id = STRTOUL(name, NULL, 10); ++ if (objent.ost_oi.oi_id == STRTOUL_MAX) { ++ lctx->status = 1; ++ lctx->ctx->flags |= E2F_FLAG_ABORT; ++ return(DIRENT_ABORT); ++ } ++ ++ if (ext2fs_read_inode(lctx->ctx->fs, dirent->inode, &inode)) { ++ lctx->status = 1; ++ lctx->ctx->flags |= E2F_FLAG_ABORT; ++ return(DIRENT_ABORT); ++ } ++ ++ if (LINUX_S_ISREG(inode.i_mode)) ++ objent.ost_size = EXT2_I_SIZE(&inode); ++ else ++ objent.ost_size = inode.i_size; ++ objent.ost_bytes = (__u64)inode.i_blocks * 512; ++ ++ if (objent.ost_oi.oi_id > lctx->max_objid) ++ lctx->max_objid = objent.ost_oi.oi_id; ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &objent.ost_oi; ++ key.size = sizeof(objent.ost_oi); ++ cputole_ost_objent(&objent); ++ data.data = &objent; ++ data.size = sizeof(objent); ++ dbp = lctx->outdb; ++ if (dbp->put(dbp, NULL, &key, &data, 0) != 0) { ++ fprintf(stderr, "Failure to put data into db\n"); ++ lctx->ctx->flags |= E2F_FLAG_ABORT; ++ return(DIRENT_ABORT); ++ } ++ ++ lctx->numfiles ++; ++ return (0); ++} ++ ++/* For each file on the mds save the fid and the containing directory */ ++static int lfsck_mds_dirs(ext2_ino_t dir, int entry, ++ struct ext2_dir_entry *de, int offset, ++ int blocksize, char *buf, void *priv_data) ++{ ++ struct ext2_dir_entry_2 *dirent = (struct ext2_dir_entry_2 *)de; ++ struct lfsck_mds_ctx *lctx = priv_data; ++ struct lfsck_mds_ctx lctx2; ++ struct lfsck_mds_dirent mds_dirent; ++ DBT key, data; ++ DB *dbp = lctx->outdb; ++ int file_type; ++ int rc = 0; ++ ++ DEBUG(lctx->ctx, "MDT: inode %u, file %.*s, type %u\n", ++ dirent->inode, dirent->name_len, dirent->name, ++ dirent->file_type & 0x15); ++ if (dirent->inode == lctx->dot || dirent->inode == lctx->dotdot) ++ return (0); ++ ++ /* only the low 4 bits are used to specify file type */ ++ file_type = dirent->file_type & 15; ++ if (file_type != EXT2_FT_DIR && file_type != EXT2_FT_REG_FILE) ++ return (0); ++ ++ lctx->numfiles++; ++ ++ rc = lfsck_get_fid(lctx->ctx->fs, dirent->inode, &mds_dirent.mds_fid); ++ if (rc != 0) ++ return 0; ++ ++ DEBUG(lctx->ctx, "MDT: dirfid "DFID" child "DFID" file %.*s\n", ++ PFID(&mds_dirent.mds_dirfid), PFID(&mds_dirent.mds_fid), ++ dirent->name_len, dirent->name); ++ ++ mds_dirent.mds_dirfid = lctx->dotfid; ++ cputole_mds_dirent(&mds_dirent); ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_dirent.mds_fid; ++ key.size = sizeof(mds_dirent.mds_fid); ++ data.data = &mds_dirent; ++ data.size = sizeof(mds_dirent); ++ ++ if ((rc = dbp->put(dbp, NULL, &key, &data, 0)) != 0) { ++ if (rc != DB_KEYEXIST) { ++ fprintf(stderr, ++ "error adding MDS inode %.*s (inum %u): %s\n", ++ dirent->name_len & 0xFF, dirent->name, ++ dirent->inode, db_strerror(rc)); ++ lctx->ctx->flags |= E2F_FLAG_ABORT; ++ return (DIRENT_ABORT); ++ } ++ } ++ if (file_type == EXT2_FT_DIR) { ++ lctx2 = *lctx; ++ lctx2.dot = dirent->inode; ++ lctx2.dotdot = lctx->dot; ++ lctx2.dotfid = mds_dirent.mds_fid; ++ if (ext2fs_dir_iterate2(lctx->ctx->fs, dirent->inode, 0, NULL, ++ lfsck_mds_dirs, &lctx2)) { ++ return (DIRENT_ABORT); ++ } ++ lctx->numfiles = lctx2.numfiles; ++ } ++ return(0); ++} ++ ++/* For each directory get the objects and save the data */ ++static int lfsck_iterate_obj_dirs(ext2_ino_t dir, int entry, ++ struct ext2_dir_entry *dirent, int offset, ++ int blocksize, char *buf, void *priv_data) ++{ ++ struct lfsck_ost_ctx *lctx = priv_data; ++ ++ if (ext2fs_check_directory(lctx->ctx->fs, dirent->inode)) ++ return (0); ++ ++ /* Traverse the d* directories */ ++ if (*dirent->name != 'd') ++ return (0); ++ ++ ext2fs_dir_iterate2(lctx->ctx->fs, dirent->inode, 0, NULL, ++ lfsck_list_objs, priv_data); ++ if (lctx->status != 0) ++ return (DIRENT_ABORT); ++ ++ return(0); ++} ++ ++/* Get the starting point of where the objects reside */ ++static int lfsck_get_object_dir(e2fsck_t ctx, char *block_buf,ext2_ino_t *inode) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t tinode; ++ int rc; ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR), ++ block_buf, &tinode); ++ if (rc) { ++ fprintf(stderr, "error looking up OST object parent dir\n"); ++ return (ENOENT); ++ } ++ rc = ext2fs_check_directory(fs, tinode); ++ if (rc) { ++ return(ENOENT); ++ } ++ ++ rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V1, strlen(OBJECT_DIR_V1), ++ block_buf, inode); ++ if (rc) { ++ rc = ext2fs_lookup(fs, tinode, OBJECT_DIR_V2, ++ strlen(OBJECT_DIR_V2), block_buf, inode); ++ if (rc) { ++ fprintf(stderr, "error looking up OST object subdir\n"); ++ return (-ENOENT); ++ } ++ } ++ rc = ext2fs_check_directory(fs, *inode); ++ if (rc) { ++ return(-ENOENT); ++ } ++ return(0); ++} ++ ++/* What is the last object id for the OST */ ++static int lfsck_get_last_id(e2fsck_t ctx, __u64 *last_id) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t inode, tinode; ++ ext2_file_t e2_file; ++ char *block_buf; ++ unsigned int got; ++ int rc; ++ ++ block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3, ++ "lookup buffer"); ++ ++ rc = lfsck_get_object_dir(ctx, block_buf, &inode); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_lookup(fs, inode, LAST_ID, ++ strlen(LAST_ID), block_buf, &tinode); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_file_open(fs, tinode, 0, &e2_file); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_file_read(e2_file, last_id, sizeof(__u64), &got); ++ if (rc) { ++ ext2fs_file_close(e2_file); ++ goto out; ++ } ++ ++ if (got != sizeof(__u64)) { ++ rc = EIO; ++ ext2fs_file_close(e2_file); ++ goto out; ++ } ++ ++ rc = ext2fs_file_close(e2_file); ++ ++ *last_id = ext2fs_le64_to_cpu(*last_id); ++out: ++ ext2fs_free_mem(&block_buf); ++ return (rc); ++} ++ ++int lfsck_set_last_id(e2fsck_t ctx, __u64 last_id) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t inode, tinode; ++ ext2_file_t e2_file; ++ char *block_buf; ++ unsigned int written; ++ int rc; ++ ++ block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3, ++ "lookup buffer"); ++ ++ rc = lfsck_get_object_dir(ctx, block_buf, &inode); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_lookup(fs, inode, LAST_ID, ++ strlen(LAST_ID), block_buf, &tinode); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_file_open(fs, tinode, EXT2_FILE_WRITE, &e2_file); ++ if (rc) ++ goto out; ++ ++ last_id = ext2fs_cpu_to_le64(last_id); ++ ++ rc = ext2fs_file_write(e2_file, &last_id, sizeof(__u64), &written); ++ if (rc) { ++ fprintf(stderr, "Failure to update last id on file\n"); ++ ext2fs_file_close(e2_file); ++ goto out; ++ } ++ ++ if (written != sizeof(__u64)) { ++ rc = EIO; ++ fprintf(stderr, "Failure to update last id on file\n"); ++ ext2fs_file_close(e2_file); ++ goto out; ++ } ++ ++ rc = ext2fs_file_close(e2_file); ++ ++out: ++ ext2fs_free_mem(&block_buf); ++ return (rc); ++} ++ ++int e2fsck_get_last_rcvd_info(e2fsck_t ctx, struct obd_uuid *local_uuid, ++ struct obd_uuid *peer_uuid, __u32 *subdircount, ++ __u32 *index, __u32 *compat, __u32 *rocompat, ++ __u32 *incompat) ++{ ++ ext2_filsys fs = ctx->fs; ++ ext2_ino_t inode; ++ ext2_file_t e2_file; ++ struct lustre_server_data *lsd = NULL; ++ unsigned int got; ++ char *block_buf; ++ __u32 cmp, inc; ++ int rc = 0; ++ ++ block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3, ++ "block iterate buffer"); ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, LAST_RCVD, strlen(LAST_RCVD), ++ block_buf, &inode); ++ if (rc) ++ goto out; ++ ++ rc = ext2fs_file_open(fs, inode, 0, &e2_file); ++ if (rc) ++ goto out; ++ ++ lsd = e2fsck_allocate_memory(ctx, sizeof(*lsd), "lustre server data"); ++ if (lsd == NULL) { ++ rc = ENOMEM; ++ goto out; ++ } ++ ++ rc = ext2fs_file_read(e2_file, lsd, sizeof(*lsd), &got); ++ if (rc) ++ goto out; ++ if (got != sizeof(*lsd)) { ++ rc = EIO; ++ goto out; ++ } ++ ++ if (local_uuid) ++ memcpy(local_uuid, &lsd->lsd_uuid, sizeof(lsd->lsd_uuid)); ++ ++ if (peer_uuid) ++ memcpy(peer_uuid, &lsd->lsd_peeruuid,sizeof(lsd->lsd_peeruuid)); ++ ++ if (subdircount) ++ *subdircount = ext2fs_le16_to_cpu(lsd->lsd_subdir_count); ++ ++ if (compat == NULL) ++ compat = &cmp; ++ *compat = ext2fs_le32_to_cpu(lsd->lsd_feature_compat); ++ if (rocompat) ++ *rocompat = ext2fs_le32_to_cpu(lsd->lsd_feature_rocompat); ++ if (incompat == NULL) ++ incompat = &inc; ++ *incompat = ext2fs_le32_to_cpu(lsd->lsd_feature_incompat); ++ if (index) { ++ if (*compat & OBD_COMPAT_OST || *incompat & OBD_INCOMPAT_OST) ++ *index = ext2fs_le32_to_cpu(lsd->lsd_ost_index); ++ else if (*compat & OBD_COMPAT_MDT||*incompat & OBD_INCOMPAT_MDT) ++ *index = ext2fs_le32_to_cpu(lsd->lsd_mdt_index); ++ else ++ *index = -1; ++ } ++ ++ rc = ext2fs_file_close(e2_file); ++ ++out: ++ ext2fs_free_mem(&block_buf); ++ if (lsd) ++ ext2fs_free_mem(&lsd); ++ return (rc); ++} ++ ++int lfsck_rm_log(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, ++ int offset, int blocksize, char *buf, void *priv_data) ++{ ++ struct lfsck_ost_ctx *lctx = priv_data; ++ char name[EXT2_NAME_LEN + 1]; ++ ++ if (!ext2fs_check_directory(lctx->ctx->fs, dirent->inode)) ++ return (0); ++ ++ strncpy(name, dirent->name, dirent->name_len & 0xFF); ++ name[EXT2_NAME_LEN] = '\0'; ++ if (memcmp(name, LAST_ID, strlen(LAST_ID)) == 0) ++ return (0); ++ ++ ++ if (lfsck_rm_file(lctx->ctx, lctx->dirinode, name)) ++ return(DIRENT_ABORT); ++ ++ return(0); ++} ++ ++/* Not 100% sure that this is correct so not activated yet */ ++int lfsck_remove_ost_logs(e2fsck_t ctx, char *block_buf) ++{ ++ ext2_filsys fs = ctx->fs; ++ struct lfsck_ost_ctx lctx; ++ ext2_ino_t inode; ++ ext2_ino_t tinode; ++ int rc; ++ ++ if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -EINVAL; ++ } ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECT_DIR, strlen(OBJECT_DIR), ++ block_buf, &tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (-ENOENT); ++ } ++ rc = ext2fs_check_directory(fs,tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return(-ENOENT); ++ } ++ ++ rc = ext2fs_lookup(fs, tinode, LOG_DIR, strlen(LOG_DIR), ++ block_buf, &inode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (-ENOENT); ++ } ++ rc = ext2fs_check_directory(fs, inode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return(-ENOENT); ++ } ++ lctx.ctx = ctx; ++ lctx.dirinode = inode; ++ ++ if (ext2fs_dir_iterate2(fs, inode, 0, block_buf, lfsck_rm_log, &lctx)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return(-EIO); ++ } ++ return (0); ++} ++ ++/* Remove files from PENDING dir - this needs to be done before getting ea from ++ * blocks but we need the inode_map bitmap loaded beforehand so load write any ++ * changes then remove references ++ */ ++int e2fsck_lfsck_remove_pending(e2fsck_t ctx, char *block_buf) ++{ ++ ext2_filsys fs = ctx->fs; ++ struct lfsck_ost_ctx lctx; ++ ext2_ino_t tinode; ++ int rc = 0; ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, PENDING_DIR, strlen(PENDING_DIR), ++ block_buf, &tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (-ENOENT); ++ } ++ rc = ext2fs_check_directory(fs,tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return(-ENOENT); ++ } ++ ++ lctx.ctx = ctx; ++ lctx.dirinode = tinode; ++ ++ e2fsck_read_bitmaps(ctx); ++ ++ if (ext2fs_dir_iterate2(fs, tinode, 0, block_buf, lfsck_rm_log, &lctx)){ ++ ctx->flags |= E2F_FLAG_ABORT; ++ rc = -EIO; ++ } ++ e2fsck_write_bitmaps(ctx); ++ ext2fs_free_inode_bitmap(fs->inode_map); ++ ext2fs_free_block_bitmap(fs->block_map); ++ fs->inode_map = NULL; ++ fs->block_map = NULL; ++ return (rc); ++} ++ ++/* partially using code from debugfs do_write() */ ++int lfsck_create_objid(e2fsck_t ctx, __u64 objid) ++{ ++ int rc = 0; ++ char dirname[32]; ++ char name[32]; ++ int len, dirlen; ++ __u32 compat, incompat, subdircount; ++ ext2_ino_t inode, tinode, cinode; ++ struct ext2_inode ext2inode; ++ char *block_buf; ++ ++ block_buf = e2fsck_allocate_memory(ctx, ctx->fs->blocksize * 3, ++ "lookup buffer"); ++ ++ memset(name, 0, 32); ++ memset(dirname, 0, 32); ++ ++ len = sprintf(name, LPU64, objid); ++ ++ fprintf(stderr, "creating %s\n", name); ++ ++ rc = e2fsck_get_last_rcvd_info(ctx, NULL, NULL, &subdircount, NULL, ++ &compat, NULL, &incompat); ++ if (rc) { ++ fprintf(stderr, "Error: reading OST last_rcvd file\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++ if (compat & OBD_COMPAT_MDT || incompat & OBD_INCOMPAT_MDT) { ++ fprintf(stderr, "Error: MDS last_rcvd file doing OST check\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++ if (lfsck_get_object_dir(ctx, block_buf, &inode)) { ++ rc = EINVAL; ++ goto out; ++ } ++ ++ dirlen = sprintf(dirname, "d%u", (int)objid & (subdircount - 1)); ++ ++ rc = ext2fs_lookup(ctx->fs, inode, dirname, ++ dirlen, block_buf, &tinode); ++ if (rc) { ++ rc = EINVAL; ++ goto out; ++ } ++ ++ if (ext2fs_namei(ctx->fs, EXT2_ROOT_INO, tinode, name, &cinode) == 0) { ++ fprintf(stderr, "Failure to create obj\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++ rc = ext2fs_new_inode(ctx->fs, tinode, 010755, 0, &cinode); ++ if (rc) { ++ fprintf(stderr, "Failure to create obj\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++ rc = ext2fs_link(ctx->fs, tinode, name, cinode, EXT2_FT_REG_FILE); ++ if (rc) { ++ fprintf(stderr, "Failure to create obj\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++ if (ext2fs_test_inode_bitmap2(ctx->fs->inode_map, cinode)) { ++ fprintf(stderr, "Warning: inode already set"); ++ } ++ ext2fs_inode_alloc_stats2(ctx->fs, cinode, +1, 0); ++ memset(&ext2inode, 0, sizeof(ext2inode)); ++ ext2inode.i_mode = LINUX_S_IFREG; ++ ext2inode.i_atime = ext2inode.i_ctime = ext2inode.i_mtime = time(NULL); ++ ext2inode.i_links_count = 1; ++ ext2inode.i_size = 0; ++ if (ext2fs_write_inode(ctx->fs, cinode, &ext2inode)) { ++ fprintf(stderr, "Failure to create obj\n"); ++ rc = EINVAL; ++ goto out; ++ } ++ ++out: ++ ext2fs_free_mem((void *)&(block_buf)); ++ return (rc); ++} ++ ++/* ++ * For on ost iterate for the direcories and save the object information. ++ */ ++void e2fsck_pass6_ost(e2fsck_t ctx) ++{ ++ ext2_filsys fs = ctx->fs; ++ struct lfsck_ost_ctx lctx; ++ struct lfsck_ost_hdr ost_hdr; ++ struct lfsck_mds_hdr mds_hdr; ++ struct lfsck_ost_objent objent; ++ DB *outdb = NULL; ++ DB *mds_hdrdb = NULL; ++ DB *osthdr = NULL; ++ DBT key, data; ++ ext2_ino_t dir; ++ __u32 compat, rocompat, incompat; ++ int i, rc; ++ char *block_buf = NULL; ++ ++ if (unlink(ctx->lustre_ostdb)) { ++ if (errno != ENOENT) { ++ fprintf(stderr, "Failure to remove old db file %s\n", ++ ctx->lustre_ostdb); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return; ++ } ++ } ++ ++ block_buf = e2fsck_allocate_memory(ctx, fs->blocksize * 3, ++ "block iterate buffer"); ++ ++ rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &mds_hdrdb, 0, 0, 0); ++ if (rc != 0) { ++ fprintf(stderr, "failure to open database %s: %s\n", ++ MDS_HDR, db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ memset(&mds_hdr, 0, sizeof(mds_hdr)); ++ mds_hdr.mds_magic = MDS_MAGIC; ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_hdr.mds_magic; ++ key.size = sizeof(mds_hdr.mds_magic); ++ data.data = &mds_hdr; ++ data.size = sizeof(mds_hdr); ++ data.ulen = sizeof(mds_hdr); ++ data.flags = DB_DBT_USERMEM; ++ rc = mds_hdrdb->get(mds_hdrdb, NULL, &key, &data, 0); ++ if (rc) { ++ fprintf(stderr,"error getting mds_hdr ("LPU64":%u) in %s: %s\n", ++ mds_hdr.mds_magic, (int)sizeof(mds_hdr.mds_magic), ++ ctx->lustre_mdsdb, db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ memcpy(&mds_hdr, data.data, sizeof(mds_hdr)); ++ letocpu_mds_hdr(&mds_hdr); ++ ++ rc = lfsck_opendb(ctx->lustre_ostdb, OST_HDR, &osthdr, 0, 0, 0); ++ if (rc != 0) { ++ fprintf(stderr, "failure to open database %s: %s\n", ++ OST_HDR, db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ rc = lfsck_opendb(ctx->lustre_ostdb, OST_OSTDB, &outdb, 0, ++ sizeof(objent.ost_oi) + sizeof(objent), ++ fs->super->s_inodes_count - ++ fs->super->s_free_inodes_count); ++ if (rc != 0) { ++ fprintf(stderr, "error getting ost_hdr in %s: %s\n", ++ ctx->lustre_ostdb, db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ memset(&ost_hdr, 0, sizeof(ost_hdr)); ++ if (e2fsck_get_last_rcvd_info(ctx, &ost_hdr.ost_uuid, ++ &ost_hdr.ost_mds_uuid, NULL, ++ &ost_hdr.ost_index, ++ &compat, &rocompat, &incompat)) { ++ fprintf(stderr, "Failure to read OST last_rcvd file\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ VERBOSE(ctx, "OST: '%s' ost idx %u: compat %#x rocomp %#x incomp %#x\n", ++ (char *)&ost_hdr.ost_uuid.uuid, ost_hdr.ost_index, ++ compat, rocompat, incompat); ++ ++ if (compat & OBD_COMPAT_MDT) { ++ fprintf(stderr, "Found MDS last_rcvd file doing OST check\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ /* ++ * Get /O/R or /O/0 directory ++ * for each entry scan all the dirents and get the object id ++ */ ++ if (lfsck_get_object_dir(ctx, block_buf, &dir)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ /* ++ * Okay so we have the containing directory so let's iterate over the ++ * containing d* dirs and then iterate again inside ++ */ ++ lctx.ctx = ctx; ++ lctx.outdb = outdb; ++ lctx.status = 0; ++ lctx.numfiles = 0; ++ lctx.max_objid = 0; ++ lctx.status = ext2fs_dir_iterate2(fs, dir, 0, block_buf, ++ lfsck_iterate_obj_dirs, &lctx); ++ if (lctx.status) { ++ fprintf(stderr, "Failure in iterating object dirs\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ return; ++ } ++ ++ ost_hdr.ost_magic = OST_MAGIC; ++ ost_hdr.ost_flags = ctx->options & E2F_OPT_READONLY; ++ ost_hdr.ost_num_files = lctx.numfiles; ++ VERBOSE(ctx, "OST: num files = %u\n", lctx.numfiles); ++ ++ if (lfsck_get_last_id(ctx, &ost_hdr.ost_last_id)) { ++ fprintf(stderr, "Failure to get last id for objects\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ VERBOSE(ctx, "OST: last_id = "LPU64"\n", ost_hdr.ost_last_id); ++ ++ /* Update the last_id value on the OST if necessary/possible to the ++ * MDS value if larger. Otherwise we risk creating duplicate objects. ++ * If running read-only, we skip this so new objects are ignored. */ ++ ost_hdr.ost_last_id = lctx.max_objid; ++ if (!(ctx->options & E2F_OPT_READONLY) && ++ !(mds_hdr.mds_flags & E2F_OPT_READONLY)) { ++ for (i = 0; i < mds_hdr.mds_num_osts; i++) { ++ if (strcmp((char *)mds_hdr.mds_ost_info[i].uuid, ++ (char *)ost_hdr.ost_uuid.uuid) == 0 && ++ mds_hdr.mds_max_ost_id[i] >= ost_hdr.ost_last_id) ++ ost_hdr.ost_last_id=mds_hdr.mds_max_ost_id[i]+1; ++ } ++ ++ if (lfsck_set_last_id(ctx, ost_hdr.ost_last_id)) { ++ fprintf(stderr, "Failure to set last id\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++#ifdef LOG_REMOVAL ++ if (lfsck_remove_ost_logs(ctx, block_buf)) ++ ctx->flags |= E2F_FLAG_ABORT; ++#endif ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &ost_hdr.ost_magic; ++ key.size = sizeof(ost_hdr.ost_magic); ++ cputole_ost_hdr(&ost_hdr); ++ data.data = &ost_hdr; ++ data.size = sizeof(ost_hdr); ++ if (osthdr->put(osthdr, NULL, &key, &data, 0)) { ++ fprintf(stderr, "Failed to db_put data\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++out: ++ if (mds_hdrdb) ++ mds_hdrdb->close(mds_hdrdb, 0); ++ if (outdb) ++ outdb->close(outdb, 0); ++ if (osthdr) ++ osthdr->close(osthdr, 0); ++ if (block_buf) ++ ext2fs_free_mem((void *)&(block_buf)); ++ return; ++} ++ ++int lfsck_remove_mds_logs(e2fsck_t ctx) ++{ ++ ext2_filsys fs = ctx->fs; ++ struct lfsck_ost_ctx lctx; ++ ext2_ino_t tinode; ++ int rc = 0; ++ ++ if (lfsck_rm_file(ctx, EXT2_ROOT_INO, CATLIST)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return -EINVAL; ++ } ++ ++ rc = ext2fs_lookup(fs, EXT2_ROOT_INO, OBJECTS, strlen(OBJECTS), ++ NULL, &tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return (-ENOENT); ++ } ++ rc = ext2fs_check_directory(fs,tinode); ++ if (rc) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return(-ENOENT); ++ } ++ ++ lctx.ctx = ctx; ++ lctx.dirinode = tinode; ++ ++ if (ext2fs_dir_iterate2(fs, tinode, 0, NULL, lfsck_rm_log, &lctx)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ rc = -EIO; ++ } ++ return (rc); ++} ++ ++ ++/* ++ * On the mds save the fid and directory information for each file. ++ * The mds ost tables have already been populated by pass1 ++ */ ++void e2fsck_pass6_mdt(e2fsck_t ctx) ++{ ++ ext2_filsys fs = ctx->fs; ++ struct problem_context pctx; ++ struct lfsck_mds_ctx lctx; ++ struct lfsck_mds_dirent mds_dirent; ++ struct lfsck_mds_hdr mds_hdr; ++ DBT key, data; ++ DB *outdb = NULL, *dbhdr = NULL; ++ __u32 compat, rocompat, incompat, index; ++ int rc, i; ++ ++ clear_problem_context(&pctx); ++ ++ memset(&lctx, 0, sizeof(lctx)); ++ lctx.ctx = ctx; ++ ++ /* Found no files with EA on filesystem - empty */ ++ if (ctx->lfsck_oinfo == NULL) { ++ if (unlink(ctx->lustre_mdsdb)) { ++ if (errno != ENOENT) { ++ fprintf(stderr, "Failure to remove old " ++ "db file %s\n", ctx->lustre_mdsdb); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ } ++ rc = ext2fs_get_mem(sizeof(struct lfsck_outdb_info), ++ &ctx->lfsck_oinfo); ++ if (rc) { ++ ctx->lfsck_oinfo = NULL; ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ memset(ctx->lfsck_oinfo, 0, sizeof(struct lfsck_outdb_info)); ++ rc = ext2fs_get_mem(sizeof(struct lfsck_ofile_ctx)*LOV_MAX_OSTS, ++ &ctx->lfsck_oinfo->ofile_ctx); ++ if (rc) { ++ ext2fs_free_mem(&ctx->lfsck_oinfo); ++ ctx->lfsck_oinfo = NULL; ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ memset(ctx->lfsck_oinfo->ofile_ctx, 0, ++ sizeof(struct lfsck_ofile_ctx) * LOV_MAX_OSTS); ++ } ++ ++ if (!(ctx->options & E2F_OPT_READONLY)) ++ lfsck_write_mds_hdrinfo(ctx, ctx->lfsck_oinfo); ++ ++ if (lfsck_opendb(ctx->lustre_mdsdb, MDS_DIRINFO, &outdb, 1, ++ sizeof(mds_dirent.mds_fid) + sizeof(mds_dirent), ++ fs->super->s_inodes_count - ++ fs->super->s_free_inodes_count)) { ++ fprintf(stderr, "failure to open database %s\n", MDS_DIRINFO); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ lctx.outdb = outdb; ++ lctx.numfiles = 0; ++ lctx.dot = EXT2_ROOT_INO; ++ lctx.dotdot = EXT2_ROOT_INO; ++ lctx.dotfid.f_seq = EXT2_ROOT_INO; ++ ++ rc = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO,0,NULL,lfsck_mds_dirs,&lctx); ++ if (rc != 0) { ++ fprintf(stderr, "Error iterating directories: %d\n", rc); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ /* read in e2fsck_lfsck_save_ea() already if we opened read/write */ ++ if (ctx->lfsck_oinfo->ost_count == 0) ++ e2fsck_get_lov_objids(ctx, ctx->lfsck_oinfo); ++ ++ memset(&mds_hdr, 0, sizeof(mds_hdr)); ++ mds_hdr.mds_magic = MDS_MAGIC; ++ mds_hdr.mds_flags = ctx->options & E2F_OPT_READONLY; ++ mds_hdr.mds_max_files = fs->super->s_inodes_count - ++ fs->super->s_free_inodes_count; ++ VERBOSE(ctx, "MDS: max_files = "LPU64"\n", mds_hdr.mds_max_files); ++ mds_hdr.mds_num_osts = ctx->lfsck_oinfo->ost_count; ++ VERBOSE(ctx, "MDS: num_osts = %u\n", mds_hdr.mds_num_osts); ++ for (i = 0; i < mds_hdr.mds_num_osts; i++) { ++ mds_hdr.mds_max_ost_id[i] = ++ ctx->lfsck_oinfo->ofile_ctx[i].max_id; ++ } ++ ++ if (e2fsck_get_last_rcvd_info(ctx, &mds_hdr.mds_uuid, NULL, NULL, ++ &index, &compat, &rocompat, &incompat)) { ++ fprintf(stderr, "Failure to read MDS last_rcvd file\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ VERBOSE(ctx, "MDS: '%s' mdt idx %u: compat %#x rocomp %#x incomp %#x\n", ++ (char *)&mds_hdr.mds_uuid.uuid, index,compat,rocompat,incompat); ++ ++ if (compat & OBD_COMPAT_OST || incompat & OBD_INCOMPAT_OST) { ++ fprintf(stderr, "Found OST last_rcvd file doing MDS check\n"); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ if (!(ctx->options & E2F_OPT_READONLY)) { ++ if (lfsck_rm_file(ctx, EXT2_ROOT_INO, LOV_OBJID)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++#ifdef LOG_REMOVAL ++ if (lfsck_remove_mds_logs(ctx)) { ++ ctx->flags |= E2F_FLAG_ABORT; ++ return; ++ } ++#endif ++ } ++ ++ rc = lfsck_opendb(ctx->lustre_mdsdb, MDS_HDR, &dbhdr, 0, 0, 0); ++ if (rc != 0) { ++ fprintf(stderr, "failure to open database %s: %s\n", MDS_HDR, ++ db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ key.data = &mds_hdr.mds_magic; ++ key.size = sizeof(mds_hdr.mds_magic); ++ cputole_mds_hdr(&mds_hdr); ++ data.data = &mds_hdr; ++ data.size = sizeof(mds_hdr); ++ rc = dbhdr->put(dbhdr, NULL, &key, &data, 0); ++ if (rc != 0) { ++ fprintf(stderr, "error: db put %s: %s\n", MDS_HDR, ++ db_strerror(rc)); ++ ctx->flags |= E2F_FLAG_ABORT; ++ goto out; ++ } ++out: ++ if (dbhdr) ++ dbhdr->close(dbhdr, 0); ++ if (outdb) ++ outdb->close(outdb, 0); ++} ++ ++/* If lfsck checking requested then gather the data */ ++void e2fsck_pass6(e2fsck_t ctx) ++{ ++ if (ctx->lustre_devtype == LUSTRE_NULL) ++ return; ++ ++ printf("Pass 6: Acquiring %s information for lfsck\n", ++ ctx->lustre_devtype & LUSTRE_OST ? "OST" : ++ ctx->lustre_devtype & LUSTRE_MDS ? "MDT" : "device"); ++ ++ fflush(stdout); ++ ++ if (ctx->lustre_devtype & LUSTRE_OST) ++ e2fsck_pass6_ost(ctx); ++ else if (ctx->lustre_devtype & LUSTRE_MDS) ++ e2fsck_pass6_mdt(ctx); ++ else ++ fprintf(stderr, "Invalid lustre dev %x\n", ctx->lustre_devtype); ++ ++ return; ++} ++#endif /* ENABLE_LFSCK */ diff --git a/patches/e2fsprogs-lustre_ismounted.patch b/patches/e2fsprogs-lustre_ismounted.patch new file mode 100644 index 0000000..ed6437e --- /dev/null +++ b/patches/e2fsprogs-lustre_ismounted.patch @@ -0,0 +1,160 @@ +Check if Lustre filesystems mounted + +Index: e2fsprogs/lib/ext2fs/ismounted.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ismounted.c ++++ e2fsprogs/lib/ext2fs/ismounted.c +@@ -30,6 +30,8 @@ + #endif /* HAVE_GETMNTINFO */ + #include + #include ++#include ++#include + + #include "ext2_fs.h" + #include "ext2fs.h" +@@ -286,6 +288,135 @@ leave: + return ret; + } + ++static int check_lustre_proc_vals(const char *procname,const char *real_devname) ++{ ++ struct dirent *direntp; ++ DIR *dirp; ++ int rc = 0; ++ char *mnt_device, *proc_val, *real_mnt_device; ++ ++ mnt_device = malloc(PATH_MAX); ++ if (mnt_device == NULL) { ++ fprintf(stderr, "Cannot allocate memory to store path\n"); ++ return 1; ++ } ++ proc_val = malloc(PATH_MAX); ++ if (proc_val == NULL) { ++ fprintf(stderr, "Cannot allocate memory to store path\n"); ++ free(mnt_device); ++ return 1; ++ } ++ real_mnt_device = malloc(PATH_MAX); ++ if (real_mnt_device == NULL) { ++ fprintf(stderr, "Cannot allocate memory to store path\n"); ++ free(proc_val); ++ free(mnt_device); ++ return 1; ++ } ++ ++ dirp = opendir(procname); ++ if (dirp) { ++ do { ++ int fd, numr; ++ char *ptr; ++ ++ direntp = readdir(dirp); ++ if (direntp == NULL) ++ break; ++ if ((strncmp(direntp->d_name, ".", 1) == 0) || ++ (strncmp(direntp->d_name, "..", 2) == 0)) { ++ continue; ++ } ++ ++ memset(proc_val, 0, PATH_MAX); ++ snprintf(proc_val, PATH_MAX, "%s/%s/mntdev", procname, ++ direntp->d_name); ++ fd = open(proc_val, O_RDONLY); ++ if (fd < 0) { ++ if (errno == ENOENT || errno == ENOTDIR) ++ continue; ++ fprintf(stderr, "Cannot open %s: %s\n", ++ proc_val, strerror(errno)); ++ rc = 1; ++ goto out; ++ } ++ ++ memset(mnt_device, 0, PATH_MAX); ++ numr = 0; ++ ptr = mnt_device; ++ do { ++ numr = read(fd, ptr, PATH_MAX); ++ if (numr < 0) { ++ fprintf(stderr, ++ "Failure to get mntdev info\n"); ++ rc = 1; ++ close(fd); ++ goto out; ++ } ++ ptr += numr; ++ } while (numr != 0); ++ close(fd); ++ ++ ptr = strchr(mnt_device, '\n'); ++ if (ptr) ++ *ptr = '\0'; ++ ++ memset(real_mnt_device, 0, PATH_MAX); ++ if (realpath(mnt_device, real_mnt_device) == NULL) { ++ fprintf(stderr, "Cannot resolve mntdev %s\n", ++ mnt_device); ++ rc = 1; ++ goto out; ++ } ++ ++ if (strcmp(real_devname, real_mnt_device) == 0) { ++ fprintf(stderr, ++ "device %s mounted by lustre per %s\n", ++ real_devname, proc_val); ++ rc = -1; ++ goto out; ++ } ++ } while (direntp != NULL); ++ ++ closedir(dirp); ++ } ++ ++out: ++ free(proc_val); ++ free(mnt_device); ++ free(real_mnt_device); ++ ++ return rc; ++} ++ ++static errcode_t check_if_lustre_mounted(const char *device, int *mount_flags) ++{ ++ char *real_device; ++ int rc = 0; ++ ++ real_device = malloc(PATH_MAX); ++ if (real_device == NULL) { ++ fprintf(stderr, "Cannot allocate memory to store path\n"); ++ return EXT2_ET_NO_MEMORY; ++ } ++ ++ if (realpath(device, real_device) == NULL) { ++ fprintf(stderr, "Cannot resolve path %s\n", device); ++ return EXT2_ET_BAD_DEVICE_NAME; ++ } ++ ++ rc = check_lustre_proc_vals("/proc/fs/lustre/obdfilter", real_device); ++ if (!rc) ++ rc = check_lustre_proc_vals("/proc/fs/lustre/mds",real_device); ++ ++ if (rc) ++ *mount_flags |= EXT2_MF_MOUNTED; ++ ++ free(real_device); ++ ++ return 0; ++} ++ + + /* + * ext2fs_check_mount_point() fills determines if the device is +@@ -337,6 +468,8 @@ errcode_t ext2fs_check_mount_point(const + close(fd); + #endif + ++ retval = check_if_lustre_mounted(device, mount_flags); ++ + return 0; + } + diff --git a/patches/e2fsprogs-misc.patch b/patches/e2fsprogs-misc.patch new file mode 100644 index 0000000..4e21c65 --- /dev/null +++ b/patches/e2fsprogs-misc.patch @@ -0,0 +1,387 @@ +Fixes a number of compile warnings hit during building e2fsprogs. A few +unused variable removals, and signed/unsigned pointers. The only possibly +controversial fixup is the initialization of rec_len = 0 in copy_dir_entries(). +It wasn't totally obvious to me what to initialize it to (or if it matters), +but 0 seems reasonable, and is better than random garbage. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/blkid/probe.c +=================================================================== +--- e2fsprogs.orig/lib/blkid/probe.c ++++ e2fsprogs/lib/blkid/probe.c +@@ -1296,7 +1296,8 @@ static int probe_hfsplus(struct blkid_pr + return 0; + + label_len = blkid_be16(key->unicode_len) * 2; +- unicode_16be_to_utf8(label, sizeof(label), key->unicode, label_len); ++ unicode_16be_to_utf8((unsigned char *)label, sizeof(label), ++ key->unicode, label_len); + blkid_set_tag(probe->dev, "LABEL", label, 0); + return 0; + } +Index: e2fsprogs/debugfs/debugfs.c +=================================================================== +--- e2fsprogs.orig/debugfs/debugfs.c ++++ e2fsprogs/debugfs/debugfs.c +@@ -855,7 +855,7 @@ void do_stat(int argc, char *argv[]) + return; + } + +-void do_dump_extents(int argc, char *argv[]) ++void do_dump_extents(int argc, char **argv) + { + struct ext2_inode inode; + ext2_ino_t ino; +@@ -876,8 +876,7 @@ void do_dump_extents(int argc, char *arg + } + } + +- if (argc != optind+1) { +- print_usage: ++ if (argc != optind + 1) { + com_err(0, 0, "Usage: dump_extents [-n] [-l] file"); + return; + } +Index: e2fsprogs/debugfs/debugfs.h +=================================================================== +--- e2fsprogs.orig/debugfs/debugfs.h ++++ e2fsprogs/debugfs/debugfs.h +@@ -103,6 +103,7 @@ extern void do_unlink(int argc, char **a + extern void do_find_free_block(int argc, char **argv); + extern void do_find_free_inode(int argc, char **argv); + extern void do_stat(int argc, char **argv); ++extern void do_dump_extents(int argc, char **argv); + + extern void do_chroot(int argc, char **argv); + extern void do_clri(int argc, char **argv); +Index: e2fsprogs/debugfs/dump.c +=================================================================== +--- e2fsprogs.orig/debugfs/dump.c ++++ e2fsprogs/debugfs/dump.c +@@ -5,7 +5,9 @@ + * under the terms of the GNU Public License. + */ + ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE /* for O_LARGEFILE */ ++#endif + + #include + #include +Index: e2fsprogs/debugfs/icheck.c +=================================================================== +--- e2fsprogs.orig/debugfs/icheck.c ++++ e2fsprogs/debugfs/icheck.c +@@ -106,13 +106,15 @@ void do_icheck(int argc, char **argv) + } + + while (ino) { ++ blk64_t blk; ++ + if (!inode.i_links_count) + goto next; + + bw.inode = ino; + +- if (ext2fs_file_acl_block(&inode)) { +- blk64_t blk; ++ blk = ext2fs_file_acl_block(&inode); ++ if (blk) { + icheck_proc(current_fs, &blk, 0, + 0, 0, &bw); + if (bw.blocks_left == 0) +Index: e2fsprogs/e2fsck/message.c +=================================================================== +--- e2fsprogs.orig/e2fsck/message.c ++++ e2fsprogs/e2fsck/message.c +@@ -263,7 +263,6 @@ static _INLINE_ void expand_inode_expres + { + struct ext2_inode *inode; + struct ext2_inode_large *large_inode; +- time_t t; + + if (!ctx || !ctx->inode) + goto no_inode; +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -404,7 +404,7 @@ static void check_is_really_dir(e2fsck_t + struct ext2_dir_entry *dirent; + const char *old_op; + errcode_t retval; +- blk64_t blk, first_dir_blk; ++ blk64_t blk; + unsigned int i, rec_len, not_device = 0; + int extent_fs; + +@@ -436,7 +436,8 @@ static void check_is_really_dir(e2fsck_t + * with it. + */ + +- extent_fs = (ctx->fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS); ++ extent_fs = (ctx->fs->super->s_feature_incompat & ++ EXT3_FEATURE_INCOMPAT_EXTENTS); + if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) { + /* extent mapped */ + if (ext2fs_bmap2(ctx->fs, pctx->ino, inode, 0, 0, 0, 0, +Index: e2fsprogs/e2fsck/pass2.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass2.c ++++ e2fsprogs/e2fsck/pass2.c +@@ -404,7 +404,8 @@ static int check_dotdot(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + ext2_ino_t ino, struct problem_context *pctx) + { +- int rec_len, problem = 0; ++ int problem = 0; ++ unsigned int rec_len; + + if (!dirent->inode) + problem = PR_2_MISSING_DOT_DOT; +Index: e2fsprogs/e2fsck/pass5.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass5.c ++++ e2fsprogs/e2fsck/pass5.c +@@ -77,7 +77,6 @@ static void e2fsck_discard_blocks(e2fsck + blk64_t start, blk64_t count) + { + ext2_filsys fs = ctx->fs; +- int ret = 0; + + /* + * If the filesystem has changed it means that there was an corruption +Index: e2fsprogs/e2fsck/rehash.c +=================================================================== +--- e2fsprogs.orig/e2fsck/rehash.c ++++ e2fsprogs/e2fsck/rehash.c +@@ -430,12 +430,13 @@ static errcode_t copy_dir_entries(e2fsck + return retval; + dirent = (struct ext2_dir_entry *) block_start; + prev_rec_len = 0; ++ rec_len = 0; + left = fs->blocksize; + slack = fd->compress ? 12 : + (fs->blocksize * ctx->htree_slack_percentage)/100; + if (slack < 12) + slack = 12; +- for (i=0; i < fd->num_array; i++) { ++ for (i = 0; i < fd->num_array; i++) { + ent = fd->harray + i; + if (ent->dir->inode == 0) + continue; +Index: e2fsprogs/e2fsprogs.spec.in +=================================================================== +--- e2fsprogs.orig/e2fsprogs.spec.in ++++ e2fsprogs/e2fsprogs.spec.in +@@ -135,6 +135,7 @@ exit 0 + %{_sbindir}/filefrag + %{_sbindir}/mklost+found + %{_sbindir}/e2freefrag ++%{_sbindir}/e4defrag + + %{_root_libdir}/libblkid.so.* + %{_root_libdir}/libcom_err.so.* +@@ -180,6 +181,7 @@ exit 0 + %{_mandir}/man8/tune2fs.8* + %{_mandir}/man8/filefrag.8* + %{_mandir}/man8/e2freefrag.8* ++%{_mandir}/man8/e4defrag.8* + + %files devel + %defattr(-,root,root) +@@ -212,6 +214,7 @@ exit 0 + %{_includedir}/blkid + %{_includedir}/e2p + %{_includedir}/et ++%{_includedir}/com_err.h + %{_includedir}/ext2fs + %{_includedir}/ss + %{_includedir}/uuid +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -28,6 +28,10 @@ extern "C" { + #if (!defined(__GNUC__) && !defined(__WATCOMC__)) + #define NO_INLINE_FUNCS + #endif ++ ++#ifndef _XOPEN_SOURCE ++#define _XOPEN_SOURCE 600 /* for posix_memalign() */ ++#endif + + /* + * Where the master copy of the superblock is located, and how big +@@ -1396,7 +1400,8 @@ _INLINE_ errcode_t ext2fs_get_memalign(u + + if (align == 0) + align = 8; +- if (retval = posix_memalign((void **) ptr, align, size)) { ++ retval = posix_memalign((void **)ptr, align, size); ++ if (retval != 0) { + if (retval == ENOMEM) + return EXT2_ET_NO_MEMORY; + return retval; +Index: e2fsprogs/lib/ext2fs/ext2fsP.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fsP.h ++++ e2fsprogs/lib/ext2fs/ext2fsP.h +@@ -138,6 +138,6 @@ extern errcode_t ext2fs_set_generic_bmap + extern errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bitmap, + __u64 start, unsigned int num, + void *out); +-extern int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func); ++extern void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap,const char *func); + + extern int ext2fs_mem_is_zero(const char *mem, size_t len); +Index: e2fsprogs/lib/ext2fs/fileio.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/fileio.c ++++ e2fsprogs/lib/ext2fs/fileio.c +@@ -377,7 +377,7 @@ errcode_t ext2fs_file_set_size2(ext2_fil + truncate_block = ((size + file->fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(file->fs->super)) + 1; + old_size = file->inode.i_size + +- ((blk64_t) file->inode.i_size_high) << 32; ++ ((blk64_t)file->inode.i_size_high << 32); + old_truncate = ((old_size + file->fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(file->fs->super)) + 1; + +Index: e2fsprogs/lib/ext2fs/gen_bitmap64.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/gen_bitmap64.c ++++ e2fsprogs/lib/ext2fs/gen_bitmap64.c +@@ -547,7 +547,7 @@ void ext2fs_unmark_block_bitmap_range2(e + bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num); + } + +-int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func) ++void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func) + { + #ifndef OMIT_COM_ERR + if (bitmap && bitmap->description) +Index: e2fsprogs/lib/ext2fs/openfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/openfs.c ++++ e2fsprogs/lib/ext2fs/openfs.c +@@ -353,7 +353,6 @@ errcode_t ext2fs_open2(const char *name, + */ + if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { +- struct ext2_group_desc *gd; + dgrp_t group; + + for (group = 0; group < fs->group_desc_count; group++) { +Index: e2fsprogs/lib/ext2fs/progress.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/progress.c ++++ e2fsprogs/lib/ext2fs/progress.c +@@ -77,8 +77,6 @@ void ext2fs_numeric_progress_close(ext2_ + struct ext2fs_numeric_progress_struct * progress, + const char *message) + { +- unsigned int len; +- + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS)) + return; + fprintf(stdout, "%.*s", (2*progress->log_max)+1, spaces); +Index: e2fsprogs/lib/ext2fs/unix_io.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/unix_io.c ++++ e2fsprogs/lib/ext2fs/unix_io.c +@@ -17,7 +17,9 @@ + + #define _LARGEFILE_SOURCE + #define _LARGEFILE64_SOURCE ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE ++#endif + + #include + #include +Index: e2fsprogs/misc/badblocks.c +=================================================================== +--- e2fsprogs.orig/misc/badblocks.c ++++ e2fsprogs/misc/badblocks.c +@@ -29,7 +29,9 @@ + * list. (Work done by David Beattie) + */ + ++#ifndef _GNU_SOURCE + #define _GNU_SOURCE /* for O_DIRECT */ ++#endif + + #ifndef O_LARGEFILE + #define O_LARGEFILE 0 +Index: e2fsprogs/misc/e2undo.c +=================================================================== +--- e2fsprogs.orig/misc/e2undo.c ++++ e2fsprogs/misc/e2undo.c +@@ -29,12 +29,11 @@ unsigned char blksize_key[] = "filesyste + + char *prg_name; + +-static void usage(char *prg_name) ++static void usage(void) + { + fprintf(stderr, + _("Usage: %s \n"), prg_name); + exit(1); +- + } + + static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel) +@@ -145,12 +144,12 @@ int main(int argc, char *argv[]) + force = 1; + break; + default: +- usage(prg_name); ++ usage(); + } + } + +- if (argc != optind+2) +- usage(prg_name); ++ if (argc != optind + 2) ++ usage(); + + tdb_file = argv[optind]; + device_name = argv[optind+1]; +Index: e2fsprogs/misc/tune2fs.8.in +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.8.in ++++ e2fsprogs/misc/tune2fs.8.in +@@ -491,6 +491,10 @@ The following filesystem features can be + .B dir_index + Use hashed b-trees to speed up lookups in large directories. + .TP ++.B dir_nlink ++Allow directories to have more than 65000 subdirectories (read-only ++compatible). ++.TP + .B filetype + Store file type information in directory entries. + .TP +Index: e2fsprogs/misc/tune2fs.c +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.c ++++ e2fsprogs/misc/tune2fs.c +@@ -348,7 +348,6 @@ static void update_feature_set(ext2_fils + { + struct ext2_super_block *sb = fs->super; + struct ext2_group_desc *gd; +- errcode_t retval; + __u32 old_features[3]; + int i, type_err; + unsigned int mask_err; +@@ -1097,7 +1096,7 @@ static int move_block(ext2_filsys fs, ex + { + + char *buf; +- dgrp_t group; ++ dgrp_t group = 0; + errcode_t retval; + int meta_data = 0; + blk64_t blk, new_blk, goal; diff --git a/patches/e2fsprogs-mmp.patch b/patches/e2fsprogs-mmp.patch new file mode 100644 index 0000000..d29ab5f --- /dev/null +++ b/patches/e2fsprogs-mmp.patch @@ -0,0 +1,1828 @@ +Add multi-mount protection support to libext2fs (INCOMPAT_MMP feature). + +This allows mke2fs, e2fsck, and others to detect if the filesystem is +mounted on a remote node (on SAN disks) and avoid corrupting the +filesystem. For e2fsprogs this only means that it check the MMP block +to see if the filesystem is in use, and mark the filesystem busy while +e2fsck is running on the system. + +There is no requirement that e2fsck updates the MMP block in any regular +interval, but e2fsck does this occasionally to provide additional +information to the sysadmin in case of conflict. + +Signed-off-by: Kalpak Shah +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/e2p/feature.c +=================================================================== +--- e2fsprogs.orig/lib/e2p/feature.c ++++ e2fsprogs/lib/e2p/feature.c +@@ -73,7 +73,9 @@ static struct feature feature_list[] = { + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT, + "64bit" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG, +- "flex_bg"}, ++ "flex_bg"}, ++ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP, ++ "mmp" }, + { 0, 0, 0 }, + }; + +Index: e2fsprogs/lib/ext2fs/ext2_fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_fs.h ++++ e2fsprogs/lib/ext2fs/ext2_fs.h +@@ -597,7 +597,7 @@ struct ext2_super_block { + __u16 s_want_extra_isize; /* New inodes should reserve # bytes */ + __u32 s_flags; /* Miscellaneous flags */ + __u16 s_raid_stride; /* RAID stride */ +- __u16 s_mmp_interval; /* # seconds to wait in MMP checking */ ++ __u16 s_mmp_update_interval; /* # seconds to wait in MMP checking */ + __u64 s_mmp_block; /* Block for multi-mount protection */ + __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ + __u8 s_log_groups_per_flex; /* FLEX_BG group size */ +@@ -696,7 +696,8 @@ struct ext2_super_block { + + + #define EXT2_FEATURE_COMPAT_SUPP 0 +-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) ++#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ ++ EXT4_FEATURE_INCOMPAT_MMP) + #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ +@@ -780,26 +781,34 @@ struct ext2_dir_entry_2 { + /* + * This structure will be used for multiple mount protection. It will be + * written into the block number saved in the s_mmp_block field in the +- * superblock. +- */ +-#define EXT2_MMP_MAGIC 0x004D4D50 /* ASCII for MMP */ +-#define EXT2_MMP_CLEAN 0xFF4D4D50 /* Value of mmp_seq for clean unmount */ +-#define EXT2_MMP_FSCK_ON 0xE24D4D50 /* Value of mmp_seq when being fscked */ ++ * superblock. Programs that check MMP should assume that if SEQ_FSCK ++ * (or any unknown code above SEQ_MAX) is present then it is NOT safe ++ * to use the filesystem, regardless of how old the timestamp is. ++ */ ++#define EXT2_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */ ++#define EXT2_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */ ++#define EXT2_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */ ++#define EXT2_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */ + + struct mmp_struct { +- __u32 mmp_magic; +- __u32 mmp_seq; +- __u64 mmp_time; +- char mmp_nodename[64]; +- char mmp_bdevname[32]; +- __u16 mmp_interval; ++ __u32 mmp_magic; /* Magic number for MMP */ ++ __u32 mmp_seq; /* Sequence no. updated periodically */ ++ __u64 mmp_time; /* Time last updated */ ++ char mmp_nodename[64]; /* Node which last updated MMP block */ ++ char mmp_bdevname[32]; /* Bdev which last updated MMP block */ ++ __u16 mmp_check_interval; /* Changed mmp_check_interval */ + __u16 mmp_pad1; +- __u32 mmp_pad2; ++ __u32 mmp_pad2[227]; + }; + + /* +- * Interval in number of seconds to update the MMP sequence number. ++ * Default interval in seconds to update the MMP sequence number. ++ */ ++#define EXT2_MMP_UPDATE_INTERVAL 1 ++ ++/* ++ * Minimum interval for MMP checking in seconds. + */ +-#define EXT2_MMP_DEF_INTERVAL 5 ++#define EXT2_MMP_MIN_CHECK_INTERVAL 5 + + #endif /* _LINUX_EXT2_FS_H */ +Index: e2fsprogs/lib/ext2fs/ext2fs.h +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2fs.h ++++ e2fsprogs/lib/ext2fs/ext2fs.h +@@ -188,6 +188,7 @@ typedef struct ext2_file *ext2_file_t; + #define EXT2_FLAG_64BITS 0x20000 + #define EXT2_FLAG_PRINT_PROGRESS 0x40000 + #define EXT2_FLAG_DIRECT_IO 0x80000 ++#define EXT2_FLAG_SKIP_MMP 0x100000 + + /* + * Special flag in the ext2 inode i_flag field that means that this is +@@ -203,6 +204,15 @@ typedef struct ext2_file *ext2_file_t; + + struct opaque_ext2_group_desc; + ++/* ++ * The timestamp in the MMP structure will be updated by e2fsck at some ++ * arbitary intervals (start of passes, after every EXT2_MMP_INODE_INTERVAL ++ * inodes in pass1 and pass1b). There is no guarantee that e2fsck is updating ++ * the MMP block in a timely manner, and the updates it does are purely for ++ * the convenience of the sysadmin and not for automatic validation. ++ */ ++#define EXT2_MMP_INODE_INTERVAL 20000 ++ + struct struct_ext2_filsys { + errcode_t magic; + io_channel io; +@@ -249,6 +259,19 @@ struct struct_ext2_filsys { + io_channel image_io; + + /* ++ * Buffers for Multiple mount protection(MMP) block. ++ */ ++ void *mmp_buf; ++ void *mmp_unaligned_buf; ++ void *mmp_cmp; ++ int mmp_fd; ++ ++ /* ++ * Time at which e2fsck last updated the MMP block. ++ */ ++ long mmp_last_written; ++ ++ /* + * More callback functions + */ + errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal, +@@ -547,6 +570,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT3_FEATURE_INCOMPAT_RECOVER|\ + EXT3_FEATURE_INCOMPAT_EXTENTS|\ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ ++ EXT4_FEATURE_INCOMPAT_MMP|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #else + #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ +@@ -555,6 +579,7 @@ typedef struct ext2_icount *ext2_icount_ + EXT3_FEATURE_INCOMPAT_RECOVER|\ + EXT3_FEATURE_INCOMPAT_EXTENTS|\ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ ++ EXT4_FEATURE_INCOMPAT_MMP|\ + EXT4_FEATURE_INCOMPAT_64BIT) + #endif + #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ +@@ -1300,6 +1325,16 @@ errcode_t ext2fs_link(ext2_filsys fs, ex + errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags); + ++/* mmp.c */ ++errcode_t ext2fs_mmp_read(ext2_filsys fs, blk_t mmp_blk, void *buf); ++errcode_t ext2fs_mmp_write(ext2_filsys fs, blk_t mmp_blk, void *buf); ++errcode_t ext2fs_mmp_clear(ext2_filsys fs); ++errcode_t ext2fs_mmp_init(ext2_filsys fs); ++errcode_t ext2fs_mmp_start(ext2_filsys fs); ++errcode_t ext2fs_mmp_update(ext2_filsys fs); ++errcode_t ext2fs_mmp_stop(ext2_filsys fs); ++unsigned ext2fs_mmp_new_seq(); ++ + /* read_bb.c */ + extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, + ext2_badblocks_list *bb_list); +@@ -1335,6 +1370,7 @@ extern void ext2fs_swap_inode_full(ext2_ + int bufsize); + extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t, + struct ext2_inode *f, int hostorder); ++extern void ext2fs_swap_mmp(struct mmp_struct *mmp); + + /* valid_blk.c */ + extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); +Index: e2fsprogs/lib/ext2fs/tst_super_size.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/tst_super_size.c ++++ e2fsprogs/lib/ext2fs/tst_super_size.c +@@ -100,7 +100,7 @@ void check_superblock_fields() + check_field(s_want_extra_isize); + check_field(s_flags); + check_field(s_raid_stride); +- check_field(s_mmp_interval); ++ check_field(s_mmp_update_interval); + check_field(s_mmp_block); + check_field(s_raid_stripe_width); + check_field(s_log_groups_per_flex); +Index: e2fsprogs/misc/tune2fs.c +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.c ++++ e2fsprogs/misc/tune2fs.c +@@ -64,8 +64,9 @@ char *device_name; + char *new_label, *new_last_mounted, *new_UUID; + char *io_options; + static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag; +-static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag; ++static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag, p_flag; + static int I_flag; ++static int clear_mmp; + static time_t last_check_time; + static int print_label; + static int max_mount_count, mount_count, mount_flags; +@@ -75,6 +76,7 @@ static double reserved_ratio; + static unsigned long resgid, resuid; + static unsigned short errors; + static int open_flag; ++static unsigned int mmp_update_interval; + static char *features_cmd; + static char *mntopts_cmd; + static int stride, stripe_width; +@@ -107,7 +109,7 @@ static void usage(void) + "[-g group]\n" + "\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n" + "\t[-m reserved_blocks_percent] " +- "[-o [^]mount_options[,...]] \n" ++ "[-o [^]mount_options[,...]] [-p mmp_update_interval]\n" + "\t[-r reserved_blocks_count] [-u user] [-C mount_count] " + "[-L volume_label]\n" + "\t[-M last_mounted_dir] [-O [^]feature[,...]]\n" +@@ -123,7 +125,8 @@ static __u32 ok_features[3] = { + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT3_FEATURE_INCOMPAT_EXTENTS | +- EXT4_FEATURE_INCOMPAT_FLEX_BG, ++ EXT4_FEATURE_INCOMPAT_FLEX_BG | ++ EXT4_FEATURE_INCOMPAT_MMP, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT4_FEATURE_RO_COMPAT_HUGE_FILE| +@@ -140,7 +143,8 @@ static __u32 clear_ok_features[3] = { + EXT2_FEATURE_COMPAT_DIR_INDEX, + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE | +- EXT4_FEATURE_INCOMPAT_FLEX_BG, ++ EXT4_FEATURE_INCOMPAT_FLEX_BG | ++ EXT4_FEATURE_INCOMPAT_MMP, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT4_FEATURE_RO_COMPAT_HUGE_FILE| +@@ -152,7 +156,7 @@ static __u32 clear_ok_features[3] = { + /* + * Remove an external journal from the filesystem + */ +-static void remove_journal_device(ext2_filsys fs) ++static int remove_journal_device(ext2_filsys fs) + { + char *journal_path; + ext2_filsys jfs; +@@ -241,13 +245,15 @@ static void remove_journal_device(ext2_f + no_valid_journal: + if (commit_remove_journal == 0) { + fputs(_("Journal NOT removed\n"), stderr); +- exit(1); ++ return 1; + } + fs->super->s_journal_dev = 0; + uuid_clear(fs->super->s_journal_uuid); + ext2fs_mark_super_dirty(fs); + fputs(_("Journal removed\n"), stdout); + free(journal_path); ++ ++ return 0; + } + + /* Helper function for remove_journal_inode */ +@@ -272,7 +278,7 @@ static int release_blocks_proc(ext2_fils + /* + * Remove the journal inode from the filesystem + */ +-static void remove_journal_inode(ext2_filsys fs) ++static errcode_t remove_journal_inode(ext2_filsys fs) + { + struct ext2_inode inode; + errcode_t retval; +@@ -282,14 +288,14 @@ static void remove_journal_inode(ext2_fi + if (retval) { + com_err(program_name, retval, + _("while reading journal inode")); +- exit(1); ++ return retval; + } + if (ino == EXT2_JOURNAL_INO) { + retval = ext2fs_read_bitmaps(fs); + if (retval) { + com_err(program_name, retval, + _("while reading bitmaps")); +- exit(1); ++ return retval; + } + retval = ext2fs_block_iterate3(fs, ino, + BLOCK_FLAG_READ_ONLY, NULL, +@@ -297,7 +303,7 @@ static void remove_journal_inode(ext2_fi + if (retval) { + com_err(program_name, retval, + _("while clearing journal inode")); +- exit(1); ++ return retval; + } + memset(&inode, 0, sizeof(inode)); + ext2fs_mark_bb_dirty(fs); +@@ -308,25 +314,29 @@ static void remove_journal_inode(ext2_fi + if (retval) { + com_err(program_name, retval, + _("while writing journal inode")); +- exit(1); ++ return retval; + } + fs->super->s_journal_inum = 0; + ext2fs_mark_super_dirty(fs); ++ ++ return 0; + } + + /* + * Update the default mount options + */ +-static void update_mntopts(ext2_filsys fs, char *mntopts) ++static int update_mntopts(ext2_filsys fs, char *mntopts) + { + struct ext2_super_block *sb = fs->super; + + if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) { + fprintf(stderr, _("Invalid mount option set: %s\n"), + mntopts); +- exit(1); ++ return 1; + } + ext2fs_mark_super_dirty(fs); ++ ++ return 0; + } + + static void request_fsck_afterwards(ext2_filsys fs) +@@ -344,7 +354,7 @@ static void request_fsck_afterwards(ext2 + /* + * Update the feature set as provided by the user. + */ +-static void update_feature_set(ext2_filsys fs, char *features) ++static int update_feature_set(ext2_filsys fs, char *features) + { + struct ext2_super_block *sb = fs->super; + struct ext2_group_desc *gd; +@@ -380,7 +390,7 @@ static void update_feature_set(ext2_fils + fprintf(stderr, _("Setting filesystem feature '%s' " + "not supported.\n"), + e2p_feature2string(type_err, mask_err)); +- exit(1); ++ return 1; + } + + if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { +@@ -390,22 +400,89 @@ static void update_feature_set(ext2_fils + "cleared when the filesystem is\n" + "unmounted or mounted " + "read-only.\n"), stderr); +- exit(1); ++ return 1; + } + if (sb->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_RECOVER) { + fputs(_("The needs_recovery flag is set. " + "Please run e2fsck before clearing\n" + "the has_journal flag.\n"), stderr); +- exit(1); ++ return 1; + } + if (sb->s_journal_inum) { +- remove_journal_inode(fs); ++ if (remove_journal_inode(fs)) ++ return 1; + } + if (sb->s_journal_dev) { +- remove_journal_device(fs); ++ if (remove_journal_device(fs)) ++ return 1; + } + } ++ if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) { ++ int error; ++ ++ if ((mount_flags & EXT2_MF_MOUNTED) || ++ (mount_flags & EXT2_MF_READONLY)) { ++ fputs(_("The multiple mount protection feature can't \n" ++ "be set if the filesystem is mounted or \n" ++ "read-only.\n"), stderr); ++ return 1; ++ } ++ ++ error = ext2fs_mmp_init(fs); ++ if (error) { ++ fputs(_("\nError while enabling multiple mount " ++ "protection feature."), stderr); ++ return 1; ++ } ++ ++ /* ++ * We want to update group desc with the new free blocks count ++ */ ++ fs->flags &= ~EXT2_FLAG_SUPER_ONLY; ++ ++ printf(_("Multiple mount protection has been enabled " ++ "with update interval %ds.\n"), ++ sb->s_mmp_update_interval); ++ } ++ ++ if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) { ++ int error; ++ ++ if (mount_flags & EXT2_MF_READONLY) { ++ fputs(_("The multiple mount protection feature cannot\n" ++ "be disabled if the filesystem is readonly.\n"), ++ stderr); ++ return 1; ++ } ++ ++ error = ext2fs_read_bitmaps(fs); ++ if (error) { ++ fputs(_("Error while reading bitmaps\n"), stderr); ++ return 1; ++ } ++ ++ error = ext2fs_mmp_read(fs, sb->s_mmp_block, NULL); ++ if (error) { ++ struct mmp_struct *mmp_cmp = fs->mmp_cmp; ++ ++ if (error == EXT2_ET_MMP_MAGIC_INVALID) ++ printf(_("Magic number in MMP block does not " ++ "match. expected: %x, actual: %x\n"), ++ EXT2_MMP_MAGIC, mmp_cmp->mmp_magic); ++ else ++ com_err (program_name, error, ++ _("while reading MMP block.")); ++ goto mmp_error; ++ } ++ ++ /* We need to force out the group descriptors as well */ ++ fs->flags &= ~EXT2_FLAG_SUPER_ONLY; ++ ext2fs_block_alloc_stats(fs, sb->s_mmp_block, -1); ++mmp_error: ++ sb->s_mmp_block = 0; ++ sb->s_mmp_update_interval = 0; ++ } + + if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { + /* +@@ -497,12 +574,14 @@ static void update_feature_set(ext2_fils + (old_features[E2P_FEATURE_INCOMPAT] != sb->s_feature_incompat) || + (old_features[E2P_FEATURE_RO_INCOMPAT] != sb->s_feature_ro_compat)) + ext2fs_mark_super_dirty(fs); ++ ++ return 0; + } + + /* + * Add a journal to the filesystem. + */ +-static void add_journal(ext2_filsys fs) ++static int add_journal(ext2_filsys fs) + { + unsigned long journal_blocks; + errcode_t retval; +@@ -557,7 +636,7 @@ static void add_journal(ext2_filsys fs) + fprintf(stderr, "\n"); + com_err(program_name, retval, + _("\n\twhile trying to create journal file")); +- exit(1); ++ return retval; + } else + fputs(_("done\n"), stdout); + /* +@@ -568,11 +647,11 @@ static void add_journal(ext2_filsys fs) + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + } + print_check_message(fs); +- return; ++ return 0; + + err: + free(journal_device); +- exit(1); ++ return 1; + } + + +@@ -640,7 +719,7 @@ static void parse_tune2fs_options(int ar + open_flag = 0; + + printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); +- while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:T:U:")) != EOF) ++ while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:p:r:s:u:C:E:I:J:L:M:O:T:U:")) != EOF) + switch (c) { + case 'c': + max_mount_count = strtol(optarg, &tmp, 0); +@@ -795,6 +874,25 @@ static void parse_tune2fs_options(int ar + features_cmd = optarg; + open_flag = EXT2_FLAG_RW; + break; ++ case 'p': ++ mmp_update_interval = strtol(optarg, &tmp, 0); ++ if (*tmp && mmp_update_interval < 0) { ++ com_err(program_name, 0, ++ _("invalid mmp update interval")); ++ usage(); ++ } ++ if (mmp_update_interval == 0) ++ mmp_update_interval = EXT2_MMP_UPDATE_INTERVAL; ++ if (mmp_update_interval > EXT2_MMP_UPDATE_INTERVAL) { ++ com_err(program_name, 0, ++ _("MMP update interval of %s seconds " ++ "may be dangerous under high load. " ++ "Consider decreasing it."), ++ optarg); ++ } ++ p_flag = 1; ++ open_flag = EXT2_FLAG_RW; ++ break; + case 'r': + reserved_blocks = strtoul(optarg, &tmp, 0); + if (*tmp) { +@@ -899,7 +997,7 @@ void do_findfs(int argc, char **argv) + } + #endif + +-static void parse_extended_opts(ext2_filsys fs, const char *opts) ++static int parse_extended_opts(ext2_filsys fs, const char *opts) + { + char *buf, *token, *next, *p, *arg; + int len, hash_alg; +@@ -910,7 +1008,7 @@ static void parse_extended_opts(ext2_fil + if (!buf) { + fprintf(stderr, + _("Couldn't allocate memory to parse options!\n")); +- exit(1); ++ return 1; + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { +@@ -933,6 +1031,9 @@ static void parse_extended_opts(ext2_fil + fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS; + printf("Clearing test filesystem flag\n"); + ext2fs_mark_super_dirty(fs); ++ } else if (strcmp(token, "clear-mmp") == 0 || ++ strcmp(token, "clear_mmp") == 0) { ++ clear_mmp = 1; + } else if (strcmp(token, "stride") == 0) { + if (!arg) { + r_usage++; +@@ -1002,15 +1103,18 @@ static void parse_extended_opts(ext2_fil + "and may take an argument which\n" + "\tis set off by an equals ('=') sign.\n\n" + "Valid extended options are:\n" ++ "\tclear-mmp\n" + "\tstride=\n" + "\tstripe_width=\n" + "\thash_alg=\n" + "\ttest_fs\n" + "\t^test_fs\n")); + free(buf); +- exit(1); ++ return 1; + } + free(buf); ++ ++ return 0; + } + + /* +@@ -1590,6 +1694,7 @@ int main(int argc, char **argv) + ext2_filsys fs; + struct ext2_super_block *sb; + io_manager io_ptr, io_ptr_orig = NULL; ++ int rc = 0; + + #ifdef ENABLE_NLS + setlocale(LC_MESSAGES, ""); +@@ -1619,14 +1724,26 @@ int main(int argc, char **argv) + io_ptr = unix_io_manager; + + retry_open: ++ if ((open_flag & EXT2_FLAG_RW) == 0 || f_flag) ++ open_flag |= EXT2_FLAG_SKIP_MMP; ++ + retval = ext2fs_open2(device_name, io_options, open_flag, + 0, 0, io_ptr, &fs); + if (retval) { +- com_err(program_name, retval, +- _("while trying to open %s"), ++ com_err(program_name, retval, ++ _("while trying to open %s"), + device_name); +- fprintf(stderr, +- _("Couldn't find valid filesystem superblock.\n")); ++ if (retval == EXT2_ET_MMP_FSCK_ON) ++ fprintf(stderr, ++ _("If you are sure e2fsck is not running then " ++ "use 'tune2fs -f -E clear_mmp {device}'\n")); ++ else if (retval == EXT2_ET_MMP_MAGIC_INVALID) ++ fprintf(stderr, ++ _("Magic for mmp is wrong. Try to fix it by " ++ "using 'fsck {device}'\n")); ++ else if (retval != EXT2_ET_MMP_FAILED) ++ fprintf(stderr, ++ _("Couldn't find valid filesystem superblock.\n")); + exit(1); + } + +@@ -1639,12 +1756,14 @@ retry_open: + if (new_inode_size == EXT2_INODE_SIZE(fs->super)) { + fprintf(stderr, _("The inode size is already %lu\n"), + new_inode_size); +- exit(1); ++ rc = 1; ++ goto closefs; + } + if (new_inode_size < EXT2_INODE_SIZE(fs->super)) { + fprintf(stderr, _("Shrinking the inode size is " + "not supported\n")); +- exit(1); ++ rc = 1; ++ goto closefs; + } + + /* +@@ -1653,8 +1772,10 @@ retry_open: + */ + io_ptr_orig = io_ptr; + retval = tune2fs_setup_tdb(device_name, &io_ptr); +- if (retval) +- exit(1); ++ if (retval) { ++ rc = 1; ++ goto closefs; ++ } + if (io_ptr != io_ptr_orig) { + ext2fs_close(fs); + goto retry_open; +@@ -1669,7 +1790,7 @@ retry_open: + printf("%.*s\n", (int) sizeof(sb->s_volume_name), + sb->s_volume_name); + remove_error_table(&et_ext2_error_table); +- exit(0); ++ goto closefs; + } + + retval = ext2fs_check_if_mounted(device_name, &mount_flags); +@@ -1677,7 +1798,8 @@ retry_open: + com_err("ext2fs_check_if_mount", retval, + _("while determining whether %s is mounted."), + device_name); +- exit(1); ++ rc = 1; ++ goto closefs; + } + /* Normally we only need to write out the superblock */ + fs->flags |= EXT2_FLAG_SUPER_ONLY; +@@ -1716,12 +1838,19 @@ retry_open: + printf (_("Setting reserved blocks percentage to %g%% (%llu blocks)\n"), + reserved_ratio, ext2fs_r_blocks_count(sb)); + } ++ if (p_flag) { ++ sb->s_mmp_update_interval = mmp_update_interval; ++ ext2fs_mark_super_dirty(fs); ++ printf(_("Setting multiple mount protection update interval to " ++ "%u seconds\n"), mmp_update_interval); ++ } + if (r_flag) { + if (reserved_blocks >= ext2fs_blocks_count(sb)/2) { + com_err(program_name, 0, + _("reserved blocks count is too big (%llu)"), + reserved_blocks); +- exit(1); ++ rc = 1; ++ goto closefs; + } + ext2fs_r_blocks_count_set(sb, reserved_blocks); + ext2fs_mark_super_dirty(fs); +@@ -1745,7 +1874,8 @@ retry_open: + if (s_flag == 0) { + fputs(_("\nClearing the sparse superflag not supported.\n"), + stderr); +- exit(1); ++ rc = 1; ++ goto closefs; + } + if (T_flag) { + sb->s_lastcheck = last_check_time; +@@ -1773,14 +1903,36 @@ retry_open: + sizeof(sb->s_last_mounted)); + ext2fs_mark_super_dirty(fs); + } +- if (mntopts_cmd) +- update_mntopts(fs, mntopts_cmd); +- if (features_cmd) +- update_feature_set(fs, features_cmd); +- if (extended_cmd) +- parse_extended_opts(fs, extended_cmd); +- if (journal_size || journal_device) +- add_journal(fs); ++ if (mntopts_cmd) { ++ rc = update_mntopts(fs, mntopts_cmd); ++ if (rc) ++ goto closefs; ++ } ++ if (features_cmd) { ++ rc = update_feature_set(fs, features_cmd); ++ if (rc) ++ goto closefs; ++ } ++ if (extended_cmd) { ++ rc = parse_extended_opts(fs, extended_cmd); ++ if (rc) ++ goto closefs; ++ if (clear_mmp && !f_flag) { ++ fputs(_("Error in using clear_mmp. " ++ "It must be used with -f\n"), ++ stderr); ++ goto closefs; ++ } ++ } ++ if (clear_mmp) { ++ rc = ext2fs_mmp_clear(fs); ++ goto closefs; ++ } ++ if (journal_size || journal_device) { ++ rc = add_journal(fs); ++ if (rc); ++ goto closefs; ++ } + + if (U_flag) { + int set_csum = 0; +@@ -1808,7 +1960,8 @@ retry_open: + uuid_generate(sb->s_uuid); + } else if (uuid_parse(new_UUID, sb->s_uuid)) { + com_err(program_name, 0, _("Invalid UUID format\n")); +- exit(1); ++ rc = 1; ++ goto closefs; + } + if (set_csum) { + for (i = 0; i < fs->group_desc_count; i++) +@@ -1822,7 +1975,8 @@ retry_open: + fputs(_("The inode size may only be " + "changed when the filesystem is " + "unmounted.\n"), stderr); +- exit(1); ++ rc = 1; ++ goto closefs; + } + if (fs->super->s_feature_incompat & + EXT4_FEATURE_INCOMPAT_FLEX_BG) { +@@ -1868,5 +2022,12 @@ retry_open: + + free(device_name); + remove_error_table(&et_ext2_error_table); ++ ++closefs: ++ if (rc) { ++ ext2fs_mmp_stop(fs); ++ exit(1); ++ } ++ + return (ext2fs_close(fs) ? 1 : 0); + } +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -878,7 +878,20 @@ void e2fsck_pass1(e2fsck_t ctx) + (fs->super->s_mtime < fs->super->s_inodes_count)) + busted_fs_time = 1; + ++ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) && ++ !(fs->super->s_mmp_block <= fs->super->s_first_data_block || ++ fs->super->s_mmp_block >= fs->super->s_blocks_count)) ++ ext2fs_mark_block_bitmap2(ctx->block_found_map, ++ fs->super->s_mmp_block); ++ + while (1) { ++ if (ino % EXT2_MMP_INODE_INTERVAL == 0) { ++ errcode_t error; ++ ++ error = e2fsck_mmp_update(fs); ++ if (error) ++ fatal_error(ctx, 0); ++ } + old_op = ehandler_operation(_("getting next inode from scan")); + pctx.errcode = ext2fs_get_next_inode_full(scan, &ino, + inode, inode_size); +Index: e2fsprogs/e2fsck/pass1b.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1b.c ++++ e2fsprogs/e2fsck/pass1b.c +@@ -286,6 +286,13 @@ static void pass1b(e2fsck_t ctx, char *b + pb.pctx = &pctx; + pctx.str = "pass1b"; + while (1) { ++ if (ino % EXT2_MMP_INODE_INTERVAL == 0) { ++ errcode_t error; ++ ++ error = e2fsck_mmp_update(fs); ++ if (error) ++ fatal_error(ctx, 0); ++ } + pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); + if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) + continue; +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -1068,6 +1068,70 @@ static errcode_t try_open_fs(e2fsck_t ct + static const char *my_ver_string = E2FSPROGS_VERSION; + static const char *my_ver_date = E2FSPROGS_DATE; + ++int e2fsck_check_mmp(ext2_filsys fs, e2fsck_t ctx) ++{ ++ struct mmp_struct *mmp_s; ++ unsigned int mmp_check_interval; ++ errcode_t retval = 0; ++ struct problem_context pctx; ++ unsigned int wait_time = 0; ++ ++ clear_problem_context(&pctx); ++ if (fs->mmp_buf == NULL) { ++ retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); ++ if (retval) ++ goto check_error; ++ } ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto check_error; ++ ++ mmp_s = fs->mmp_buf; ++ ++ mmp_check_interval = fs->super->s_mmp_update_interval; ++ if (mmp_check_interval < EXT2_MMP_MIN_CHECK_INTERVAL) ++ mmp_check_interval = EXT2_MMP_MIN_CHECK_INTERVAL; ++ ++ /* ++ * If check_interval in MMP block is larger, use that instead of ++ * check_interval from the superblock. ++ */ ++ if (mmp_s->mmp_check_interval > mmp_check_interval) ++ mmp_check_interval = mmp_s->mmp_check_interval; ++ ++ wait_time = mmp_check_interval * 2 + 1; ++ ++ /* Print warning if e2fck will wait for more than 20 secs. */ ++ if (wait_time > EXT2_MMP_MIN_CHECK_INTERVAL * 4) { ++ printf("MMP interval is %u seconds and total wait time is %u " ++ "seconds. Please wait...\n", ++ mmp_check_interval, wait_time * 2); ++ } ++ ++ return 0; ++ ++check_error: ++ ++ if (retval == EXT2_ET_MMP_BAD_BLOCK) { ++ if (fix_problem(ctx, PR_0_MMP_INVALID_BLK, &pctx)) { ++ fs->super->s_mmp_block = 0; ++ ext2fs_mark_super_dirty(fs); ++ } ++ } else if (retval == EXT2_ET_MMP_FAILED) { ++ dump_mmp_msg(fs->mmp_buf, NULL); ++ } else if (retval == EXT2_ET_MMP_FSCK_ON) { ++ dump_mmp_msg(fs->mmp_buf, ++ _("If you are sure that e2fsck " ++ "is not running on any node then use " ++ "'tune2fs -f -E clear_mmp {device}'\n")); ++ } else if (retval == EXT2_ET_MMP_MAGIC_INVALID) { ++ if (fix_problem(ctx, PR_0_MMP_INVALID_MAGIC, &pctx)) ++ ext2fs_mmp_clear(fs); ++ } ++ return 1; ++} ++ + int main (int argc, char *argv[]) + { + errcode_t retval = 0, retval2 = 0, orig_retval = 0; +@@ -1137,6 +1201,8 @@ int main (int argc, char *argv[]) + _("need terminal for interactive repairs")); + } + ctx->superblock = ctx->use_superblock; ++ ++ flags = EXT2_FLAG_SKIP_MMP; + restart: + #ifdef CONFIG_TESTIO_DEBUG + if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { +@@ -1145,7 +1211,7 @@ restart: + } else + #endif + io_ptr = unix_io_manager; +- flags = EXT2_FLAG_NOFREE_ON_ERROR; ++ flags |= EXT2_FLAG_NOFREE_ON_ERROR; + profile_get_boolean(ctx->profile, "options", "old_bitmaps", 0, 0, + &old_bitmaps); + if (!old_bitmaps) +@@ -1319,6 +1385,21 @@ failure: + + ehandler_init(fs->io); + ++ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) && ++ (flags & EXT2_FLAG_SKIP_MMP)) { ++ if (e2fsck_check_mmp(fs, ctx)) ++ fatal_error(ctx, 0); ++ } ++ ++ /* ++ * Restart in order to reopen fs but this time start mmp. ++ */ ++ if (flags & EXT2_FLAG_SKIP_MMP) { ++ ext2fs_close(fs); ++ flags &=~EXT2_FLAG_SKIP_MMP; ++ goto restart; ++ } ++ + if ((ctx->mount_flags & EXT2_MF_MOUNTED) && + !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) + goto skip_journal; +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -414,6 +414,16 @@ static struct e2fsck_problem problem_tab + N_("Disable extra_isize feature since @f has 128 byte inodes.\n"), + PROMPT_NONE, 0 }, + ++ /* Superblock has invalid MMP block. */ ++ { PR_0_MMP_INVALID_BLK, ++ N_("@S has invalid MMP block. "), ++ PROMPT_CLEAR, PR_PREEN_OK }, ++ ++ /* Superblock has invalid MMP magic. */ ++ { PR_0_MMP_INVALID_MAGIC, ++ N_("@S has invalid MMP magic. "), ++ PROMPT_FIX, PR_PREEN_OK | PR_NO_OK}, ++ + + /* Pass 1 errors */ + +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -238,6 +238,11 @@ struct problem_context { + /* Clear EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE flag */ + #define PR_0_CLEAR_EXTRA_ISIZE 0x000042 + ++/* Superblock has invalid MMP block. */ ++#define PR_0_MMP_INVALID_BLK 0x000043 ++ ++/* Superblock has invalid MMP magic. */ ++#define PR_0_MMP_INVALID_MAGIC 0x000044 + + /* + * Pass 1 errors +Index: e2fsprogs/lib/ext2fs/swapfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/swapfs.c ++++ e2fsprogs/lib/ext2fs/swapfs.c +@@ -70,6 +70,8 @@ void ext2fs_swap_super(struct ext2_super + sb->s_min_extra_isize = ext2fs_swab16(sb->s_min_extra_isize); + sb->s_want_extra_isize = ext2fs_swab16(sb->s_want_extra_isize); + sb->s_flags = ext2fs_swab32(sb->s_flags); ++ sb->s_mmp_update_interval = ext2fs_swab16(sb->s_mmp_update_interval); ++ sb->s_mmp_block = ext2fs_swab64(sb->s_mmp_block); + sb->s_kbytes_written = ext2fs_swab64(sb->s_kbytes_written); + sb->s_snapshot_inum = ext2fs_swab32(sb->s_snapshot_inum); + sb->s_snapshot_id = ext2fs_swab32(sb->s_snapshot_id); +@@ -312,4 +314,12 @@ void ext2fs_swap_inode(ext2_filsys fs, s + sizeof(struct ext2_inode)); + } + ++void ext2fs_swap_mmp(struct mmp_struct *mmp) ++{ ++ mmp->mmp_magic = ext2fs_swab32(mmp->mmp_magic); ++ mmp->mmp_seq = ext2fs_swab32(mmp->mmp_seq); ++ mmp->mmp_time = ext2fs_swab64(mmp->mmp_time); ++ mmp->mmp_check_interval = ext2fs_swab16(mmp->mmp_check_interval); ++} ++ + #endif +Index: e2fsprogs/lib/ext2fs/ext2_err.et.in +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/ext2_err.et.in ++++ e2fsprogs/lib/ext2fs/ext2_err.et.in +@@ -446,4 +446,25 @@ ec EXT2_ET_EA_NAME_NOT_FOUND, + ec EXT2_ET_EA_NAME_EXISTS, + "Extended attribute name already exists" + ++ec EXT2_ET_MMP_MAGIC_INVALID, ++ "MMP: invalid magic number" ++ ++ec EXT2_ET_MMP_FAILED, ++ "MMP: device currently active" ++ ++ec EXT2_ET_MMP_FSCK_ON, ++ "MMP: fsck being run" ++ ++ec EXT2_ET_MMP_BAD_BLOCK, ++ "MMP: block number beyond filesystem range" ++ ++ec EXT2_ET_MMP_UNKNOWN_SEQ, ++ "MMP: undergoing an unknown operation" ++ ++ec EXT2_ET_MMP_CHANGE_ABORT, ++ "MMP: filesystem still in use" ++ ++ec EXT2_ET_MMP_OPEN_DIRECT, ++ "MMP: open with O_DIRECT failed" ++ + end +Index: e2fsprogs/lib/ext2fs/openfs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/openfs.c ++++ e2fsprogs/lib/ext2fs/openfs.c +@@ -22,6 +22,9 @@ + #if HAVE_SYS_TYPES_H + #include + #endif ++#ifdef HAVE_ERRNO_H ++#include ++#endif + + #include "ext2_fs.h" + +@@ -82,6 +85,7 @@ errcode_t ext2fs_open(const char *name, + * EXT2_FLAG_FORCE - Open the filesystem even if some of the + * features aren't supported. + * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device ++ * EXT2_FLAG_SKIP_MMP - Open without multi-mount protection check. + */ + errcode_t ext2fs_open2(const char *name, const char *io_options, + int flags, int superblock, +@@ -365,6 +369,18 @@ errcode_t ext2fs_open2(const char *name, + + fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; + *ret_fs = fs; ++ ++ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) && ++ !(flags & EXT2_FLAG_SKIP_MMP) ++ && (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) { ++ retval = ext2fs_mmp_start(fs); ++ if (retval) { ++ fs->flags |= EXT2_FLAG_SKIP_MMP; /* just do cleanup */ ++ ext2fs_mmp_stop(fs); ++ goto cleanup; ++ } ++ } ++ + return 0; + cleanup: + if (flags & EXT2_FLAG_NOFREE_ON_ERROR) +Index: e2fsprogs/lib/ext2fs/closefs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/closefs.c ++++ e2fsprogs/lib/ext2fs/closefs.c +@@ -455,6 +455,11 @@ errcode_t ext2fs_close(ext2_filsys fs) + if (retval) + return retval; + } ++ ++ retval = ext2fs_mmp_stop(fs); ++ if (retval) ++ return retval; ++ + ext2fs_free(fs); + return 0; + } +Index: e2fsprogs/e2fsck/e2fsck.c +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.c ++++ e2fsprogs/e2fsck/e2fsck.c +@@ -202,6 +202,7 @@ int e2fsck_run(e2fsck_t ctx) + { + int i; + pass_t e2fsck_pass; ++ int error; + + #ifdef HAVE_SETJMP_H + if (setjmp(ctx->abort_loc)) { +@@ -214,6 +215,9 @@ int e2fsck_run(e2fsck_t ctx) + for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) { + if (ctx->flags & E2F_FLAG_RUN_RETURN) + break; ++ error = e2fsck_mmp_update(ctx->fs); ++ if (error) ++ fatal_error(ctx, 0); + e2fsck_pass(ctx); + if (ctx->progress) + (void) (ctx->progress)(ctx, 0, 0, 0); +Index: e2fsprogs/e2fsck/e2fsck.h +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.h ++++ e2fsprogs/e2fsck/e2fsck.h +@@ -569,6 +569,8 @@ extern blk_t get_backup_sb(e2fsck_t ctx, + const char *name, io_manager manager); + extern int ext2_file_type(unsigned int mode); + extern int write_all(int fd, char *buf, size_t count); ++void dump_mmp_msg(struct mmp_struct *mmp, const char *msg); ++errcode_t e2fsck_mmp_update(ext2_filsys fs); + + /* unix.c */ + extern void e2fsck_clear_progbar(e2fsck_t ctx); +Index: e2fsprogs/e2fsck/util.c +=================================================================== +--- e2fsprogs.orig/e2fsck/util.c ++++ e2fsprogs/e2fsck/util.c +@@ -48,6 +48,7 @@ void fatal_error(e2fsck_t ctx, const cha + if (msg) + fprintf (stderr, "e2fsck: %s\n", msg); + if (ctx->fs && ctx->fs->io) { ++ ext2fs_mmp_stop(ctx->fs); + if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL) + io_channel_flush(ctx->fs->io); + else +@@ -709,3 +710,24 @@ int write_all(int fd, char *buf, size_t + } + return c; + } ++ ++void dump_mmp_msg(struct mmp_struct *mmp, const char *msg) ++{ ++ if (msg) ++ printf("MMP check failed: %s\n", msg); ++ printf("MMP failure info: last update time: %llu node: %s device: %s\n", ++ (long long)mmp->mmp_time, mmp->mmp_nodename, mmp->mmp_bdevname); ++} ++ ++errcode_t e2fsck_mmp_update(ext2_filsys fs) ++{ ++ errcode_t retval; ++ ++ retval = ext2fs_mmp_update(fs); ++ if (retval == EXT2_ET_MMP_CHANGE_ABORT) ++ dump_mmp_msg(fs->mmp_cmp, ++ _("UNEXPECTED INCONSISTENCY: the filesystem is " ++ "being modified while fsck is running.\n")); ++ ++ return retval; ++} +Index: e2fsprogs/lib/ext2fs/freefs.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/freefs.c ++++ e2fsprogs/lib/ext2fs/freefs.c +@@ -53,6 +53,11 @@ void ext2fs_free(ext2_filsys fs) + if (fs->icache) + ext2fs_free_inode_cache(fs->icache); + ++ if (fs->mmp_buf) ++ ext2fs_free_mem(&fs->mmp_buf); ++ if (fs->mmp_unaligned_buf) ++ ext2fs_free_mem(&fs->mmp_unaligned_buf); ++ + fs->magic = 0; + + ext2fs_free_mem(&fs); +Index: e2fsprogs/lib/ext2fs/Makefile.in +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/Makefile.in ++++ e2fsprogs/lib/ext2fs/Makefile.in +@@ -64,6 +64,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_O + lookup.o \ + mkdir.o \ + mkjournal.o \ ++ mmp.o \ + namei.o \ + native.o \ + newdir.o \ +@@ -132,6 +133,7 @@ SRCS= ext2_err.c \ + $(srcdir)/lookup.c \ + $(srcdir)/mkdir.c \ + $(srcdir)/mkjournal.c \ ++ $(srcdir)/mmp.c \ + $(srcdir)/namei.c \ + $(srcdir)/native.c \ + $(srcdir)/newdir.c \ +@@ -646,6 +648,8 @@ mkjournal.o: $(srcdir)/mkjournal.c $(src + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/bitops.h $(srcdir)/jfs_user.h $(srcdir)/kernel-jbd.h \ + $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h ++mmp.o: $(srcdir)/ext2_fs.h $(srcdir)/ext2fs.h \ ++ $(top_builddir)/lib/ext2fs/ext2_err.h + namei.o: $(srcdir)/namei.c $(srcdir)/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ +Index: e2fsprogs/lib/ext2fs/mmp.c +=================================================================== +--- /dev/null ++++ e2fsprogs/lib/ext2fs/mmp.c +@@ -0,0 +1,420 @@ ++/* ++ * Helper functions for multiple mount protection(MMP). ++ * ++ * Copyright (C) 2006, 2007 by Kalpak Shah ++ * ++ * %Begin-Header% ++ * This file may be redistributed under the terms of the GNU Public ++ * License. ++ * %End-Header% ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#include ++ ++#include ++#include ++#include ++ ++#include "ext2fs/ext2_fs.h" ++#include "ext2fs/ext2fs.h" ++ ++static int mmp_pagesize(void) ++{ ++#ifdef _SC_PAGESIZE ++ int sysval = sysconf(_SC_PAGESIZE); ++ if (sysval > 0) ++ return sysval; ++#endif /* _SC_PAGESIZE */ ++#ifdef HAVE_GETPAGESIZE ++ return getpagesize(); ++#else ++ return 4096; ++#endif ++} ++ ++#define ptr_align(ptr, size) (void *)(((unsigned long)(ptr) + (size) - 1) & \ ++ ~((unsigned long)(size) - 1)) ++#ifndef O_DIRECT ++#define O_DIRECT 0 ++#endif ++ ++errcode_t ext2fs_mmp_read(ext2_filsys fs, blk_t mmp_blk, void *buf) ++{ ++ struct mmp_struct *mmp_cmp; ++ errcode_t retval = 0; ++ ++ if ((mmp_blk <= fs->super->s_first_data_block) || ++ (mmp_blk >= fs->super->s_blocks_count)) ++ return EXT2_ET_MMP_BAD_BLOCK; ++ ++ if (fs->mmp_cmp == NULL) { ++ /* O_DIRECT in linux 2.4: page aligned ++ * O_DIRECT in linux 2.6: sector aligned ++ * A filesystem cannot be created with blocksize < sector size, ++ * or with blocksize > page_size. */ ++ int bufsize = fs->blocksize; ++ ++ if (bufsize < mmp_pagesize()) ++ bufsize = mmp_pagesize(); ++ retval = ext2fs_get_mem(bufsize * 2, &fs->mmp_unaligned_buf); ++ if (retval) ++ return retval; ++ fs->mmp_cmp = ptr_align(fs->mmp_unaligned_buf, bufsize); ++ } ++ ++ /* ext2fs_open reserves fd0,1,2 to avoid stdio collision */ ++ if (fs->mmp_fd <= 0) { ++ fs->mmp_fd = open(fs->device_name, O_RDWR | O_DIRECT); ++ if (fs->mmp_fd < 0) { ++ retval = EXT2_ET_MMP_OPEN_DIRECT; ++ goto out; ++ } ++ } ++ ++ if (ext2fs_llseek(fs->mmp_fd, mmp_blk * fs->blocksize, SEEK_SET) != ++ mmp_blk * fs->blocksize) { ++ retval = EXT2_ET_LLSEEK_FAILED; ++ goto out; ++ } ++ ++ if (read(fs->mmp_fd, fs->mmp_cmp, fs->blocksize) != fs->blocksize) { ++ retval = EXT2_ET_SHORT_READ; ++ goto out; ++ } ++ ++ mmp_cmp = fs->mmp_cmp; ++#ifdef EXT2FS_ENABLE_SWAPFS ++ if (fs->flags & EXT2_FLAG_SWAP_BYTES) ++ ext2fs_swap_mmp(mmp_cmp); ++#endif ++ ++ if (buf != NULL && buf != fs->mmp_cmp) ++ memcpy(buf, fs->mmp_cmp, fs->blocksize); ++ ++ if (mmp_cmp->mmp_magic != EXT2_MMP_MAGIC) { ++ retval = EXT2_ET_MMP_MAGIC_INVALID; ++ goto out; ++ } ++ ++out: ++ return retval; ++} ++ ++errcode_t ext2fs_mmp_write(ext2_filsys fs, blk_t mmp_blk, void *buf) ++{ ++ struct mmp_struct *mmp_s = buf; ++ struct timeval tv; ++ errcode_t retval = 0; ++ ++ gettimeofday(&tv, 0); ++ mmp_s->mmp_time = tv.tv_sec; ++ fs->mmp_last_written = tv.tv_sec; ++ ++#ifdef EXT2FS_ENABLE_SWAPFS ++ if (fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ++ ext2fs_swap_mmp(mmp_s); ++#endif ++ ++ /* I was tempted to make this use O_DIRECT and the mmp_fd, but ++ * this caused no end of grief, while leaving it as-is works. */ ++ retval = io_channel_write_blk(fs->io, mmp_blk, -fs->blocksize, buf); ++ ++#ifdef EXT2FS_ENABLE_SWAPFS ++ if (fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ++ ext2fs_swap_mmp(mmp_s); ++#endif ++ ++ /* Make sure the block gets to disk quickly */ ++ io_channel_flush(fs->io); ++ return retval; ++} ++ ++#ifdef HAVE_SRANDOM ++#define srand(x) srandom(x) ++#define rand() random() ++#endif ++ ++unsigned ext2fs_mmp_new_seq() ++{ ++ unsigned new_seq; ++ struct timeval tv; ++ ++ gettimeofday(&tv, 0); ++ srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); ++ ++ gettimeofday(&tv, 0); ++ /* Crank the random number generator a few times */ ++ for (new_seq = (tv.tv_sec ^ tv.tv_usec) & 0x1F; new_seq > 0; new_seq--) ++ rand(); ++ ++ do { ++ new_seq = rand(); ++ } while (new_seq > EXT2_MMP_SEQ_MAX); ++ ++ return new_seq; ++} ++ ++static errcode_t ext2fs_mmp_reset(ext2_filsys fs) ++{ ++ struct mmp_struct *mmp_s = NULL; ++ errcode_t retval = 0; ++ ++ if (fs->mmp_buf == NULL) { ++ retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); ++ if (retval) ++ goto out; ++ } ++ ++ memset(fs->mmp_buf, 0, fs->blocksize); ++ mmp_s = fs->mmp_buf; ++ ++ mmp_s->mmp_magic = EXT2_MMP_MAGIC; ++ mmp_s->mmp_seq = EXT2_MMP_SEQ_CLEAN; ++ mmp_s->mmp_time = 0; ++#if _BSD_SOURCE || _XOPEN_SOURCE >= 500 ++ gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename)); ++#else ++ mmp_s->mmp_nodename[0] = '\0'; ++#endif ++ strncpy(mmp_s->mmp_bdevname, fs->device_name, ++ sizeof(mmp_s->mmp_bdevname)); ++ ++ mmp_s->mmp_check_interval = fs->super->s_mmp_update_interval; ++ if (mmp_s->mmp_check_interval < EXT2_MMP_MIN_CHECK_INTERVAL) ++ mmp_s->mmp_check_interval = EXT2_MMP_MIN_CHECK_INTERVAL; ++ ++ retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); ++out: ++ return retval; ++} ++ ++errcode_t ext2fs_mmp_clear(ext2_filsys fs) ++{ ++ struct mmp_struct *mmp_s = NULL; ++ errcode_t retval = 0; ++ ++ if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) || ++ !(fs->flags & EXT2_FLAG_RW)) ++ return 0; ++ ++ retval = ext2fs_mmp_reset(fs); ++ ++ return retval; ++} ++ ++errcode_t ext2fs_mmp_init(ext2_filsys fs) ++{ ++ struct ext2_super_block *sb = fs->super; ++ struct mmp_struct *mmp_s = NULL; ++ blk_t mmp_block; ++ errcode_t retval; ++ ++ if (fs->mmp_buf == NULL) { ++ retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); ++ if (retval) ++ goto out; ++ } ++ ++ retval = ext2fs_alloc_block(fs, 0, fs->mmp_buf, &mmp_block); ++ if (retval) ++ goto out; ++ ++ sb->s_mmp_block = mmp_block; ++ sb->s_mmp_update_interval = EXT2_MMP_UPDATE_INTERVAL; ++ ++ retval = ext2fs_mmp_reset(fs); ++ if (retval) ++ goto out; ++ ++out: ++ return retval; ++} ++ ++/* ++ * Make sure that the fs is not mounted or being fsck'ed while opening the fs. ++ */ ++errcode_t ext2fs_mmp_start(ext2_filsys fs) ++{ ++ struct mmp_struct *mmp_s; ++ unsigned seq; ++ unsigned int mmp_check_interval; ++ errcode_t retval = 0; ++ ++ if (fs->mmp_buf == NULL) { ++ retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ } ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ mmp_s = fs->mmp_buf; ++ ++ mmp_check_interval = fs->super->s_mmp_update_interval; ++ if (mmp_check_interval < EXT2_MMP_MIN_CHECK_INTERVAL) ++ mmp_check_interval = EXT2_MMP_MIN_CHECK_INTERVAL; ++ ++ seq = mmp_s->mmp_seq; ++ if (seq == EXT2_MMP_SEQ_CLEAN) ++ goto clean_seq; ++ if (seq == EXT2_MMP_SEQ_FSCK) { ++ retval = EXT2_ET_MMP_FSCK_ON; ++ goto mmp_error; ++ } ++ ++ if (seq > EXT2_MMP_SEQ_FSCK) { ++ retval = EXT2_ET_MMP_UNKNOWN_SEQ; ++ goto mmp_error; ++ } ++ ++ /* ++ * If check_interval in MMP block is larger, use that instead of ++ * check_interval from the superblock. ++ */ ++ if (mmp_s->mmp_check_interval > mmp_check_interval) ++ mmp_check_interval = mmp_s->mmp_check_interval; ++ ++ sleep(2 * mmp_check_interval + 1); ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ if (seq != mmp_s->mmp_seq) { ++ retval = EXT2_ET_MMP_FAILED; ++ goto mmp_error; ++ } ++ ++clean_seq: ++ if (!(fs->flags & EXT2_FLAG_RW)) ++ goto mmp_error; ++ ++ mmp_s->mmp_seq = seq = ext2fs_mmp_new_seq(); ++#if _BSD_SOURCE || _XOPEN_SOURCE >= 500 ++ gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename)); ++#else ++ strcpy(mmp_s->mmp_nodename, "unknown host"); ++#endif ++ strncpy(mmp_s->mmp_bdevname, fs->device_name, ++ sizeof(mmp_s->mmp_bdevname)); ++ ++ retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ sleep(2 * mmp_check_interval + 1); ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ if (seq != mmp_s->mmp_seq) { ++ retval = EXT2_ET_MMP_FAILED; ++ goto mmp_error; ++ } ++ ++ mmp_s->mmp_seq = EXT2_MMP_SEQ_FSCK; ++ retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ return 0; ++ ++mmp_error: ++ return retval; ++} ++ ++/* ++ * Clear the MMP usage in the filesystem. If this function returns an ++ * error EXT2_ET_MMP_CHANGE_ABORT it means the filesystem was modified ++ * by some other process while in use, and changes should be dropped, or ++ * risk filesystem corruption. ++ */ ++errcode_t ext2fs_mmp_stop(ext2_filsys fs) ++{ ++ struct mmp_struct *mmp, *mmp_cmp; ++ errcode_t retval = 0; ++ ++ if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) || ++ !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP)) ++ goto mmp_error; ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ if (retval) ++ goto mmp_error; ++ ++ /* Check if the MMP block is not changed. */ ++ mmp = fs->mmp_buf; ++ mmp_cmp = fs->mmp_cmp; ++ if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp))) { ++ retval = EXT2_ET_MMP_CHANGE_ABORT; ++ goto mmp_error; ++ } ++ ++check_skipped: ++ mmp_cmp->mmp_seq = EXT2_MMP_SEQ_CLEAN; ++ retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_cmp); ++ ++mmp_error: ++ if (fs->mmp_fd > 0) { ++ close(fs->mmp_fd); ++ fs->mmp_fd = -1; ++ } ++ if (fs->mmp_buf) { ++ ext2fs_free_mem(&fs->mmp_buf); ++ fs->mmp_buf = NULL; ++ } ++ if (fs->mmp_unaligned_buf) { ++ ext2fs_free_mem(&fs->mmp_unaligned_buf); ++ fs->mmp_unaligned_buf = NULL; ++ fs->mmp_cmp = NULL; ++ } ++ ++ return retval; ++} ++ ++#define EXT2_MIN_MMP_UPDATE_INTERVAL 60 ++ ++/* ++ * Update the on-disk mmp buffer, after checking that it hasn't been changed. ++ */ ++errcode_t ext2fs_mmp_update(ext2_filsys fs) ++{ ++ struct mmp_struct *mmp, *mmp_cmp; ++ struct timeval tv; ++ errcode_t retval = 0; ++ ++ if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) || ++ !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP)) ++ return 0; ++ ++ gettimeofday(&tv, 0); ++ if (tv.tv_sec - fs->mmp_last_written < EXT2_MIN_MMP_UPDATE_INTERVAL) ++ return 0; ++ ++ retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, NULL); ++ if (retval) ++ goto mmp_error; ++ ++ mmp = fs->mmp_buf; ++ mmp_cmp = fs->mmp_cmp; ++ ++ if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp))) ++ return EXT2_ET_MMP_CHANGE_ABORT; ++ ++ mmp->mmp_time = tv.tv_sec; ++ mmp->mmp_seq = EXT2_MMP_SEQ_FSCK; ++ retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); ++ ++mmp_error: ++ return retval; ++} +Index: e2fsprogs/misc/tune2fs.8.in +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.8.in ++++ e2fsprogs/misc/tune2fs.8.in +@@ -167,6 +167,11 @@ separated, and may take an argument usin + The following extended options are supported: + .RS 1.2i + .TP ++.B clear-mmp ++Reset the MMP block (if any) back to the clean state. Use only if ++absolutely certain the device is not currently mounted or being ++fscked, or major filesystem corruption can result. Needs '-f'. ++.TP + .BI stride= stride-size + Configure the filesystem for a RAID array with + .I stride-size +@@ -523,6 +528,11 @@ future. + .B Tune2fs + only supports clearing this filesystem feature. + .TP ++.B mmp ++Enable or disable multiple mount protection(MMP) feature. MMP helps to protect ++the filesystem from being multiply mounted and is useful in shared storage ++environment. ++.TP + .B sparse_super + Limit the number of backup superblocks to save space on large filesystems. + .TP +@@ -559,6 +569,9 @@ and + .BR flex_bg + features are only supported by the ext4 filesystem. + .TP ++.BI \-p " mmp_check_interval" ++Set the desired MMP check interval in seconds. It is 5 seconds by default. ++.TP + .BI \-r " reserved-blocks-count" + Set the number of reserved filesystem blocks. + .TP +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -813,6 +813,7 @@ static __u32 ok_features[3] = { + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| + EXT2_FEATURE_INCOMPAT_META_BG| + EXT4_FEATURE_INCOMPAT_FLEX_BG| ++ EXT4_FEATURE_INCOMPAT_MMP | + EXT4_FEATURE_INCOMPAT_64BIT, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| +@@ -2381,8 +2382,20 @@ int main (int argc, char *argv[]) + } + no_journal: + +- if (!super_only) ++ if (!super_only) { + ext2fs_set_gdt_csum(fs); ++ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) { ++ retval = ext2fs_mmp_init(fs); ++ if (retval) { ++ fprintf(stderr, _("\nError while enabling " ++ "multiple mount protection feature.")); ++ exit(1); ++ } ++ printf(_("Multiple mount protection has been enabled " ++ "with update interval %d seconds.\n"), ++ fs->super->s_mmp_update_interval); ++ } ++ } + if (!quiet) + printf(_("Writing superblocks and " + "filesystem accounting information: ")); +Index: e2fsprogs/lib/e2p/ls.c +=================================================================== +--- e2fsprogs.orig/lib/e2p/ls.c ++++ e2fsprogs/lib/e2p/ls.c +@@ -394,6 +394,12 @@ void list_super2(struct ext2_super_block + fprintf(f, "Last error block #: %llu\n", + sb->s_last_error_block); + } ++ if (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) { ++ fprintf(f, "MMP block number: %llu\n", ++ (long long)sb->s_mmp_block); ++ fprintf(f, "MMP update interval: %u\n", ++ sb->s_mmp_update_interval); ++ } + } + + void list_super (struct ext2_super_block * s) +Index: e2fsprogs/debugfs/set_fields.c +=================================================================== +--- e2fsprogs.orig/debugfs/set_fields.c ++++ e2fsprogs/debugfs/set_fields.c +@@ -130,7 +130,7 @@ static struct field_set_info super_field + { "flags", &set_sb.s_flags, 4, parse_uint }, + { "raid_stride", &set_sb.s_raid_stride, 2, parse_uint }, + { "min_extra_isize", &set_sb.s_min_extra_isize, 4, parse_uint }, +- { "mmp_interval", &set_sb.s_mmp_interval, 2, parse_uint }, ++ { "mmp_update_interval", &set_sb.s_mmp_update_interval, 2, parse_uint }, + { "mmp_block", &set_sb.s_mmp_block, 8, parse_uint }, + { "raid_stripe_width", &set_sb.s_raid_stripe_width, 4, parse_uint }, + { "log_groups_per_flex", &set_sb.s_log_groups_per_flex, 1, parse_uint }, +Index: e2fsprogs/misc/util.c +=================================================================== +--- e2fsprogs.orig/misc/util.c ++++ e2fsprogs/misc/util.c +@@ -291,3 +291,11 @@ void print_check_message(ext2_filsys fs) + fs->super->s_max_mnt_count, + (double)fs->super->s_checkinterval / (3600 * 24)); + } ++ ++void dump_mmp_msg(struct mmp_struct *mmp, const char *msg) ++{ ++ if (msg) ++ printf("MMP check failed: %s\n", msg); ++ printf("MMP failure info: last update time: %llu node: %s device: %s\n", ++ (long long)mmp->mmp_time, mmp->mmp_nodename, mmp->mmp_bdevname); ++} +Index: e2fsprogs/e2fsck/journal.c +=================================================================== +--- e2fsprogs.orig/e2fsck/journal.c ++++ e2fsprogs/e2fsck/journal.c +@@ -881,6 +881,8 @@ int e2fsck_run_ext3_journal(e2fsck_t ctx + ctx->fs->io->manager->get_stats(ctx->fs->io, &stats); + if (stats && stats->bytes_written) + kbytes_written = stats->bytes_written >> 10; ++ ++ ext2fs_mmp_stop(ctx->fs); + ext2fs_free(ctx->fs); + retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW, + ctx->superblock, blocksize, io_ptr, +Index: e2fsprogs/debugfs/debug_cmds.ct +=================================================================== +--- e2fsprogs.orig/debugfs/debug_cmds.ct ++++ e2fsprogs/debugfs/debug_cmds.ct +@@ -163,5 +163,8 @@ request do_set_current_time, "Set curren + request do_supported_features, "Print features supported by this version of e2fsprogs", + supported_features; + ++request do_dump_mmp, "Dump MMP information", ++ dump_mmp; ++ + end; + +Index: e2fsprogs/debugfs/debugfs.c +=================================================================== +--- e2fsprogs.orig/debugfs/debugfs.c ++++ e2fsprogs/debugfs/debugfs.c +@@ -78,6 +78,8 @@ static void open_filesystem(char *device + "opening read-only because of catastrophic mode"); + open_flags &= ~EXT2_FLAG_RW; + } ++ if (catastrophic) ++ open_flags |= EXT2_FLAG_SKIP_MMP; + + retval = ext2fs_open(device, open_flags, superblock, blocksize, + unix_io_manager, ¤t_fs); +@@ -2127,6 +2129,39 @@ void do_punch(int argc, char *argv[]) + } + } + ++void do_dump_mmp(int argc, char *argv[]) ++{ ++ struct mmp_struct *mmp_s; ++ errcode_t retval = 0; ++ ++ if (current_fs->mmp_buf == NULL) { ++ retval = ext2fs_get_mem(current_fs->blocksize, ++ ¤t_fs->mmp_buf); ++ if (retval) { ++ com_err(argv[0], 0, "Could not allocate memory.\n"); ++ return; ++ } ++ } ++ ++ mmp_s = current_fs->mmp_buf; ++ ++ retval = ext2fs_mmp_read(current_fs, current_fs->super->s_mmp_block, ++ current_fs->mmp_buf); ++ if (retval) { ++ com_err(argv[0], retval, "Error reading MMP block.\n"); ++ return; ++ } ++ ++ fprintf(stdout, "MMP Block: %llu\n", current_fs->super->s_mmp_block); ++ fprintf(stdout, "MMP Update Interval: %d\n", ++ current_fs->super->s_mmp_update_interval); ++ fprintf(stdout, "MMP Check Interval: %d\n", mmp_s->mmp_check_interval); ++ fprintf(stdout, "MMP Sequence: %u\n", mmp_s->mmp_seq); ++ fprintf(stdout, "Last Update Time: %llu\n", mmp_s->mmp_time); ++ fprintf(stdout, "Node: %s\n", mmp_s->mmp_nodename); ++ fprintf(stdout, "Device: %s\n", mmp_s->mmp_bdevname); ++} ++ + static int source_file(const char *cmd_file, int sci_idx) + { + FILE *f; diff --git a/patches/e2fsprogs-new-opt-shrdblks.patch b/patches/e2fsprogs-new-opt-shrdblks.patch new file mode 100644 index 0000000..8c672c9 --- /dev/null +++ b/patches/e2fsprogs-new-opt-shrdblks.patch @@ -0,0 +1,346 @@ +E2fsck fixes files that are found to be sharing blocks by cloning +the shared blocks and giving each file a private copy in pass 1D. + +Allowing all files claiming the shared blocks to have copies can +inadvertantly bypass access restrictions. Deleting all the files, +zeroing the cloned blocks, or placing the files in the /lost+found +directory after cloning may be preferable in some secure environments. + +The following patches implement config file and command line options in +e2fsck that allow pass 1D behavior to be tuned according to site policy. +It adds two extended options and config file counterparts. On the +command line: + + -E clone=dup|zero + + Select the block cloning method. "dup" is old behavior which remains + the default. "zero" is a new method that substitutes zero-filled + blocks for the shared blocks in all the files that claim them. + + -E shared=preserve|lost+found|delete + + Select the disposition of files containing shared blocks. "preserve" + is the old behavior which remains the default. "lost+found" causes + files to be unlinked after cloning so they will be reconnected to + /lost+found in pass 3. "delete" skips cloning entirely and simply + deletes the files. + +In the config file: + [options] + clone=dup|zero + shared=preserve|lost+found|delete + +Signed-off-by: Jim Garlick + +Index: e2fsprogs/e2fsck/e2fsck.h +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.h ++++ e2fsprogs/e2fsck/e2fsck.h +@@ -192,6 +192,17 @@ struct resource_track { + #define E2F_PASS_5 5 + #define E2F_PASS_1B 6 + ++typedef enum { ++ E2F_SHARED_PRESERVE = 0, ++ E2F_SHARED_DELETE, ++ E2F_SHARED_LPF ++} shared_opt_t; ++ ++typedef enum { ++ E2F_CLONE_DUP = 0, ++ E2F_CLONE_ZERO ++} clone_opt_t; ++ + /* + * Define the extended attribute refcount structure + */ +@@ -346,6 +357,8 @@ struct e2fsck_struct { + time_t now; + time_t time_fudge; /* For working around buggy init scripts */ + int ext_attr_ver; ++ shared_opt_t shared; ++ clone_opt_t clone; + profile_t profile; + int blocks_per_page; + +Index: e2fsprogs/e2fsck/unix.c +=================================================================== +--- e2fsprogs.orig/e2fsck/unix.c ++++ e2fsprogs/e2fsck/unix.c +@@ -562,6 +562,49 @@ static void signal_cancel(int sig EXT2FS + } + #endif + ++static void initialize_profile_options(e2fsck_t ctx) ++{ ++ char *tmp; ++ ++ /* [options] shared=preserve|lost+found|delete */ ++ tmp = NULL; ++ ctx->shared = E2F_SHARED_PRESERVE; ++ profile_get_string(ctx->profile, "options", "shared", 0, ++ "preserve", &tmp); ++ if (tmp) { ++ if (strcmp(tmp, "preserve") == 0) ++ ctx->shared = E2F_SHARED_PRESERVE; ++ else if (strcmp(tmp, "delete") == 0) ++ ctx->shared = E2F_SHARED_DELETE; ++ else if (strcmp(tmp, "lost+found") == 0) ++ ctx->shared = E2F_SHARED_LPF; ++ else { ++ com_err(ctx->program_name, 0, ++ _("configuration error: 'shared=%s'"), tmp); ++ fatal_error(ctx, 0); ++ } ++ free(tmp); ++ } ++ ++ /* [options] clone=dup|zero */ ++ tmp = NULL; ++ ctx->clone = E2F_CLONE_DUP; ++ profile_get_string(ctx->profile, "options", "clone", 0, ++ "dup", &tmp); ++ if (tmp) { ++ if (strcmp(tmp, "dup") == 0) ++ ctx->clone = E2F_CLONE_DUP; ++ else if (strcmp(tmp, "zero") == 0) ++ ctx->clone = E2F_CLONE_ZERO; ++ else { ++ com_err(ctx->program_name, 0, ++ _("configuration error: 'clone=%s'"), tmp); ++ fatal_error(ctx, 0); ++ } ++ free(tmp); ++ } ++} ++ + static void parse_extended_opts(e2fsck_t ctx, const char *opts) + { + char *buf, *token, *next, *p, *arg; +@@ -597,6 +640,36 @@ static void parse_extended_opts(e2fsck_t + } else if (strcmp(token, "fragcheck") == 0) { + ctx->options |= E2F_OPT_FRAGCHECK; + continue; ++ /* -E shared=preserve|lost+found|delete */ ++ } else if (strcmp(token, "shared") == 0) { ++ if (!arg) { ++ extended_usage++; ++ continue; ++ } ++ if (strcmp(arg, "preserve") == 0) { ++ ctx->shared = E2F_SHARED_PRESERVE; ++ } else if (strcmp(arg, "lost+found") == 0) { ++ ctx->shared = E2F_SHARED_LPF; ++ } else if (strcmp(arg, "delete") == 0) { ++ ctx->shared = E2F_SHARED_DELETE; ++ } else { ++ extended_usage++; ++ continue; ++ } ++ /* -E clone=dup|zero */ ++ } else if (strcmp(token, "clone") == 0) { ++ if (!arg) { ++ extended_usage++; ++ continue; ++ } ++ if (strcmp(arg, "dup") == 0) { ++ ctx->clone = E2F_CLONE_DUP; ++ } else if (strcmp(arg, "zero") == 0) { ++ ctx->clone = E2F_CLONE_ZERO; ++ } else { ++ extended_usage++; ++ continue; ++ } + } else if (strcmp(token, "journal_only") == 0) { + if (arg) { + extended_usage++; +@@ -627,6 +700,8 @@ static void parse_extended_opts(e2fsck_t + fputs(("\tjournal_only\n"), stderr); + fputs(("\tdiscard\n"), stderr); + fputs(("\tnodiscard\n"), stderr); ++ fputs(("\tshared=\n"), stderr); ++ fputs(("\tclone=\n"), stderr); + fputc('\n', stderr); + exit(1); + } +@@ -690,6 +765,7 @@ static errcode_t PRS(int argc, char *arg + profile_set_syntax_err_cb(syntax_err_report); + profile_init(config_fn, &ctx->profile); + ++ initialize_profile_options(ctx); + + while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF) + switch (c) { +Index: e2fsprogs/e2fsck/pass1b.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1b.c ++++ e2fsprogs/e2fsck/pass1b.c +@@ -474,6 +474,9 @@ static void pass1d(e2fsck_t ctx, char *b + q = (struct dup_block *) dnode_get(m); + if (q->num_bad > 1) + file_ok = 0; ++ if (q->num_bad == 1 && (ctx->clone == E2F_CLONE_ZERO || ++ ctx->shared != E2F_SHARED_PRESERVE)) ++ file_ok = 0; + if (check_if_fs_block(ctx, s->block)) { + file_ok = 0; + meta_data = 1; +@@ -529,13 +532,26 @@ static void pass1d(e2fsck_t ctx, char *b + fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); + continue; + } +- if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { ++ if (ctx->shared != E2F_SHARED_DELETE && ++ fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { + pctx.errcode = clone_file(ctx, ino, p, block_buf); +- if (pctx.errcode) ++ if (pctx.errcode) { + fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); +- else +- continue; ++ goto delete; ++ } ++ if (ctx->shared == E2F_SHARED_LPF && ++ fix_problem(ctx, PR_1D_DISCONNECT_QUESTION, &pctx)) { ++ pctx.errcode = ext2fs_unlink(fs, p->dir, ++ NULL, ino, 0); ++ if (pctx.errcode) { ++ fix_problem(ctx, PR_1D_DISCONNECT_ERROR, ++ &pctx); ++ goto delete; ++ } ++ } ++ continue; + } ++delete: + if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) + delete_file(ctx, ino, p, block_buf); + else +@@ -552,7 +568,8 @@ static void decrement_badcount(e2fsck_t + { + p->num_bad--; + if (p->num_bad <= 0 || +- (p->num_bad == 1 && !check_if_fs_block(ctx, block))) ++ (p->num_bad == 1 && !check_if_fs_block(ctx, block) && ++ ctx->clone == E2F_CLONE_DUP)) + ext2fs_unmark_block_bitmap2(ctx->block_dup_map, block); + } + +@@ -698,11 +715,15 @@ static int clone_file_block(ext2_filsys + printf("Cloning block %u to %u\n", *block_nr, + new_block); + #endif +- retval = io_channel_read_blk64(fs->io, *block_nr, 1, +- cs->buf); +- if (retval) { +- cs->errcode = retval; +- return BLOCK_ABORT; ++ if (ctx->clone == E2F_CLONE_ZERO) { ++ memset(cs->buf, 0, fs->blocksize); ++ } else { ++ retval = io_channel_read_blk(fs->io, *block_nr, ++ 1, cs->buf); ++ if (retval) { ++ cs->errcode = retval; ++ return BLOCK_ABORT; ++ } + } + retval = io_channel_write_blk64(fs->io, new_block, 1, + cs->buf); +@@ -711,6 +732,11 @@ static int clone_file_block(ext2_filsys + return BLOCK_ABORT; + } + decrement_badcount(ctx, *block_nr, p); ++ if (ctx->clone == E2F_CLONE_ZERO && p->num_bad == 0) { ++ ext2fs_unmark_block_bitmap2(ctx->block_found_map, ++ *block_nr); ++ ext2fs_block_alloc_stats(fs, *block_nr, -1); ++ } + *block_nr = new_block; + ext2fs_mark_block_bitmap2(ctx->block_found_map, + new_block); +Index: e2fsprogs/e2fsck/problem.h +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.h ++++ e2fsprogs/e2fsck/problem.h +@@ -593,6 +593,13 @@ struct problem_context { + /* Couldn't clone file (error) */ + #define PR_1D_CLONE_ERROR 0x013008 + ++/* File with shared blocks found */ ++#define PR_1D_DISCONNECT_QUESTION 0x013009 ++ ++/* Couldn't unlink file (error) */ ++#define PR_1D_DISCONNECT_ERROR 0x01300A ++ ++ + /* + * Pass 2 errors + */ +Index: e2fsprogs/e2fsck/problem.c +=================================================================== +--- e2fsprogs.orig/e2fsck/problem.c ++++ e2fsprogs/e2fsck/problem.c +@@ -1003,6 +1003,14 @@ static struct e2fsck_problem problem_tab + { PR_1D_CLONE_ERROR, + N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 }, + ++ /* File with shared blocks found */ ++ { PR_1D_DISCONNECT_QUESTION, ++ N_("File with shared blocks found\n"), PROMPT_CONNECT, 0 }, ++ ++ /* Couldn't unlink file (error) */ ++ { PR_1D_DISCONNECT_ERROR, ++ N_("Couldn't unlink file: %m\n"), PROMPT_NONE, 0 }, ++ + /* Pass 2 errors */ + + /* Pass 2: Checking directory structure */ +Index: e2fsprogs/e2fsck/e2fsck.8.in +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.8.in ++++ e2fsprogs/e2fsck/e2fsck.8.in +@@ -180,6 +180,19 @@ separated, and may take an argument usin + following options are supported: + .RS 1.2i + .TP ++.BI clone= dup|zero ++Resolve files with shared blocks in pass 1D by giving each file a private ++copy of the blocks (dup); ++or replacing the shared blocks with private, zero-filled blocks (zero). ++The default is dup. ++.TP ++.BI shared= preserve|lost+found|delete ++Files with shared blocks discovered in pass 1D are cloned and then left ++in place (preserve); ++cloned and then disconnected from their parent directory, ++then reconnected to /lost+found in pass 3 (lost+found); ++or simply deleted (delete). The default is preserve. ++.TP + .BI ea_ver= extended_attribute_version + Set the version of the extended attribute blocks which + .B e2fsck +Index: e2fsprogs/e2fsck/e2fsck.conf.5.in +=================================================================== +--- e2fsprogs.orig/e2fsck/e2fsck.conf.5.in ++++ e2fsprogs/e2fsck/e2fsck.conf.5.in +@@ -129,6 +129,19 @@ This boolean relation controls whether o + will offer to clear + the test_fs flag if the ext4 filesystem is available on the system. It + defaults to true. ++.TP ++.I clone ++This string relation controls the default handling of shared blocks in pass 1D. ++It can be set to dup or zero. See the ++.I "-E clone" ++option description in e2fsck(8). ++.TP ++.I shared ++This string relation controls the default disposition of files discovered to ++have shared blocks in pass 1D. It can be set to preserve, lost+found, ++or delete. See the ++.I "-E shared" ++option description in e2fsck(8). + .TP + .I defer_check_on_battery + This boolean relation controls whether or not the interval between diff --git a/patches/e2fsprogs-osx.patch b/patches/e2fsprogs-osx.patch new file mode 100644 index 0000000..509a6b7 --- /dev/null +++ b/patches/e2fsprogs-osx.patch @@ -0,0 +1,64 @@ +The BLKFLSBUF and FDFLUSH ioctls are Linux specific, and do not +really have anything to do with __GNUC__ (which is also used on +OS/X and Solaris). No need to print these warnings on OS/X. + +O_DIRECT is not defined in the OS/X headers. Since this is only a +performance enhancement, and not required for correct operation, +just ignore it if undefined. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/lib/ext2fs/flushb.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/flushb.c ++++ e2fsprogs/lib/ext2fs/flushb.c +@@ -65,17 +65,13 @@ errcode_t ext2fs_sync_device(int fd, int + #ifdef BLKFLSBUF + if (ioctl (fd, BLKFLSBUF, 0) == 0) + return 0; +-#else +-#ifdef __GNUC__ +- #warning BLKFLSBUF not defined +-#endif /* __GNUC__ */ ++#elif defined(__linux__) ++#warning BLKFLSBUF not defined + #endif + #ifdef FDFLUSH + ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */ +-#else +-#ifdef __GNUC__ +- #warning FDFLUSH not defined +-#endif /* __GNUC__ */ ++#elif defined(__linux__) ++#warning FDFLUSH not defined + #endif + } + return 0; +Index: e2fsprogs/lib/ext2fs/getsize.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/getsize.c ++++ e2fsprogs/lib/ext2fs/getsize.c +@@ -235,7 +235,7 @@ errcode_t ext2fs_get_device_size2(const + #endif /* HAVE_SYS_DISKLABEL_H */ + + { +-#ifdef HAVE_FSTAT64 ++#if defined(HAVE_FSTAT64) && !defined(__OSX__) + struct stat64 st; + if (fstat64(fd, &st) == 0) + #else +Index: e2fsprogs/lib/ext2fs/unix_io.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/unix_io.c ++++ e2fsprogs/lib/ext2fs/unix_io.c +@@ -474,8 +474,10 @@ static errcode_t unix_open(const char *n + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; + if (flags & IO_FLAG_EXCLUSIVE) + open_flags |= O_EXCL; ++#ifdef O_DIRECT + if (flags & IO_FLAG_DIRECT_IO) + open_flags |= O_DIRECT; ++#endif + data->flags = flags; + + #ifdef HAVE_OPEN64 diff --git a/patches/e2fsprogs-rpm_support.patch b/patches/e2fsprogs-rpm_support.patch new file mode 100644 index 0000000..d54563e --- /dev/null +++ b/patches/e2fsprogs-rpm_support.patch @@ -0,0 +1,1176 @@ +Index: e2fsprogs/e2fsprogs-SUSE_LINUX-11.spec.in +=================================================================== +--- /dev/null ++++ e2fsprogs/e2fsprogs-SUSE_LINUX-11.spec.in +@@ -0,0 +1,1106 @@ ++# ++# spec file for package e2fsprogs (Version 1.41.9) ++# ++# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. ++# ++# All modifications and additions to the file contributed by third parties ++# remain the property of their copyright owners, unless otherwise agreed ++# upon. The license for this file, and modifications and additions to the ++# file, is the same license as for the pristine package itself (unless the ++# license for the pristine package is not an Open Source License, in which ++# case the license is the MIT License). An "Open Source License" is a ++# license that conforms to the Open Source Definition (Version 1.9) ++# published by the Open Source Initiative. ++ ++# Please submit bugfixes or comments via http://bugs.opensuse.org/ ++# ++ ++# norootforbuild ++ ++ ++Name: e2fsprogs ++License: GPL v2 or later ++Group: System/Filesystems ++Supplements: filesystem(ext2) filesystem(ext3) filesystem(ext4) ++BuildRequires: libblkid-devel libuuid-devel pkg-config libdb-4_5-devel ++PreReq: %install_info_prereq ++AutoReqProv: on ++# bug437293 ++%ifarch ppc64 ++Obsoletes: e2fsprogs-64bit ++%endif ++# ++Version: @E2FSPROGS_PKGVER@ ++Release: 0%{_vendor} ++Summary: Utilities for the Second Extended File System ++Url: http://e2fsprogs.sourceforge.net ++Source: %{name}-%{version}.tar.gz ++BuildRoot: %{_tmppath}/%{name}-%{version}-build ++ ++%description ++Utilities needed to create and maintain ext2 and ext3 file systems ++under Linux. Included in this package are: chattr, lsattr, mke2fs, ++mklost+found, tune2fs, e2fsck, resize2fs, and badblocks. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%package devel ++License: GPL v2 or later ++Summary: Dummy development package ++Group: Development/Libraries/C and C++ ++AutoReqProv: on ++# bug437293 ++%ifarch ppc64 ++Obsoletes: e2fsprogs-devel-64bit ++%endif ++# ++Requires: libext2fs-devel = %version libblkid-devel libuuid-devel ++ ++%description devel ++Dummy development package for backwards compatibility. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%package -n libext2fs2 ++License: GPL v2 or later ++Summary: Ext2fs libray ++Group: System/Filesystems ++AutoReqProv: on ++ ++%description -n libext2fs2 ++The basic Ext2fs library. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%package -n libext2fs-devel ++License: GPL v2 or later ++Summary: Development files for libext2fs ++Group: Development/Libraries/C and C++ ++AutoReqProv: on ++Requires: libext2fs2 = %version libcom_err-devel ++ ++%description -n libext2fs-devel ++Development files for libext2fs. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%package -n libcom_err2 ++License: GPL v2 or later ++Summary: E2fsprogs error reporting library ++Group: System/Filesystems ++# bug437293 ++%ifarch ppc64 ++Obsoletes: libcom_err-64bit ++Obsoletes: libcom_err2-64bit ++%endif ++# ++Provides: libcom_err = %{version} ++Obsoletes: libcom_err <= 1.40 ++AutoReqProv: on ++ ++%description -n libcom_err2 ++com_err is an error message display library. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%package -n libcom_err-devel ++License: GPL v2 or later ++Summary: Development files for libcom_err ++Group: Development/Libraries/C and C++ ++AutoReqProv: on ++# bug437293 ++%ifarch ppc64 ++Obsoletes: libcom_err-devel-64bit ++%endif ++# ++Requires: libcom_err2 = %version ++ ++%description -n libcom_err-devel ++Development files for the com_err error message display library. ++ ++ ++ ++Authors: ++-------- ++ Remy Card ++ Theodore Ts'o ++ ++%prep ++%setup -q ++# e2fsprogs patches ++patch -p1 < patches/sles/11/rpm/e2fsprogs-1.41.1-splash_support.patch ++# libcom_err patches ++patch -p1 < patches/sles/11/rpm/libcom_err-compile_et_permissions.patch ++cp patches/sles/11/rpm/README.SUSE . ++cp patches/sles/11/rpm/%{name}-1.41.4.de.po po/de.po ++ ++%build ++autoreconf --force --install ++./configure --prefix=%{_prefix} \ ++ --with-root-prefix='' \ ++ --mandir=%{_mandir} \ ++ --infodir=%{_infodir} \ ++ --libdir=%{_libdir} \ ++ --enable-elf-shlibs \ ++ --disable-evms \ ++ --disable-libblkid \ ++ --disable-libuuid \ ++ --disable-uuidd \ ++ --disable-fsck \ ++ %{?extra_config_flags:%extra_config_flags} CFLAGS="$RPM_OPT_FLAGS" ++make V=1 ++ ++%install ++make install install-libs DESTDIR=$RPM_BUILD_ROOT ELF_INSTALL_DIR=/%{_lib} ++%{find_lang} %{name} ++rm $RPM_BUILD_ROOT%{_libdir}/e2initrd_helper ++rm -f $RPM_BUILD_ROOT/sbin/mkfs.ext4dev ++rm -f $RPM_BUILD_ROOT/sbin/fsck.ext4dev ++rm -f $RPM_BUILD_ROOT/usr/share/man/man8/mkfs.ext4dev.8* ++rm -f $RPM_BUILD_ROOT/usr/share/man/man8/fsck.ext4dev.8* ++ ++%clean ++rm -rf $RPM_BUILD_ROOT ++ ++%post ++/sbin/ldconfig ++%install_info --info-dir=%{_infodir} %{_infodir}/libext2fs.info.gz ++ ++%postun ++/sbin/ldconfig ++%install_info_delete --info-dir=%{_infodir} %{_infodir}/libext2fs.info.gz ++ ++%post -n libext2fs2 ++/sbin/ldconfig ++ ++%postun -n libext2fs2 ++/sbin/ldconfig ++ ++%post -n libcom_err2 ++/sbin/ldconfig ++ ++%postun -n libcom_err2 ++/sbin/ldconfig ++ ++%files -f %{name}.lang ++%defattr(-, root, root) ++%doc RELEASE-NOTES README ++%config /etc/mke2fs.conf ++/sbin/badblocks ++/sbin/debugfs ++/sbin/dumpe2fs ++/sbin/e2undo ++/sbin/e2fsck ++/sbin/e2label ++/sbin/fsck.ext2 ++/sbin/fsck.ext3 ++/sbin/fsck.ext4 ++/sbin/mke2fs ++/sbin/mkfs.ext2 ++/sbin/mkfs.ext3 ++/sbin/mkfs.ext4 ++/sbin/resize2fs ++/sbin/tune2fs ++/sbin/e2image ++/sbin/logsave ++/usr/bin/chattr ++/usr/bin/lsattr ++/usr/sbin/mklost+found ++/usr/sbin/filefrag ++/usr/sbin/e2freefrag ++/usr/sbin/e2scan ++/usr/sbin/lfsck ++%{_infodir}/libext2fs.info.gz ++%{_mandir}/man1/chattr.1.gz ++%{_mandir}/man1/lsattr.1.gz ++%{_mandir}/man5/e2fsck.conf.5.gz ++%{_mandir}/man5/mke2fs.conf.5.gz ++%{_mandir}/man8/*.8.gz ++ ++%files devel ++%defattr(-,root,root) ++%doc README.SUSE ++ ++%files -n libext2fs2 ++%defattr(-, root, root) ++/%{_lib}/libext2fs.so.* ++/%{_lib}/libe2p.so.* ++ ++%files -n libext2fs-devel ++%defattr(-, root, root) ++%{_libdir}/libext2fs.so ++%{_libdir}/libext2fs.a ++%{_libdir}/libe2p.a ++%{_libdir}/libe2p.so ++/usr/include/ext2fs ++/usr/include/e2p ++%_libdir/pkgconfig/e2p.pc ++%_libdir/pkgconfig/ext2fs.pc ++ ++%files -n libcom_err2 ++%defattr(-, root, root) ++/%{_lib}/libcom_err.so.* ++/%{_lib}/libss.so.* ++ ++%files -n libcom_err-devel ++%defattr(-, root, root) ++%_bindir/compile_et ++%_bindir/mk_cmds ++%{_libdir}/libcom_err.so ++%{_libdir}/libcom_err.a ++%{_libdir}/libss.a ++%{_libdir}/libss.so ++%_libdir/pkgconfig/com_err.pc ++%_libdir/pkgconfig/ss.pc ++%_includedir/et ++%_includedir/ss ++%_datadir/et ++%_datadir/ss ++%{_mandir}/man1/compile_et.1.gz ++%{_mandir}/man1/mk_cmds.1.gz ++%{_mandir}/man3/com_err.3.gz ++ ++%changelog ++* Thu Nov 19 2009 hvogel@suse.de ++- Update to version 1.41.9 [FATE#305340] ++* Thu Oct 8 2009 crrodriguez@suse.de ++- fsck during boot up fails with Too many open files [bnc#503008] ++* Thu Sep 10 2009 coolo@novell.com ++- fix the super block even if someone mounted the file system ++ in wrong timezone in between (bnc#537542) ++* Thu Sep 3 2009 coolo@novell.com ++- update to 1.41.9: ++ "All users of e2fsprogs are urged to upgrade to the 1.41.9 ++ version as soon as possible" ++ * Fix a bug in e2fsck routines for reallocating an inode table which ++ could cause it to loop forever on an ext4 filesystem with the FLEX_BG ++ filesystem feature with a relatively rare (and specific) filesystem ++ corruption. This fix causes e2fsck to try to find space for a new ++ portion of the inode table in the containing flex_bg, and if that ++ fails, the new portion of the inode table will be allocated in any ++ free space available in the filesystem. ++ * Make e2fsck less annoying by only asking for permission to relocate a ++ block group's inode table once, instead of for every overlapping ++ block. Similarly, only ask once to recompute the block group ++ checksums, instead of once for each corrupted block group's checksum. ++ see more changes in RELEASE-NOTES ++* Mon Aug 3 2009 aschnell@suse.de ++- added Supplements for ext4 ++* Mon Jul 13 2009 coolo@novell.com ++- look for libreadline.so.6 too ++- refresh patches to avoid fuzz ++* Mon Jul 13 2009 kay.sievers@novell.com ++- update to 1.41.8 ++ - Fix resize2fs's online resizing, fixing a regression which in ++ e2fpsrogs 1.41.7. ++ - Fix resize2fs bugs when shrinking ext4 filesystems ++ - If the resize2fs operation fails, the user will be told to fix up ++ the filesystem using e2fsck -fy. ++ - do not install disabled uuid binary and man page ++ - Fix filefrag program for files that have more than 144 extents. ++ - allow V=1 to disable silent build ++- enable verbose build again (V=1 merged upstream) ++- move awk scripts from libcom_err2 to libcom_err2-devel ++* Wed Jul 8 2009 meissner@suse.de ++- moved baselibs.conf changes to util-linux. ++* Mon Jun 29 2009 kay.sievers@novell.com ++- update to 1.41.7 ++- disable libuuid and libblkid packages (moved to util-linux) ++- drop libvolume_id support (util-linux's libblkid will work) ++- removed patches: ++ e2fsprogs-libvolume_id-support.patch ++ e2fsprogs-no_cmd_hiding.patch ++ e2fsprogs-base_devt.patch ++ e2fsprogs-mdraid.patch ++* Mon Mar 9 2009 pth@suse.de ++- Fix errors in German messages. ++* Fri Feb 20 2009 coolo@suse.de ++- ext4dev is now ext4 (2.6.29) ++- don't call autoconf as long as it works without ++* Tue Feb 3 2009 mkoenig@suse.de ++- update to version 1.41.4: ++ debugfs: ++ * enhance the "ncheck" command ++ * enhance "hash" command ++ * fix a potential memory leak ++ * fix the usage message for logdump command ++ * fix ncheck command so that it prints all of the names of ++ hardlinks in the same directory ++ * e2fsprogs 1.41 broke debugfs's logdump command for normal ++ ext3/4 filesystems with 32-bit block numbers, when the headers ++ for 64-bit block numbers was added. This regression has been fixed ++ * ncheck command has been fixed to avoid printing garbage ++ characters at the end of file names ++ e2fsck: ++ * don't accidentally print the translation file's ++ header when asking the user a custom question ++ * print the correct inode number for uinit_bg related problems ++ * will now offer to clear the test_fs flag if the ext4 filesystem ++ is available on linux ++ * fix a bug where in preen mode, if there are disk I/O errors ++ while trying to close a filesystem can lead to infinite loops ++ * no longer abort an fsck run if block group has an errant ++ INODE_UNINIT flag ++ * distinguish between fragmented directories and fragmented ++ files in verbose mode statistics and in the fragcheck report ++ * fix a bug which caused it double count non-contiguous ++ extent-based inodes ++ * e2fsck will leave some slack space when repacking directories ++ to allow room for a few directory entries to be added without ++ causing leaf nodes to be split right away ++ * fix a bug which caused e2fsck to crash when it comes across a ++ corrupted interior node in an extent tree ++ * e2fsck problem descriptions involving the journal are no longer ++ referred to as "ext3" problems, since ext4 filesystems also have ++ journals ++ * fix a long-standing bug in e2fsck which would cause it to crash ++ when replying journals for filesystems with block sizes greater ++ than 8k ++ badblocks: ++ * support for normal files which are greater than 2GB ++ * display the time and percentage complete when in verbose mode ++ resize2fs: ++ * fix a potential memory corruption problem ++ * fix a bug in resize2fs where passing in a bogus new size of ++ 0 blocks will cause resize2fs to drop into an infinite loop ++ * fix resize2fs for ext4 filesystems ++ tune2fs: ++ * now updates the block group checksums when changing the UUID ++ to avoid causing e2fsck to complain vociferously at the next reboot ++ * inode size resizing algorithms have been fixed so it is not ++ vastly inefficient for moderate-to-large filesystems ++ * fix inode resizing algorithm so it will not corrupt filesystems ++ laid out for RAID filesystems; in addition, tune2fs will refuse ++ to change the inode size for filesystems that have the flex_bg ++ feature enabled ++ dumpe2fs: ++ * fix bug which caused dumpe2fs to abort with an error if run on a ++ filesystem that contained an external journal ++ mke2fs: ++ * new option -U, which allows the user to specify the UUID that ++ should be used for the new filesystem ++ * treat devices that are exactly 16TB as if they were 16TB minus ++ one block ++ blkid: ++ * fix a file descriptor leak in libblkid ++ * correctly detect whether the ext4 and ext4dev filesystems ++ are available, so that the ext4dev->ext4 fallback code works ++ correctly ++ * fixed a bug which could sometimes cause blkid to return an ++ exit value of zero for a non-existent device ++ * recognize ext3 filesystems that have the test_fs flag ++ set as ext3 filesystems ++ * recognize btrfs filesystems and swap devices currently used ++ by user-level software suspend ++ libext2fs: ++ * add a check in the Unix I/O functions in libext2fs so that ++ when a device is opened read/write, return an error if the ++ device is read-only using the BLKROGET ioctl ++- the libcom_err patches for bnc#66534 have been removed because ++ git commit d7f45af802330a0e1450afa05185d3722e77a76c ++ should fix the problem ++- remove patches ++ e2fsprogs-1.41.1-e2fsck_fix_automatic_blocksize_detection.patch ++ e2fsprogs-1.41.1-function_signature_fix.patch ++ e2fsprogs-1.41.1-link_fix.patch ++ libcom_err-disable_test.patch ++ libcom_err-mutex.patch ++ libcom_err-no-init_error_table.patch ++* Tue Jan 13 2009 olh@suse.de ++- obsolete old -XXbit packages (bnc#437293) ++* Thu Dec 4 2008 mkoenig@suse.de ++- send bootsplash messages in one write call ++* Tue Oct 28 2008 mkoenig@suse.de ++- fix function signature to avoid compiler warning [bnc#439129] ++* Tue Oct 7 2008 mkoenig@suse.de ++- e2fsck: fix e2fsck automatic blocksize detetion ++* Mon Sep 29 2008 mkoenig@suse.de ++- e2fsck: shut off splash screen when check is needed [bnc#237283] ++* Mon Sep 15 2008 mkoenig@suse.de ++- remove recommends of uuid-runtime from libuuid [bnc#426278] ++- move uuid hints README.SUSE.uuidd to uuid-runtime package ++* Fri Sep 5 2008 mkoenig@suse.de ++- update to version 1.41.1 ++ * mke2fs ++ + issues now a warning if there is no definition in ++ /etc/mke2fs.conf for the filesystem to be created ++ + creates now the journal in the middle of the filesystem ++ + now avoids allocating an extra block to the journal ++ + will correctly enforce the prohibition against features ++ in revision 0 filesystems ++ + previously would occasionaly create some slightly non-optimally ++ placed inode tables; this bug has been fixed ++ + will now set the creation timestamp on the lost+found directory ++ and the root directory ++ * blkid ++ + recognize MacOS hfsx filesystems, and correctly extract the ++ label and uuid for hfs, hfsx, and hfsplus filesystems ++ + improved detection of JFS and HPFS ++ + more efficient handling of devicemapper devices ++ + fix cache validation bugs ++ + The blkid program will now print out a user-friendly listing ++ of all of the block devices in the system and what they ++ contain when given the -L option ++ * resize2fs ++ + will now correctly handle filesystems with extents and/or ++ uninitialized block groups correctly when file/directory blocks ++ need to relocated ++ + support for on-line resizing ext4 filesystem with the flex_bg ++ filesystem feature. The method for doing so is not optimal, ++ but to do a better job will require kernel support ++ + is now correctly managing the directory in-use counts when ++ shrinking filesystems and directory inodes needed to be moved ++ from one block group to another ++ * e2fsck ++ + now correctly calculates ind/dind/tind statistics in the ++ presence of extent-based files ++ + now prints the depth of corrupt htree directories ++ * debugfs ++ + htree command now correctly understands extent-based ++ directories ++ + new command which will print the supported features ++ * Add support for setting the default hash algorithm used in b-tree ++ directories in tune2fs (from a command-line option) or mke2fs (via ++ mke2fs.conf). In addition, change the default hash algorithm to ++ half_md4, since it is faster and better ++ * Fix support for empty directory blocks in ext4 filesystems with ++ 64k blocksize filesystems ++ * The filefrag program now has a more accurate calculation for the ++ number of ideal extents ++- fix linking of blkid ++ e2fsprogs-1.41.1-link_fix.patch ++- remove patches ++ e2fsprogs-1.41.0-fix_messages.patch ++ e2fsprogs-1.41.0-tst_link_fix.patch ++* Fri Aug 29 2008 kay.sievers@novell.com ++- update libvolume_id patch to work with libvolume_id.so.1 ++* Thu Aug 21 2008 pth@suse.de ++- Add current german messages. ++- Fix e2fsprogs-base_devt.patch and e2fsprogs-libvolume_id-support.patch ++ so that the package tools work. ++- Add missing space to two messages and resync message ++ catalogs by configuring with --enable-maintainer-mode. ++* Wed Aug 20 2008 mkoenig@suse.de ++- add uuid related manpages to uuid-runtime subpackage [bnc#418568] ++* Mon Aug 18 2008 mkoenig@suse.de ++- currently do not install *.ext4 links for mkfs and fsck ++ tools, but only the *.ext4dev links. ++* Wed Jul 16 2008 mkoenig@suse.de ++- update to version 1.41.0 ++ * add support for ext4 filesystem features: ++ extents, uninit_bg, flex_bg, huge_file, dir_nlink ++ * support for checking journal checksums ++ * tune2fs supports migrating fs from 128 byte inode to 256 byte ++ * add support for "undo" ++ * e2fsck now performs more extensive and careful checks of extended ++ attributes stored in the inod ++- fix e2fsck make check ++* Wed Jul 2 2008 schwab@suse.de ++- Remove doubleplusungood -fsigned-char. ++* Tue Jun 24 2008 mkoenig@suse.de ++- update to version 1.40.11 ++ most important changes since 1.40.8: ++ * Mke2fs will not allow the logically incorect combination of ++ resize_inode and meta_bg, which had previously caused mke2fs ++ to create a corrupt fileystem ++ * Fix mke2fs's creation of resize inode when there is a ++ non-standard s_first_data_block setting ++ * Teach fsck to treat "ext4" and "ext4dev" as ext* filesystems ++ * Fix fsck so that progress information is sent back correctly ++ * Add detection for ZFS volumes to the libblkid library ++- remove e2fsprogs-1.40.7.de.po, updated upstream ++- remove patches ++ e2fsprogs-1.40.7-uuidd_security.patch ++ e2fsprogs-1.40.8-e2fsck_recovery_fix.patch ++ e2fsprogs-1.40.8-fix_ext2fs_swap_inode_full.patch ++ e2fsprogs-1.40.8-missing_init.patch ++* Tue May 27 2008 ro@suse.de ++- fix baselibs.conf to not generate unresolvable deps ++* Wed May 21 2008 cthiel@suse.de ++- fix baselibs.conf ++* Wed May 21 2008 mkoenig@suse.de ++- e2fsck: Fix potential data corruptor bug in journal recovery ++ [bnc#393095] ++* Tue May 13 2008 mkoenig@suse.de ++- libuuid: do not use unintialized variable [bnc#386649] ++* Wed May 7 2008 coolo@suse.de ++- fix provides/obsoletes for rename ++* Thu Apr 10 2008 ro@suse.de ++- added baselibs.conf file to build xxbit packages ++ for multilib support ++* Tue Mar 18 2008 pth@suse.de ++- Readd the current de.po just submitted upstream to the TP robot. ++* Fri Mar 14 2008 mkoenig@suse.de ++- update to version 1.40.8 ++ * Fixed e2image -I so it works on image files which are larger than 2GB ++ * Fixed e2fsck's handling of directory inodes with a corrupt size field ++ * Fixed e2fsck handling of pass 2 "should never happen error" ++ * Fixed Resize2fs bug resizing large inodes with extended attributes ++- update README.SUSE: give some hints on enabling uuidd, since it has ++ been decided to not enable it by default [bnc#354398] ++- removed ++ de.po (updated upstream) ++* Tue Mar 4 2008 mkoenig@suse.de ++- update to version 1.40.7 ++ * Remove support for clearing the SPARSE_SUPER feature from tune2fs, and ++ depreciate the -s option, since it can result in filesystems which ++ e2fsck can't fix easily. There are very good reasons for wanting to ++ disable sparse_super; users who wants to turn off sparse_super can use ++ debugfs. ++ * Add missing options to mke2fs's usage message ++ * Fix bug in resize2fs when large (greater than 128 byte) inodes are ++ moved when a filesystem is shrunk ++ * E2fsck now prints an explicit message when the bad block inode is ++ updated, to avoid confusion about why the filesystem was modified. ++ * Allow mke2fs and tune2fs manipulate the large_file feature. ++ Previously we just let the kernel and e2fsck do this automatically, ++ but e2fsck will no longer automatically clear the large_file feature ++ * Suppress message about an old-style fstab if the fstab file is empty ++ * Change e2fsck to no longer clear the LARGE_FILES feature flag ++ automatically, when there are no more > 2GB files in the filesystem. ++ * Fix bug which could cause libblkid to seg fault if a device mapper ++ volume disappears while it is being probed. ++ * Enhance e2fsck's reporting of unsupported filesystem feature flags ++ * Fix option syntax in dumpe2fs for explicit superblock and blocksize ++ parameters ++ * Add support to tune2fs to clear the resize_inode feature ++ * Teach blkid to detect LVM2 physical volumes ++ * Add support for setting RAID stride and stripe-width via mke2fs and ++ tune2fs. Teach dumpe2fs to print the RAID parameters ++ * Add support for setting new superblock fields to debugfs's ++ set_super_value ++ * Add support for printing "mostly-printable" extended attributes in ++ Debugfs ++ * Add support for the -M option to fsck, which causes it to ignore ++ mounted filesystem ++ * Fix uuidd so that it creates the pid file with the correct pid number ++- The -M option is now used upstream to ignore mounted filesystems, ++ this has previously been in SuSE with -m. This has to be changed ++ since lower case characters are reserved for filesystem specific ++ checker options. The "like mount" behaviour previously in SuSE ++ with -M has been removed. ++- add patch from Eric Sandeen to fix the loss of extended attributes ++ in large inodes upon resize ++- removed patches ++ fsck-ignore-mounted.patch ++* Wed Feb 27 2008 mkoenig@suse.de ++- update to version 1.40.6 ++ * Add support for returning labels for UDF filesystems in the blkid ++ library ++ * Fix bug in the blkid library where cached filesystems was not being ++ flushed ++ * Added logic to the blkid library to automatically choose whether a ++ filesystem should be mounted as ext4 or ext4dev, as appropriate ++ * Allow tune2fs to set and clear the test_fs flag on ext4 filesystems ++- removed patches: ++ e2fsprogs-1.40.5-blkid_cache_file_env.patch (merged) ++ libcom_err-no-static-buffer.patch (fixed upstream with TLS) ++* Tue Jan 29 2008 mkoenig@suse.de ++- update to version 1.40.5: ++ * Fix a potential overflow big in e2image ++ * Mke2fs will now create new filesystems with 256 byte inodes and the ++ ext_attr feature flag by default ++ * Teach e2fsck to ignore certain "safe" filesystem features which are ++ set automatically by the kernel ++ * Add support in tune2fs and mke2fs for making a filesystem as being "ok ++ to be used with test kernel code" ++ * Change e2fsck -fD so that it sorts non-htree directories by inode ++ numbers instead of by name, since that optimizes performances much ++ more significantly ++ * If e2image fills the disk, fix it so it exits right away ++ * If ftruncate64() is not available for resize2fs, let it use ftrucate() ++ instead ++ * Add support for detecting HFS+ filesystems in the blkid library ++ * Add supprt in the blkid library for ext4/ext4dev filesystems ++ * Fix a bug in blkid where it could die on a floating point exception ++ when presented with a corrupt reiserfs image ++ * Fix blkid's handling of ntfs UUID's so that leading zeros are printed ++ such that UUID string is a fixed length ++ * Fix debugfs's 'lsdel' command so it uses ext2fs_block_iterate2 so it ++ will work with large files ++ * Allow the debugfs 'undel' command to undelete an inode without linking ++ it to a specific destination directory ++- enhance init script ++- add sysconfig parameter UUIDD_ON_DEMAND_ONLY setting the startup ++ policy for uuidd ++- remove merged and obsolete patches: ++ close.patch ++ e2fsprogs-1.33-codecleanup.diff ++ e2fsprogs-1.35-libdir.diff ++ e2fsprogs-1.39-resize2fs_manpage.patch ++ e2fsprogs-1.40.4-uuid_null.patch ++ e2fsprogs-blkid.diff ++ e2fsprogs-blkid_probe_hfsplus.patch ++ e2fsprogs-strncat.patch ++ elf.diff ++ e2fsprogs-mkinstalldirs.patch ++ e2fsprogs-special_make_targets.patch ++ e2fsprogs-probe_reiserfs-fpe.patch ++ e2fsprogs-1.33-fsckdevdisplay.diff ++ e2fsprogs-uninitialized.diff ++* Wed Jan 16 2008 mkoenig@suse.de ++- update to version 1.40.4: ++ * Fix potential security vulnerability (CVE-2007-5497) ++ * Fix big-endian byte-swapping bug in ext2fs_swap_inode_full() ++ * Fix a bug in ext2fs_initialize() which causes mke2fs to fail while ++ allocating inode tables for some relatively rare odd disk sizes. ++ * Fix bug in ext2fs_check_desc() which will cause e2fsck to complain ++ about (valid) filesystems where the inode table extends to the last ++ block of the block group ++ * Change e2fsck so it will not complain if a file has blocks reallocated ++ up to the next multiple of a system's page size ++ * Change e2fsck so it uses sscanf() instead of atoi() so it non-numeric ++ arguments are detected as such and the parse error is reported to the ++ user ++ * Make the e2fsprogs program more robust so that they will not crash ++ when opening a corrupt filesystem where s_inode_size is zero. ++ * Fix e2fsck so that if the superblock is corrupt, but still looks ++ vaguely like an ext2/3/4 superblock, that it automatically tries to ++ fall back to the backup superblock, instead of failing with a hard ++ error ++ * Fix fsck to ignore /etc/fstab entries for bind mounts ++ * E2fsck will no longer mark a filesystem as invalid if it has time ++ errors and the user refuses to fix the problem. ++ * Enhance blkid's detection of FAT filesystems ++ * Enhance e2fsck so it will force the backup superblocks to be backed up ++ if the filesystem is consistent and key constants have been changed ++ (i.e., by an on-line resize) or by e2fsck in the course of its ++ operations. ++ * Enhance the blkid library so it will recognize squashfs filesystems ++ * Fix e2image so that in raw mode it does not create an image file which ++ is one byte too large ++ * Fix heuristics in blkid which could cause a disk without partitions to ++ be incorrectly skipped when a loopback device is present ++ * Avoid division by zero error when probing an invalid FAT filesystem in ++ the blkid library ++ * Fix sign-extension problem on 64-bit systems in in the com_err ++ library ++ * Format control characters and characters with the high eighth bit set ++ when printing the contents of the blkid cache, to prevent filesystems ++ with garbage labels from sending escape sequences ++ * Fix fsck to only treat the '#' character as a comment at the beginning ++ of the line in /etc/fstab ++ * Filter out the NEEDS_RECOVERY feature flag when writing out the backup ++ superblocks ++ * Improve time-based UUID generation. A new daemon uuidd, is started ++ automatically by libuuid if necessary ++- new subpackage: uuid-runtime ++ containing uuidd and uuidgen ++- removed obsolete patches ++ e2fsprogs-1.39-uuid_duplicates.patch ++ e2fsprogs-1.40.2-open_fix.patch ++ e2fsprogs-1.40-be_swap_fix.patch ++* Mon Nov 26 2007 mkoenig@suse.de ++- fix build: missing third argument to open ++- do not remove buildroot in install section ++* Fri Jul 27 2007 mkoenig@suse.de ++- fix typo in specfile ++* Thu Jul 26 2007 mkoenig@suse.de ++- Fix big-endian byte-swapping bug in ext2fs_swap_inode_full() ++ e2fsprogs-1.40-be_swap_fix.patch ++* Wed Jul 25 2007 bk@suse.de ++- e2fsprogs requires libext2fs2 of the same version number to work ++- enable make check and make gcc-wall in %%check (executed last) ++- shut up bogus gcc warning for use of uninitialised variables ++* Wed Jul 25 2007 mkoenig@suse.de ++- remove e2fsprogs-blkid_probe_ext4.patch ++ broken and it is way too early to support ++* Wed Jul 18 2007 mkoenig@suse.de ++- update to version 1.40.2 ++ bugfix release ++* Mon Jul 9 2007 mkoenig@suse.de ++- update to version 1.40.1: ++ * Bugfix release ++- removed patch (merged upstream) ++ e2fsprogs-1.39-cleanup.patch ++* Wed Jul 4 2007 mkoenig@suse.de ++- update to version 1.40 ++- branch off libraries: ++ libblkid1 ++ libuuid1 ++ libext2fs2 ++- renaming libcom_err to libcom_err2 ++* Tue Jun 19 2007 mkoenig@suse.de ++- fix e2fsprogs-1.39-uuid_duplicates.patch [#189640] ++ * detach shm segment after use ++ * set SEM_UNDO for semaphore operations, otherwise we do not ++ get a clean state after interruption by a signal ++* Wed Apr 25 2007 pth@suse.de ++- Fix German translations. ++* Wed Apr 11 2007 mkoenig@suse.de ++- blkid: fix hfsplus probing to detect HFS+ volumes embedded ++ in a HFS volume ++* Wed Apr 4 2007 mkoenig@suse.de ++- add Supplements line [FATE#301966] ++* Fri Mar 30 2007 mkoenig@suse.de ++- update to current hg version from 29-03-2007 ++ * Fixes a lot of memory leaks and other bugs ++- remove merged patch: ++ e2fsprogs-1.39-check_fs_open-in-dump_unused.patch ++* Wed Mar 28 2007 mkoenig@suse.de ++- blkid: add hfsplus volume detection (FATE#302071) ++- blkid: add experimental detection of ext4dev (FATE#301897) ++* Thu Jan 25 2007 mkoenig@suse.de ++- fix segfault in debugfs when using without open fs [#238140] ++* Mon Jan 22 2007 mkoenig@suse.de ++- don't chmod -w headers in compile_et to avoid build ++ problems with some packages ++* Fri Jan 19 2007 mkoenig@suse.de ++- update to version 1.40-WIP-1114 (FATE#301897) ++ * support for ext4 ++ * several bugfixes ++- remove ext2resize from package, because the online resizing ++ functionality has been merged into resize2fs since version 1.39 ++ and ext2resize is unmaintained. ++* Tue Dec 19 2006 meissner@suse.de ++- fixed build ++* Wed Nov 8 2006 ro@suse.de ++- provide libcom_err-devel in libcom_err ++* Thu Oct 19 2006 mkoenig@suse.de ++- fix bug in uuid patch ++* Mon Oct 16 2006 mkoenig@suse.de ++- fix build of shared lib ++* Thu Oct 12 2006 mkoenig@suse.de ++- fix uuid bug [#189640] ++- fix blkid problem with empty FAT labels [#211110] ++- fix small typo in resize2fs man page ++* Tue Sep 26 2006 mkoenig@suse.de ++- fix bug in fsck udev/libvolume_id patch [#205671] ++* Wed Sep 20 2006 mkoenig@suse.de ++- update to version 1.39: ++ * Fix 32-bit cleanliness ++ * Change mke2fs to use /etc/mke2fs.conf ++ * Mke2fs will now create filesystems hash trees and ++ on-line resizing enabled by default ++ * The e2fsprogs tools (resize2fs, e2fsck, mke2fs) will open the ++ filesystem device node in exclusive mode ++ * Add support for on-line resizing to resize2fs. ++ * The blkid library will now store the UUID of the external ++ journal used by ext3 filesystems ++ * E2fsck will now consult a configuration file, /etc/e2fsck.conf ++ * E2fsck will detect if the superblock's last mount field or ++ last write field is in the future, and offer to fix if so. ++ * E2fsck now checks to see if the superblock hint for the ++ location of the external journal is incorrect ++ * Resize2fs will now automatically determine the RAID stride ++ parameter that had been used to create the filesystem ++ * Fix mke2fs so that it correctly creates external journals on ++ big-endian machines ++ * Fix a bug in the e2p library ++ * Add a new debugfs command, set_current_time ++ * Fix debugfs commands ++ * Fix mklost+found so that it creates a full-sized directory on ++ filesystems with larger block sizes. ++ * Fix a file descriptor leak in blkid library ++ * Allow fractional percentages to the -m option in mke2fs and tune2fs ++ * Add support for device mapper library to the blkid library ++ * Fix the blkid library so that it notices when an ext2 filesystem ++ is upgraded to ext3. ++ * Improve the blkid's library VFAT/FAT detectio ++ * Add support for the reiser4 and software suspend partitions ++ to the blkid library. ++- update ext2resize to version 1.1.19: ++ * Add support for ext3 online resizing ++ * Support LARGEFILE compat flag ++ * Make the resize inode part of the fs struct ++ * Add the FL_IOCTL flag ++ * Bugfixes ++* Fri Aug 11 2006 pth@suse.de ++- Fix to comply with gettex 0.15. ++- Move ext2resize sources to toplevel directory. ++- Fix use of MKINSTALLDIRS. ++* Fri Aug 4 2006 kay.sievers@suse.de ++- update libvolume_id integration to match util-linux ++* Fri Jun 16 2006 ro@suse.de ++- added libvolume_id-devel to BuildRequires ++- updated e2fsprogs-udev.patch to match header rename ++* Wed Feb 8 2006 hare@suse.de ++- Fix fsck -m (#146606) to really check filesystems. ++* Mon Jan 30 2006 hvogel@suse.de ++- Document -I inode-size [#145445] ++* Sun Jan 29 2006 hvogel@suse.de ++- fix hares patch ++* Fri Jan 27 2006 hare@suse.de ++- Add option to not return an error code for mounted ++ filesystems (#145400). ++* Wed Jan 25 2006 mls@suse.de ++- converted neededforbuild to BuildRequires ++* Fri Jan 20 2006 hvogel@suse.de ++- Support ext2/ext3 online resize ++* Mon Dec 12 2005 hvogel@suse.de ++- remove lib/et/test_cases/imap_err* from the tarball because ++ they are not distributeable. ++* Tue Dec 6 2005 pth@suse.de ++- remove unnecessary type-punning ++- reduce compiler warnings ++* Tue Nov 15 2005 jblunck@suse.de ++- added close.patch provided by Ted Tso (IBM) to fix bug #132708 ++* Mon Nov 14 2005 hare@suse.de ++- Use devt when comparing devices ++- fsck: Use information provided by udev for detecting devices ++* Wed Oct 5 2005 hvogel@suse.de ++- fix too few arguments to a *printf function ++- require libcom_err on e2fsprogs-devel ++* Fri Sep 9 2005 hvogel@suse.de ++- add gross hack to avoid divide by zero in probe_reiserfs ++ [#115827] ++* Mon Aug 8 2005 hvogel@suse.de ++- added environment variable BLKID_SKIP_CHECK_MDRAID to work around ++ broken software raid detection [Bug #100530] ++* Tue Jul 5 2005 hvogel@suse.de ++- update to version 1.38 ++- mt reworked his patches a bit. See Bug #66534 ++* Thu Jun 23 2005 hvogel@suse.de ++- call ldconfig in post/postun ++- add version to devel package dependencie ++- readd missing patch (7) ++* Thu Apr 28 2005 hvogel@suse.de ++- update to version 1.37 ++- mt reworked one libcom_err patch a bit to provide more ++ meaningfull error handling ++- fix retuen value in inode.c ++* Thu Mar 31 2005 hvogel@suse.de ++- split libcom_err to a subpackage ++- add mutex synchronization to e2fsprogs/lib/et ++- removed usage of a static buffer in error_message() ++- disabled init_error_table function ++- disabled build of unused e2fsck.static ++* Fri Mar 18 2005 hvogel@suse.de ++- fix endian unsafeness in getopt (#73855) ++* Tue Feb 8 2005 hvogel@suse.de ++- Update to 1.36 final ++* Tue Aug 10 2004 pth@suse.de ++- Update to 1.35 RC5 ++* Wed Mar 17 2004 pth@suse.de ++- Don't build the EVMS plugin because it's out of date for ++ EVMS in kernel 2.6. ++* Thu Mar 4 2004 pth@suse.de ++- Add patch from Olaf Hering that makes fsck read a different ++ blkid file via BLKID_FILE environment var (#35156) ++* Thu Feb 19 2004 kukuk@suse.de ++- Remove obsolete recode call ++* Mon Jan 12 2004 ro@suse.de ++- removed run_ldconfig again ++* Sat Jan 10 2004 adrian@suse.de ++- add %%run_ldconfig ++* Thu Oct 2 2003 pthomas@suse.de ++- Add patch from Kurt Garloff to make e2fsprogs compile ++ with latest kernel headers (SCSI_BLK_MAJOR undefined). ++* Mon Sep 15 2003 pthomas@suse.de ++- Fix czech message catalog which has been transformed twice ++ from latin2 to utf-8 and add an iconv call to the spec file ++ that will make building fail if the file is corrected upstream. ++* Sat Aug 30 2003 agruen@suse.de ++- Fix an endianness bug in ext2fs_swap_inode: Fast symlinks that ++ have extended attributes are acidentally byte swapped on ++ big-endian machines. ++* Fri Aug 1 2003 pthomas@suse.de ++- Apply patch from Ted T'so for badblocks. ++* Thu Jul 31 2003 pthomas@suse.de ++- Update to 1.34. ++- Various fixes to libcom_err to make it really compatible ++ to the heimdal version. ++- Fix int<->pointer casts. ++- Fix places that may break strict aliasing. ++* Fri Jun 20 2003 ro@suse.de ++- added directory to filelist ++* Wed May 14 2003 pthomas@suse.de ++- Use %%defattr ++- Include all installed files. ++* Tue Apr 29 2003 mfabian@suse.de ++- add libblkid.so* and libblkid.a to file lists ++* Thu Apr 24 2003 pthomas@suse.de ++- Update to 1.33 and adapt patches. ++- Add missing headers where necessary. ++* Thu Apr 24 2003 ro@suse.de ++- fix install_info --delete call and move from preun to postun ++* Fri Feb 7 2003 ro@suse.de ++- added install_info macros ++* Tue Oct 1 2002 garloff@suse.de ++- Fix segfault in display of real device in presence of volume ++ name. #20422 ++* Tue Sep 3 2002 mls@suse.de ++- remove duplicate evms scan (already included in 1.28) ++- fix volume group scan bug ++* Mon Sep 2 2002 agruen@suse.de ++- Update to 1.28. Includes very minor fixes in htree, which we have ++ disabled anyway, one fix that we had in a separate patch, and ++ has additional release notes. ++* Mon Aug 19 2002 agruen@suse.de ++- Update to 1.28-WIP-0817, which includes Extended Attribute ++ and several smaller fixes. We disable htree support and don't ++ install the evms library for now. ++- Remove `make gcc-wall' for now (as it does a `make clean' in ++ doc/). ++* Thu Aug 15 2002 mls@suse.de ++- support jfs, reiserfs, evms in label/uuid scan (code stolen ++ from util-linux:mount) ++* Sun Jul 28 2002 kukuk@suse.de ++- Remove unused tetex from neededforbuild ++* Fri Jul 19 2002 olh@suse.de ++- use a better method for finding missed filelist entries ++* Fri Apr 12 2002 sf@suse.de ++- added %%{_libdir} ++- added fix for lib/lib64 ++* Thu Mar 28 2002 bk@suse.de ++- fix man pages, filelist and add check for missing files in packs ++* Wed Mar 27 2002 bk@suse.de ++- Update to 1.27, fixes resource limit problem for other archs and ++ merges many patches ++* Thu Mar 7 2002 pthomas@suse.de ++- Add patch from Ted T'so to keep e2fsck from dumping ++ core when the journal inode is missing. ++* Mon Mar 4 2002 pthomas@suse.de ++- Fix implicit function declarations and some other gcc warnings. ++- Include patch from Kurt Garloff to make e2fsck display the ++ device name in addition to the volume label. Adapt it to 1.26. ++- Adapt BSD_disklables.diff to new code. ++- Set LC_CTYPE in addition to LC_MESSAGES. ++- Repack with bzip2. ++* Fri Mar 1 2002 bk@suse.de ++- Update to 1.26. This release has a number of critical bug ++ fixes over the previous release, version 1.25: ++* Fri Feb 15 2002 pthomas@suse.de ++- Use %%{_lib} and %%{_libdir}. ++* Wed Feb 13 2002 pthomas@suse.de ++- Make heimdal-devel conflict e2fsprogs-devel. ++ Temporary solution for bug #13145 ++* Thu Dec 13 2001 pthomas@suse.de ++- Add mkfs.ext2.8 because mkfs.8 from util-linux references it. ++ Fixes bug #12613. ++* Fri Nov 23 2001 pthomas@suse.de ++- Add accidently left out e2image to file list. Fixes bug ++ [#12009] ++* Wed Oct 31 2001 ro@suse.de ++- fix for axp: should malloc buffer _before_ use ++* Wed Oct 10 2001 pthomas@suse.de ++- Update to 1.25. ++- Remove patches not needed anymore. ++- Change mke2fs to output warnings to stderr not stdout. ++- Repack as bz2. ++* Mon Sep 24 2001 olh@suse.de ++- replace ext2fs_d ++* Fri Sep 21 2001 pthomas@suse.de ++- Add patch for mke2fs from 1.25 as that bug seems to be the ++ reason for the mk_initrd warning. ++* Wed Sep 12 2001 pthomas@suse.de ++- Update to 1.24a: ++ - Fix brown-paper bug in mke2fs which caused it to segfault. ++ - Revert the BLKGETSIZE64 support as this ioctl has been used ++ by an unofficial kernel patch to update the last sector on ++ the disk, and this was causing disk corruption problems as a ++ result. ++ - Mke2fs is now more careful about zapping swap space signatures ++ and other filesystem/raid superblock magic values so. ++ - E2fsck will no longer complain if the the mode of ++ EXT2_RESIZE_INO is a regular file ++ - mke2fs and tune2fs will allow the use of UUID= or LABEL= ++ specifiers when specifying the external journal device. ++ tune2fs will also search devices looking for the external ++ journal device when removing. ++* Fri Aug 17 2001 ro@suse.de ++- update to 1.23 to enable external journals on ext3 ++* Wed Aug 15 2001 pthomas@suse.de ++- Update to 1.22. ++- Drop fsck Patch as code changed. ++- Use LD_LIBRARY_PATH to run test programs. ++* Fri Jun 8 2001 pthomas@suse.de ++- Remove incorrect use of AC_REQUIRE (fails with autoconf 2.5) ++- Recompress tarball with bzip2. ++* Thu Jan 18 2001 schwab@suse.de ++- Add Obsoletes: ext2fs_d and Requires: e2fsprogs to devel ++ subpackage. ++* Mon Nov 6 2000 pthomas@suse.de ++- use _mandir and _infodir more consistently in spec file. ++* Sun Nov 5 2000 ro@suse.de ++- renamed packages to e2fsprogs/e2fsprogs-devel ++* Fri Jun 9 2000 kasal@suse.cz ++- Build dynamic libraries. Partition Surprise requires them. ++- Make /usr/lib/*.so symlinks relative. ++* Thu Mar 23 2000 kukuk@suse.de ++- Don't erase BSD labels on Alpha ++- Add Y2K fix to debugfs ++* Wed Mar 22 2000 kukuk@suse.de ++- Fix ifdefs for gcc 2.95.2 ++* Tue Feb 22 2000 garloff@suse.de ++- Bugfix for the change ... ++- ... and change version no of fsck to 1.18a to reflect the change. ++* Sun Feb 20 2000 garloff@suse.de ++- Patch to be more clever WRT to basenames (used to find out wheter ++ a fsck for this device is already running). ++- Give better message in case fsck fails, to tell the user what to ++ do. (e2fsck only displays the label, nowadays :-( ) ++* Thu Feb 10 2000 kukuk@suse.de ++- Use autoconf to create new configure ++* Wed Jan 19 2000 ro@suse.de ++- man,info -> /usr/share ++* Mon Jan 17 2000 ro@suse.de ++- fixed to build on kernels >= 2.3.39 ++* Sat Nov 13 1999 kukuk@suse.de ++- Update to e2fsprogs 1.18 ++- Create new sub-package ext2fs_d which includes libs and headers ++* Mon Nov 8 1999 ro@suse.de ++-fixed coredump in e2fsck ++* Fri Oct 29 1999 ro@suse.de ++-e2fsprogs: 1.17 vital bugfix in e2fsck ++* Sun Oct 24 1999 ro@suse.de ++- e2fsprogs: update to 1.16, sparse_super is default on when ++ called on a > 2.2 kernel, can be overridden with -O none ++* Fri Oct 15 1999 garloff@suse.de ++- Disabled flushb again. (Moved to ddrescue.) ++* Mon Sep 13 1999 bs@suse.de ++- ran old prepare_spec on spec file to switch to new prepare_spec. ++* Wed Sep 1 1999 ro@suse.de ++- mke2fs: sparse superblocks default back to "off" ++* Tue Aug 31 1999 ro@suse.de ++- update to 1.15 ++- cleanup diff and specfile ++* Sun Jul 18 1999 garloff@suse.de ++- Enabled flushb compilation ++* Sat Jun 26 1999 kukuk@suse.de ++- Add fix for fsck core dump from beta list ++* Tue Mar 16 1999 ro@suse.de ++- fixed configure call ++* Fri Mar 12 1999 ro@suse.de ++- update to 1.14 ++* Thu Oct 29 1998 ro@suse.de ++- respect change in 2.1.126 SCSI_DISK_MAJOR ++* Tue Sep 1 1998 ro@suse.de ++- update to 1.12 ++* Sat Apr 26 1997 florian@suse.de ++- update to new version 1.10 ++* Sun Apr 13 1997 florian@suse.de ++- update to new version 1.08 ++- do not include ext2 libs and include files as they are only used by dump ++* Thu Jan 2 1997 florian@suse.de ++- update to new version 1.06 ++* Thu Jan 2 1997 florian@suse.de ++- update to newer version ++- use now static libs instead of 4 small shared libs ++* Thu Jan 2 1997 florian@suse.de ++ update to version 1.0.4 +Index: e2fsprogs/configure.in +=================================================================== +--- e2fsprogs.orig/configure.in ++++ e2fsprogs/configure.in +@@ -1232,7 +1232,7 @@ test -d lib || mkdir lib + test -d include || mkdir include + test -d include/linux || mkdir include/linux + test -d include/asm || mkdir include/asm +-for i in MCONFIG Makefile e2fsprogs.spec \ ++for i in MCONFIG Makefile e2fsprogs.spec e2fsprogs-SUSE_LINUX-11.spec \ + util/Makefile util/subst.conf util/gen-tarball \ + lib/et/Makefile lib/ss/Makefile lib/e2p/Makefile \ + lib/ext2fs/Makefile lib/ext2fs/ext2_types.h \ +Index: e2fsprogs/contrib/build-rpm +=================================================================== +--- e2fsprogs.orig/contrib/build-rpm ++++ e2fsprogs/contrib/build-rpm +@@ -34,11 +34,46 @@ EXCLUDE="--exclude .hg* --exclude .pc*" + + [ "`rpmbuild --version 2> /dev/null`" ] && RPM=rpmbuild || RPM=rpm + ++# which distro and release ++DISTRO=$(lsb_release -is) ++RELEASE=$(lsb_release -rs) ++# now the hacks in case either is empty ++if [ -z "$DISTRO" ]; then ++ echo "You really ought to install the lsb_release binary for this distro" ++ if grep "SUSE Linux Enterprise Server " /etc/issue; then ++ DISTRO="SUSE LINUX" ++ fi ++fi ++if [ -z "$DISTRO" ]; then ++ echo "Could not determine the distribution. Please install the lsb_release binary" ++ exit 1 ++fi ++if [ -z "$RELEASE" ]; then ++ echo "You really ought to install the lsb_release binary for this distro" ++ case "$DISTRO" in ++ SUSE\ LINUX) ++ if grep "SUSE Linux Enterprise Server 11 " /etc/issue; then ++ RELEASE=11 ++ elif grep "SUSE Linux Enterprise Server 10 " /etc/issue; then ++ RELEASE=10 ++ fi ++ ;; ++ esac ++fi ++if [ -z "$RELEASE" ]; then ++ echo "Could not determine the release. Please install the lsb_release binary" ++ exit 1 ++fi ++ ++SPECFILE="$currdir/e2fsprogs-${DISTRO// /_}-$RELEASE.spec" ++if [ ! -f "$SPECFILE" ]; then ++ SPECFILE="$currdir/e2fsprogs.spec" ++fi + $RPM --define "_sourcedir $tmpdir" \ + --define "_topdir ${RPM_TOPDIR:-$(rpm -E %_topdir)}" \ + --define "_tmpdir ${RPM_TMPDIR:-$TMP}" \ + --define "extra_config_flags ${EXTRA_CONFIG_FLAGS:-''}" \ +- -ba $currdir/e2fsprogs.spec ++ -ba $SPECFILE + + rpm_exit=$? + rm -rf $tmpdir diff --git a/patches/e2fsprogs-size_high.patch b/patches/e2fsprogs-size_high.patch new file mode 100644 index 0000000..60623ad --- /dev/null +++ b/patches/e2fsprogs-size_high.patch @@ -0,0 +1,117 @@ +Access inode size via EXT2_I_SIZE() instead of using i_size directly, +so that files larger than 4GB are correctly handled. + +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/debugfs/debugfs.c +=================================================================== +--- e2fsprogs.orig/debugfs/debugfs.c ++++ e2fsprogs/debugfs/debugfs.c +@@ -722,12 +722,9 @@ void internal_dump_inode(FILE *out, cons + } + fprintf(out, "%sUser: %5d Group: %5d Size: ", + prefix, inode_uid(*inode), inode_gid(*inode)); +- if (LINUX_S_ISREG(inode->i_mode)) { +- unsigned long long i_size = (inode->i_size | +- ((unsigned long long)inode->i_size_high << 32)); +- +- fprintf(out, "%llu\n", i_size); +- } else ++ if (LINUX_S_ISREG(inode->i_mode)) ++ fprintf(out, "%llu\n", EXT2_I_SIZE(inode)); ++ else + fprintf(out, "%d\n", inode->i_size); + if (os == EXT2_OS_HURD) + fprintf(out, +@@ -901,9 +898,7 @@ void do_dump_extents(int argc, char **ar + return; + } + +- logical_width = int_log10(((inode.i_size | +- (__u64) inode.i_size_high << 32) + +- current_fs->blocksize - 1) / ++ logical_width = int_log10((EXT2_I_SIZE(&inode)+current_fs->blocksize-1)/ + current_fs->blocksize) + 1; + if (logical_width < 5) + logical_width = 5; +Index: e2fsprogs/debugfs/ls.c +=================================================================== +--- e2fsprogs.orig/debugfs/ls.c ++++ e2fsprogs/debugfs/ls.c +@@ -79,7 +79,7 @@ static int list_dir_proc(ext2_ino_t dir + if (LINUX_S_ISDIR(inode.i_mode)) + fprintf(ls->f, "/"); + else +- fprintf(ls->f, "%lld/", inode.i_size | ((__u64)inode.i_size_high << 32)); ++ fprintf(ls->f, "%lld/", EXT2_I_SIZE(&inode)); + fprintf(ls->f, "\n"); + } + else if (ls->options & LONG_OPT) { +@@ -102,8 +102,7 @@ static int list_dir_proc(ext2_ino_t dir + if (LINUX_S_ISDIR(inode.i_mode)) + fprintf(ls->f, "%5d", inode.i_size); + else +- fprintf(ls->f, "%5llu", inode.i_size | +- ((unsigned long long) inode.i_size_high << 32)); ++ fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode)); + fprintf (ls->f, " %s %s\n", datestr, name); + } else { + sprintf(tmp, "%c%u%c (%d) %s ", lbr, dirent->inode, rbr, +Index: e2fsprogs/e2fsck/pass1.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass1.c ++++ e2fsprogs/e2fsck/pass1.c +@@ -2033,8 +2033,7 @@ static void check_blocks(e2fsck_t ctx, s + } + pctx->num = 0; + } +- if (LINUX_S_ISREG(inode->i_mode) && +- (inode->i_size_high || inode->i_size & 0x80000000UL)) ++ if (LINUX_S_ISREG(inode->i_mode) && EXT2_I_SIZE(inode) >= 0x80000000UL) + ctx->large_files++; + if ((pb.num_blocks != ext2fs_inode_i_blocks(fs, inode)) || + ((fs->super->s_feature_ro_compat & +Index: e2fsprogs/e2fsck/pass2.c +=================================================================== +--- e2fsprogs.orig/e2fsck/pass2.c ++++ e2fsprogs/e2fsck/pass2.c +@@ -1220,8 +1220,7 @@ static void deallocate_inode(e2fsck_t ct + if (!ext2fs_inode_has_valid_blocks(&inode)) + return; + +- if (LINUX_S_ISREG(inode.i_mode) && +- (inode.i_size_high || inode.i_size & 0x80000000UL)) ++ if (LINUX_S_ISREG(inode.i_mode) && EXT2_I_SIZE(&inode) >= 0x80000000UL) + ctx->large_files--; + + pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, +Index: e2fsprogs/e2fsck/super.c +=================================================================== +--- e2fsprogs.orig/e2fsck/super.c ++++ e2fsprogs/e2fsck/super.c +@@ -170,8 +170,7 @@ static int release_inode_blocks(e2fsck_t + if (inode->i_links_count) { + pb.truncating = 1; + pb.truncate_block = (e2_blkcnt_t) +- ((((long long)inode->i_size_high << 32) + +- inode->i_size + fs->blocksize - 1) / ++ ((EXT2_I_SIZE(inode) + fs->blocksize - 1) / + fs->blocksize); + pb.truncate_offset = inode->i_size % fs->blocksize; + } else { +Index: e2fsprogs/lib/ext2fs/extent.c +=================================================================== +--- e2fsprogs.orig/lib/ext2fs/extent.c ++++ e2fsprogs/lib/ext2fs/extent.c +@@ -253,9 +253,8 @@ extern errcode_t ext2fs_extent_open2(ext + handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max); + handle->path[0].curr = 0; + handle->path[0].end_blk = +- ((((__u64) handle->inode->i_size_high << 32) + +- handle->inode->i_size + (fs->blocksize - 1)) +- >> EXT2_BLOCK_SIZE_BITS(fs->super)); ++ (EXT2_I_SIZE(handle->inode) + fs->blocksize - 1) >> ++ EXT2_BLOCK_SIZE_BITS(fs->super); + handle->path[0].visit_num = 1; + handle->level = 0; + handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE; diff --git a/patches/e2fsprogs-skip-extent-tests.patch b/patches/e2fsprogs-skip-extent-tests.patch new file mode 100644 index 0000000..d92a21e --- /dev/null +++ b/patches/e2fsprogs-skip-extent-tests.patch @@ -0,0 +1,9 @@ +Index: e2fsprogs-1.41.1/tests/f_extents_ei_block/script +=================================================================== +--- /dev/null ++++ e2fsprogs-1.41.1/tests/f_extents_ei_block/script +@@ -0,0 +1,3 @@ ++rm -f $test_name.ok $test_name.failed ++echo "skipped" ++ ++ diff --git a/patches/e2fsprogs-specdotin.patch b/patches/e2fsprogs-specdotin.patch new file mode 100644 index 0000000..9a0041a --- /dev/null +++ b/patches/e2fsprogs-specdotin.patch @@ -0,0 +1,40 @@ +Add the distro version to the RPM release number, so that it the +RPM names do not conflict. + +Allow the RPM built from upstream to replace the split packages provided +by the distros. At some point in the future it may be desirable to also +split the RPM built by this spec file, but this is complicated by the +fact that SLES and RHEL have different splits. + +Signed-off-by: Girish Shilamkar +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/e2fsprogs.spec.in +=================================================================== +--- e2fsprogs.orig/e2fsprogs.spec.in ++++ e2fsprogs/e2fsprogs.spec.in +@@ -6,13 +6,22 @@ + Summary: Utilities for managing ext2/ext3/ext4 filesystems + Name: e2fsprogs + Version: @E2FSPROGS_PKGVER@ +-Release: 0 ++Release: 0%{_vendor} + License: GPLv2 + Group: System Environment/Base + Source: ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/e2fsprogs-%{version}.tar.gz +-Url: http://e2fsprogs.sourceforge.net/ ++Url: http://build.whamcloud.com/job/e2fsprogs/ + Prereq: /sbin/ldconfig + BuildRoot: %{_tmppath}/%{name}-root ++%if %{_vendor} == "suse" ++Group: System/Filesystems ++Provides: e2fsbn ext2fs libcom_err = %{version} ldiskfsprogs = %{version} ++Obsoletes: ext2fs libcom_err < %{version} ++%else ++Group: System Environment/Base ++Provides: e2fsprogs-libs = %{version} ldiskfsprogs = %{version} ++Obsoletes: e4fsprogs e2fsprogs-libs < %{version} ++%endif + + %description + The e2fsprogs package contains a number of utilities for creating, diff --git a/patches/e2fsprogs-tests-f_bad_ea_value.patch b/patches/e2fsprogs-tests-f_bad_ea_value.patch new file mode 100644 index 0000000..936cc05 Binary files /dev/null and b/patches/e2fsprogs-tests-f_bad_ea_value.patch differ diff --git a/patches/e2fsprogs-tests-f_data_in_dirent.patch b/patches/e2fsprogs-tests-f_data_in_dirent.patch new file mode 100644 index 0000000..21b91c9 Binary files /dev/null and b/patches/e2fsprogs-tests-f_data_in_dirent.patch differ diff --git a/patches/e2fsprogs-tests-f_expisize.patch b/patches/e2fsprogs-tests-f_expisize.patch new file mode 100644 index 0000000..c2e3ef5 --- /dev/null +++ b/patches/e2fsprogs-tests-f_expisize.patch @@ -0,0 +1,1355 @@ +Test case for expanding inode size. + +Index: e2fsprogs/tests/f_expisize/expect.1 +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_expisize/expect.1 +@@ -0,0 +1,427 @@ ++Adding dirhash hint to filesystem. ++ ++Pass 1: Checking inodes, blocks, and sizes ++Expanding inode 2. ++Expanding inode 11. ++Expanding inode 12. ++Expanding inode 13. ++Expanding inode 14. ++Expanding inode 15. ++Expanding inode 16. ++Expanding inode 17. ++Expanding inode 18. ++Expanding inode 19. ++Expanding inode 20. ++Expanding inode 21. ++Expanding inode 22. ++Expanding inode 23. ++Expanding inode 24. ++Expanding inode 25. ++Expanding inode 26. ++Expanding inode 27. ++Expanding inode 28. ++Expanding inode 29. ++Expanding inode 30. ++Expanding inode 31. ++Expanding inode 32. ++Expanding inode 33. ++Expanding inode 34. ++Expanding inode 35. ++Expanding inode 36. ++Expanding inode 37. ++Expanding inode 38. ++Expanding inode 39. ++Expanding inode 40. ++Expanding inode 41. ++Expanding inode 42. ++Expanding inode 43. ++Expanding inode 44. ++Expanding inode 45. ++Expanding inode 46. ++Expanding inode 47. ++Expanding inode 48. ++Expanding inode 49. ++Expanding inode 50. ++Expanding inode 51. ++Expanding inode 52. ++Expanding inode 53. ++Expanding inode 54. ++Expanding inode 55. ++Expanding inode 56. ++Expanding inode 57. ++Expanding inode 58. ++Expanding inode 59. ++Expanding inode 60. ++Expanding inode 61. ++Expanding inode 62. ++Expanding inode 63. ++Expanding inode 64. ++Expanding inode 65. ++Expanding inode 66. ++Expanding inode 67. ++Expanding inode 68. ++Expanding inode 69. ++Expanding inode 70. ++Expanding inode 71. ++Expanding inode 72. ++Expanding inode 73. ++Expanding inode 74. ++Expanding inode 75. ++Expanding inode 76. ++Expanding inode 77. ++Expanding inode 78. ++Expanding inode 79. ++Expanding inode 80. ++Expanding inode 81. ++Expanding inode 82. ++Expanding inode 83. ++Expanding inode 84. ++Expanding inode 85. ++Expanding inode 86. ++Expanding inode 87. ++Expanding inode 88. ++Expanding inode 89. ++Expanding inode 90. ++Expanding inode 91. ++Expanding inode 92. ++Expanding inode 93. ++Expanding inode 94. ++Expanding inode 95. ++Expanding inode 96. ++Expanding inode 97. ++Expanding inode 98. ++Expanding inode 99. ++Expanding inode 100. ++Expanding inode 101. ++Expanding inode 102. ++Expanding inode 103. ++Expanding inode 104. ++Expanding inode 105. ++Expanding inode 106. ++Expanding inode 107. ++Expanding inode 108. ++Expanding inode 109. ++Expanding inode 110. ++Expanding inode 111. ++Expanding inode 112. ++Expanding inode 113. ++Expanding inode 114. ++Expanding inode 115. ++Expanding inode 116. ++Expanding inode 117. ++Expanding inode 118. ++Expanding inode 119. ++Expanding inode 120. ++Expanding inode 121. ++Expanding inode 122. ++Expanding inode 123. ++Expanding inode 124. ++Expanding inode 125. ++Expanding inode 126. ++Expanding inode 127. ++Expanding inode 128. ++Expanding inode 129. ++Expanding inode 130. ++Expanding inode 131. ++Expanding inode 132. ++Expanding inode 133. ++Expanding inode 134. ++Expanding inode 135. ++Expanding inode 136. ++Expanding inode 137. ++Expanding inode 138. ++Expanding inode 139. ++Expanding inode 140. ++Expanding inode 141. ++Expanding inode 142. ++Expanding inode 143. ++Expanding inode 144. ++Expanding inode 145. ++Expanding inode 146. ++Expanding inode 147. ++Expanding inode 148. ++Expanding inode 149. ++Expanding inode 150. ++Expanding inode 151. ++Expanding inode 152. ++Expanding inode 153. ++Expanding inode 154. ++Expanding inode 155. ++Expanding inode 156. ++Expanding inode 157. ++Expanding inode 158. ++Expanding inode 159. ++Expanding inode 160. ++Expanding inode 161. ++Expanding inode 162. ++Expanding inode 163. ++Expanding inode 164. ++Expanding inode 165. ++Expanding inode 166. ++Expanding inode 167. ++Expanding inode 168. ++Expanding inode 169. ++Expanding inode 170. ++Expanding inode 171. ++Expanding inode 172. ++Expanding inode 173. ++Expanding inode 174. ++Expanding inode 175. ++Expanding inode 176. ++Expanding inode 177. ++Expanding inode 178. ++Expanding inode 179. ++Expanding inode 180. ++Expanding inode 181. ++Expanding inode 182. ++Expanding inode 183. ++Expanding inode 184. ++Expanding inode 185. ++Expanding inode 186. ++Expanding inode 187. ++Expanding inode 188. ++Expanding inode 189. ++Expanding inode 190. ++Expanding inode 191. ++Expanding inode 192. ++Expanding inode 193. ++Expanding inode 194. ++Expanding inode 195. ++Expanding inode 196. ++Expanding inode 197. ++Expanding inode 198. ++Expanding inode 199. ++Expanding inode 200. ++Expanding inode 201. ++Expanding inode 202. ++Expanding inode 203. ++Expanding inode 204. ++Expanding inode 205. ++Expanding inode 206. ++Expanding inode 207. ++Expanding inode 208. ++Expanding inode 209. ++Expanding inode 210. ++Expanding inode 211. ++Expanding inode 212. ++Expanding inode 213. ++Expanding inode 214. ++Expanding inode 215. ++Expanding inode 216. ++Expanding inode 217. ++Expanding inode 218. ++Expanding inode 219. ++Expanding inode 220. ++Expanding inode 221. ++Expanding inode 222. ++Expanding inode 223. ++Expanding inode 224. ++Expanding inode 225. ++Expanding inode 226. ++Expanding inode 227. ++Expanding inode 228. ++Expanding inode 229. ++Expanding inode 230. ++Expanding inode 231. ++Expanding inode 232. ++Expanding inode 233. ++Expanding inode 234. ++Expanding inode 235. ++Expanding inode 236. ++Expanding inode 237. ++Expanding inode 238. ++Expanding inode 239. ++Expanding inode 240. ++Expanding inode 241. ++Expanding inode 242. ++Expanding inode 243. ++Expanding inode 244. ++Expanding inode 245. ++Expanding inode 246. ++Expanding inode 247. ++Expanding inode 248. ++Expanding inode 249. ++Expanding inode 250. ++Expanding inode 251. ++Expanding inode 252. ++Expanding inode 253. ++Expanding inode 254. ++Expanding inode 255. ++Expanding inode 256. ++Expanding inode 257. ++Expanding inode 258. ++Expanding inode 259. ++Expanding inode 260. ++Expanding inode 261. ++Expanding inode 262. ++Expanding inode 263. ++Expanding inode 264. ++Expanding inode 265. ++Expanding inode 266. ++Expanding inode 267. ++Expanding inode 268. ++Expanding inode 269. ++Expanding inode 270. ++Expanding inode 271. ++Expanding inode 272. ++Expanding inode 273. ++Expanding inode 274. ++Expanding inode 275. ++Expanding inode 276. ++Expanding inode 277. ++Expanding inode 278. ++Expanding inode 279. ++Expanding inode 280. ++Expanding inode 281. ++Expanding inode 282. ++Expanding inode 283. ++Expanding inode 284. ++Expanding inode 285. ++Expanding inode 286. ++Expanding inode 287. ++Expanding inode 288. ++Expanding inode 289. ++Expanding inode 290. ++Expanding inode 291. ++Expanding inode 292. ++Expanding inode 293. ++Expanding inode 294. ++Expanding inode 295. ++Expanding inode 296. ++Expanding inode 297. ++Expanding inode 298. ++Expanding inode 299. ++Expanding inode 300. ++Expanding inode 301. ++Expanding inode 302. ++Expanding inode 303. ++Expanding inode 304. ++Expanding inode 305. ++Expanding inode 306. ++Expanding inode 307. ++Expanding inode 308. ++Expanding inode 309. ++Expanding inode 310. ++Expanding inode 311. ++Expanding inode 312. ++Expanding inode 313. ++Expanding inode 314. ++Expanding inode 315. ++Expanding inode 316. ++Expanding inode 317. ++Expanding inode 318. ++Expanding inode 319. ++Expanding inode 320. ++Expanding inode 321. ++Expanding inode 322. ++Expanding inode 323. ++Expanding inode 324. ++Expanding inode 325. ++Expanding inode 326. ++Expanding inode 327. ++Expanding inode 328. ++Expanding inode 329. ++Expanding inode 330. ++Expanding inode 331. ++Expanding inode 332. ++Expanding inode 333. ++Expanding inode 334. ++Expanding inode 335. ++Expanding inode 336. ++Expanding inode 337. ++Expanding inode 338. ++Expanding inode 339. ++Expanding inode 340. ++Expanding inode 341. ++Expanding inode 342. ++Expanding inode 343. ++Expanding inode 344. ++Expanding inode 345. ++Expanding inode 346. ++Expanding inode 347. ++Expanding inode 348. ++Expanding inode 349. ++Expanding inode 350. ++Expanding inode 351. ++Expanding inode 352. ++Expanding inode 353. ++Expanding inode 354. ++Expanding inode 355. ++Expanding inode 356. ++Expanding inode 357. ++Expanding inode 358. ++Expanding inode 359. ++Expanding inode 360. ++Expanding inode 361. ++Expanding inode 362. ++Expanding inode 363. ++Expanding inode 364. ++Expanding inode 365. ++Expanding inode 366. ++Expanding inode 367. ++Expanding inode 368. ++Expanding inode 369. ++Expanding inode 370. ++Expanding inode 371. ++Expanding inode 372. ++Expanding inode 373. ++Expanding inode 374. ++Expanding inode 375. ++Expanding inode 376. ++Expanding inode 377. ++Expanding inode 378. ++Expanding inode 379. ++Expanding inode 380. ++Expanding inode 381. ++Expanding inode 382. ++Expanding inode 383. ++Expanding inode 384. ++Expanding inode 385. ++Expanding inode 386. ++Expanding inode 387. ++Expanding inode 388. ++Expanding inode 389. ++Expanding inode 390. ++Expanding inode 391. ++Expanding inode 392. ++Expanding inode 393. ++Expanding inode 394. ++Expanding inode 395. ++Expanding inode 396. ++Expanding inode 397. ++Expanding inode 398. ++Expanding inode 399. ++Expanding inode 400. ++Expanding inode 401. ++Expanding inode 402. ++Expanding inode 403. ++Expanding inode 404. ++Expanding inode 405. ++Expanding inode 406. ++Expanding inode 407. ++Expanding inode 408. ++Expanding inode 409. ++Expanding inode 410. ++Expanding inode 411. ++Pass 2: Checking directory structure ++Pass 3: Checking directory connectivity ++Pass 4: Checking reference counts ++Pass 5: Checking group summary information ++Block bitmap differences: -1385 -2019 ++Fix? yes ++ ++Free blocks count wrong for group #0 (8, counted=10). ++Fix? yes ++ ++Free blocks count wrong (8, counted=10). ++Fix? yes ++ ++Expanding inode 133. ++Expanding inode 165. ++Expanding inode 181. ++Expanding inode 286. ++Expanding inode 387. ++ ++test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** ++test_filesys: 411/2048 files (0.2% non-contiguous), 2043/2048 blocks ++Exit status is 1 +Index: e2fsprogs/tests/f_expisize/expect.2 +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_expisize/expect.2 +@@ -0,0 +1,7 @@ ++Pass 1: Checking inodes, blocks, and sizes ++Pass 2: Checking directory structure ++Pass 3: Checking directory connectivity ++Pass 4: Checking reference counts ++Pass 5: Checking group summary information ++test_filesys: 411/2048 files (0.2% non-contiguous), 2043/2048 blocks ++Exit status is 0 +Index: e2fsprogs/tests/f_expisize/name +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_expisize/name +@@ -0,0 +1 @@ ++test expand_extra_isize feature +Index: e2fsprogs/tests/f_expisize/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_expisize/script +@@ -0,0 +1,4 @@ ++FSCK_OPT="-fy -E expand_extra_isize" ++SECOND_FSCK_OPT=-yf ++ ++. $cmd_dir/run_e2fsck +Index: e2fsprogs/tests/f_expisize/image.gz +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_expisize/image.gz +@@ -0,0 +1,888 @@ ++‹+€hFimageìÝ àlUY÷ñ9œ9ŠzTTTLTJTÔ=³ï…z4´SQ¢R¢QQ¡’QRQYYiYZš÷[eEey-±¬¬,©ÈKQYYQYQQâõý={ï5³föZ{†Ù<¼~?oË÷̹üÿÃÿ™½÷º<ëY“ €/XÓ¶=®ûåcnûˆ®MžÒ5ýáq<÷¡S;brâä‘Ú3٣߾칏{èäk?Ðü›=ݗ¼Y÷N龯MÔÞzÏ;<þoÈ[~ﻞ=¿ü-|ô ùŸç<þ¿ã¾?ò’‡~ü|î žüÆ×Ýäˆ=Ë?³ÿŽ›êõÍԎQ»¹Ú-Ôn©¶_íVj·V»Ú±j·U»Ýžõïv€Ïk®~dÓW~ìÑGð#àÿ;Ÿû‚öî³?Bö2ÿÀ‹ÛþW×ȊøÂñé’Éä<÷¡'u­ý“›L޳ÿoûêÈ=“ÉSŽžLžzôõûý$7¨§¿^þÔ6ÿ§¸»¶xþ{vÿÏþòc?~ó£†âÄ{§{Îo>U®Ïù]ßò­“t¶oÏyÍïßÄûýY]Ì û»{N޳콴VÍêrºçøæ÷oîý~^äå¾=—4¯Ïô¿VQ—óæk½i²þý³yžîÛóÆIïû§Užv¯÷Ä'Z›ÕI>Óÿ?ŸÍÊ|žÏ“ù|žÖ³yY•å<¯çYQU³4g³<«ë:OëjVUú‹ú/©’Ù¼˜U…¾[’UI–I'e’–I2Oõ·š¯[äżJ³¼ýžúJÕ¼¬ ýçf…¾i–—E™Tó:ÑËr–Õå¬,õíç©þQ’Ìò:KÒ*Íg³y]»÷<«g•‹ÿ÷ªß÷îøßvDüŸ£øßnCü÷í9»‰ÙíWâ<+ªfqZóg·öþLÿQŬù³ƒýÏGUæí¿;ÐüÙ^ÿßÍÒ"mþ¬ê}Þf ++GÝüÙI½ÏBÓýÙþæÏnëýÙ¼šeEóg×LÖÿæ©¢?ð³±8dål¦÷¸e¦À¥³¬ýûs‹ö¬®Ë¤û÷ú¨¤úÿõ™©Üçqžë7çõL¡OªYÑþ»´,õÕäl®¯¡‡¾‹ÿ÷wñw$þwÿç*þ_´Ãõ_ÖIºþõóNêæš=³÷¹(Êt>ÝsFïß(~õ¾=§6¿¿ßÿZº„òækeý{ÆÜ¾V{/¹ÿµÒ"ß·§} ++Þjås7¯óæspõ¤÷geUØ'E‘ÎÊ:¯ò²ª»øÖ³²ÐmD—îÌŸ®ôqOª¢šÏ‹2Ku«˜µWo1×ß*«öï)¸…nivi>íu®¿=˓¢´;P²¸gÙ-jæâïb‹ÿˆÿóÿ/Ùxý·?ÏóýŸÙ,i>óûöÙÿ ¤y•4q»¶wßΓ¤šîyÿd=ž³ª.öíyç¤ÏYVµ×ö¥“õûÅL×^{m¿mÒÿLéߏ©5ݚÛkXAÔMX˜,×_w­º{^Tz$³²‹¹¾–»/ÏuÑêVgºmÏÒ,MŠù<Ë{Rd•"©{VdYÛ}§Ô­½Ò#¬ÊûêóJ?˜|®VY’•éL=Dô[zºè¥ž•%i¢/«O]µmüï3"þÏWüï»1þçöï¹³¼jãvÿ^­‹¦lþìÌþŸéŽ7k>z÷ê,-õ8¹wߘµ¡Ñ×;±ÿõÊdîßûýëZÏÞYûšÞ™æÞgÔÿìdy’®}fÒ$·k¹¬Òî¯Ï¿Âd·ˆ²é£Øg£Èʲ¹o¤ÕL—¯ºHŠrÝÝ7yÝØKÝ,fõ¼žw}ý0мù·e^7ß§VCïmæõÿ,îWÄ?ÿ(þŖñ_¹7geÒ>«Ïé?ãçY6?Û³zñJõ|s×ëóVbUw÷“KzñÐõQ̛?»h»¯¯]ç¡ûtÛ7ÓVZ­ï¦άJí¡T¶¿.ôê|¦b™•º§uR[/Q}5½Rϲéê÷‹L·¥¹â”Ôºàu£ÐM!Ñ_Ñ£¿´w¡@Ïõ¾ævг>Ss®ç€:­µžêÔúxd‰{¯ú‚îýé««“:W (\ü¯ìâedþ÷þ#âÿBÅxügÏÿþõ¯ÿƔÚõË> ¥n4ú@äþõŠ¿ý?`Dü_¤ø?p‡þŸÂ_ûêÙV͵nïϪÒþÍéý±DYwϋª×ŸÓ}&oï3ÉÀ˜àø1ȱý{P’æí÷kïý+ㅢ®òµ˜äzJë^R龡±Z™Í㼬Žôç]¿_ÿB·—´Ö Ý:ˆºíT]ßp––MßF£GõTêy•»{TóïußÙúúȈø¿x‹ëßÅùÿgŸè^Öü Ï跟ֻoÔÛ|_ãzâçöðp}€õqA–[Ÿq>O¶½þ:"þ/Qü¿bãõß>“ßà÷‘ë«=¥yýà•ë5™µý»s{}ùÕ(¡š7!ÏÒ$íÆ4ú1éî1³[¥ÛGÑ®ÿä¥!zÛÆÿûFÄÿ—ÿïßxÿ?§÷<.ôðts9·^[ûi¯ÙSú6Ë»¹ú¤?Ÿ ~ué­ïî]SJÛ{Mÿ~NÁý>|U×{»ëßÿ>í,óòYQéF¬Ÿ²˜·v¯ñ_óɪRcкªšq§Þ~3ïœÚÒn·Æ¤!’-,gͶ[k.lµ1ÍthÖ ýø¿w þ?2"þ¿¬øÿèõ˜ÿ±œ«?#:¾sŸ•{†¬½9ÀÐxÌõ)üuÈLã4°fà®ïµu},t㵙ø¹õèt¡ëš¬=Íç6wg³v‰nê¥Â­Žƒ.Õù<×]Z¦RÑTÜç¶ÜoOz[üQ·R—ð¼P×q®ÏEiËA–-RØ?[ÜOt;(tW¯Rý£LŸ¡™‹÷ÀXp%ÿã½]ü߉ÿOŽˆÿ…ŠÿOíòü_¬ñž\ƒŸvýµ‹üόn ûö¼²¿¾c MìŸÛŸÕÏ7 ôñæµ-ãØí³°LŒ™ÿ³Ël±loÔמê_è:Íô Ðƒ»Ö•©¾·-ꪣm“HúùöĶ.žFöfæ©>2¹>'ê誒TúêE’è¾®†­÷聡¡ÿÌ֏tKÓ A~¥Û{¥Û½¾RÏlØ:Šy’¤}É¶ñÿÙñÿÅÿÙãß¿þݳՍ Ãù8ïhsLVæì³ÂîÀ{»±œÿLÑÍWÿæå×9OgC®NÖÜ?Ô±·)A·V›é¦­‡rm7ò¼²I®¸*äMÝôëJC±Ô.[û¨cgÓ8™M!ê~PXw°HK[:L­‹ ¯¥OPaÙd͸P7z{¸ëI_ÕºÊm4¡ÉÜÆÅúm»[Ø'¤¶[ŠÆ¼¡¦?2þçE#âÿ«[ÍÿŸß&«ßSzy>þ5k½àXž[XÏ ùBZãóòIª¤Ô°@·£²Pï@}‚.þ(¦“mãÿâñÿµ­âAtÏõBýµàØ@Wh»>pl$?tìk~¾×lÖûf×C_q6Kr u[П궨GMóu]rëûÿKFÄÿåŠÿK7öÿúù©¾¡ÜE¾«ÞŸs×M¯íÇ_™O ++Ìÿ$e7¿ÿòIlžÑÅ(4¯¦Z~¸Íë4Ÿ¤POb®¨—Íz‚ú Íø!ÉûÊzOuæÇÿ}ñÿÅñÿuÅÿ—Žºî÷=SË6.çF?î°>þŸvŸ›¬Î Î\ü_´2Ïãr‚ßÐã©+]įÙö3a7½uï ýŸÛÍ3>)2‹—•ýqnÌ-ÃGð*­l:xV©Ÿ§`ª÷®èØZ~[ã«+]´ºu«ŸaK}êꓧN_f_Y½Ž¹-2Îlâ'³õ}ëóÍu7Ðg3ós‘BsÝç@Ùâú_ÿ÷Eâÿë#âÿŠÿoìÐÿ³%Ú,Òÿ[®É5°6xf4oÌ­Ü<˜’õ×l-®ù³“ûïSýôöysb0‡eÈ´µ† Ïƒàœ¿ål4}¹ºÉ )çvw×hÀ2ɺuA=ô9¨Ò´X]÷[_?œéƒQÅßþÿæˆø¿b«ü¯Øú ¯‹ÅtÏËz¦NxužÍºªs[V¶ý³îÙúÙßh×ÿ7]ÿ¿5"þ¯Tü_·ÃüŸnT…[û ­á¹ý+s|ežÞßmWÆ~å,™Döpt9Yn­>œçuÕ$¾~pŤ?ßX¬L5ë„6S¯aßÚ<p¿F$'¬Öß´ü½ºyfh X¹¼–J½“ªÎÖ­¢çTië6¼rÿÿ@üwDü_¥øÿÞÆøŸÉÇ8s _p`OlŠ¿ËI«öÄû€íüßׯ¼´7?4p¯ÐÇÅvz–$”4×]݌æç‰FðÌ«/ª‡2³_ºèÑlùø³ªœëñ®®ˆåtXz~:SoQ·‚&‰ËëgêŠOÔsHt 7ÿ¬Ê†ç&šç|,_ÄÅÿý]ü߉ÿˆÿ«ÿ?Ù2þþu^ÕE2íæwží?SuM»~ÜíV~¿V¿ïÂȚð3úëtIVVøÙl¬n°6ӝ³®²özŒ­ëê§Úì³°7ÝnõÔêöæd‰-èÌ­c8·‰@ëꞦðdúX8,5_ßÎ.sõ ›Žœ†®³æÃ˜UÖO³RnóÖÇг?׸®ÐŸTÍ×Ê-C®r K}÷¶Çh{m©GOI}˜ô æÝœ€Æ ÖEµµ$ë£Ö³íãÿ#âÿÅÿ-;¬ÿ麨ç^}G¨ßîó:m`Íà”ޘѺXþºÐʾM–ûBV× tóõî'¡=¢¡œ1·/dã}du?È¢g›{R›Vg¶jÇóum:õþ-›Ñÿ»‘=!•u0lÚۏÿâÿ×#âÿZÅÿovØÿ±ŒËý}7U{ý…öôé§Ðõ^;0֋¯lˆËá<æ³Û‰ž÷zÎéaÐÜûÕoLìûY¶Á¤ÿYqñÿ@ÿDâÿ#âÿ›Šÿ?í°þã®/÷lX™ÇOlþ7ülpûøÂ×ã&ñ~áEý7_ÍÕ_ûÄúb‡åý¿¶ä³ÌVÊÅØp(þþøïßGÄÿ·¶ÿ]ÙËqþ@Ç9½gFªÿð¹77Î ìÉ«ìó:Wٗq¨æ&^î±"®ª.Ë8i¦ã¹`©Í‡¸ø°‹ÿ#ñÿ؈øÿ¶âÿñâ¿ÜC¯ä>«¹¹íÜÖ¾ÀÞ@·_ÇͯçE×fo\ù>½½CöÁѐÃå/ö–nÿόˆÿï(þŸÝeü·ǝ>°7¤“ í×p¹¼+s‡–>×Ä¿}v<ÚÿšYž/æ€,-Ï.ºÒêp¶¿MËÓ3¢½È*ûÝfŠ]𦨎%s—––W×ú»v¹Õ‰åð¤VªZ¬è&œÝ{F¢µGü1â¶ñ?jDÝÿ7(þG½)þm*tßuyûáyÞ«ú÷d]¬íXïýãÀxž÷!fqµ€ZU=õË2žÇ=$Ϗmãóñÿ]ÅÿG_÷þ»+Ðÿϲ̯ ¶:/ԎÁÝ>®P^ ›XíËg]?ÿµýü—¯=t—nóktÁ†¹~úO­r›;ÒM&ñƽ5åmãÛñÿ=«ÿ¶ñú¿r ^ïèçk꿾í´y>¡º1Ón>g¥6€~\ûö¼t[ ++åÒEÖ[ô<×Ï]=ñîç»RW¥Ýã‘Ûò®B:·«ÎÊÒvy¡ÛÆÿÎ#âÿûVÿmcüώ®×¹yþõûº>ÜëWú EᏠo¾¶ŽÛ~.žÑ.ÔÍmÙ7Ò@jf?F—˫ШϩŸ[eóteÕVžJ/5êš[/À&Yl[N¢ÈTQ–6zQ˜g–q]zÃóÊò/ôêy³D_69|µM[qÊ2¸êZ_¯J­Ã õ0ô3P_0m2útÛ± àBOˆÚ:"ïYÓ¦+ýwÛ÷Tß1¼Z"ø9Þ6þ_<"þo´úoG_÷þ¿›_q÷†g¬ô㚡MpOÖr?gOÖ27èÒIllªõf%ÛÏb`HÙ.¯ÔVYíO¼}¢¶ 0on ³æ™¬Or³…o®Ï„† ++VçÓºšYYZ²êÌÒ>ÕÊmH¯Þ¨ete3›¾)›´^kêÊÏ­ºT2×GG]Τ²ž©"Ý€«l>(³¹`K¨jÝq’™›Kòãÿ¡øßgDüÿÀê¿mŒ`ÿ_íöxŸÝËÌóÓOzÚÍ ®Œ'uŸ Õuû<§=ƒÛк`ÚåQO¹$ízó´ÿyžÏ6&'µ×m6XoÖ½¦´ ÞòG²4ïÕœ¥m~Éྠ¹­.ÖËýêâÿ¡Xý·ñÿC«ÿ¶Küs··²ÍÉYߓåî áºïœÄ× /ÄóI/éýY»íâIlÂ_ìöÖ.s,ûëoÁùÆxÏXoÿç¦øßDüÿHñÀÆø_X˯gþü_¸žW[4TÓÙíé׆¹jËwŸ«éZp{Þtõ&7^×]ÆRº@~öäP֏ŽÕÛ6þÿ7)þÝ!þ6“xù¿á¼Œ³Öyë‡ê‚¸uƒ½Ý:Ïú~^—Ç~ôkÿè‡?sõ ·K¦êéՖA¤~Þï [[²šoaê{ØÆ:?þWuñ¿*ÿ¯ÿ?Qü¿~cüωæøìíúxý}œûûÂln6²þ«ñ_·oèäùÄcê»XNÒë»Ø`sOHÛ\ÏH øØa“¨·ۓÚëlÿoÿ7[ýŸ®ÿåõ˜Eöñ©Ú¿m Õ>¿Ûz \}¶×í5üŽHß¹Ýün×ÔÀM¯Ffú™Û3Ýî@YZYÕìȟ[âO“©¯ÿIJ}~-‡£)1¨‹´yvÛ®²¤é4¥%¼} £ÏØ6þÿ‹­þÏó?./Ë=Çû¹Á§Ç~nÞ?¼–pE´ïïúvá>È;zóºø¢ëMÜr›yÏr/Ӎ éZp(Ï7–«¶mü¿sDüÿÔêÿlyÿåk¹úþ}^£š,´ö¿œ¸2¸¾ç愎Y——Þ˜1¼ý¶þ= ÛkÒëç/÷a¸ú½é܂\Õ!^[Œ÷óY9æ„mÿïÿ?³ú?;Ýÿ]͎ójœÌ¥Úè3,û~§ äk¨7}jp~(žOvâ@Mû¢5hÖ ××Bù_ƒ5»œ²fïÿúýÿÃñÿ‘ñÿs«ÿ³ÓüO’¶ý®~o]?i,7`Yãñ@?7¤9äYÑuƒÉx¾íL‘Áúei;U’¹‹ÿ‡»ø8’ÿû“#âɎõ–ùßçG®»3{±·úÏ¡½½ËZÂY.A?÷¹7.Ýg³œ_wýª¿`³•%æU¬+«w½rý‡âï_ÿ?5"þ¡ø?}‡ñŸ;3)¸t‘ãwêžØZ~è¾lgJ¸ùŸðý¤_ÎÖÊü1~ÿŒ¨ý‘þÉ1Ñ9­-rDÜ3{ýŒ'݇²E_Ï?ËÁËGˆæ®Ÿ7µmüvDüßbõŸvYÿ›»Znç ìè?\Í·o$—‡¯<ÿ³,÷æ“C9àÓnÎøÖ+_Ïö¨ö󌿶¿g8¾ó2³C›Òf°,×öxÚ³Fτ¶Çn[B[ìŸÙ8Æ>å¼]И!›ë™¢¡ež'6üœ[ÿ¾°C¤l§¥Œuc÷yZ<liÛø¿hDüߪø¿xcþO[ù1þØ»9qt_ «åñ¨Õ1C·Ç÷¢Il®Æíý ++՚˜vùæ¹MÝoŽÆvé떛T•uÊõV'[ÏsE!MòR/-êäÛöÛ”i8oƒ9ۉ¡Ž…bÚLèŸÚîl»y§ó•=zÍx±ÐW-lïªA‡-å7Ƀë›YÒ·-éeö;Ö ÉëyRÍs«[j8 ±TÚtûí˜!+6›_ýød þ¿8"þo³ú/»Ìÿé]úg|ôëõûêv®–Û¼^ûg¨ïÓæ˜]8‰­!¬]³Áš‡Yݟ¡š_–7`Ñ/íÁáç}¤‹ÿGbõ_FÄÿíVÿecü«ÞŸbP¶÷ädOüz=yOèz ێÉöԅí×~Xö ¯žÄž nN)tvÝÚ}åìµÕû}¯·Rß50Îs÷!;=Ì~ig€Ù\¨ëߦ2]óI¢–m>µsÃÛ¤byÆó¦dH^lÿßÿ¿Tük—ùŸ²}†îíúùǬ\ÿóÅX=¼†{ÕÀà»âŸÚÛ嬯Ct± Í·/Îo ++Ä÷PÍ®¯+ÛXÀ> Í3KÃ×Ú‚´R1iºzýt þ¿;"þeõ?¶Œÿ±«kü+söÏ\¹þ“nwÎÞír5àV×ëf³ðî<É@ °á=Àî\Ź=ÉÁ²œ,÷ר½Ø*²§eaÇyfYS¶Ç†òŽ×åÌöøÛŒNmׯ®Ñæ3·²½3õKËäµÇ¿þ/³Á¾mÈm:qÞä@è¯ê“Õt:,$U²¶y^K+Ô'Ñ×Ó··mÁÍs!³}bú,Ú\DQ‹ý?íâÿÑXýñ¿Ôêlìÿµóµý½ÜWDŸÍÁùú.OÏ}fÂuc.žÄóIÚ¾a¨ž¤›ßÔTŒåX¸ú+‡å¾ðmãÿ#âÿ×Vÿccüûû?Ô¡)ܹ{áº Ç ŒãÛ8>Ñÿ3»ˆšûÂK'¡|ÈXm=/Ã~´v\¬®¢*·sô®uÑÙù{µ}üj»g–}a'4Øé¼s[ú³S|çöƒ·…¡Ò²‹+ûú8ØG ,›bÓúO³©ºBCzõ ÒÕúmºyØV0}zìíØ§Ù΀µJavLpÝlSŸ©LÊ&õ¼(šÕFë7úXe6ž˜ÛèÌrÆÓæ&¹müÿzDüÿÆêì’ÿaûwÈÿY捌ö)‚y Ý<ëo†çO¨S½¿?O¥Þûý¦{byÊëëGî<™¢hk¯-êvc)ꉎÄú<Ÿ›ê=ã·Éÿ ÅߟÿýÇñÿÛ­æÛëü¬•Ÿ]Þ­•LÖóÛu¹«s9I2ùühž÷¶Þncr]ÝEi'ùªYi¤™Îš'¹îä…}žj[­³Á€lƒÇ¢ë‡×ûk»õg–Á£î|eπ*±å]څîNµm1µÅïÒ: ¶3ܾ—%~§Í'Ç>GYs¸}uuUÓÚú•™ÿ«®ÿÿw(þÿ¼åó¿_¯·ŸÇ;³í·“åÿðgæ‚IìÙ°Ö;d?ÛfŽO7» -Y·: ç \ü¯îâu$þÿ>"þ§øÿÇÆû;W:çÓÝBóÿÓîÞЯyõ$~ϸj Ï#û»ØOòÎè¸1–ZŸéîï±Üž^Æ¡ùü±g–nÿÿÿ¿·ú[Îÿ>z5¿¢tsõ¡º`.öýý/öýöíyá¤ß_˜¥U||÷ùèï­×sÓ%«[…¥méSTÛþÁ$KìÜ÷¦¦€Õ«¬è@a£? ,½ÇÆ 6Ék9&Ù̲Eto̚9DO›¢¬ýó¿7Åÿ#âÿVÿccüÃõ‡ûw§n<¬Ÿvrÿ~a7ØI¸Æ«íÊטgn¿Øñãi4¯)–û¨Û4YÖÿió‰ô*j}tWþ³Èy_ë?nŠÿÇFÄÿVÿccüÏÝš«™jÿµu¡NÈá œï¤K¢}^œ\KبմœG:2’Û=¨MÈýïö¬?#ºý ±\ïÅ«çB–y›óÙ°WÐÛ'Øöû-™`ÖÎuù{ ++Bµ<æ 7îÿÙÿ›ˆÿeVÿecüύžñ1í®WŽÇö„ê¸/sù÷œ Ô®ñôÇ/ïÍ ÏótqþKósTЦ&x™Ê~ùÀù=c÷|¬œ2ÿùÛñÿ—]ÏÿÒ0/™Döÿ* •7ÇÊóî©êÚå®ÏÿOyí˜á¸hm’à«?Z›ˆŸýnÕšédë؜AÞ»þ?>pýßnDüÿUñ¿ýÆëÿü½|mÿû +ó|óî ˜«zóƒí¹Áã†ö-çxÞџãiK§-æšC}Q?^]KwÊÖgôYÖäõæ~Bç½éYž5«·•-äÚ¾ËíHmç~–d6:°²©Õó)š’6˗ØC_>uaR;ò»´z¢Yݜò©A‘5GÔ4Ȣԃ.)&‹}‚.þïâÿñXýŸñÿ7«ÿ³wSÿÿ‚`.W¸þó¬‹ÇÙÏåÓÖp纊¼u¡›­æu㍓Ɯ'ô)ûý‡¡½cþg)¸‡,<Ö+S+™.æzyàk}‰•ëSü¿xDüßeõvéÿ-jõ õÿFóÝA(–¡ú¯mß0‹|ßÍ5v¹C9£‡(Gt‘—èž—ã·MÿoSüï3"þÿnõ6ÆhÿÏÙµaΊԍ?s`Þð@¿žhwŒ«ÿ÷¼Õy Y¶–ÐÌÏͬsf•—ªÔ ++K”í¯mÉÖB¦0e¶“6ec+ë“YòmZ5U;춞ÙÞ?õ)“ÚŠ´Ø‰_º=W¶>ÓÌ!ºÔ5+b}JÝ ,{ǪÄäµñåÔz$¸³bçÖ,ö¸š/¡ý?÷O Ä?ÿÿ°ú?;ÜÿÛêý¾Ÿe»»¹ŸÐüÚÞîžÐ¯áXó×µÖ~&²úS'õÿlqî× ÑÓnü·rßʋ*¾ç×v°$}™æì:Ÿø5žýsÃuœš˜&Éz7·¨ÛMnw“y3al/ŠÙÊõÿ‰.þŸˆÕÿÿÿ´ú?;\ÿ3Û7YÖø¯O¢õ¦9زN’i·6دïqùÀšáèýß¡µ¾ö÷u©ÊÚ?5è,ožËó6Åÿ!#â¹ÕÿÙåù?w¹:g Ìåî‹\ÎSúã¶Emà¶Òè«Vúe“Sê®Cõœìð[WÏ-íNCq«âÐl˜Ûz¿ý¡ÝÂ+;yÑ6ƒZY¿ÔNglÎòÓ=Ú ++z†WMž€†]™þrb§üØI¶ÙM|–X঒_›Æ«AÂÜ ++y©ß^ë;ÖöÙ´Eä¬)ßeå< [ V t}¹X-a—››/¼þýñÿ׌ˆÿí:þ_ôÿÚ±\¨þã´[“ªÉÿyœp¸Ô€\‰ÿ5×ÿ׎ˆÿ+þÛxý·ã§G¬Ü_ÛýðÁù×îúwksýïþ¼@jWÚd™:7ÆåŒ÷÷½©÷Ìȫ模M{nbç±äö[M·¿Ìgy`m.p–ož–0nO{ŒÏm7gf™©ÝžšC­Kn·§™î–I^[¹‰¢9V½TÛ#’é”XÉrþïš.þ×Äê?ˆÿÿXý§ñïïÿpó.±ý_®Ïê_¹ñZxÿGû,ñß4‰­C Ó××UÖÆd‡j¯G¬¯Ýÿµ>'µmü¿qDü¯°úO;Ìÿ-ûæçFëní œÿ¾¬Ë8RrõDý{®»Å^ƒPí/Wj}Íhð3X{ÕóÒ]¹´3šÙú¬(5~×'<Ïm8iYEVnbÖV—Òc^# Âv•è`§ŽæM€¥™ÙH±9Ãõ-5ûVm¼°mü;"þÿkõŸv¸þ]ƒg¬ÕÿŸrJ4oxÚõõ×ëMûFÚ=ãï쏺}æÖßݾëCY÷'˜3¼vdðóàÇÿ“ñÿÎñÿ?«ÿ´1þg÷çV»ÿ{»k¼?ž?5°Vßî» ­ý¶{ƒO ® ýêö¯×vk‚7píÞ`ÿ"W`m©?:ÀÅÿ“]ü?«ÿ4"þï¶úOãßöמ¾šÿÛÍ­Örf®oªçæöcôïÙúwIô9_7?ÎEí€P°•9ÀeM¯¹í´+‹¬².Yח«m"®°Z³ÅúŽÛ»Ñ®Óå ++j¡N™Íî•M¢¨ÓfÓ ++µ†‹¥2§+¼²§>V Ç v,PsàC5· u;ÎÍV”gv&•@§¢mû͊̎zËm¢4Ëm"ÒzšvXlb§Î–µ>SéÖñÿ‘ñ¿Òê?í°þ¿<«+pþ¯8¡³­øRæõñÏ[éÿeݺQà^Þåñ¸çüúºÀ¾À^R·ž4™ëî,žÁUûtÎòª²^™þ×¶†4C?= ++š…€æ<'…>Ït/°^[iG)þêÍ'u›Ê]Ù¤6»_ZÙßÂ&xìÀ(KUD›9¤æôÁ*×SÃ>gê<äVòÚæŽÜ³bål‚mãÿ“#âÿÅÿ§v˜ÿms¹ß?p_¸2°Æëjÿö.òr.Ÿô皲Ô?㯟‡Ü?÷Á­®çnEê/®Öf; ®}ü¿)þ?;"þïµú?¯ÿöç~Ñê5ٍ×Þ40^ œå”—]ÿïe“ؼáuœÇ‰ÍŸÙþ›tm¬g»j»’m%_½‚Ô¦sæ¶?@}Ï:ÕÓ<±EùRA² HŸ–ª9nÆFf¹ÍÒ¨o¯\e'’Õ6¾Ëìà·bnWºí!·Šs¶G¤°„Nuèm 5ì”Ïč¶ì¯ÎŽþ¶^&¶J”¨Ûi{ÍSgf¶SÉêFeÅlÛø¿hDüßgõFÝÿώäå60f8%0/äj\107ðÎI,ol‡ù¿õ®CWóaí¼¢Ð¸ÏM»ÿj þ¿8"þï·ú?ïÿ홯^ãÏ2wí¯Ä#Éó6VoœÄ× ^Ù{^Ïmjµù<½p«±|l ŸÚó֎ëZÞómjÞÊCZ^UÖÕÜK¬Ödf‰Ê•õkKðkÕÀβ~l¯XùH]Ìvä—ååÍ,W§™ÝK¬R„þ<ÑÝ"¯›Oˆn볺®,1`Ö¬òÛ:o™–v\dÓó·ú‘¶EÌþšº6˜ZéË9h–#šCájûˆ^ýOuñÿT¬þψøÀêÿì²þیËúµ_ݞẠæxόÐúŽËó ­ÿoºž#kì7¦µ"ÿ ÒÁøûë?¿9"þܸþƒÏ—m¯ÿßÿ)þ¯Ûrþ'´V; Ìñµç«ˆîÕpù]ýó¿NŠæ™÷~,ú Çôóºúß¡}¨mґÑ5íùÂ~ ñµg»Ÿ¿í÷µ¾O¤W·$´F¼müwDü¯²úO»Ä±&wpOh×­ÿ¬Ì Ìfݞñ“£ë ¡}mÍð¶_x`e ª­%1”3òG׆èêw»\ŸÔ ++ƒÚ´aaƒÁá5çà:¤ÿOÄÿGÄÿÃVÿiãó?pþ»ÏÓÀÚOÛ÷?g༨3úkúQϼµäû¯ôòª½þ¯ ädݸàêÞºÀ2?ýʍó…‘yCwV‹•·íàêºÙˆ½pçF¦ö›Ü7½= ó\£ù¼°® â`Cþ¢™ñ±}6ÓPÎ4RPÇ©»”bCÖ¢¬ªríŒ: ¯ŠEýOwñÿt¬þӈøÄê?íÐÿkçÝÚ½Õá¯íœA¨Ž¯[Çïßÿûg/ÏpêׅµódÖ¯ëîì•õ3˜Ü}øPÔî=dùÃ~ü¯ˆÿ_ˆÿG­þÓÆøŸ9ã÷ÌÀo5kçwFkC ?^ۛSTG9÷놅ΠôçølbÍNç´­v3;z͊ÕE[Nòº²ò›•¥"&¶Â7o–[æM½6]Ã3[ݳza»%ôÛÁ– ++tqÏ,Á/µµÜæ´fÝôÇ6j×õ`ç>è[ÕºÎc÷ÿõÚVLïÃòÓtý\`ÿk»ø_‰ÿ?ŽˆÿՊÿ?m¹þ»uý÷ŧD꼞4p6üþhÝ7Ÿª)zÆÂÚA±Z¡³Ý×ëÃÆÎ~ˆÖßÿÿYýŸQùŸçœ×rntßµËÿíŸ{yï9o)rE$Ïw¹§¨¿ÿËՈXy¾·õz{w“:/¬è»ÕüµÂ0ÙçiýØÛ[¾ÿÏ ÄÿGÄÿãVÿg—ýV¤ÐËÿ çòݛéærÏ_YÿMºë¼¿Î·ŸÁñ(þþüßÇFÄÿš­ò¿Ûù•ðzý$º7gÚ­÷k9¼kê|>æØÏçк‚¿—çËØöúÿøˆøRñÿÄã?»¯ºùÿй0îü§þy,§íÙ´^ü¢•{IÕՙyù$6Ÿèžíksl¹•`¨šþ»ží©†õê˜f–aY§¼¹LSë½)zp'MoÌò„Sõt·¥ë+6[ë×¥V¡×ŠB§zbë³QåU;lL›BñuW´°™ý§æ–á—Ù‰d‰n ++IZåýÜãÐ93ÍÙ/þóSü?3"þŸRü?»åýÿv«¹š].ÏYµ×NŽ Üp¨OÚÿ[èî~๲KÍákúùÁêšå[Œ [*(ÒÔ«ñ²>‡»Ÿ‡rÌc{Â÷YÜ?7ÿãFÄÿsŠÿ6Æÿ„è>þ¡Zn®Ï® uaï:ok¹<·?Ç·–Ø{yC×gZÏ<$õ\ü?×Åÿs‘øßqDü'§ûñ;mŒÿÑz-ÓÀùí8ï¬ÀÙoîl SæøO¸g7ÐÿÛ?Ðÿ?&Ò¹¦?ŸÔ՛^Œ)õœýü@ß/vÖŒ'ÛÆÿøñߣøßecü‰ÖxsyÜáù¿gMbyÃûöÙË{_ËÕqτ®žÆznU,çÆ]ÇK½‡Þ½ÆÿäyñøßmDüo¢øß}cüϨ½VôlÀi þ‹ú½•›[yàêyaëˆûj¬=±7T ޛ}ZÙ#¨ã;+ìY‘f¹7V´£fì“a–XRyý˜Ð¹ÁêêÚlÃÌ?ÿaSüï5"þG+þ÷ÞxýŸ7Pc³úâóÃÓà0« tâžØÜ[ŸCuiïúwõ$Ö¯ûP=†±g5 ÌIõ΍̸3sÎ~ü÷¬Åß_ÿ=yDü÷žºÍùçF®±3Îp \ç‹ý¿µá³.ÿ»_Üj9¹½Æá\ÓË£óø®fÈzîòbA}ôõº‡°Ï`³FÉâúrqñßÓÅOäú¿ßˆøOÿd—ù¿Å™Ü§Œ ö×ø}æ½{}8—ë¢hè–kú‡KèzžY™ÔEl^¡wݶñŸˆÿ>žåúß­WæUÓ¹‹}øì×~§e͸«c9Wã=pþ_wnô4Tk¤®Ó}Á:ƒÙ<Ùð‰äõ/çÚzð×{]·H˜™ýû™ÿmÆ0Ù>þ鈸ßTñÏvXÿYö»ÃçL5×m.~8«­Ý5žœ¿ÏÚÜ­½z±Ög }Ž\MˆÐçÈò ‚9‚Ö¨W7$v†‹7/8îüü±müËñ¿™â_íØÿws¿ýuõËrø/í?«»ý8.ÿ'œgøòÁ5œÀZM¬îêJm Ãä9ár ‚ý‹ûñ¯GÄÿÅÿK·¼þÃçõÄ®ÿã"gîîsùàþX!ÏÓÒ]Ç¡ùW'®ÿ¹ìç‰çóåQ°ÍuœZ®XâÖåV~îÞÜj̬ܼ²á½­ø­žõ´Þ·yý¯¬+¹øÑÅÿˆHü¿lDüo®øŸ²Ëü_÷¼v÷€•ùZ]H.ý3£ßØÏï¯gÝ9moèß³µ. ++æ ¬´÷ۘWèó’”Í¬Ü¢Öæatγ­)$Yb_Aß»ÙWÜô=†âïÿŒˆÿ-NeÿÿájÛø?hDüoyê6ùßçœåvöžøßYѹüØÚÀJl½ùÿКfsžÜ¶÷ÿˆÿ~ÅÿË7öÿúù¿…ÆêÓÀ9Nöœuëûá=í}üùþ×ÊæEh¯}¦]¿/ÔWÜóÝÏÔR¾ëª´¡tÒä×Ù~ËKjÖfK˯×-;·ú-U³œWÚ]ޞɶÛnñ©­é–V Æ’ÉkKÓû´‘_R•¶C_OìÊ­d¯}%=-¬Ê—¾u©gVeEޚõåÙ¼îï!XëèGЬ=[ÅàÚ֑ËÙðõïÇÿÔñ¿•âp‡õWã×ÍË÷ûíŠp¿fÔS&ý{I[tèZéjsÞhj7]}Á­ïÿ_9"þ·¾ó¿ë}<7ÿÚ€á¼ÂP¾ÿz?ЏÿM®ÿ¯ÿÛ(þ_½ñúmol¶ÌónÇ`á=;ïìõç†]Ú×Ít!µsÊýý|®>Ì6?ÛH>µ«Ëb#ù‰ÎÖáºWÈÅÿ&]üo‰ÿi#â¬âÿ°ñoçæÂ9^íxîa«ó9ݾ‹—OÂóÆÏíýþP½žPŒCçw®ÏŸ¶uµ­¦gVÛpÕÒ³“2Ëj;NwZ½O›¡[²eZ47«¿“êæ¯'Li§ºåöx×ÿIšßà¹fÛÆÿôñ¿­âÿð]ÆÿÝÙª®ëµ€öÏÎ87âôÀþª¶–ÇÐú «+ÚS¼/PWLý¼Žä´¹á'¬CÍa å%Î𜫇QzûŠWÖÿºû‘:¦ISñ=k֛—çÔnÿGŒˆÿíÿGnìÿŸ©×vVt]p8ã±ÍïîŸï¨k¥«åߎ ž½2ΰ:3¯ Ì …kµ¹Ÿ»®É™u¤²f‰Ö&kš»’®]uÓ¬ˆkfG¹kœje·jKÕÒÓØ*|郝Y‘H¿ìöÛ‘u K]šÖyןTÍ×ÊmÊØvó¥M¶om¥¥ÕkLšzÅÌòût-ç]n@Q4<×¶Ñ¿lª‹x瀬­û¹zEÛÆÿŒñ¿½âæ.ùŸ‹züÇD÷ÄòiÜÚ`xð£9ÓÀü ­ Ì^yëg÷²³×Ï)Ø6þÿãÿÇlyÿ_YÇ×h¦½G¶ù¿Ï[™çwu/è7¾¶?\¸3=.ìõ­Üö@@k{^ùP-—X¿0·™ý¤©ØªNBÞìÏ*jK ´LbÝì«dÖ§Píüu,½¿®-QØî¥F¡,ÚG¨(5–´¾‰¢ouí¬¨Å^_©½U…­Héo7ƒW[OÖð×JHÚìÄ¢n¤0ü÷ #â‡çÿ–稞­óíæõÀ›ódýø9pýŸ5"þwTü¿y‡ý¿mß)¨×xÒÀ™ÑýýøËzÇì?vO|-ðâ^¾‰¶/\ÿgx-òt½Z‘þ˜rl}ÈÅõdÿ##ñ?{Düï¤øË.ó‹u¹s"¹gökòæE·‡óȁó$'Ѻ .Æës{ç?º¼Ýë)/crˆò€ô-ìÝ´õc×󇷍ÿ·ŽˆÿñŠÿ·mŒ¿þÓ²&ۙ{âó8gr½Ó¬}þÎÿír¶Üºþcüýä÷r9Ýøno ¯¤¬æ¡û­dxJo|få}k]–V>W×0Él@®Ïkaù6Ùo¥Üô±É2û«ã®Ÿ>@¹Ý=Ô©Ð|ž¶’`ÇÈëîb¹½ÕÆ<³Å\T¨ÏâÇÿ¨øŸ3"þwVü¿ÃõoÙìm¬ÎÖŠå¸ÏK¸¾Çg ž=gr¨5ÒæNöM¢{šBÏhۏs=ìùñÏxô넬¯ÿ¯\ÿGuñ?*ÿsGÄÿ‹ÿ'ìœÿ¹¿w·95¿†ß•Ÿ¯«×ݯÕèöºñ_(ÏËåoZ;ò׋ÖrÂܞ¿±µ¾õ÷Ó¦¢Daóo…_ã ++«9QÙ´@i Rн}~g6*´£¤²æ‘aˀu³}®Qƒí%M†ó?7Åÿ;FÄÿ.Šÿyãßßÿaã1·‡³_ß㠓øx±ۅëE¾´?ï¨ÿâûº:0¡ŠÍêFXd1–Š¿?þ{âˆøŸ°ëø¯›ÿêê*ªÜýzÿêØ¿ëÇU‘ûÉIÑóbCùÄv?ŒÆq¡s]Ck©%X9SËmö$¶¥X}ã¬]7[ŸÿÝtýŸ?"þwUü¿{—þ:¯Û1Y¿ÿ¿<Ë)°7$·3žFò† Ì3œ˜KLg…7ïڇèêI¬ŽCÛgÆ´kö÷šý¼¯ô £À~óܒ Ôõ/üqã…Øyq¡:.ºŸÏ¼<¢ë}ý°™aèÎ"ÕüðDŽ.þGwñ?:ÿ FÄÿîŠÿì°þçúìîêŸ×¾?z&ë—¯Ö uç µ½ ÿü¿¬ÎŠë:§–gÖÈíak—¦Hgí ob˶uó€VÊ¤lŽ^.Ц7oùºEYÙ±ßÍʀu)r+KYuë8YÙÔæôÏ:sK͸`(þþóÿI#ââVù?Dö윭ljÝçƒ]íÐm¯ÿÿ/Vühãõßέ„Ïë{c¯??³.ö$œÏ¿Üüòþ½yQ¯óY½u#Û âær#{2Öër¶?ËҖä“ÊŠò»l7–ó·½þxDü¿d«þÿ9Zžu­ÿ×Í׆æz–ucNèë폮+&×èØ¹}×tóJí\`Ï;Ï͟_‡ø?yDüï±UüÏîïÍÔç´òòøÂ뿁{CWƒÃ]ÿ«çƗE;ÏóÂIlLáß'×úËVƒÉf^-u/ws:‡ãz¯-èÏ-EÄz»6}”oÿÿ“ØÿsØÚöùÿ”ñ¿§âÿÔò?–ç5öÏÌ4à™jµç{œÕ_ûíÎê˜΋ÉÒ²pcÿpÎßu‹ú ×í\q—™“ Õ`·\mõÒ4lo&æ­/8·­;zškXVÔ¥=Øõð®l4Wh°˜Ú€z‰zHXÕ¦ÜryíX7 $k;ÊöëhŒ7×`ßr€K‹·m/WÏ@}Ôž5¥þÈNö¨õPHCgVؓßÖ'kýooÿ½‘ø?mDüï­ø?}—ýÿº$B±_îý;Ë Ö~YÌ&ÁûIè|‡åYB'FΧ¥Ül×l«š¨íü¡µdÿ¹gÅ#&g­äoÿŸÿû(þÏÜ)ÿ§êÎ×>/r½öç…]ý•}º!nÏÅê‰+ÿnÖÍÎ[ÌC^™~Wày‘,ö¨¹ëv1ï۝ÛQْnb™ÙUnóte¥øZ§f©?ýY1ÃÌVul†Ï.sK °Ý –¾a5AԉW8+ûzêY ++zY6‰ ©­ûVúl¥Vk õ×1ý>ÀJü§ñֈøßWñΖù?ázü=Þz¤¶s§öǍ‹:0Gî‰ç\4‰çötk=^<ÅúüèóÁmRx–Y¶wfóÏ¥Fš“¡3a\ü§]ü§‘ø?wDüï§ø?o‡øÛ¶«j‡ü/ûÁûgC†Ÿ)Δ ++­º³!O8Sbô {— êoºqÀZ2x^{ä̇¡ýA.ÿ+µ±ú°Ø?¯*Û{\lÿ珈¢ø¿`‡ú?Ëuùv­_çåi×ð“ûy]ÍÐà\[[óäÜfu`Vú‡ÛÆÿ…#â?SüncüÛgë‹Vãßå]÷÷øZnо`}÷6¿ÓÅ›ùÝëc®5’¹²g¤Ù¶“Ú„]Uèÿ4’³N»U°å9}]ëÈÙö-{îé#¢¡ OX¦g|®Ç»úCVã·¶núÈÚ.¢ºêv…%ºñÛ;·)~õŽ2ûÊi¦Ž¡‚Vý¹j¶ŸY.UÓ³ óë¿YÜ÷ ÄÿçGÄ®øÿÂ.ùŸ‹3žÏ8ç}¨>äiќR7ÆÏ)¿¶÷y³zóåç¥n*±ê§x˜ÎõÆê?®Ÿ+´ˆÿ¾.þû"ñوø§Šÿ/ïTÿÑÅãœhþGðløÅïԁ=¾ý3`æÖ©òò ú5gŽéÏQ¤³î}LÆ/G÷©FƄíý$ŸÛEœ/î/«µ\lá°´.¶cǀ”]énïol¬Øæ£èg˜Ô»þCñ÷çÿ/ÿl«õŸj`ŸO .».1ÿLÎPc Ÿåsd –›Ïë:Äk~ë¹Ä¡³Ös¿F=»¶½þeDüsÅÿWw˜ÿkkµŸ>°/äà@]øÐ~—“wJd./8û5Øgrü@}‚c¢9ªCk¿kù›¡ýû“µ3`]>ºëËÆö¨®Ô“ôãӁøÿڈøŠÿËw™ÿYÔj8?z6H(7¸=7öà@>A6¯$0.̲Ê{f„îñn®7”£2 Ìõ¶ûWö>S͒Íʳ _²ïõ?½5þÈyã+ùŸ7íâÓÈýÿ#â_î˜ÿáöÿ‡r|ÛŸ:pï?=OÎÕ ++ŸxIo]¨Í×½8gÔÖ ÷çs×òtoÈóן ¡˜G÷ÿ‡âï_ÿ¯ÿJñÕÆë¿}އrrÝý5œç:“¹šùë¯áçÿ哸ºíÛ¢ãJ÷ùՈ]ôÝÂcÁØznð¯ð¨{oõš³¿ý\Ðë5_xÛø¿zDükÅÿ5;ìÿ\žÉrp Ÿ œ\´Lpý­R‡ÓûL…÷^È)²üðþç)M‹Ü{¦×•åZYKBlâÐÎùZêQg5=f®V´¿/R×%Vß-ºN:;fÛûÿkGÄÿKwÌÿm×ÜÎÝx.Pø·ø¸ðÿwÆþ94[Çÿ¢ñÿ²õÉкÞ?Áú÷› Üÿ_?"þ§(þ¿}=Ÿÿ½<¯¥«{ƒ?·’X>ׅÍëPý'—û½¾7п~{êüM¶Âª[n]VVwe;)›[îN™ÙøÝffÔ+¬2X¥1©-ÐW6‹g_ÐßÖ©W¯/·Ý"v”eeÔêZY¿Â ++ ++[ª¸-×è‘Q[§ÑÖìB¶ÜnËÏ­@b[B‹f¥¢)1³c',Û»¶7a7ÃBÿ"o֛Ïÿ¾Yÿ›Eâÿ;#âÅÿ ;åµç¯¸þú VÖÎêîl¨v œÿqÑ$Öotu#·­ÿ4 Ìç¯öÉ"9s˽±)`Û4/ôðžÙQ­µþÖ¼V×½MךÙZ@b¡³Ï¨­ðÕ©UüRÏÒº{45ÅôgMáʶ ++(ô¶Ë ËʪР éÛי %,ÉF»¶à7«­HQ[Þ@Ú;ofÛøÿþˆø?@ñã.õtq¸¾ø\øcÎ ™FÎx›ôçŒõ°¼ñBx>©¿/Н ìò?Bs ®ï“»³„»ùšL—ärŽö8ûÝþoŠÿŒˆÿÿ?Ü¡þc›[sÖ@îm{ÆR¸fì;î ïèå³YW7ªvˆ‡Dî ±3‡s³nØóă9ÖNäÇÿ˜øÿшøPüß´Ëù?‹qü9g·Oþ‹VîñÅÜÏñ¹ÉêŸ%íœRÿ,€b–Ö¡³l®ÎÏÇÔÕW,ö\Ûö°<Ël–§Ê, ++I=äó*­›½Mؔ ++¦­ꃒ&VÙÁÖôôÈmÊGOd íá£çDYZ7¢°Êimó³Ô⮛{a‰Ýe¡ß²>XVŸM e¹>MµÍÔesÚ£¾­8úd©›’”sË÷̊™›#òç\üéâL$þoÿ)þïPÿÓ*øû¸Â{|ª3ÝÚ¼‘oZyv”YååôëÍõçÿ–y(ý9@W4R›¡»Ï[™'Û&¬{„u«™Ø)ñ–©ÑÔ붙:›®Ó½¢°cšõ(í4w»¢5’ÓH¨°âºØÒ@b+Äuš žÊ!Míðh›b,,±Ü{þoŠÿŸŽˆÿƒÿ?Û¥þ³ÕTñò¿Â÷òÓj3P›)0³ø¼½¿×7\žwE¿”Ý>•Ë'¡9 nÐÖbÖ·ëÅäz¨å׌=ƒ¬8q¾müÿ|Dü¿\ñ¿d—ü¿YÖõ½Î˜Ë?]˙ÖyÚ0— ô.šÄÖq֟ûu™ü¹§F× ++õ$)íÜK+HçíàڏÿÍâÿÖñ?Uñۖñçñž¹'v͹užPÎå´[¯óc©^qæê±‡sϨxd¤¦L»/ ”²a<¹žç±¨ÝË'ër¸õ£ÑSÎ&~ëEh,_ÔÝs‚¹Á.þ7ïâóHüß>"þQüÿr—çÿ¢Ÿ˜ÿYô×ÏÜXÿ(? œoÈÿÕHʯÿ®{R?ßxQ‹úØ~ÆÆí›òA,µT‘®òö}7}ΤœÙ‚b±º¼’×ãçtg÷úñ¿Å@üÿjDüªø_ºåù_+yIšºçû­Wçøçµ‹p·l ^Óñ{ މîs×yx­)tpû™‰Ävh g}OW0w±æ¨K§î‘¥Z±ÐYÖÎý§is ++­Í5Ù!1íü„‹ÿ-ºøß"ÿ¿ÿ¯Püß±ÃüO»þsv´öw°Îçܝå{úÀ~ÞÓ¢¹ÿÓ@Π%T»uÆcWÇݚàɃç~LWç »üôc£sW~ÐÚ<Ьš7µd›uÃÌΉË5ÖÑÿ_E³ÿCcÎlmŸ «'ª¾uüÿnDü*þ¿eý¯ð|ý¹‘Ú@gFsø‚uõdO žìž ášaU´žxèܽó2tŸY®[ý|úý·×s`=ÏÕ÷ë~¹³ƒC9…+k~üo9ÿÿ¯Tüß¹Ãõoó.áúOón_À¹‘{F g°;ÿ×Յì?g²>F2÷uÒ@ý™ã¢ù±3ªWÖ ºóŸ×s½z.ÑûúÀ¹Äí×Öïû×ÿ-»øß2ÿÿ¯Rü/Qÿ1TÿݶFºqaè³áîñ¡zÓ@¿Áꉆö…·gËm¦@OüZ#Kö³Ñ‰E›•Cë¿÷ýñÿ·ñ?Mñ×.ù_‹=þmŸüá+Ÿ¬{Î÷ûä3;HÑûl„ö …æêÚÚ1—F×òBgFÚ«Ò[V0bë}¡ý7¶0«Ø”¶!0/Õ§©J÷9±=àöàžÛ ++ƒMZ®Ÿ>c͏yi£ƒÌV -oT¾$Í5þW`^k¤PØD”íú²©äÅg/PÀÅÿý‘üŸËGÄÿk¶Êÿ½``\ÝÏÿ¶yüě Çëôš²§ ¬7$ýÀÀ³À&ð&±ðd6æÀñ~/4‡ìŸûû<Æß¿þÿkDü¿Vñÿï]öÿÍÝÞéþóßæXÛ9÷³#y§GëÆL»{Æ£ýÏZ–çî~®3tyà™áöôë?4÷þÕ±~¨nT‰ÕZؾl«7iÕÞmY£¢íôWö»MŠO®~o³{iõõX±Ê‘³ªNl^8µü€j™CºV÷¥Û#RÛ9Ջ}‚~üo5ÿÿÿ‡)þW\ÏçX?Ú]oëu|Ý^¼p-©«'±õ·î^ƒº²ÿ®ÎÀ´ûܬçšDæ|k/‘¹úõ¾Û¡ª3¼ÿ[uñ¿Uäþÿîñ?}ÇúÿËùšv¬ZÇuýìPŽ×07s%§ìP¯ÛÜÂPüýëÿÊñ¸âÿžQõÎ ž âæxBsꡳ|–Ÿ§SÖ Ôó:e`?y¼Ï°·›ôÿ¬že»|>ô±?Êdíù¿˜×éևóFõ?‡q²müß;"þPüß·1þÕ@­ž“¢s¥ûBgvt9>nþ-\rÚïÿåIåæñC5Cy~¡µáÉvkűº¡ý ~ýÆõ9áQ5ƒ¶ÿûGÄÿ‘Šÿ‡Fìÿ™Öÿm¿î40ÇÓîÓ¯¢s Ó®&\þ¯_«of+ªÞºïúÓÀ9‚¶ӝ!±~^áúgbý,¾Èy –Á;<Ï×?§~½^ÀÆý?›âՈøŸ¡øx—ûÿbNæ¬^Ìô$œ%ޘ|¥n̬ss9{Wïåi= ×øtçMkÊwãÍHNãô¦FcnG?VY©žš~Ô©ÛT&vԓÝ`Y×65¡A¹]{z‚'V¤TŒ7¬P]WÖKÓUš¨‹okµ¶£À Ÿ¥Eb…J}Õf ++À6€Ú>¾:³JE¹*jÝRôõ¬4„eªkY¹Z²V6Îfšú1i»®¾~ÿ¿õ@ü?2"þ_§øt§þ¿›??ºÿÃÝ7ÂûΊæî Ì ØYŽn^ÞÙùŸÁZ¾‹ZC—÷ׅ»}†þõÙÇËõ{ž¨e/ï½ÿë.þ·ŽÄÿêñÿzÅÿ»äÿYBãdYÿq½~ŠÛ“>3¢Íï½ýê8¯nïçN†Ö^b}ón=Æ·lÈf‰^vñÕv¿1ù°8#2Kêmã͈ø?Jñÿ䯸·{®ÃyÜOâù_¯ì]—Ëú ý\îeÝÈöæ†]¾¹óõ}ØÃu5º<«SNø¶ñÿԈøŸ©øz‡ó¿t§«ü<pîÈÈÙP“ýÝWNâ9~—õúnzdfnÏHèþ»_ØõÕôéô÷æºÞû.âgõŠsžBýC›ÒM£.†âïÏÿ\;"þ¾ç„êq…ó?Ý~ükƒs¹7²yŸC:ÜÕÖ ó㛁ëÿs#âÿ‹ÿћâ?Tÿÿì<Î@mˆ2éjÀgњh¨þÿmºøß&ÿ=GïÿoPüØÿËÆq— <ÿÛõÚPޘ†Ïí$6¦t{ÃöqÄÆS®¶·¿WÜõ ˱á¶ñ¿ÉˆøŸ¥ø¹1þþ¿nníµÕ?ÿe>«»Ú€ç ¬Éÿ?m`­ù`´™ËºíʘÑêP<°>}b4Gi—õ—·eó~V&ʆ”ê*ÞmN¬¿ÆØ#Ў+çy;œ•å¶ñß;"þߨøO¾îùºük·&>ߥ¿kYßóѼ 7ÖÍõ¹¹ŸÐ}<4¯¸_»ùºP®Ï¢>çar6ÌÖ×ÿ¾ñÿ&Åÿ¦¯ÿ{ýxÝÖæmŽÝ1‘3›úõ½–ã‚þ~}ukü¡½}Ó@¾˜Ý/Üôëù‚?ï'ƒ¸þü}ö®bó·‘sœòL×{nUÇËÒ„šÂã–þ•ÚtƒÕ’Ó²ª›-cµdv¯¯­kY4åAô­3Ë0œéscIÄ«÷ÿcâ³ñÿfÅÿ˜ñ?{ ïY‘üê3ó‚îìÏõÄNÈý9v †ÿ‘Ñ<wŸ ++õ'÷hÿa-?#¶§+¸gt ÁdSÿÿØ.þÇFÆ·ÿ³9ÿï°µmü÷ˆÿ·ÿeüýûÿ­FÄÿ[ÿ[ïrÿ_ÔjáÕ:á=‚nþ ¸þ´müo3"þߦø»1þ äݜ7°î¬@ݘ²Û“yæ@nÈéÑúà. \ö„zäÇDó‘Bõ¨¬3 ¯)‡òvbëñº²m=ðйå‹}„ÛÆÿö#âŽâÜÆñ_ þsn}¼ÓöÄ×ñ^Ö[3ÒOlæÎ ++Í n_GæÎtEά7¯gigÙxKý1;ÈN ªJØšov"î[³Ê&vJËôC}ªfF¾´΅ºmÖ}·Ÿl¦îÍôÚ\Pn:¥…­TvâGÒ¤uÎ,Ý˒?uß°½›©ÞUZN`UY.·¯Tç¶,؜;’«[8°F9¯ò:in&vŽÐu¸ÿßaDü«øßqcü«Èºû Ѻ›¬æòÌÜæƞ¼uüOÿïPüï¹Ãüϲ¯vz´&Ó40V/ÔgŸjqé'‘NûEÚ¾A»öÞc~qo\°~V\èì¶C°‡»ýüXîžîW]­Â£µ(ë¹^[/¯œkHû†~üo7ÿ{ˆÿyŠÿ½w¾þîýsû/Öë;N»µ˜õõ:7·ÒËÛ:jÓnM¸ÿŒ¹8š{²þ|uùŸû¬•aŸ͙Ëe´fG –ã¡Þ¸ˆÿíºøß.Òÿ;yDü¿ó:ôÿö¯®ÿf³ ®ç~`)©Mt•UUÅß¿þï7"þߥø'¯ÿ¶ßõÿ¾¬‹3ÔïÒ» õ»ÜÙ^îߟÛïçö.×oûÏñ¹®m?ãÒþ=ÀæUúÚµ:`‘=÷‹Ÿs¿f…õÿlr»²G†U éj@èæ¡þžm%ÐÂJy47=ºt·çi|ê.—ÙïXþ¿ú I¥»V멯7 sS°°"byikÞýSüg#âÿDžCþ×2W¯ý „ëÿ\;‰¥Ýþ¯PÿÐåÿ…Ö ‚ù«ç2®Ï§íǹ1þ Y ¨ÉUôãûø§#â¾âŸí²þ·Èã=cO¼ÿ}j¿ŸWՅ›— Ÿ yÒ@í×rùŽÈ ¹&:?¼i\Ê!‹ä}„ê¼úg>Ú2•­*̺/+甇Ö6\üoßÅÿö‘ç9"þß}ê?¬\Ǚ>¿Þüoxw{OöJÿ^ºs×÷ìê9–Ðþ]õ¿f6Ùn§·Û‘b`»xҙõáJ+ñfå@R=ˆlÉÏJ»ÏgÍÈ­éhÚn±ymi¾¹!¬¶`YÍäžþ¤j¾Vn•Ò-²i³¨@eçË'¶@ýÛQ¤çQ>_ÙK>³Cñ÷¯ÿjDü¿Gñ¯7>ÿÛgì«WžÍ³,”ÃíÎdŽÇàòõÖkM{~Û:­¯ì÷ º½¡y›µú,«gõ¶ç1Ûs<±ûPf…%*õý5×EÚ, ++êaYvŸ†b•€×.ÉR"4¹€ºÄmè˜èᢏù<)ôwk;л9ü©nŽõ´‚nð6¦(Ó҆MºB¿•µ¿¦GEe™€VòOw…Y³½°)þ\ÛYRņëߏÿ—Žˆÿ÷*þ_¶åúo¿V;f{ÆÊçb¾rŽo¸^O»:Ovèú½>ÏVõëüØÐ«9†¡¹3è‰^6Û¸›È°:¶Ý'+K[ôœÙ2žu,ÊzìÛ9ÁêÔe“àÙìü´Þ„žµ}+õs;T¬°Q_sp@eϏæ@a»áWúŒè;‡Æ˜ÛÆÿ”ñ¿@ñà.ùÝYž¡õŸößÎã>x噑tç͙p6wÜvúæm¶>ZvˆÍývŠ`ž7¿ßÍ9¯ö¶Žÿñÿ>ÅÿA»ìÿ°‹ÐëÇ¿~5§;çµO_®é]xvÌWö‡o;¦ Œíü½êöë~¯nvm²ÆuV[ÙP½´ü¬9®pf›ôJ Üì†_؝»¨Ù°£¶ÝÞz~ëþ¯~¨nÜv´cÙ¬ßë¹®ËÜÎüÓ=^CI}½Êfq­òO“ù¯;Bb væxi‡LêþPÚmÉrIì³PÚ]H?;|\c„ùbN*O²mãÿàñÿ~ÅÿË·Üÿ:w)¼ÇÇՆhû /Zýw]ŒßÖÿlÌÝÙ oì=ó­FKð3Óí5]ïtû*Cu\f͑|©uùªBÿ—Íš‰X{’ÛOo«Ôf‹U–«¨ÏL1·á¡þ‰V§Ñj_Ynx­N°žô6‡ ·Þõì’ÚŽ­rÛÚoå‚í+ëûÏí@R›1®š.¤åÍëfÛGæï1öϨòãÜ@üOÿPü¿b—ëQGû́u¾3¢9~nÿ×ú½yØÿÕ®ˆÖ Õ_ž3’ äê….ê̜=Û:8¶ðÎmöòûÜùþžÃ•}`±õ@«#îâ\ÿã"ñ?8"þORü¿r—üŸEO;Ïÿ„Õ\¹_³1\Ïñµ“ØÚ¡ËªÑäÿì×®ñ±ën¡µßB7ÛbG»4;½ ›SJ‹ÂÖt2ëZ÷Ï6n¤EÓµ«lˆ%…Ì5êÑcͶÿ«ã¯«½nz¢3+3¡!b³ÔúzcI±š´mü¿jDüPñÿê ñ߈¿Õã ç~µyAnÍîÅ+×~ÙÕjkïï¡s§{|{ÆGÿL`ÿz\»ÝY±ó÷t÷±}Þì¥[¹ù›Ø¼‹F­[µ[Á¯­›ŸYßæÁo9›ìkºýº7¾ÚÜ­MñåESÆÎñ°B z'• UŠÒêÇÙ:`3C˜[GÑʎëa«B¹•ŠS·8Yæ.jmÿÓFÄÿ‡ÿ‡m¼þûã?7Ÿ:ÿI?´y;683˜|.,òÉN¬5¾1ڗÊã8ŒŸõ~ÞOpÍÁÿâúˆøÿ°âÿðê?¸œœày]Î}èYnû†]ÿîùþ8Otw¾kçËz÷Wj¥öSO§mç¯Õ)Ol¿ÍÒØ3À֎šûµMèى޹Õpªša½Ý¢æv÷ÖÇæ±u'°ÚÞVª®máÆRÊõ^mg§zû6û«Ie“Öå´¯¤”Ý?ô­K=y*ÛìÛÜffóÚÛCÞ/°’Gäâ‡.þwˆÄÿ#âÿdÅÿ‘»ôÿôËõÿ–{9û<õ:«:¯'D×B9`mÿpÿÀšÂt 8ÙXÀOº~?¯?´7ÁÕ|Õí µ²é¶ñ?cDüDñÔÆøÕÿºd[“™îiW×k€oÚÚ7Êú_›âæˆøÿ¨âÿèñoÇñáZ~oè÷å{@Úûvÿü—ö×ó»s¦{ž1 Í'.ò2׿ÈÎá‰íɸÑÔôãǁø?fDüLñÿ†Qõ.l~/|Žó³æmŸÖ{¦»ý±¾œÛ_:Ûwä™Ì‡uýŸ;vñ¿c$þgˆÿSÿoÞeþ¿›'qû9Ös<ݜ}(/dÚ­õçù/ëßtõÞx2ôœÞÛ=ƒÖǧkŸ¿æª??œ×¿s=b9¢[Çÿìñªâÿ-[ŽÿV®ãv+kpü§±áÊßÐ`¨6 ®§E-ßðœá½û‰·íÖyÖÏ ÛÐÏX?oÍêºÌ¬oa‹y^-V}bêÒÆþ֟¬++˜é’OÒfϨ#+ÛTZèÞ£ÇùÜJ†Øíƒ¸¬^ ¾œõ*û›is÷™mßÙ[ƒl¿¿uʶ‚Lr®ÿoÿWü¿m§ým=¾àþïnl:²=7òôý§ Ìɞ2°éäÈ>´“"uàž[1 œ1ìú‘>Èʙ }\ë9ACûC}ÿërýŸ3"þ?¡ø?~—ü¿Åøé܁úçl¬ Þ|zO_V&íçã`à½ÔÝý&°¯H½êlÞW´<v=W~}l©»¾¿ÀŽ{¶¿dÓ¿6΋îü ˲τM*Ø4™z‘ÅJ ¶d3ÎÜ6þ玈ÿÓÿoÿi Æ{{ÎÃYÑýœÓ.†ýÚ힡P1—kr»ÕÏDwϸ¤7ÎX¯ï4Pש™Ò%Ø$^W¶R[šz^uÿÖï½øßi þOÿŸTü¿ccþϹ‘ŸÍ Î wgr…>Ë{üÁ=ñ5£S6žýއt\ïkÖuYëÂFΌ‰Œ;låGý9ë,Ú*SpoÏÊÙρµ¥è`ÿ;uñ¿S$þ獈ÿO)þOÜòú_¹ÇÛ¬Ì$|Æcj#_/–¡3÷êu.׍Û1åsý?Ó՘ å†Y¿ÌÒêt½æ•±õ˜f®¿ÐVý6 µ9ŒÎú ®M¹øß¹‹ÿ#ñîˆø?_ñވúÁóŸûÿΎ®É Í»º!ëköÁºÀÝ^7qÛÕ±f×ß8!ºmowÿˆ5í¯¼jʚôöi¸ýZM½,Q‡/É {êë^³V‡ :ÿ»6]yþoŠÿóGÄÿŠÿ vxþ/ûÝgô×ëò*-½üÔÕí=y Ö÷‰ë5‡ö¹gAèì¸Pßš/ðæ€–5%¼=G®Æ\ N¸u +++¡!c±8kVCÝ¿,_±ù–ëã‘mãÿÂñ¡âÿ’]úÿÝYÍ¡ýÿ홼§õ¯ï*éΌ͢k.§_ ö‡•gܨAær>¦³=ë¦ýU“Øgh±Ö»ŒëbI,§£9FNã!·vïjDÖõühöÙ ++š-?&yw®ØÚYÄ+ñÿ¢ø¿tDü_¤øÿÜÎûÿÎÈý9càžq zÏp5Cý˜eM­¹X½îcî×NâŸÁ«£ù¤.ÏËõï¢ñZ~Fbõ¿›±Ã6׺ׯìíÿû¢.þ_‰ÿϏˆÿ‹ÿ_ØÿÐø¿Xä~…çwN¨ÇuÊÀY,í<àúÞ°à< W§±¯êðÛï:/&VC̟_šlÿ—ˆÿKÿ_Uÿ÷¬hnÀpþǁó²è5z>´{JØ£:‰Ž_¦ù&«GÙ}¦\=Èø™€ý:‘nmxåÒí]ål¬ÿ»)þŽˆÿKÿ_•ÿ}ÚÀ_íÚëWãØÝ.›Äó?Cs¹.W3°ß¬«²aÜÊÓlƇ•MÝ$v"l¥kÑîȶgÛö[ڟ¢bÉä–S’fµ-ØV[ôg™mÝ,lR¹´”’ÊþÆÜö‹«»Z6‰¢©ÍïèvQ§¹m˜ œÍÿÞÿ_ÿŸSüm§þ^µ}¬Ë"s|¡ý³n\pqtþÏÕxYÍñnŽC[ԌÿÖó‚줝Y]—Id.±›ƒ9ÜæÓf‹’=Z®Cü_>"þ?¯ø¿bËûÿíWs(ºXž>“0rŽßzRíœQhßÐõ½þ{îñiê9­œ ¸º' )C0O¬>Ü\?<›NÌW◁ø¿rDüAñÕÆõß+#×x›¡yæÊÚ_Ýå…>%º·oÏù“X~¿›c]ˏ__·³²©º¡*Bó¦O­[viٚê;U6Ó®g¦þ›¹3kÎwS¤²eË1²E[ÛX$un'îZÁw Ùáv?pñ¿Kÿ»Dâÿêñ™âÿšîÿ®g¨Ÿ¿ì[©ç×ÎÕ»Òÿ¯»ûÉqyÜÓþ\C6_ÔŸOÝöAÖ×!¼û@ð,ðÐyÌm?Β}gîÌïõy;E¹hΖ·úpEQ$‘ý…ѽ~ýÒmãÿÚñÿEÅÿu»ä-ÎyIöãœ8Pº&›å\»þ]xÝøâÀo]–[öýÑÚ­žM>ßJ=çnŸÏ¨ZTÛÆÿ¢ñÿ%Åÿõ;Ôÿ[îÇ:{O¼Ÿwp`àԁ5…,z¦››Z9>·¼â~]«¼·»g¬ç’º¹¡P=¹µÏŽ_»-”ÓÙ\÷…>Öú(ÚsÇÍ®Ÿû64îwýѕçÞ¶ñÿíñÿeÅÿwv¹ÿ/úëg Ìåµ?ãõú.×{}¿®ëgôkC_ÌߘÆusÆà¥ý1â²^_3(”÷ÑÛ|ˆê‘„æWÆ)Cñ÷×ÿß0"þnµþ˜ÿÓ­Ë?“m=ÆÁuùEÿ˜h>Á¾@þï2×üªèØÐ}¦úçM¾+š<¼>~ôא›µy¯OÈêÕl{ýÿþˆøÿŠâÿƍ×ÿ1g|L£Ÿ 7Ǿ2odÃÛfÝ5¯•“Ðpmý¿+r.Î …òÿóÆËýDmÝÀæ¾?·¹¼)ÒXûõn¨q£ÿâÿ#âÿ«ŠÿnÿÌñqûB†Î…íýώî ++æ,Îv?0pM6Pûëāg×þè¼æ¦¹ƒõ¹ºÐYB^°æ<—óàý¹æE‹ÿ ]üOˆÄÿFÄÿ×ÿ7myý‡j¼N÷<¹Í#\‰g‘ííÆøý¼Šó&¡~ÚZ_}¥VKby3¥Ý9guÙÔà´ô ;±ÍæTu +u2Ë߱՜Ԗ4W8šû®½>KŠZC·ÒâÐý2·¥Yݪ3;hY—­ºX!ø*±Û=VlfÕ=u5ë;êh¬yƒÖ‚Ý6þoÿ—+þšÿ?+0þË2¿þçêÚPë®­ †ÆxÓÀyÎJ•n Î;~ ?åØþúµõÐ#ù"kgèÓ8õãÖó̆КY-õ¡ùÿMñÿÓñÿuÅÿÏv9ÿIW¿Æž>5ZÀ­ãõÏí¯ãµûC§Á3C]1¼7ýځ~A¿ÎÛ»2é÷ šý؁ó=C{C£õœbó¼Í^K(, Æ>³¦S;¿ÿÿç#âÿ[ôÿCç¶×Ý9眭×îjüöÇmÃó…C×ðê|@YäÞó}(Æ;®´¹esʏ•ŠËóxNWhþύ?ý¹…•Úÿ~ÿßâ~ׁëÿ’ñ…âÿ֝ó?ú¹_v÷ë8…jêìíîãý9™“£uæ§]œû{‚öÔëçöÍk—xõ$¶n寅kk46fk¦òÝ=!¶WÈÕoíŽÕj&$gm¤ÿ»vñ¿k$þoÿW*þoß¡þMc¶×ßy9—í|mÿܰ¡5Þ ûkCÝُCýñµ3×Çï7š3¿çfËó6Åÿ/GÄÿUŠÿ_mÿ™ã9n`LÖÏŝg®fx`þ§;toh>¡¹×ôç–ufúµ¡ššÿ^~ÂP?.µ„N»™dVÏSw:Z—eâ:ñÆu‡dhÛø_:"þ¯Vüÿv‡õWã78f_Ô\ ÕkJS?xe~P?–ÚË Ÿ{ü@Ÿãȁ}BW÷ï+Ý^ôÈ=¥·<²Ïgý¹í>ú´É/jò«¡â`­â¡øûý¿wŒˆÿk¶šÿ='š«? Ìç´ç<ö×~2Ýø&_Àº}ž–Pªó0kÎñïCkû¶½þÿnDü_«øÿýÎç·s9~§Z÷Ì}{ΘÄr¼ŸEt <³}àeÔ6c¥¼fV-Ù6UZ2®®&=T-ÉÒvTÎm»}Ö<ÆÛj ú`Z¾G³¿ÐýÕ:äVñÉ*vZtnµõHmBV?ë*· ++aÍíyfÛ;ì&žY5/›Ž±mývK¯*ËÈí+é2µ ++6©”'IzCœÿ½éúÿ‡ñÿÍ]×Öêü…s|FsC¿@¯ÿXîg0/xÛø¿sDükÇñ»3Pû·Hçí³ÿœhßpØbë¿¡šPËñځèy!7‚¸»s@ü1do¹ëK6ƒ®Ëøï²ñâÿ/£Îÿ<³ß7Ô¸©½þÛ\žçÆØÁ\ž®¦ÄÞîL‰õ=ynܸ:¦È²*«ö°ÎfIe³¾³r®N{iu}s»²k«éh÷ ++›¨µÊï•ÅÍÒ}s›…¶•]áv ·•Ëí<©yóy´"ñõ¬™ë·Ÿ“¥ÔM6M&6ÿ£ð̶¬ÄÿîñÿŸñƒâÅõ_–ëõýŸúiûk@ûW¯ó¹¿6îS8W6ðŒèînžº_Cø¸|Ãc÷Äֈ·xn»\Àõ<Òõ{†Ÿ/X×öm™7««¡üÿ»wñ¿{$þïÿßUü¯Ü©þC›“Ú¾|ž÷k@éßugƒµ9ºOÌ)»óAWæ²,x>¨Õw÷‹@ mËRg\÷çyÛ_içZ«¦2“ÝögÖÕ²ÍLEÑî¿UO¬®¬-ç»h&…mžÇf”òBß½²ãcm»’Íè×™í ² ‘")­/ o¥{@»§ØVž;cÖ¶%Ö·ÿ{FÄÿ÷ÿ÷îrþ·mqõúÿý\î~îm‹ºðá5ãS£ëõnJøì‡dãZB(o4t6å¢ëuµ)#÷ÿ'î߯÷\ã ÌØC,µ´´mãÿ¾ñÿ}Åÿý»ÔZÔx:/ºßåP­Ï»þ_hïÇ´[§ñÇ U]$.¿{½.ŒËý í1 ++æþvg“®ÝÇý½;®~‹mÌKíØh«õmçF×Ë~ú!›óõj¬\ÿ'ÄÿC#âÿFÅÿªQçœ;PðôHŽ×iÁÚZ{»{C?'< ÖÜØ Ô։ŸFjÅ9pŽÅ$x/XË‹Õy åyÄÎúÊsý‰•ó?Nìâb$þÿ?Pü?2¢ÿ?ãýÔþ³_ÏBÿ¬žÐXíºÖñXž'}mt>1˜ë×Õ/Þ¢7x~s¨þGdL™ª'` þIa'«µB†ú›âÿÑñÿCÅÿê®ÿeÿù¸:¿Ó}|m-‡þ³á…½µCWÇo}|©µw(ïÍë{ú՞ҕúŸ›âÿ‰ñÿ#Åÿš-÷ÿ†ÏøʽnçæÎZéÿçݾÑ~ PWSÎÕù ír5@Vúu›Wäúbsû»Š\woŽíãѕi[ö3ÛÙ¥Ge{÷msŽÕ-§YüuÛ@ÞªAٞÝĖª› ]Ë×Íì·,•£Ô#@_Þ*OyùߣÎ%Þ6þŸÿ7)þŸÚ¸þßÏÿÑ;N‚ç4&ú{ýõ•…«ïÚ3>ër†Žï¯'kð4óî5«ãƒy]Ş ‹úŸ×ôúŽ®þç¦|-êzÖö€/¬êÃlñœ×¿K›¹Ã¤Î K·ÚV,¨ûwväw³¥ab3_PÛ{7M[ª¡m Û:þŸÿ?Vü¯Ý1ÿ#\{y¶²÷·^˕“øœ@{¿Xyöw}¬ðý¢=,X3¸{>­Ïùwý«öùQ«gÇ÷Y|“Ç΄q{¶uþÇ+î®…â¿øßÁŸ(þ{önºÿŸ8PãýøÈ>¿ãæ'Ñ5ãi §d9 ôáÚù„«¢×¶[õ[Ýõۏß]÷Ëܬð\´¿oïz_OÚ6þGŒˆÿ›ÿ›ì½îý?ëÅ^žGhŸ‡Ë¹ ×ëïÿ]Öëïå^ž+wEdàÒÞýÆíQZ¿§‡öÚxãþÏW]¸•:ú˜lÿ#GÄÿbÅïÆø_=Ë7Tÿ{®Û\Ë YÌñŒœ)Tõ× ,¿b²<`}Þ`_à\8wÆ[hþo™‡~Â@ýÒ~n»-Ùkó~e–Ôëu;½¦[as¬pQVU¨5Ìû]¯ÿ½)þÓñÿSÅ߯øŸ='7xŽ÷bx{ŸïýYVe•»/¯\«yÕìñØ83 º¤×ïok?½©ÿïj…/îñm]îõÚMmížÊæ÷‹Ä¦i¬ï]v5[u)–suóæV,–Ï_©‹®aœÆù6»›Tå¬LôqNÔ{°Ó£ìXàZ7ºjøM=¯Úº‹‰еⶨÛHÙÜ<íSaÿ¬Zœ¿~¾°ÿ/ˆÿMGÄÿÏÿ›mŒÿUk5—÷âÒÖå¾´?†ëjüº¼°Ð˜qÈ ³|ò}ݚPhŽ ÿîæáý=¹¡z¼½އÑ‹ÿ—tñÿ’Hþ×1#âÿç;æÿÏ­¬r¯¶_¾^¯ù0Ϲ:,ëDë“ei‚öíf™·ÿ'ÿú¿åˆø_¢øïßåù¿˜7??òL>sàüçcõ“úû<“f8´Xßï׆9>:/0 œ5ÚîŸFû-æƒ×÷€ûucì4ñ™å€ØþÞªYÿœ«Œ²òü·¸ßc þ·ÿ¿Püo½eÿ?<_sæ@m€3öÄÇì§|¦^Öæ¦øÏ”$¼w¨¹n2+ÞQW…mßÔåf3¬r¥Má½B¿g{ðtcµ XuÃ*ۀ_ِ޺îvì¯=xuñÙÃ9±]‹°®uÍô°„í-¬M2.|Ã5‡´êÙ¯nE•Û =±-%ÍÁ’vj¤¢o˸öß[ۛ° v¨x^¦þ¸26±ù#ÿ{tñ¿G$þ·ÿ·(þÇnŒÿyÑ}ÙnÝ%<Æ»b›t5ÚÖ÷‡M»þÜúy"î\€Pî‡?¶ 倬«ۃ«»Ç‹ýãÛÆÿ¸ñ«â‡½›æÿÎÎñLç;µg¿œ>P/ò”ZÕÀ9£' ìí<~à\¨cr—¯í}ÖÒöèâ•Ï”­Ò¨Ï_–nÝÉËÑ]Ô ï žó³^ßxí3ÚÌ)¹øŸ¤¸»ŠÿGÄÿmŠÿvÿ-ÖcÚëøÅ+ýü²Y“ÝÈãjë<ôó¸–{¹/Œ® mx.‡ökë/ä…ÕqΛΗRk€—4ažêR·>š=•kËܵkUlÛ¹ou§lŦTÿOŸˆ&ù׿m­¬[®áa¡\ÚLpSH ²£ä-¯´¶ þmU8+#UÚ[É5HæV| °õÁ¤ ++¯SmÿãGÄÿíŠÿ]vèÿéy;kë$¬ãë΅\¯åÊ \Î%ú‹9Áýëxq&D»¦^ƒÔ äwêÁs'zãýŜD—/¶müOÿ¿TüïºCü—ç9ç3~.¤»g„k½±·T×eµ¯Ûªó2pO°jl6£ˆYåå^=ßÃåüÇ`®Ð¶ñ¿Ûˆøÿ•â÷-ŸÿýsÔú¹_Öns+ûuÛ8ž²'6÷çjB„Ï;!šªýÜÖ§:r žä$:gù, Õn å-ΉÌ1†>›zTU‹úP~üï9ÿGÄÿRÅÿ»\ÿ‹¯çÔÿ9oOx.ḯz‚§FsÆÝüßð‰Ñ5·FÎQ˜DëZ¬÷g:®¯á¯Ïõ¯çõ†Ö–CuD{ãÿ{vñ¿gdþï¤ñÿëóø|Š¿ýßsDüÿFñ¿×Æû`þÏ»ÿ‡×~Ïȏ׆s×ÿÊڀîåþØ1”—ïîá:DÇE÷¨„êJÚúEl®im`e?ì|Ðno€ýáPý·õ¾ÉÖñ¿÷ˆøÿ­âòÆûÿæúŸá36“˜œ¸±ÖŸ“¼°çùd 7¸_~9>äDò#çÄó|V+ù#¯î_ô³;Kt¨þç¦øßoDüß¡ø'»Œÿ»çõ4p-Û<^èŒßåžÁãûŸ' šÓXŽß¢>øþè9Þ.?è¶«÷¨Ôå ìxfŒzù¶ ++¨ vžÚ€Q«ÃËj֏ԭiþMžh5œ[™ŒÖÿÝÿوøÿâ?ßiüïjlž»±öúƒWǀÝ€ýóýýA©Ýy½œ¢ð€þ!›|K¯ÛÚ >ŠÍþ›XÎlìnuÉK«GRάBˆîµ•§R¿1i þÏÛ ++Uó²Iðµs£ ++[Yз±ßïՌß:þ鈸ÿ½âŸm|þ÷ïÿ¶'+x¾nvÅ$r¾Ïbo5wsÂÀ³f׳žûç͸3Bñ_«ã¿Íùϱuœõ¼ ymO|}ÎËÒDÒYæÆ½f~üï5ÿrDüÿAñ¯6Æ¿_[¯ñÊ×Õy:÷ò8üë[äÊåq„ûwíÜo(_lÓ5É£r}.+³ NWQë^Q»û­­è´º,¯Šn è0:kÀÅÿ^]üï‰="þïTü¿tcüÏÿf?öé{Â1>8p&Ü©{ÉÛùšû¯|ÎòjîõïÂuæúgÆ,×§ó¿Ý:shm¿ËÛÕcK­Ó®'TSé7QLó\×ae€­‚¡MûMb›³²+X‘̬ÈCêÏ/·çÂ?ë{Õ·ÿ—ˆÿ?*þ§ì°þ¿¬óvæ@.÷ۂ÷ 7ÇÛÏý|å$¾nøòÁ~œë¯­­«­ç[ng‰DëY ¸mãÿÀñÿ'ÅÿÀÆøgý¸þyìúÑVí3à¸àð´»Îûg<\; ¯%õsÿÛ£ö¹C¾kÊû =;Öòyüqœ¿:ë!4‡Ûâr}ô·ÿƒFÄÿŸÿï”ÿ“e±ýßË3TΉœÿrâÀ}þ„µÆ~ÿ¯ÒæÆ «ûæÝ:Ä4¸¯{83ÖJ€wŸ‰Xmÿvn¾HíÞRÎ숯tQ÷áúx>¸3eš3aüøß{ þ_>"þ—)þ§î2þëÆc¡ü¿¶†ÆÙ½¿eæ?3B¹õ5wù$>n>çmÃ8ßï§ß ç‚wûÖÏ/X™ÿ»wÿ{Gâÿ#âÿ/ŠÿÁ-ûë÷ëÐ<î2¿ë`dÎ8pö{—¯<ûi‘ÇS ԓ;!:Ÿ4 ìãh×.Ø·²?ºße²ºFãÎq‰Í-×Û=Cyf½ç˶ñÿÊñÿWÅÿ«vZÿŸwuϏ¬ñ7podžë炸¿þ\⅓Ø3f²˜›æöÝÈÎÿØxýûë_="þÿ¶cýç¶ÿuö@}¯3æ9Ýyín'\k ?“ªŸM®?ÍØ¯n"—º3¾Æìá8KÞŸë ­ o}ýŸ6"þïRüOµÿ봁\þƒÑÚzÓnmh½¦À4°_¯Íå8)P3*ÍR¯_¸žì&eí×&¹.5a}´´H#¹ÆË³ÁûùûÎÃ{¢û¿6]ÿÿßjÿÏyÑs\By~V2#¸þÛÕÞÚ¨ÿ¾\«;½oÜØ­]ó¡œÀ•Ú³~üO¸þ1"þÿ¡ø?r—ùŸEŸí¬þšlW³ÁÕóê×çê×óҘ¸Í%XÉ$¿.Tøœ¿ÀِÙ|¥Ö@¸6` fT¶¬%㏺}„vw¶½.÷;t`³á«ë‹Ìì`ûKÝZB09P‡¢é/ºøŸÜÅÿäHüÏÿÿTüµCþ‡¡Zû[Öd<³“åo§ì8e žP5°g¨_S¦­ pÒÀÜåñ½÷¿¬xܞMãÉ@í@wvƒ_K`Q (°`ýœº•z‘ÛÆÿÌñ¿\ñôù¶ÛÁÏٝ£èâ:ÿ%/›ësc¹ðçæøhÝÈà>Å3åȁõˆÉàXoҟ»ær¯Ÿ7ØÍFÏ{Y?[r–äíÞbÛh”ÉÜ«ÿbq¿Ï@ü3"þÿ¥øÃù¿YSÿ'0Çӝ©æòBú÷øS®ï“ú’'ôåNô3ç3¿Ÿž£¸fpŽ847»¯ô #ý»Å} ð\è5W'ùÌÅÿ>]üï‰ÿY#âÿߊÿ7ï´ÿύåÎ8ò¬hmØáÚà—Ìê ++,ö"½mp­ÏݏõànÈ9¿õú߮ޫ;ÿgÑGŠ¿ßÿ?{Düÿg×óÿÚc27ÔøyÞ¦Ëç?Œûè.oÿß÷™4sMºô»=Û^ÿß2"þW(þߺñú?7šCZã±z]ߋË{y#VçÛ¯ÙZkrëÉ+÷ëª.\=‘Ðþ„õgx^TvàÌÕv³u–æ÷5f± œY³>÷yÙ÷ÛÛS°mü¿mDüÿWñ?gDþ§{.‡çëúy¼sÝBýz·Z½§tµÞ¯ÆÓ}®Bã¹i ¦X»ÕÏрn¨8/²öìµµÚ1VÊ­°ÉÜ*͋ÅymvOWœ¯§yÂhþ§Åý¾ñüˆøÿŸâîÆø·}¨óWúÝI—_sM4·ÎåyðçòÔéÙ·çIÑ9Þ^ª×¦«=±~²ÊžùúšEf©•m Ïk»”­ä…Սµ½‚¹z‰™•ÈšúßvøO>ojÈ6ËÇúÙfdu”óåüÏ}»øß7ÿoÿw+þOØaþgèü÷å<ßÙùšgöóê´ûÜôψÈ¡áó¤‡j´Ï›ÐyS‹õ£Cw¦“–”¾ºú‰eR.r†“d=—´wþû¦øLjø_©øŸ·1þmŸûU+ë#VùSÃÀ,¹ñÿÁñÿ€âÿC»<ÿ›5þ6օïŸä@Mè«&á<ËzŸ±Y]”yüþ¬þ{³§°Zg}fc³Ys²ª.RuÔ}G àÌ ++úZrneó6MI¿¼ˆäzÕj>g oÿÿ*þOÞrÿ_om{ËëWs2‹vý´½åxoœ—G=·JË6õ^Ï-Rº-dµ¥‰é¥%÷Yxì¡¡NžÆa©%û–µ×Ì`)ʵõèՇѸ?iJYiDz¹Ôvù[â~e;9êZ_¯J›³Þó¬©þc5|m"ўù¥™Ôõ®–Ú²™åù—V  ÒÏȾ§Ûý7‡öÅߟÿÿ±ñÿÐVùýõ_;Ë#´Ægû¿¦3¾-Oòjm¯@hïWðŒ?þÉÀõÿ”ñ¿Jñêëv¾É¼éã9ÿ»ß÷_Î ˆœÓ{r4—(”ÿ³ìƒNjC¶s¿·[ý^Á5¨fN× ++6ØFÝÒy»È5Pß1xöO Ÿgý|àõyEÿÜïÊ ++ÑZ9ÿ¤‹‰ÿˆÿ‡ÿŸØxÿ?/²ï¦×Õ1~’xëáZ^ûêIê8,΍º¼Ëeí°þþmÆs›Îˆ¬÷‡ÖÝº¡ޔžë2.ÔO¶a¹ÕKgÍÉà+ÖS´”çõ±Úñê1&þ½bÛø?mDü?¢ø?}Cü÷âoã87‡¯¹óšž±ãùJþÿz͝PþÛÏìýÌô³ïÇ1V¯£W·ÇêïÛ.Фéáé_éú¶Šýz֗v<¯uÔÙ+KÌÌlHa—§eù7@m#¥o”Íq Ö§¯­â伩©Ïz•Í äºåÙ$Aeµ@ÔI)ìœwu+K-ˆŒcã¡øûÏÿgŒˆÿG·Zÿ:ÿµŸÿ¹\Ë=}ã€pNA50ßtrôYt˜<ë÷ïÅ<äÚºþzp`íyåü×M×ÿOˆÿՊÿÏì°ÿ«­åxÚ@­Žvíï+k¿uÚ~fúõ—gþl[Šü¼ÝJð|U»åhh0k&~’y‘ia—¦ýÕh-)ÚRœ3ï'VÔê—ÙS]C±R·û\2uËʤٻ[TVÐúÿ¶0Km¤Pg™k’ÙÔA¥Wµåq¥vêkm'{ØÎ¤ÌÊü[^@:T󽷗؏ÿl þÏÿ)þÏÚÿþùoùÌÎÞ¹b_ûï×w·ÿâÊûl„ë†ô?m­‰ ƒkû½g­~B´Æ‡ *‹T×ZÙ¬"'×ÏZ³ÝÙK;O¤™]ʬb¬:­Ÿ®k˱aç¬Íðµ¹=9êÔf-·$ÉË6­™…¬šª‹ÿ¬‹ÿ,rÿΈøü:ŒÿÖÏӝý\{{<õ¿’<ÝÖw¯Øi>á:å}›wð×yûõãµÀÜþÑà¹âCñ÷¯ÿ玈ÿ'ÿçí²þ³8C-°8+»³¼Ï¨åxöÀ™ru£E}¸jàìðÀYÄvôG3N=12N=a NÕñkûgº{c8=/Š¡³À›é>ûlûç»úE™×þüߦø?Dü¯Qü_°Ëø±ÿëŒà½ÁÝBçMgü´õÄÚ\‚oZË%i?G󷸶]žŸ~¶V­ßÖf ++}õTOÒ&=W·z«Ô2·Âޖm)ÚsÝÄmYV=ÖÒzò–¥cC ;N´nÓVn&ÑÁ*ÁÇëxEÎ ^ó¡ý_›âÿÂñÿ¤âÿ’QõßÏŠÌ Ÿ6pH{ÆËsWúðYÑ®ôÏyÑϺÚ4ì®!;oÍÊY¾Îâ,7ݺmÈVÛäŽÆáó"·óšõ øK=™ŠÜ6{Ûcyfg7Ììì>KÒÔ)ÊÚr²l)ÁR´4†´Ó¬ô»Ø¡¸ë¡nÅ>Õc«jõ,,ÃËηރ~»9á-·É¾Ú’¾ëP¢È˜uåúŸÄÿ¥#âÿ)ÅÿçFÿØÿ»¨Çx``X5°§0‰ž+¬Û唹5§þ°cæ"¯ ®9¹ùÀÐ:ÐzN`·×k¥`w6´«ûàïëŠÕ•Œžÿ1ïâ?ÄÿçGÄÿӊÿ/ìRÿ·›w‹­¸ø†ëµeќÁi —C?©zØÿӞývÂÀ9Óû}ÍYW·æšþ¼pWÿÇ{nÄêYj·-äæ~¾Ywœen>*PG.8ÿšÜ6þ/ÿkÿ_Þ%ÿ¿»—‡òÿÛuÞÓ÷ÄÆx.¿;´n¼/PëË~êm¿áŠàØÐÍý†ú}Ón?Ází ++è«Ə‡jm74.íÕ¯óãŸÄÿÂñÿŒâÿ+»Ä_C¡|©ó¾èǟ1Pêô@ÞPUfÞÜàJœë¬»nOê}®,ÓÝÂùÄÓH­‰k‚óÐ~¿q}Þ8R×ÁÍAYÿ@-±½aËXÛ°"³{Há×Ô|ÊõWtg°<ã4uñO»ø§‘øÿêˆøVñÿµñ¯¢{<öîåv^sp/¿åáxãªð¾#£sŠÓ.d}*Ôß¿¾çb†Îj\ßRçEº8ßqĜҶñùˆøNñŖ×xOök¶£ç.ëC/·ÈÆÿ'̝00Oq\ ß´êê”ìì¯ák¶ÖU;3 4Æ÷΋Ö}ð÷‘ûñÏâÿÊñŸ<äØ¿j‡ø/ûÏg×ò§míÏð>®^ç×û1¨mÞ÷ÒIÿ³7›…ÎoŽUÏhˆ–ÏsÔ(Ïn6)`k¶²5kòõíÜX[6Țگvô“eê>Ð\ÉVãµÐ`1³õž¹%"Ïll˜6ÅOçÿ„j…æ¸øg]ü³Èüï«GÄÏC¶Yÿêÿ·ë¼ÏöŸÇżœƚ9=¸-M+kŽñ³™V6.Óm:SçË·´D-Ý;lÚ¶¶Û´>¶rß RmgÈܲ>l‚§9óÝæ¶š [R5_+·Y¿ÄòyšSúLPÛ×oǁÌl-Xω|¾¹ÿŠ¿ý¿fDüPü_»CýËÿrÏñp]àéÀüß$2Nïïûtû‚¦Ý¾Ïõ3hCg>,Ϻ¢ÿgÝþ”àa»ï×ӜÁº8õã‡æñ®só¿6Åÿ¢ñ¿‰âÿú-ÇÿáºgöÝUÝ>ïÓ£kõn=o}À´Ë÷c–'I»Žu{®o„¹ÿë9Áš!~üóøÿöˆø©øÿÎ.ý¿®îâ´Û¯µ~V»[Çí?·_Ö¿&õ¸^ÚûÔä[Û§½þ\¿1ž ¿R{ÒÅ?ïâŸGžÿoÿ£¶zþ_¯ÛØÿ՞ñ|Vt^Îõ ×÷dMç»ÙµÌZÔÔþµ$Doþ/|öãtÏuÉ3YË5Y?ûQÝBÝLlgSìµjÝܵÝÝ£bûÅbuáãï_ÿ¿?"þG+þoÜ!ÿßÀšv?{?ÿ³Ýû8§ÇJ_xÏþ~]¨k&ñõ€«úk‹CWNây¦íÜ_hÞª‹çÊ|‹—Ãéjñ,æïƒ5›ìB.‹êzØdNËC´4@ýf•d®?þ0"þ{ÿ?Uÿ£·…Ïy~Jó{g­ÌåäÝà“û÷zÛ ¹ÇÏkëvgVM¡ÈóÊúßVtɶ딅ûµ=ÂmS’•w¶Ý¹åÚZÒeÚÌÔØ¼MÖÔY°‡».·´¶ üÙatt´þǦøÿшøOÿ7íRÿ³Ëñp÷†þxþ¢`ÿÎíZÍ·¨º¹—MbóLCc¹µÚ{7ƽ ësMȶñóˆøïSü/Þ¡þŸ­É¹uÚ+±tùÿÇõž©~²‰·þº/L»ÏÇz¿Ñå¬×™Ü+zýÀCxï¨mÛ íüoö~êtëc÷4kˆÛÆÿOGÄÿ¦ŠÿŸí’ÿэñBùÖ7pgş m.ϱ«9\Ýúþ+{ë²Ë³^¾)4vƒb^4kn¶¯(Šä0ºïŸý×¥ÿ÷ç#â3Åÿ’æl­Ü­«­ÏÙº¹Ùð¼Ðk£ñݸÆ-“ºš„Ïÿrµä×òðbŸëcžæPÍó \ü ÅݵPüß:"þÇ(þoÛÿsƒÏx7Æ[™ß±}±“áúžÓÀÙÀmÎXÍ3 =Oܾ°½]~O¿ÎÄ4R·úê~þy·÷de ±¿oc²V·a¨l,¯k½þ§>/Vþ¥½ïûý€mãÿöñ¿¹âÿ—[öÿBy¼nýgýÞàÖC¹³ÓÀº`»Ÿ0XKlï Ï\‰²2—ÛoB{ƒC5¥]¾w/wdÛøÿíˆøßRñǖãÿPmÈã·xº8÷sn^œ/vµ¶9¿mñœ¿ñÍï Óë£nÿ¿ÿýŠÿßïRÿ¿«ã?\ã«Ø—ßæú‡êO¹þí¾¢ÀÙÑ6ñ:p­«Ëåï³¹Ák:Gê¬×ÿ ++žàÇ¿ˆÿ?Œˆÿ­ÿwîxþ·[û_¿ÆÝÞ¿P_=˜·±ØK|ñ$žü¦þŸÕuºÅZÿ¢î£í©Ýp>ÓayþwÙÅ¿Œ¬ÿüóˆøßz×õŸEŽõygyžÍåûB7OèÎŒ¿ý_6"þ·QüÿeÄü[G{ÂJŒçݏ#öÖ]50tE¯_·Ü7òÎI?ÿ¯Íéw5'Vëƒêb ßÖsøý=¡ù¢öyb9ÜvL›uþm‘u ôø·õ¼Ì2¼¬$„ò—M¹»ÒÛ襣þÓSK--k»{ÖMo_ï½Èš-ͱÑêÊ$ER¬ÎÿlºþÿuDüÝêúçºþ__Æg+¶ñ ØPýßà:pšWíó¡¿÷³Í:>PŸ´§½ž®ã™›*¿E™tc|?wh½6±[Sôύr{G‚ùŸ›âÿo#âۍñÇç˶÷ÿwˆÿíÿÿµÿûü蹜Á³á»ÝàÜa—¶/pn »fCóËzÃÇœõtl±@> œj÷¯¡ç¶»VKÝÞæC5}C÷ ++?Ìå(÷îÿÕ@ü/ÿÛ+þÿµKü»çª›Z¯ÉìòÂúù}ýÞm-ÑW†ò?ºó½{»yáõgzw׍q ¸W/ÚÅ¿êâ_Eâÿß#âœâňü7þ×d;0p.g5p.cÝ«áÖVê?Ô³nÇ$Rë»ÍzžÎôŒånYÙx}wëÆ[η]¹¿/ĝÙ;74Ro.˜ÿ¿)þïÿ;(þWŽØÿªÇµ¬ñu| H÷NlªËèâбË÷Z­ ¦˜4ñ¿|êNµ­ž¼wßXÉõŽÅ4RRߢYj,tU—kµ½®—ý_›âÿžñ¿£âÿލñ?q ÎóþÈÚ@›ß®ÿõ¤À8-zŽÃáXÃ+´Ïózß'ìÇ¿ˆÿûFÄÿNŠÿûw¨ÿmg²»gÿ<¶ëxö[W3r8û­Í3ê¯ó,ûŠ—ôsCua¼0~ËíÕÕa¼ÁçŠ×Φ[Ä¿îâ_Gâÿ¡ñ?^ñ¿j—ýßÝ9¯nm \ãéàÀ¾±þþOÝrg.g7|öçŽܑYšÏ²-ÆèV¢E<›†±£¹ò"¹ÁÏý¬3ÛÕ~Z9vÛøxDüï¬ødËõŸPÍ­ià¯vÞ¥¿ÿsyþӁ=±û¿›ÿ ç€$Ñ9¥ihž'Oªi öK[köÈàxphÜçÆ{k5B5‡ü¹¡ó¨\¿#X'ÌâoîúÀsz’×®Ï9†7>çQofþìêµc&{ޏo÷ë«oyÄ÷½o÷gÓÉäÚ=GLöè×Ï~ͳ~¢ý»GîyÜŸ˜Ü|ùëÙ-–¿žßrùëtÿò×Ù­–¿Îo½üuq›å¯Ëc—¿®n»üu};ýzÿ䍿{%úõí½×3ýú8ïõ\¿¾ƒ÷:Õ¯ïè½Îôë;y¯sýúxïu¡_ßÙ{]ê×_ä½®ôë»x¯kýú„åë¹½¿»z¯íýÝÍ{mïïîÞk{'z¯íý}±÷ÚÞߗx¯íýÝÃ{mïï$ïµ½¿{z¯íýÝkù:µ÷woïµ½¿“½×öþîã½¶÷w_ïµ½¿ûy¯íý%Þk{3ïµ½¿¹÷ÚÞ_ê½¶÷—-_göµrïµ}­Â{m_«ô^Ûת¼×öµjïµ}­/õ^Û×ú2ïµ}­S¼×öµîï½¶¯õ€åëÜÞß½×öþx¯íý=È{mïïÁÞk{_î½¶÷wª÷ÚÞßC¼×öþê½¶÷÷Þk{—¯ {_é½¶÷÷UÞk{_í½¶÷wš÷ÚÞß×x¯íý}­÷ÚÞßü×öþN÷^Ûû{¸÷ÚÞß#–¯K{ô^Ûû;Ã{mïïë¼×öþ¾Þ{mïïQÞk{gz¯íý=Ú{mïï1Þk{ßྲྀ÷wÖòueïï½×öþ¾É{mï×öþÎö^Ûûûïµ½¿oõ^Ûûû6ïµ½¿s¼×öþë½¶÷÷¸åëÚÞßã½×öþÎõ^Ûûûvïµ½¿'x¯íý}‡÷ÚÞßyÞk{ßé½¶÷÷]Þk{Oô^Ûû;¿y}t{ÖünÿµÞà÷ø¯õ¿×­7xÿZoðûü×zƒßï¿ÖüÿµÞà“ü×zƒ?è¿Öü!ïµ=@~Ø­÷÷dÿµÞߏø¯õþ~Ô­÷÷cþk½¿§ø¯õþžê¿ÖûûqÿµÞßOø¯õþžæ½¶ÈOú¯õþ~Ê­÷÷tÿµÞß3ü×z?í¿ÖûûÿµÞß3ý×zÏò_ëýý¬ÿZïïÙÞk{€<Ç­÷÷\ÿµÞßóü×zÏ÷_ëý½À­÷÷BÿµÞߋü×z/ö_ëý½Ä­÷÷Rïµ=@~έ÷÷óþk½¿_ð_ëý½Ì­÷÷‹þk½¿_ò_ëýý²ÿZïïBÿµÞ߯ø¯õþ~Õ{m_ó_ëý½Ü­÷÷ëþk½¿ßð_ëý½Â­÷÷JÿµÞß«ü×z¯ö_ëý½Æ­÷÷Zïµ=@~Ó­÷÷[þk½¿×ù¯õþ.ò_ëý½Þ­÷÷Ûþk½¿ßñ_ëý½Á­÷÷»þk½¿ßó^Ûä÷ý×zoô_ëýýÿZïïý×zä¿Öû{“ÿZïïý×zâ¿Öû{³ÿZïïbïµ=@þÔ­÷÷gþk½¿?÷_ëý]â¿Öûû ÿµÞß[ü×zoõ_ëý½Í­÷÷vÿµÞß_z¯íòWþk½¿Ký×zí¿ÖûûÿµÞßßú¯õþÞá¿Öûû;ÿµÞßßû¯õþþÁ­÷÷Îåë¹=?þÑ­÷÷Oþk½¿ö_ëý]æ¿ÖûûÿµÞß¿ú¯õþþÍ­÷÷.ÿµÞß¿û¯õþþÃ{mϏÿô_ëý]î¿Öûû/ÿµÞßû¯õþþÇ­÷w…ÿZïïý×zÿç¿Öû{·ÿZïïJïµ=?Þã¿Öû{¯ÿZïï}þk½¿÷û¯õþ>à¿Öûû ÿZïïCþk½¿«ü×zö_ëý}Ä{mϏú¯õþ®ö_ëý}Ì­÷÷qÿµÞß'ü×z×ø¯õþ>é¿Öûû”ÿZïïÓþk½¿k½×öüøŒÿZïï³þk½¿Ïù¯­ƒµÇ{­÷·Ç­÷w„ÿZïï&þk½¿#ý×zGù¯õþŽö^Ûóc¯ÿZïoê¿ÖûÛç¿Öû»éãv¯³ÕñÿÍÆÿàÿ#ûùÀø0þŸOYmåsl_íw¿ÜÓµž·ÞóÀÛò–ßû®gÏ/Ë#û{\·ß3™§vµ;ªÝIíxµ;«}‘Ú]ÔNP»«ÚÝÔî®v¢Ú«}‰Ú=ÔNR»§Ú½Ôî­v²Ú}Ôî«v?µDm¦6WKÕ2µ\­P+Õ*µZíKÕ¾Líµû«=@íjÔ¤ö`µ/W;Uí!jUû ++µƒj_©öUj_­všÚר}­ÚÃÔNW{¸Ú#Ô©v†Úש}½Ú£ÔÎT{´ÚcÔ¾Aí,µoTû&µoV;[í[Ô¾UíÛÔÎQ{¬ÚãÔ¯v®Ú·«=Aí;ÔÎSûNµïR{¢Úùjß­ö=jß«vÚ÷©}¿Ú¨=IíÕ~Hí‡Õž¬ö#j?ªöcjOQ{ªÚ«ý„ÚÓÔ~Rí§Ôž®ö µŸVûµgª=Kíg՞­öµçª=Oíùj/P{¡Ú‹Ô^¬öµ—ªýœÚÏ«ý‚ÚËÔ~Qí—Ô~YíBµ_QûUµ_S{¹Ú¯«ý†Ú+Ô^©ö*µW«½Fíµj¿©ö[j¯S»Híõj¿­ö;joPû]µßSû}µ7ªýÚªý‘Ú›ÔþXíOÔÞ¬v±ÚŸªý™ÚŸ«]¢öjoQ{«ÚÛÔÞ®ö—j¥v©Ú_«ýÚߪ½CíïÔþ^íÔÞ©öjÿ¤öÏj—©ý‹Ú¿ªý›Ú»Ôþ]í?ÔþSírµÿRûoµÿQ»BíÕþOíÝjWª½Gí½jïS{¿ÚÔ>¨ö!µ«Ô>¬öµª]­ö1µ«}BíµOª}JíÓjת}Fí³jŸS›1™ìQ;Bí&jGª¥v´Ú^µ©Ú>µ›ªÝLíµ›«ÝBí–jûÕn¥vkµÛ¨«v[µÛ©Ý^í8µ;¨ÝQíNjÇ«ÝYí‹Ôî¢v‚Ú]Õî¦vwµÕ¾XíKÔî¡v’Ú=Õî¥voµ“Õî£v_µû©%j3µ¹Zª–©åj…Z©V©Õj_ªöej§¨Ý_íjT; ö µ«}¹Ú©jQ{¨ÚW¨TûJµ¯RûjµÓÔ¾FíkÕ¦vºÚÃÕ¡öHµ3Ô¾NíëÕ¥v¦Ú£Õ£ö jg©}£Ú7©}³ÚÙjߢö­jߦvŽÚcÕ§öxµsÕ¾]í jß¡vžÚwª}—ÚÕÎWûnµïQû^µ Ô¾OíûÕ~@íIj?¨öCj?¬ödµQûQµS{ŠÚSÕ~\í'Ԟ¦ö“j?¥ötµg¨ý´ÚϨ=SíYj?«ölµç¨=WíyjÏW{Ú Õ^¤öbµ—¨½TíçÔ~^íÔ^¦ö‹j¿¤öËjªýŠÚ¯ªýšÚËÕ~]í7Ô^¡öJµW©½Zí5j¯UûMµßR{ÚEj¯WûmµßQ{ƒÚïªýžÚ﫽QíÔþPíÔÞ¤öÇj¢öfµ‹ÕþTíÏÔþ\íµ¿P{‹Ú[ÕÞ¦övµ¿Tû+µKÕþZíoÔþVíj§ö÷jÿ öNµTû'µV»Lí_ÔþUíßÔÞ¥öïjÿ¡öŸj—«ý—Ú«ýÚjÿ«öjïV»Rí=jïU{ŸÚûÕ> öAµ©]¥öaµ¨}Tíjµ©}\íjר}RíSjŸV»Ví3jŸUûœÚä&ºþՎP»‰Ú‘jG©­¶Wmª¶Oí¦j7S;Fíæj·P»¥Ú~µ[©ÝZí6jǪÝVívj·W;NíjwT»“ÚñjwVû"µ»¨ vWµ»©Ý]íDµ/Vûµ{¨¤vOµ{©Ý[ídµû¨ÝWí~j‰ÚLm®–ªej¹Z¡VªUjµÚ—ª}™Ú)j÷W{€ÚÕ¨=HíÁj_®vªÚCÔªöjÕ¾Rí«Ô¾Zí4µ¯QûZµ‡©®öpµG¨=Rí µ¯SûzµG©©öhµÇ¨}ƒÚYjߨöMj߬v¶Ú·¨}«Ú·©£öXµÇ©=^í\µoW{‚Úw¨§öjߥöDµóÕ¾[í{Ô¾WíµïSû~µP{’ÚªýÚ«=YíGÔ~TíÇԞ¢öTµWû µ§©ý¤ÚO©=]íj?­ö3jÏT{–ÚϪ=[í9jÏU{žÚóÕ^ öBµ©½Xí%j/Uû9µŸWûµ—©ý¢Ú/©ý²Ú…j¿¢ö«j¿¦örµ_Wû µW¨½RíUj¯V{ÚkÕ~Sí·Ô^§v‘ÚëÕ~[íwÔÞ ö»j¿§öûjoTûµ?Tû#µ7©ý±ÚŸ¨½Yíbµ?Uû3µ?W»Dí/ÔÞ¢öVµ·©½]í/ÕþJíRµ¿Vûµ¿U{‡Úß©ý½Ú?¨½SíÕþIíŸÕ.SûµUû7µw©ý»Ú¨ý§Úåjÿ¥ößjÿ£v…ÚÿªýŸÚ»Õ®T{Ú{ÕÞ§ö~µ¨}PíCjW©}Xí#jU»ZícjWû„Ú5jŸTû”Ú§Õ®UûŒÚgÕ>§69R׿Új7Q;Rí(µ£ÕöªMÕö©ÝTífjǨÝ\íj·TÛ¯v+µ[«ÝFíXµÛªÝNíöjÇ©ÝAíŽjwR;^íÎj_¤vµÔîªv7µ»«¨öÅj_¢vµ“Ôî©v/µ{«¬vµûªÝO-Q›©ÍÕRµL-W+ÔJµJ­VûRµ/S;EíþjP{ Úµ©=XíËÕNU{ˆÚCÕ¾Bí ÚWª}•ÚW«¦ö5j_«ö0µÓÕ®öµGª¡öuj_¯ö(µ3Õ­öµoP;KíÕ¾Ií›ÕÎVûµoUû6µsÔ«ö8µÇ««öíjOPûµóÔ¾Sí»Ôž¨v¾Úw«}Ú÷ª] ö}j߯öjORûAµRûaµ'«ýˆÚªý˜ÚSԞªöãj?¡ö4µŸTû)µ§«=Cí§Õ~Fí™jÏRûYµg«=Gí¹jÏS{¾Ú Ô^¨ö"µ«½Dí¥j?§öój¿ ö2µ_Tû%µ_V»PíWÔ~Uí×Ô^®öëj¿¡ö ++µWª½JíÕj¯Q{­Úoªý–ÚëÔ.R{½Úo«ýŽÚÔ~Wí÷Ô~_íj ö‡j¤ö&µ?Vûµ7«]¬ö§j¦öçj—¨ý…Ú[ÔÞªö6µ·«ý¥Ú_©]ªö×j£ö·jïPû;µ¿Wûµwªý£Ú?©ý³Úejÿ¢ö¯jÿ¦ö.µWûµÿT»\í¿Ôþ[íÔ®Pû_µÿS{·Ú•jïQ{¯ÚûÔÞ¯öµª}Hí*µ«}Dí£jW«}LíãjŸP»Fí“jŸRû´ÚµjŸQû¬ÚçÔ&GéúW;Bí&jGª¥v´Ú^µ©Ú>µ›ªÝì(æ4àÿ±÷/à–Uå÷[;Í® —$xIBD¢ÜÄq¿¨’`K<ˆ€E`(b)ÅEšNó)vxO$j#Égr쒏'rZˆD1!ŸDPLié„N E$J ²DÔI0b{ÞwŒ9çÞµ×®êîÓ!Aùÿ’¥ÖškÍËcÎ=çïxàéã'~ò§ÖP ++|¯û¾Gæä?õuòí«öX¾tÏ9³·þ÷¿×;{à¸óÞpîÙ.¦Uósgî¥ïÿ޼ü»ÃŽÑ÷­±a~îyÓçØqáO´÷­‹ósÛÛï ߯ïÿ—}îëë1e~îÖÕãû‡ýɧ_§ï{“êüÜ¥«Çõ¼tǾohïW›ççŽ]§ï?[^ï8p‡¾|Nós÷·íž,¯ËûÛö~ òþûÚzæåµîÕÏþS}?Ýî~kõ}=ˆóßöÒo´÷wósO¬·û’?w§¾Ÿ¢³ós—ì=îçáÿùY_kï#Ç{s[ÿžòzà´mû“s–÷ÃÞã~Þ¾ùà¶?¹èqÛÞ׃xÉ7~à[ú~ñV¶{E{ÿ9òºí±¿ÙÞ¯ÉÌÏ]·fÜϟ<눶þœ”ÃÍëÆýÕÊãDy÷ˆ3}Yr±-{Ǻ± ìÿá ý{Áú¾ÎK¦eŸ¼úŒ;ú2—ú1Ўý¹òúâïŸðH_–b_ç“S¹¼õ•[¾Ò–ÅTú²ËÚ~ž.¯¿¿á_mËRýønnÇ·¯¼Ì8ý/û²êú¾Üµf\ö¶ Ǘ½éë¼fj>òæ¾½blÿÞUÓ1l~ÑÆ/µeÕÙ^·ûOíögïºðe}YÊúþÕcy^N¿·/Ky(³Õã¾|îãÛ¾ÐÎWc/ëûÛ1l“×Ûj¶ÌSÛ²ƒÛ²_‘×ñwŸ8,«6ôe{ûyÉ>ç|vXVz›xϺq{¯¿ñÜvÞ9m_çÅÓ9|Úåç|®/+vhƒ{ËN=hÛÛ2o‡í]=µÏM }°- >öeejŸ¿q˖…¾,æ¾Î‡öËú®6<ؗå¡Íj:¯7ß²iøÞ¸/ë¦s{Ãö—üèpó½®\·¸/o~q_æ‡:ºrº†üfÙÚ×cîÇ^֌Ç÷Ö#Ϲ»/ËC›Ø¶÷XfóÑ7õeÒÎúñݾv¼¼þá·Ì·e¹˜¾½£Ú:ßÜêÏ^זçl[vßTf>ôÞ¾¬æÞήY7®óµüáGúµÚ¤þ½-ëÆ2{ÿ-G?ܗ…<œÓ{ëãuâßïyìB_Kà6¾ËýìùçË%%XùoýßÁÈéå<“kPÐer~TùïTäJ6|&æXäKþRæhc_G´ÙµuÕ­ òW­æv½¾£¯\²-.g.Y¹Ý°rEö.†à|’8FùkQdUNÎJùÛ`¼üõ/Îú˜tÝrÛmð¥ÈßvÙFŽÕ¶mú’}ÛG¹¨:Ùÿâ½\Ь\‚d{>%゠^þ¢øœå*Xå½ •\ñÆ“u²ùS³³Yþ&¹uÐk¢a ++!È:dµÑ$ù˜ôÂ%Û²²¯ÎÊÿ Ç/«²¯Y._&Ê!֒‡ÏÉ-ŠÏQîH³–qI!êe,ØlY,Ÿê¥Èdï² UVT¤{ÝÈ­ ”­ÉK>+;“´äª”‘qUWöÌåþ¿“”¨”’3òF–ñÕÈIÉ;ý—õÅ%—Š‹”HÐC0rQ•ê”bÃ+rM×ò×ò òß5JUImk…äd?¤îj’­Ô,û\ƒéûUkÑ ·Ü%„Zô¸‹)Õù§””÷ýXdûAîÁC,E¶&{¡ ++Nþ§sR™Rëò×F¾${#MBږìs–›'©_c1Un£dEªBvOþFÊ?¤¡¥¤MB*G>%{òÐeB®roRår¨'ù£+{å?¥¬ŠüÍC}JEµ6&{[›$e$ÇlZÛjŸ‘"ÖsAÿìy)k#­§Ø4ÕK”[2i6R\9ÙÙ/¹K“]ö²§mOj¦H‰Zi[Ò®¤è”‘|ÐiìR‹z^ë¤ÊŠþlõõl íoþbýG£çªü]kû¥-I?+ږۜôè¼4xiurƒi†¶(Í×Êͼ´4©ƒ*·{Ò΍‘-dÙ+©'9o³«7R3²ÏR5Ažu¤ü‹Õs •4¹½ÌR>òÙ*‡« M6]å3rÀR'҂¤\³—‘ˇ´°œ¤ýË;U?&U\´²®œ¶µ]ٔœ@R˜%õ¶¢ç‚œµÆ ÇìŒVq’sQŠ5.–EÑÓWޑer!qÆíQڐü¿O­.¥‰È—µñI‘ mQ.3N—Ãie˜äÔאg»á\“늬¯H™YiêRèµ×‰`–K¬Õ%½‹3±¶÷ƒ\úŠ\¤¬×Ö!gÕ°ŸrÔ¾´vô²)ÍÄÊIgä ++$û$gšñ²gzM rrée@JFjDªQJPÊ0¦,`¯—ŸõÒ+åîÛ «–œàòvГI¾­g¶ñrwå —ÓI.´VÏf'µ-U![ózuuÉh;Ò-ëNx;쯬C¶¨»™¤5Hc”æ®§—ôòÓV#—Hي|KvK/„ôÿðL°Øÿ¿úÐ'Þ¶|éüÜû¦~ûƒ?}Ø)½ŸSûá×ï5¾¿sþíSÿØÎýóWLýê‡ï­/DãççnÖ®­UÈë½_ýÁ[Ûû%h\@뿚í·ßÚÖ?ÛoWëGÒþ§­§Úߏ^ö󮵋Ûýµ³Ûû%Êç×µ¾¥_•×a¿ºõ)¦àd?hë?J÷äöÖo«¬ç†ö¾öøªý¾ÓúՍ5ósOñKûáWÏ]ÑÊç2ymþÐ Ÿíýínèóºlê úòSÿ[_Rï_<³}OwèüÏßgèÿb®ÚMÿ÷¶ö½ òºò]'ýß¹ïâ©?s¶ÿûØ©\Þ¼°ýc½ÿ;ǾÎçM}À³ýß½_yåþïõk×¹Æýß®oÛwñúKOê}²&Ûþ½Û§2»ðCc´5}Ù óã²Ùþè í{ÚÏûÜ¿±¯SPìå9ÓkÎýR_V‡¾\ÓÚö;µþ>ôÆû{Ÿ³ÊúÒuã:gû±ËÚñØOûÜØ¡ï8õò¼qêçݼpHïÎÞ÷eWM1$³}Ǐ¶ï­ÜwüÄk°ñîç~¼/ ¾—KQ¸V^Çñ“íËòg±aºÆløâú±Ï¹öréñ5zÞ}ÿÛú±W7ÄnlâVÖxbï§×[Û²{¦8„ãî»éƒc_ußÞöéò‰w½æ¡¡¯zhó—Lû2Û}øTfÇ-}`_憶tÙTfÇ}ùÛyë‡ßÅüãYÒ·cKÙiï¨Óž›´o§£]ÙEþæ˜Ö©f³œÝф ½~Ú)—¬=Üò±mëýÑ>iocÔà/¢³Y»gSJ¶hO¶“›†±?ÒGy#Ÿ´‡6»˜ôâ/ÿçe½rÉÚl))Ë_D#„µC(í¾ YþÌ'kȲ&TÝç(×ù‚†vÇËßאµµ$íKÊ©h¿µYi/k•ýñc?œkV&d¹éñëŸÄ±ÏQö(y¹Žújµw¸•Û?e_}ÕÞMSä&On|òPo^ûŠ¥È†>¯•bzŸu”»«(Å¥öêðÝP¼l±Ê¾Éb©ò¥ÛʤÊäLԎÓR´/XJÜjÝÊ_{í}N¹¦¨G§}`ÖÚ¨}y­:äNAûȼÓ}Ð>¼RåFS㠂–ƒ)rõÚ"\ÔH½ªíjëOË­×Uڟ‰c<‚¶¸á¤Y´þá¢ý‡Ò¬Lk·²'Å"… {ªY÷ ¤R´ÿRãä_ôµèaÄ5 …¯­PŠÛ„"µ”LR%>ã´ ~I¼ˆ4¦)¦DQjÞôžNÛ¢K¤«Ñ^Dí¯zŸ'ÍAþLÉÈDi¢ ++!'‡•攃˵úì³x´7Q÷Lچ¬OþÏi#“"‘o;i–ròéÖÁ­ýð¾$ùLÐÖR†˜9Çt¶ ëý·c?ú®ú›eeÒ𵞝ìqÐN}ÙiHI£4´«UjXE RÏ!ê˽¿TXnñ5µÎnÝ! ÐðÙ 6¥j¼…”‹œÍrÐúW¾ÈfµS¼¶R“ò× ƒ´o9ïJÕ „ÔY ír Í#E=ZYw\s³R¼‰î`–Ó,ë ¡§XúeåìHR®5 e¤]·í´Ög¹28­ÕHz*ÅPôªrÖùŒ´f¯MÅk„…žÃR;R×¹uѧÐZxÔ(ِœÏr%,zîGõº‘ä Õp]‘Ôb©ECC–Ä]HåKT¹ÉÕM[²œjÙ½|%§3r}Õ8=-åËÆ¤–½œ{®·É Õ·BLÍò qHVCä>Nå¹RL‹4º¨§……×ð MYµ›ø§{­ Û,֓Tf È¦ŽíSžaŠÜëÚ`Z¹^º¶`-άq.R ++QÛMiÅ.G.>9î˜4º$Êí§î’¶B ŠrHzz$H‘¿DAê\B¤²´·_פ! ^ÿ€Ä,WŸ¢£Ç%Å÷ÔÇÐÿÀ3Ábÿÿ¼ìÈ/,_ºç܍­/W;ïÞù¢óoýÛ6¬šŸÛwêS~Á›y¢÷ãZ??wÅÔߺs\À]SŸÛ!ßü±¿kýüVãz_Üåò:öÞþ¡õÃ'ß~ÑÔ¯¹ó¸úÚûåuè·®}mÛýÒ1»³cØ÷¶=;ÞüŽ©ß|v¼¹™úô¶>öœO ã¿}_秦uÞøûç=ԗ•ÔÇG¯šúrgûÔ¯šösvÜx流gßîµ½L}í}½¯ó×åuÂ+Ï}¸÷çaÜñAÓ¸ã7|õ°+{߸úHŸb fûÍßѶ§±þðY}uìǾ}ŸÅï-ï¢õ­j®…Wròc}·wýØ·®÷eó¯û•±o¼ïËÓøïÙ~ó£w3Žû’)îá¤.zy_K/—«—Œ«¾õ¦Þÿ†Xƒ[÷×9;vzýÔNgûƯ™Žá´íïzE_VR_gÃ~¤¼Þ¾×I½?Zг·‰¦¶´qáUéýØvˆÏèy6iý}ùèwöeÑôú»£íçÊ}ÜWNõpÜÂAØk;ô©ÏOeöù«Þú¥¾ÌÇþ½‹–|ofÌõ£sÒåÇ>Òûª³¥¯€ïmmü±Ñˆƒ¤½û&Ÿ\mQδÑå>FëkÖÁᚢ@´G’Ñ>l¹Sò­oÚx:)¦w˜/é³]!6BNø”SY’·Bn‹M‹Z ¶¤a¼ü®r5DðnLMmߓ­rG­!ÑÈ.Ó:IkÒ`ídÕÐbúŽöÛÇêLq1…j³¯I¶ì“öàjzÙS³ßcdt—åÉÁÇ!FeŒ©ý¬!EÛFۛRbŒ!k·¯Ž¡—{íŸn£ÛåpŠŽZÏVJʖ:äm Oh»ò…*Eg¼|TVQªÑ>`ÍfQµ+?¯y tÔ¾<$i¢†Öµeõ8¢û®é4þ%ɗ³–FK"Päð¤u| ++Cv‡¨½óYîÝc-ÚC5½‚±íÆ{I̊4ƒPw‘û ”Ö÷]Úxz«†Ah'y,içx,'õ¦ëÉ®¤K Ái ™ÊIRV¡å- H¾«cУph‚o±‰ô­¬1<ò„(U¥Ò8MK"õRµ´õ c¾m„º•°¸¿}÷¤ÄÆÏ£¹;z¤J•fo5áJRæÚV´^äé5ù(+Öø&4~XGð[ƒÑÈWõt‘jÕh%ùŸì’%¥­+JЎûê[F‘ªi ²­¦Å—%«ñrþD7íc–Š“SÌ÷¸mPÉK‹zÖXUÿã%z„®d³$ËîbÂVÌOAÿ?Ï‹ýÿ¿½ðØW–/Ýs?­ÿqùÁ?ñ¦žÇÞ­šŸ{^{¶ÿÕ.úÿ·µ~SÛ}éÑÏÿ³>v6˜ù¹û¦1¼qÜaÿ½½ïSœŸ{rŠ/Ø9^ L}ÈÏúëçýYϓo☷v|¾™úéùç}|ˆ_ósÇLc¿w·A[ÏÊãöïÙÍØüƒ§ü׳ñ[öYüÞò<ùKÇûmm?(C®ñû¦Þ³ñ}캎 ¿çÖÿÕιéßßöeåqû=?ûÊ1=ŸøÊãö˔·~…±ùSÿõúy|¯Èµö~胦>ê›>2|¯Ø!gxÏç¯måÜ;Nù¾¬ý¼¥±­VŽM8|êgŸMè¹VŽMØwíXGß<à”/ËB_¶~ê¿øNýʐÞôýÜoŠ18caˁøýÚ÷e1ÂwŽÜÖsÚûzmÝg¬¿Ù¸…ǧvüÑUoüL_6ƘiÙl.€Ã§<³9íÞMNû£¦óé3¿´ñk;ç´_·›œöÇ,ÙÞò¼õ=~ä|­£œÓיì'àÒ麱iáÑß– ãèjËVŽ¡Óy¹qáuò q=·Èʹ.Ùkñ{ÇÝ4äæ›8v7ù¾>ÍrÏs7>:äÊó¨)þg6ßý%SlÉlìřSîˆÙüë§ëÝlžüçí&÷ÀãSÖk¶?¶çpýԟ“àÕnÆæï¶¯j¥1ÿËÆÞ>mÆ7ïb ±Õ©W¬ðnÉÓK»ù[Ö_·ÒøåžÏ^î‰úœ ²™à³v ++ZMU®A­©å4wš BVƒüMUóŠkòí¦s­o1Fí¹Ö‰Ú®3hærM³®]¾Ñjr¯ÙZV‚´—Òjqšœu{rRn}^ˆújõ“Nî³ìP»êo_Þ¾«üöÿÛýâ¹õ\'×r&ø63E~:æ{òLãÙee­?¼J³ÕxÛ%9v5ßA2Á²!ÆÆÏ>…qµhM÷®µŒC,BmùL–÷“ï*—¾vŽÇ©]h J£ór¬0/ƒd˜ g`ê»Z†¾ù§:Çý?e~9䜤 µ™'†sI¶ì³&zÐð9ñª´ÜÅ|³±.c̅†h*79[‹´ ÉBc8t]:ùƒœaZ·rÖyªæ¯is…h@„4ÆÔRÐDj!ꁇê4~ÄJié|%R µ…™È©¬}´v¡“Fh2úÿøÞÇó?Ï‹ñÿ·oÖ Ë—ÎÏ­Ÿb×_ºcß7´¸Óªqø=n_¿pð7îøûŸotž¿ Úç—çó[=·aÊ5÷—{Óö[^b~²ÅÙ®<'ÜmÙ¶UóûS{ô˜íÐrªº6Æ%ø¢aö){olöYç3t:i.É{Ùø]Ò¬x¥ä¢‰ãŠÎꨡæ)i y› Q'D56蔕&V[S®$$Os0êPkJÕ`{£ÓFguÞD]1jrEã­®Í͐J±mœCÑI¬“fã‹òŒh}l9ìœN­h­ QvÈÈCbÑ`÷І  ] {Cõ»œdw5!¢¯QÓ :͚Xt@O’­{«™kJ:Y¦6Ð9HkÈOá|œ}œTòät,ƒ~1Žc žN¹—>ÿ¿éñßøñÙçÿ>ÆWö_ø–ÿ=ä·óCÎr«zàŸ¾û íù?ç?å·¿í±¿ÙÇç'³zîæi¼ìþמÑǁ3ä8_ÌÝÿùŸõµ>>Þc“ß?ýþpîÂÑ}¬·´§¥ùÝuLìÙíýÎ>~< ãß·$ýò¼÷WN¿E„=6=8ü¦0Œ¿aÚÏÙ<ôÇOûy× Üy õöi{³¹ßÙÍXá­Kò´_³¶ë-:5(àéù[Ë8–ßÖ¨9 t M¼P«-‹95äAܛÒò€xëô~È¡`åi1å<äL™>ïjÂoK§{ytó Œó-h:…–WÁå¢é04O‰1š2%UJ]š·Eg—p:3ƒN !;X2ñÿ<3,öÿñçÿåKç‡>oíç?øÓ‡ÒsÉküÿñSö#vìwfÏÁ^ýüÜÍíý_•×a¿ºÍñž‚KóC¾sýüKvüܝíýèìüÜÅS^ò¥ùùWyþu»[?ÿÖÚÖoӐ}ý”S~ÿoè±Á±‹s°o[8¼çèÎ÷¾ý'¦mÝøûç=ԗ•Ô—õq +çÌ¿¡­Sóªæez BÆ.ô9Øu?·Ü{Óº¾¬¤¾lKÛÞÊñ W¶e§ÈëßÚ³{Þq;æ›?f:¾Kö9§ç”·uȏ¾©-;Q^'=ì¯éyê­ò¿ï&‡½™rÿýÛzŽw—J/³£¦ívù9ŸëËÆüï[¦‹ Û_ò£Ã|¾ßÓ:³líëÔä¹mÙ±Sžó·¾xs_–Í0_ÀþSÍæj?hZ6;ßýeS›˜Í~ý’ï}`_æJáÀÿí_M¥çP×äþI#±5Ø|Õ0·EJA§™¨.xMº.]µ¬6VÊ£¿Ò|qoä¾¹[ª òäÕÂßSµÞÄ,ÿ4í ºÉLŠÕÿ–Ý]Ö¯½Ê:E‡|Un̍¬Igû–uÒWLâÒ­IIÎc‰¹ û´S_ô®rú‡lëÿ–ƒiŽ´_:I)”œ\M¾´è+{ã­<[ŠCvH¾]uHBÖbôšKßä ;¢m±¶É4½æõ7Ó>éä}Ÿcª²+ÆêPáÁÛè4¿æù×àùjkˆN§iӈä,ÿ¡Yÿu‚ +++eïu~€,µàk­6VÝYy^µ:¯IÉrh² ++yôҒñ:i‰Î߆1€öMŸñßèï{˜âŽØqáOô~~ççnœ¶{Ðý҉½¯>¤ù¹Ö}¿ê½òºí³ûÿMïWN²þ¦y¼ùæý]ËG`5NáÊuãû<÷°–¿ ¦(ï_1Íí}ÄãgÝÛâ²w²Ýöù£äuðÿÈí-­òù»Úç¯×c>éûÿ¼Å)ÄbWy/“׿ðÙ~\mÊX½­KûÕ¿uý˜ó sÃ_7Íñ~â‘îîÇjníxìgßõÅ[z>„4ôs÷ùæO×–»Ÿ|e[æCèýê×µ2ÖØ€óq¦/K®/ûÔ´½O^}ÆC\Dê}ü·í5–ÅÖǞó‰¾L)\̕°r̄iû²¯¼Ì8}ÌÛèú1Ü0mÏ¿dã=.¸ðžuã÷Þö‚M½\²bn˜úñgó6Ü>Åa\týé òÒ×yÔÚq{³y®Ÿêá;GnëñRfýøžX7®ó7nÙÒãB̽\®Z;¶ñÙØ‡+¦v»yá˜óۗ¾½«÷ïo>ú¦»û²ú²mm{+ÇE\·n\çÆ…×}`˜ßÞ û2oyõóû<õ¦ôzز÷¸Îõžøà0‡½íõpÌÚqÄEð?g…9ÒkÕ ÜåÞ҇Z–ŒÅí}¤Qçë.É9ù ¬cwµƒÖFë´ÛQ'¶—:7|®:ÿx5r£ÑîaWSµÉéçõ_:ñùªÙ¾CMÇf‹)²Š2ö9'“Œ-²B J-Ú']½¬'j×j”ûFlÈQÀYo í^LVûd½wYwÙÔ“,7I>[ÛÌó!ËÖ¢ÉVn¥bÖyì³Ï:M»‘#Ê)Êvƒvc×êb,NJ)'´ŸZo¦å¾Ü¹Tuêúäwß?®9ÒÚ±ø(ïËzC¶­lSÔIÚÃÒqÌz¯ØÇ['å(·ç!9Íl–S6EîŠäŸY便䬥×þ^©ÁŒ/>jêµ6N;H¶>ä,ëÈÚ¹+7úš9Îê]W’£ÕùÒM±Q€“ÝÎN{¥lå¨å&±Ví@N5k ++·TS”ÚõÚç´ç¶ÈŽÛ’¬\ÊR·,» ï÷íe}­AêGJSJÖÉj˜úæ“f£ÓæÒڟÜkz·6ç|L-GžÔRžÊ#ùÔ۞ìQk¬Ò ÒPÞ^k%¶äyQÊQŽ@êSv(™lu‹Ólq9ëCŽÕbÔÍj»¬ÔR[²@;Óm’ªk½ÌÒ^[T‚‘´€â5ɞ‰Ò24¡»ÑT}º"£üEÓöi]É3C–F,å -^ŸBÛ¿ =JH3©c{×sMÖ¨9ýÆ>ióRj¡D/54žkR7²úì4á0.ÞÛz܄4:9ÉLÕ*Ó.vy¦¬Aƒ´ƒ¿ä*WÊUÓïi/»Th;]¤¬µ’KËõ—å4ŠÉHIó(ZåzèòÔä|Êú  I åœ3%jϽ šxÏF]]”MÉ9Päôò²šôtÕ2ˆº¦­fІÑúô²A>)•£×‰Z‡¸å11ÈnG’Èí¬mšîÐËyíZ5ÉS©´*-à ;!ן*àRK»(û-û%Ç!'‰æhdü?Ï<ÿðL°ÿÿØAû¾fùÒ=箙âœßqØÇõè´j~në”knçxþùÃ<·ÿž%qþKó<åäÛy~Áƒ§xîcú¡OqËn~.L±ã—ýü?ëï3?·núüïÞþCÜâÿ]”õ=íÏÎón˜âÓ·}úÙÒâÿ­¯ósOñÒ;ç)|b_ðÓß|i;Þbœ|¾çԍ¼ä?ð­ö¾ì¨”ôžCw\ÑbÀKÐqë÷Z|ÿôÏ·÷³n÷˜iÿŸõ×Ïû³>o¢‰ós÷´÷gçSÜŠiŸOqû”'ï¬/øc0†¼ƒŸšâÈß°ðÀo ãb¡_µ÷xŒûžŸ}°/‹Cœü“Óö6}l¯`ríë¼bÊõwá‹Îïß³¶ôe¦˜öóÎÿxËjißcúÞiù̇ûx…8Ä쟹×â÷¾¶¶/+Ã\‹Me;›ãññi?ïÀ3ú~F—úñ]ÚÖ©_>ûþs¯íãüp ûN1û³c6´1äuå»N—å!_ánÆ2|}ÚÏÙ¹+7µïýº¼Nxå¹ýØ59ɪű!ûÉ뜿~qã‘ëP·ûï&§ä±S>ÆÙñOLí}6§äõíø^'¯מùАSr¯pø4æb6od™ÆœôÀE/ïã*âPï··eÏÕöÏ{lXVûö.mëüIy­ÿê¦ÿÔÇ\ÈIߖßÊìò:ñCo¼X6|/Lãfçߨ¯Mf3c¦óuvNÏý¦kÅ'Þõš‡ú²0´Á-»ÉayñT·üØÏ-ôe¾mðÔc©uŽìo4ܽf³¸Lþ,¤°tž/§ùß4&>åÐbó“ksrù˜Œü‰Ô Î5f<êéFþÏÛRå¯@Öpú`KIÙÊ'ƒüÃۘuNvßyùC™²¦ U>«±ËE¾à²,Ï§ )Çb,:#XÐØuo³Õ‹ ³š×’’ßÝ\cÓ±ݚìÐk¼B<õ8¿Øò¸|ٖÑ(wùNÝݜcrð:Ÿyl Òª UþzûOQӓi5•¬jÈy0^ã™u$Æàë ++ A—£o“³G§3ÈË¿SvI¾œ¥è]ØPB•¿’r/ZuÀAŸ!^C곆•Ç*•àt0DÒ¡¦ Ç%Ï*­ž}‹§o)Ó¤@¤¤³ÔZˆÉÌäí[>G›ÜVou®n¹óf§øó>n$—4üï•rûE“Ûøƒì5 ÜûÅñ &jIs0r÷-miqþ¸4/]”†)ÿRÒq!¶9ݜiqïYï¼å>ҚŠT|hyò²Ó5Æ´Òªa¾ºž¯OFÕ± exùø–,Xƒöã’܇»šãnéXëô™£¸qκ]ŸÛ6H#H«¶:VC*·jH¾–©F¶Ë›=*ßeýbÚÕÁI›‰¾?ԅŽ—0š„OυØbëS•7|ԐøªÏ:äÄÉ­¤4òåt˦â²?:(;ËÓhöºr>çulŒ´¯# ¢¶Â$X59 Tˆ¶Dýtl£qø¾$ùLÐ̃c9jFiئ5_m rNKã ©Ù¤­È—£n¥7-šºQïç£Ü0ä|¯QGMè &UÔóZÙ¼ÑF¯•ƒì½\(t䆔V‘ZÖûÔï=ÿå|ÇF­GYµÕ²jwzþÿï;þç—_ççîŸîWû“O÷ñÿ&Éóê{¯ü¼ýÄ4Ÿýá;ýyÛÈûLyë_ðíãŽnãð¥Læ‡qÍG­Z>ÞþÉ}V~~>|ÏÏ=ÿF}ÿ[×¾¶ÏoûsÏ.Æío›Æ™Ÿ·°Úó cåÍtÌ[î|Ë!ýÙsk}ô´¿¿|xÞóÒâÛ²wì5þ&ò—{ÓöþœX†y.Ûg×ω·îfÌû–©œ7¿hã—úï&Îöu.ΩpÆÂkÞ=äí7ò©ü6-ÜÚsìË9Ö×y咱ëÛ~§O7uù Ýtò_÷eµôgž÷·unÒgÖ/ýÎ>>=ãÓoۛg|/þFäƒ<å$1 ϰ¥jžM/Í)ËC£vèï3^M<ÒÉÅ ò ,_Éé˜qY¤þÜ.yÉÉsœæAÁ·÷¿›ç@+²:8]ò§%ÇÑ&°ýùD·£)ä^?ÉADyô6ò`©?·Ty4ÐlòrNǸ‡ ïx«éòìHLò,*Ï`òì|ÒIžú­ì¦yü] ˜:n×hb|íïÑ= ú+X.Iv²Êƒ¯¬IžV]KR5‚<ÄË3¶×ø5Ølbvr$šæ@§ ++¥NÇ3þž2þ†÷ݖ`ùolR}RèòhŸ¥b”Íô÷Å,Å¢¿Óh9»¨i?ô7˜¨mM0xßrþK}}KÒÊRhREšbé¼ÄÿðL°Øÿ¸}Ö/,_ºçÜñ»ˆÿ´ýn0›çÿê]äó¿¢õŸªŸ¿ýšS{ÿ·öç_²‹ø‚Ÿܝóù5õOŸÿ¶‡æí¿jÚîá;~íìö~‰nœ_àWuý¿ºÍmŸ‚Kósï"nÿí}[>ðUû}§Å kVÏÝ0ÅôÎÆÆ—)n÷?¾ìŒ…!–`ˆÿ¿ÿùŸõµÿ嫧± ³qw´e+çò?¨mOc ¾uä ÷ËB!¾cÍX³qówMËÎ]¸½Ç¤úöîY3í˽7­ëõSR%¸f7ñè‹ãfcîoÇ®ñþðY=ƽÚ!þýÖ)~z6®áþVÛäuÆöŸÚ£ÇªÓã§/žæ‘{lzpXæú1ܸf\vñ/œú•ÍÒ1 ++Zf¯¿ñÜ;‡e¶¯sëT³1îÇOñ³sÛöeåø÷+wã¾uj۟ù¥_Û9Žý‚)¾ÿ´íïzE?ßJæ?X;nïõ¿e¾Ï0Æ{ôy+ôØÿö×7÷¸bC_¦:šW k¹V^Çñ“íËòã~ýÚÅï]÷Âïr/ëG÷ÛËlû†éýW«_»½/˾·Ý3§ú;éòcéó‰ä#ÀÿÈnæ#Ÿú7W˜Ïü»*W¾FÆ»Ûmbξê ÉW¿sÌöØ¿ªSTo²†˰c4½—RÊ:¼â±k­Aþœëø+ǯ ÄC.Þ·`Ý=íöÕlY4ˆ_ƒ«£­u²¿rWSÛq ~nýAŠA>,{ ó­GÞ=i'§ÜײǻÚ"´]Ô áM¡Êåڗ,¥mœ~U¥¨‘Õ²î±oz¥>w'%5Â?gísõö©Ê‘®qïBCÝS.eÌ»_eEm?t^›µ÷y§ö§Yû£îƒïóQ‹l2í¢o^ڣ즎̐z\²¾•bÿ¥l¥ÍdíÕ5-&_ã ôMgˆ7Yۏ­Ag­×0p+%ª3hœ@Lzô±ÊQI™híVíA®Ú5.ÏGZbr ++íö—v­ÍZƒtMR4:nC6ƒœ&:¥ ï°®®Z:?Ãòy3äcÙÚâÇã\:®@ný£†¾ëz´Ò¢Iökl€+=b@Î÷¢ÓÈj˜F›a-"Ÿ÷º3Úg¯YçÐÁ&^ZŠ©}SEw*É©-ç·4tiý/Ç*Ÿr:òfcBªñ}6Tu”rðcy8¤ê°ɓÆqNÖ10zß_¥Á˙bŠ”T‹Eæ*Ôêêå¬É:šAŽÅéH!¹I+=3rý¤^Ú²\Öú8í•Æ¡ÐÿÀ3Ábÿÿê“[»|éü0û{åuÛg÷ÿ›Þç˜Âü«JûSלð£Ôúñ²™òäÍæÛ; õOÎöÃ=õM¾dÇ¿kãùSvf~î’ÖGª}G<~Ö½ý}íç¿gÊ'·óøÿ3§Ü`;çÉÛ´›qþ—-É1wnÏ#§™/Ú²£§õúÛÛ– yÈ.Zò½w¿°÷±»Ôû‹¿¾›~û¯O}ÞûxCÏìЏ~û´ì“WŸqǐÓnè‡íóÞkN´{þ`ý_õe)öuÞ<õ%ßøûç=ԗõü-«ç¶ï3®Ó¿d㝽ßÞ¸Þç½nŠ=8÷ŽS~§÷Û»Ú×y̔×휯~ñ²¾lÌcpßô½Ÿ½ë—õ~ûPzÿôú¶½£äue8½Ç%Ԕû:¯šÚËç>¾­µ gbìûùžÝ䑻~*ëM o~ñ»mˆ¸kÊ©0›×톶Ÿ+÷£_?Å~lZxô·zŽ;ô]_5åü›¾éî¾,¹ð®˜–ò‹çýe_Vl?¾÷µ}9R^oß뤞·.Ç!¿Þ£SœÀl¿ý]Óù²á‹ëßÛûß{n”ÕCŒÊÊýïí&ÿܙSÿûlþ¹ ¦ò¹í‹²ï¼1‹cÂeýEWІŒy÷ž‚ø€žoQFbÈî—Åœ}+å’lõ¡™éŒ—”‰›ÆäÏökXDËhçB Sl‹æ}ÌZX¶æ–/QÃD4eÔ<ŽrSZŠ‘4Ú5.…â4úDV ےÿH:ìܚTå!BŠ®äv ïôßÙ’¬ÜÉ}¦—:”¹b4¤ÞBJÍÄhœ&X” H=ö¼‡9UyFð­Zj̒rÙuJ«el£Ñþvïúw¢Ôˆ´J͋7äh,ò­Pä[ûm!:©åÂ3PLb?œ&ÅÔ,ƒzÛ*íU5Iý§žOÑÆ,5¦Y5}·¼4Ó@Ñ< Ú×£ŽÞ—jÖí×dŠ££ü¥-[MÔç5+€|Jª?Hk7šå0™œ5"Cšµ”J‹m"•†'¥¬m%É×´«ßjÿ}Ð$žF ++¾êe&Ò} Ðæäcjå©É¢mÑD¾#û–õtÒøù¸Æ÷´RѸ'-QÙ®4ÔR‡X“™Ü¤)ä¼R|ýÿ|ïãù€g‚Åøÿ͟xà³Ë—ÎÏ}}ŠA>bÇɯêy=Ÿ»zùüökïώ¸ŠSß9oߺ)FýYox~›G0WcVÏÝ7m÷ô…˼çy‹©Ç)ß³$.ú¸>·fiËŸâö×xâƒÃ|Þ6SÑð=iÉ8‹•ò3ê°Öì‚É:@Ƨêt kû¬óöi8¾â)Ë ¸ôùÿº—>ÿ«³ÏÿLÏç¿{ûµçó࢟ÆBëûë^ýì?mÏóƔùa¬úòqøãïåuè·®}mË«/ëç”ׁÇoXxà·úï .ö1ÇGOs؟·ð/îc÷}ècâoæ›ÿù6÷œû.¿¼gú}àü…Ÿ¾¼/“šk˶·e+Ï¿x:ÖÙ1ø[§už»ptÏ#ÓËþ˜)úlîüK§|ç³9ðß?•Õ78åËý7?äãß·-{¼v\{æC='½Æ¡Ÿ9íË Ǿr/ß¿wÑÞãö6ß²©ç²Å¹å§ïmZØ»'ÒäÛ²MÓ1œö¹?°}YN½\ÊTG³cé·ï5nïí=½ÿޒƲîãìuï~îLJßi|ÿޓӼ³ãÞ·Lû9;F}ےeGØÇ¡»–ÀSÞ8Íù.‰5V͸Ðß_)O„<Õ¦dM¨Ög«Ó؛äQRS;/Ï šAžV5B›ðB×éåqUó4Ÿ¿fçÒIí}2>.}_ú ++Qç„(IGýWydÍqՒ|¦¶¹,¢Î¡B´‰3ä¿{>Ù#yŽnÓed3Îa«Û]®§"çÃÒ»œo¤æ6H–§ýÇ÷L´Kruìj~ŽÛÜδ¹$’ajSsD“têM•!oh~M ‘5@ˆ!è;:ŸF¬R±.&©Çì¥ú¢óI³s$-Py²óA!þ€g‚ÅþÿO~é\¾tϹ-Ó|ä—üojñùÅéûSŸð;_tþñ­?߆Uós«¦~äƒþè—Nì}è!ÍÏÕr‹ëÊ^ø–ÿÝût­•÷§8‚cú¡Oý¹nŒ;Ð\ë—ýü?r‘›ù¹c¦Ïÿâk~¸ޅÂÕ­¬VޱèãCVž¯àª¶ìtyýý oüj[–rèñÇNåò™—mèå’Ã0'ÁEëÆýœ¯àž©\fç+¸líØÆfç$(Ó~¾þғz…ɶïàiî<í°·a‡y#öoë¦Å?̏°n<ö·b[ß—JÿÞ=k¿·åÀ âjßÏK§yfçUès ü¤¼ÖuÓêq"f8†÷Mq7›níûÂP}~mƒwݰ¡Ç{„{|ÉAëÆsg6öä²u‹ë\{rÕÚÅeËçxز›y^1­sóÂ1æq(=Fæ‚%Ëþkß^v¡ß¾Ó³±'óÓ¾·pۇúuÊ q7­ËóµüáG†e©¯óý»™áøi{ÿús÷¾´_ËÌp޳ÏâövŽg‘zØÍ| ë§öùï÷é>Y{’›¢µQW§iܣԺ좆`‡¤ÍHcÊ£®©F«¥©Aàò¬¡9쥎ZöwÍÁ.û©µ¢¹åcÒcÔÎaÝ=_A³ÙË=šìe±ÒÌdߌÜú¬s2È]¤Fž×*;à5’ÜTù¢vËQi;•Ý•ó©Hx {÷­‘jÉ«w¶ÒzªT¥¬OÃߥÈê}êHɽ†¦·>i/ßðVqŒ[_.;,ÿÔ§9{–ÔõIÛ«ÕÚjÿŽQC•s•“¢J«疈µJ*%õkL}ÖûJ98§‰í}ÕªÒy´e˛½¶¤¾ôô“VÁÉaèûmÅHËORÕ9é¿dŽ…•æ~¨AóâW­Z;ŽÐxþ ÷öÒ"úsÈ ++ó ++HãÕÈ ¹–Šö_JW÷)¶û¿±ýÖÔb¤åéޜZÃg¥(dõYûò“ FGÈvkØÅœ휓¢oßM­«_ÛX’kŠœÀFÏ[¹Êmª¦Õs´FÏQ©Ï ­ROՒ¥5K]©s+M+ic”}ðrF.YRmþžûÿ×>ð¶ßZ¾t~îšÖwü;ò:ðï;fèÇósWOó±ãù[zŸk­óÃøó äõÞ¯þà­­¾„2?·~ê·Ö_?ïÏz^WÏ=¾dŒÿj?ô[}ŗL1ßÜëœz?rKç“×ïm[8üÃXý¡¿ô‰¶­•û‘{_ªö…ÿþsξ¿÷#ûaŒÿ†¶/¿.¯^yn«¯“™¶e_ŸöóÍ Û?֏7Ça üÔO>Ûÿ|PÛÏmò:cûOíÑûƒÃЇ~Å4Oûg~iã×vîK}bIìò>Ñ'—ô.ï£Ü4Å/œtù±ôøˆl ÿÌZ?sIÚóëÇy˽vÂûœâ.)ØÖÁêLÒg6]5–sÕ¹â’ÓiÔ}ÑîO«1 ®!ÝÕåÎÝjŸ³«¥êÀp¹ ®±Í¦nƒŽA×ìCt¦–$¹Y[Òþ{ÉÝæÆþ࢛·.ÄR´ÇYþÓiŽ5ùŸÎå¨sÄ»Ö×*ÏF1È®htÖðo}ÅÔÞ¥-{(²QG…ç`kJ^;©½±Ú—\Cnýç²9&?ô3O±,É$££ìƒ¾íÇ®šÌ­6D—¢Vž²÷Fö®9B¼Nßúòå)@#GLÍ1Ér)QÙïŲkA®Í6/;§óÆgŸµk¹õb§hÚ|ý˜fÑ(“œ\ºç*¯ìÚ7¯a0ú Õâk’Ó8‚ªÓÚ»êk«ßsµyèkÌZÞÎiÏ´M)k8Ž‘RÕxfƒ°ÙÙvÉ5T§Ö,µÙ»Kqj¦= HðÚ&‚KE!l¹Lے’~­Ä]ě<¥ýê-® É¡„h4¢C¿ÊG—&,5%¾UÃkR‹pÒμÆôhéj®AiTÒªdï¤ùË®hFÀ¤M)J1I‹©Y³´Ê.š¦AsùU­„Þ5u`– ++HQªDö\H2ƶ¤sËs1ÐÿÀ÷>žÿx&XŒÿ͗Êß-_:?·ÿ”_ìˆ'¿ªÇÿkÞ»;Zìú©ò:ðökNí±ò1ÏÏÝ<åTÛ9oß»ÈÛ·G[Ï ò:øwü}/`4oߣS^ºÿôÝ-7[ˆ:Žà-~v|ÁUºê–+ëà{kùSªòþÓüt;çó;¼íÏsuý¯Úï;=ŸŸ•ý,m»Ëç)œŸ;¨½¯1þ‡>ùÐ9íýšËê¹ýÚû+çë{ÿ”+m6_ßí»™£ðšÕã±o¹ó-‡ y÷†ùýX³ø½åy÷.›Êà´|f¿à£íãVMyÍfÇKÜÚÖ¹rN¾žïíÝòzãW~ùwûX ++3Œ—xhšÛð/?ö¦žW0ãmßÓÊ:û¡½ßÙÇD¤!ÿá SÙßph÷ i9úXŠƒÚ±%¯+Ãé÷öe)¹ ++§ñ ³9ùnnß[9ïÞû¦¼‰³ó,ÞØÊlåñ×­/ì±éÁaÙ°ÎKçÇö|É>ç|¶/«eé…+çùëã3ôüxýçÞٗEÛ·wÉÚ±-Íæù»ª¿3^ó˜^Öï˜òÒÍæùÛÒÊeå<=7â;åuâ‡Þxÿ°¬öcØ>íËoܲeÈås¯÷£§y+gsî1µùï¬;yaÈ×7ŒM¹}j³¹üÎlmé|=W>pÎ׆\~Ãñݱϸη¾¸Ïõé²1½Mì?•Ëæ…Cú8™ì}_v@[¶I^'|ùèwö<Ñôý¼~ڗ ¼úùmYϱ‹§öùýlëåRïõpǒù'—½¹g79çú|ÿ-G?ܗµ)XvÊý8;ßåõ»œïR¾7µëåùï-¦åƒ’?U¶«©¿Š 1õ\H×èmÒð_SNÚlÿÉcrs‘?3.g¯yÝ4Ǩ|Ö¶Œ^Aþˆ&cRŒˆl5€µêlÌøª©Ö|LÿH¹®ä/VJŒ[dÃüROU~º1÷Ôâ|Ù5iØ­¬@ùaÛOќT»™ûKÊT ^›I*ÒBì.òuí*œüÕÐL½©ºÐó±Õ¾ïäÆFƒ¨Ëbγžs®ÊÁ„ ³qI5—¢i挦2‹)§jjÕtr:5·†ek=ij²E wÖ,}RFºÇÚ5ќ4Y9t©°$ßÝJ9Àv•»PZ„‰²™´B.±¥yö–æÔ«Ç<»\JÏÓVª/Öç$g‡ Áš¢‘áÒ‹´Ù´Üôfٌ¶y«é䂯Æù”üïRå %jÿ×ÃnaÓQSÈ9›«®A ++F*U•K­^g&×Xpk´˜e—CÍkPþ?O<øÎ¹Û¤‚t2öZ’†ÏK㔶h¤š5³žÎîu¦x)ZYƒ”Z‘k†4÷"/'¶×Øl£ %¥ªtƒRµòÇ;›X嬩šUNn¸ôl–Vœc+h¹˜Èê[Öí+'uÔÀhÊA• :MÜhÛ9]ô¦,i‚¿˜’^R²ßMî»§l®øVNr­¶®%)ÔázéÜ].IY\›’ ·}^šc° åbï8­sN½jIA¯5¬íLsq“–äéÔèû¤—bM5¨×֙¹õü4riÑ´šÞO+@Z‡\þK•Ó2ëp9/¤Î¥\MЙ奴Υ(ôÒèô —f´t¬æ˜,òi¦zÉI®æšë°è•H¾P4ã¥1:úDêVþ´ki©zñ•æ wr!ÈòÇDZ†×²’F(g¸^{ƒ6$i7š6R.¨:‘¢œ"RÒºÛQ/½QDŽÈI¨c´½µ ¡—ö¨C ++ª´<ùc×Ï¥”ät֓T3GÊß?Œµ©²®tÿ=û†× ãùWÍ/™ÏïˆþDóîâüÜí}Ípèí×¼¾}>Dy6¾uvüÿ×§q½‡ïwöñÿÆÏÏݺ׸ÝÃÿó³Ú8áTL˜ŸÛ·}~vœÿ5m?ÒõÿñÜÞæ´5ÏϽb«»t>Âùa²nä—þÐÇÛ8dý«¦q¸‡î0›ÛûÉäÕs÷LûsÖü‡‡ù‡qîONsΎñß:•ßìÿG§ygç=þ’)§Àæ[6 ß+C¹<ã?ãÑøÃøøáØ?5Õûæ…ÿúÂ>Î݅ÞΔãâo}ó_÷qî6ô6qt[çµò:þ‹Ÿüh_–‡:Ú£Õ߯Èë¸ûnúà0–}XöøšñØgDz?¾vlKÿjõk·÷qçyso¦ý¶:ÚO*\k\>Ý&±«šCÚ@”:”-Ã~>]çlõ^5û„“²ÍšxÀÛ°d™|XJWÓµ¶’KÎNî(C*EÛ¹ìuƒŽZ:¥h:§é 4«ˆ´y©J=í’ìžæЄšŽ¤_r$+äºè瞴âªÉ+¤Asìe§Ù#b:ýÜX¦Ëæ[œ¾ÿ]˜ÿàé<¿^тÐTaí!ë’]ˆcΖ¨é+4ùJË·¤ñ é+äºØŸ}·CŒ¡]H“ìeÖsZνzØ¢Y¤L´•`‡:×Ó¾½ò¡Ðڅ¦ (Úú¥½}"šò$HEúÿxFXìÿ¿êûß»cùÒù¹W´>Bí[<âÛG|{Èsæç˜r±¿ð-‡»÷Z;?wéÔÏ|È7ìïZ¿½µSžÿÙþü¦~Æu¯~öŸêûј2?wÇ´þóßöÒo´÷wóC¿ùåò:öÞþ¡çùw²þÛ֍ëyãkäÏz>§àúûóWϙöùÖϼðÀoõ~{{_ù“Óº¾uýŸéËòЗ¦œÛ³9ýo]7ãù çöûšà±-›oǯ}Ðß:ò„ž×^mË^±÷¸³ýý÷/Yç×ÖöeeèK¾yZ6 ð©vÜ+Ç\Úúo5ïû=°þ¯ú²ûöž·×x|o}喯 ±CÌÂÕmÙÊýýûMýö[yÕ÷ óA ùÛ÷æ,8wáhߗ%Óûí¯˜â'¶Ü{Óº¾¬ ó'Û¾·Ÿ¼Îù뿲/«CøüTG7}dS¯£bS/ÏõmÙÊslŸÚólNÿÇWûyúÂå?ޗÅÔë}ßVžÚW~üÝ'óÔan…‹§8Ù¹®[7Öûl¾ÿc[½¯œïÿSSݞ±°åÀ{àj/³ÞǾrNÿ'֌u;›ÓÿÌé\{ë‘çÜÝã òGÿê)d67ÿÁSÝnZxô·†Üü±ooßéøþæ£oêëLyˆ‘xbõXÖ³q [Ú±¯—°~:îyîÆG{þ}û:/"¾þÿô?чiSñ!•–SÞyÓúϵ=ǜÜnrӗtîZ³üwJ©õùÒûë‚IV;㵸jožvV…à­Ñ¹´/Oþ~'¹Î;oµ«¾uÀÊuÛn¾´çÜUî ê^³m—Ôá˒ÒÖuöÍ|í5Ͷzz«i¹á“uT çSxzäwú|֝·AJOoh¥ìZùÊåNB{q5ìÒh/¡k©Ò]+ƒu†§9ÂKÒcÔ? 6‚’½–¢]â.:ͅ/ÛÕÒ´:G†öØJ %íÝv½ÎåZÿu‘»Vú¨¹ý[ËʁæUC̆΄àZߦVš†(Z훵:Àª§t^ŠåùäwêÃÖ<ñ-NÃklƒûÁw;o„æB>#ØBbR.Eçü¨Þ¶V¤¡%-¾ ö}øÇ˜Ëc§yO\‘Rˆ~ìÃÕÙ ++ôˆ%öF«TKՓQ¶-Ýtÿß²«Å`ä 9Xç«ì¹Î£+òQZ4‡^ô`dó²ë:…FEHûQ[kóÙhĄŠèÜ ÒîõÊ©3`èù¯q5ÒþêXÎKçõXOð¿·Eÿ?Ï‹ýÿ[Ozë~˗Îý‚:nÿÀÛ¯9uè×Í«çÞÑÞ_¹|K[¦ã˜·>öœO ý˾/»d§ý›eë0?x̽?ôâ)wÀƅW}dè/æbÏ4×üò¾DžZΆXkôQ\ 1 Ia—Æ¡ì*&ËÉrÖÜæS‹¦Fãrõ.j H)VCP¼­Y3txÍ)P“-Ç@°š-Àý¤oQNsȺéÿà™`±ÿï8ë˗ÎÏÝÖúÝu<ø_wØoãm}šòäküÃ;ÜÑÆó{ÍÛG»;;>ÿýíýåyûWÏÝ°ÏøþY÷|U3oì06|Úö©¿½ía<ý0–ùж>?Øÿ Ó¾ÔÇÅËÿµe—¶e+µ?|Êã?;žþþ)¦á“WŸqG[pØd3IžÍŸßsÝkY\øÃg=<䥯·4ñžw8ª-;R^oßë¤>V;ÇaÜøÅ»ŒwX=w]ûž¼ÞðÈ«ŸßÇGs\¿$†âºž'¾ºÜ—]3Å^Üòc?·ÐÇNã÷š¶wÒåÇ>ÒçsÈmü€gŽ%ýÔ«V˜Àkb…5e½oYb 9&Mô 4%Fj%lÉE“wd낳¥Ž9–å]Ðôrusèèö–ò£åЍ%y~1¹ts:<ÍòŒhýR®¥M€á†9NvÕ×/ۓr+Å·î{MèfzÍh1Íß¡ÓsSœÏe̱P不Né¢ ¸d÷õa¸åŐ2Òåòyz–Õj¼–)ýÿ<,öÿ¯þý««–/Ÿ;vêÿÝÛè[?¿‹~ìçïùüí얟¿D7?·­}þWåuØã¯þ\ëç.ùÿ5'ÀŸÕúä5­â˜ËüyüÂ͟íùô͐W}[ÛÆ òÚr÷“=ÿ»C^ü»vÓÇ¿~Š˜Ía×nrØooë'{¬ó6d§óÈWªîi5ÖHyÙ½ì´ß:iáëd—[œ´«‡<¦•1ÿJ1)x_rÒ©JυïƒN.!ÿåŠvågy`«Þ)h)T©n$èD ACª«rزËò¹©}Èg²Ö^•úÀÚêÄD»»¹#L”‡¸¬iL«WRD㳓×OW§BJ\çÐx©÷¬Sd’´ÐeÅÚç¯3$è±êAÉóµÕø‡’C։ªÔ§—– U¬s +ߒ’ŒYkÑIIZ;”½¦ÿ€g†ÅþÿßøÒÏܲ|éžsïÑ.ï6ÖüòƒâMÚל‹[5?wÌ4Wú;ö;³y¯~~îð©¿û°?ùôëZß´Iu~îÖöyGàÐÛ¯y}{?Ä8?wc[¿ö¹¿àÛÇÝâ¬æ ¸¸Í+®+;ÿm/ýF{ßy7?wl[ö}o=åÐþ~ôòùG׌Ÿÿ็}»½Ÿ¢¾?õ±/;˜Ÿ; }^ǻ߾ùà¿íÇ¥ûY¦õüäYG´¼:ÙäüÜQí¸®×²8éûÿ¼½‹]=wɔ×à¬/ø÷y¬ëq[§Ø‰ÜpwmuèߟÊ%վ/K®Ç¬oû 1 ++'ØmÛû²Rû²æÇpþÇ{N„P{\ÀºÕ㾜}×oéËÒ0Oû~m_VŽ¥8sÝX¦§å3{þ‡Œ+¦˜ˆóqfˆ³ös¿iî÷ÙŒ‡¦<ÛÿÀKÁ÷<OL¹~ïÀ3z¹D—zN„÷Ϗû2»ñõVï–׿ò˿ۖ%3Änô| äuå»Nþ˾¬æŸ1¿v,Ï٘USþ‰-÷Þ´®/+©çY8¨ßsåuá¿6äuH=¯Ã«ÇcÿÜÇ·}¡Åg˜ûñÝ1åR{lêñ rðC~†©þN_¸üÇû²˜ú~^Ö¶÷+ò:þî÷èËêPO®ÏÃͼîW†ØÓÛÒS;;íòs>חۏï˜5ã²SÚöÅ·b‡un_;.ûèª7~¦/+Ãñ]Ֆý¤¼ÖuÓê1-Æöº=~Íx ›ú`_æã°Ÿk—ÝzS_B_ç+¦v6'cVe¶ù–M=OF¡Çå¬'sÙTž^÷ž'Ùþ½-m›´ÝùèwöeqX¶~ÝXž³94ÚÛ­MüëÏÝûÒ_c†óhÿ½ÆëÿßóØ!‡F,ýØ];.ûW«_»½/Ë>òGØ­1²ö¦h7ÐnúP¦ù¾+YûQl¬Á¥]ÿ‚ǨÓ4‡jmՙҵë¨' Œü=ðE.îUVkb֎0Mɬ30·à¹6·rÖ®$SdQƜêTÑr†ËߒC›ÿ\ç˜.I{‰ª­9ÇÅý×?Gòç?y*GêÐWçª- Ú˜b,:Æ´˜štú,»Vk‘ÑôÎ9ÄÖǵCÐè0Í6ßµÎnZ¡ö:ÉÞùªs§‡q<¨,ÑyÕå`µ_²u[9U*—åd5ߐ-ú®vÔI éŒñZ2¾f[ŠWgܖ[ £}>:)Ú0ÎG^L–5¦èrÒ¾(ãǹ¿“öd:;g•/ÃþH$Y…ÎE/Û¼OÚI)[ Z_:zØÉë¡TYjdsr˜Ùfíg5ÑÈÛµX-›6}¶ :Ì×ù¬ƒråÃ聹ùj]†¾M(/´gOê&ç*U$ë EêØH!_¦}”tŇáߚ<[v.•§óëÿóÍKñ”ØÆ G§%Tüb›YŠÒèä,nÕÊc²}ÖYÒ[³Ñ[=Ví®ozé8mY­4&)΢5bûO½î‹Çv?ç]÷mÚtíJ]5å–êքêÒ‡ú‘†§#Õu‡´?Yn¸µ5jDzvΖ\³œ¬I{•¦i×!×^k¶´+PËãžäÜÒÓ[.Ú֌–´ÓsGږ&ê’ßHrÉè.HÕë1Ø(›ŠVËÄk:xiX²NÙ))vY“šÖJÕSįç³^}N¾‚´Éš¥™KÕH5Zm>KÕIý;í׋–žEE¯ËҖåúRäb#W¹¤©ì5U›žØrI1U]ƒ\Ìl듗­Ê1{½ë­ª´niÿ²>Ù¼ž­É÷¥^åþPjt(O95t'´ ² ´Nxmé¾Èi?¹|CŽKC&ä‚î]Õ˟^qж))?¹“Å^¯'íïˆn!Ë:åïG]õ”Å)HÛI¾å'ëw»əáôZëÚ~Ik–š–K±´cýÛ"-@þðÉ &×ÂÖF´…KkLr68@ ++^.†5ÊõY®FR\;VÝߪ§\Ò Ö,ùû´<΅þ¾÷ñüÀ3ÁbüÿÿçûÎùÙåKççöo±Åï•×mŸÝÿoúu)Ìϕ“;;/à+ÆÛ¯ž[?å :Å6¿þá·Ì÷ò-¦ÇŸo_2—ßòØæ}Û²•㗏ŸÊ츅ƒ>ÒÇ`Xßc°ãò[8úÀ£ìZ¬#´Øu›“ŽÏÑ8úÿÁ|sÓ<¡xy¯VM¤‹Œˆ)÷15ÉĜjI1xêN×s±:`ÉVJjS®:I‡!hšC½fËËI#ä5_omðƗjLѱH:NÊË3ŽkСIÑÊUöÏÖ1þ½˜R5Ñ¢l z¿âø®çÌIGèÚkÖÁ6VŸÀ’•'Pu¤R,Ÿ ŸÓÁr¤Æêà¨ƒXbM:ìš$‡³ó%kzG9Ú¢#›RЁGÎe9y<‹ò¾‘G1Ùz‡Ñª $½Ñq+:<ª×sR–ì‡cÙÕ8´•rYNy½‘oeár¦ÿ€ï}<ÿÀó?ø^°8þÿþMë¿ÔüÜ{Ú|W7ÈëàoÜñ÷:^<˜œæ‡±÷³óöõñå:gځ¯Úï;mžçÛú¶lOyýü ›úÿhúœh7¶í¬ÕŽa_y]øo»»- Ùôcÿú>ãñ}æ—6~mXû²÷OusÆ£?ð/Ú²X†\÷ï3®ó”_<ï/Û²TlßÏçM¹!6<òêç÷¦˜¶ì¢i{÷åGø÷{»Ðó#Ä8áþYŒó‘—ܦ!×±öÑ%[tª÷j½‹!8Ÿäf.ê|ïEÇç›jC)Æ;׆«GŸÝGoœË^ž b0rÃlƒsA§‘—å6Æ\5y—Žì—¯Çt.9_³|-Ö*ŸÕëÕè\ó>:ínKß¿¥óÀ÷ñì1Ւ‹Ñ1íUg£÷zÃì²ÎRoru: »lA¶Vä(¼ÓtcÎYKŠš·«Ês€ó9É65‘A¬9¹*Ï:V³ ”ä©D6Wœfð:¦ÞˇÕñâ²é¼)!»Ú†•[×ÇÃ;£3Í»¢;KÇyûÚò%xgõA§å¨Æ:]풲75µuHÉë÷8ä%°1I!Dcsÿw¬A‡þg«à¼OÙe#Ç´LN}vE;tÂz#åⳕG/{gäí*ÅáuÆ{#ÅŠ”´”‚Ñ4RÃZy%-)yÛkeJń"5[‚”¨¬)‡’åûFVïË0ϽŽ™o¹!´P£Žœw)µ|FsEhÑj–ٌԵ R[F ++8ëØ|M+!ÏNÓ6H{сüVëL CѼº{±j5ÊÿɳVk²¤´uEi‰ZÕÙE3d ¨Fž¦ °ÉÉQF7짬´ #¥%ږV‡4ã1g@ÁÈáëKÎý=)Ò,û["¹]äšÈR*²£IsvÕÏéI5Ô³´y9\i°µø–¯¡Ê¾Ê™æÓ²çÿ“®;ü%³Ïÿ=ÏܳõY÷â#¾ÑŸŸ½ŸŸÛ¾f|&=è~éÄþ,ä¹ýø5ãs× Þ|Èý9ÖÊçׯ^ù÷‚£ÖŽÏ…kNøÑ?jÏiÙØù¹ëÛsílÞÁ‹÷÷çáîhï{}ÿæ5ãóóºW?ûO[>BcÊüÜû¦çÀóßöÒ¶ÿrb¹ù¹«ÛûÏÑgñSíïK3žŸÛoÝÊ¿G½f|æɎ÷ùö~vf~î˜i»ÏzÃóÿ¸ýQ¼¿eõâïW´gèb^=wۚñ™ü?¶±ç:”JíÏò÷LËfó ¾gï]ÿæ°ßÚñ9øg¾è…ý7cú³üÖ½§ßî|Ë!òáÙú̶=ÍáxÞ#ÎôeÒÛ²£¦çõoy½òП­¯˜žÉ¿¹×9ôe9ôïm~ÇØÿÃúï-Á¿5•á¶…Ã?ЗÉ5£-Ûcí¸Îßÿ¦‡eÃï-Wµ²|§þðëÿjøÝ$öí]3åkü½Ïhå,WåԏýÒÕc¿õ•[¾Ò—¥¡ÌßgüÍáüÏßgXV{Yß0Õ©Éð[ŒüÁèë¼f7ù(Ýg¬¿Ï¼lC¯?)–^·OLÇ~îÂѾ/K¦ÿ.t|;v͹þ_ß3ʵö2Û:Ə¼¹Cé׿ÕsLÛ»èúÓûöJ¿.¬ž;xíxž\øÃgõü—ÕÛ;x͸½í¿áȲԗÝ:íç›Öøá÷$׏áê}vý[Ó¥»ÉùþÕcy^²Ï9Ÿrc–^ÖÛ§örá‡Îiç›\a‡ý¼ڗ3¿©/ C{9~º\ü §~¥/“?Z½½ì³ø½×¼»/+C^Ðþœû¦xÞc=gêýÉ©Þgót^±÷XwݰáÁ÷ºdú½ìo>ú¦þ{YÊÃ÷¶¶z¸V^Çñ“mËJÚË]m_4gèq÷ÝôÁñ÷«¾ìŽi_>Õ[¿Ô—ùØë}Ëôûãq ׬í¿mÉ ·•ÀÓáÙfù=t/·œTz5•Ç“`b¿‡—üv™m¨-O•ÞÄõœgQó†¹"ë’Ë^֛N«_ӎ”ŒÕ;}Y«\IåqIn-åöZŸ|\KÁåÚ½«<óhÆà$ë*IïMÛ}¼f‹òšV*ÊeXSbé#€|Cî™õ.XïN“f“û’¤Ù­Z.3¹Ë–ǩԡôÁ"ËWÆcë÷«²7í^V›ô7úáY#ʟj'KEsŸéƒ‰>¥É]†õEþKŸäiJî\Õ§$¹ù–;媏u©¥“ç }6 ²sFüú½q ++íþVnj¶/B/·ê’ló‚Üü›¬¹Ä’YR'S7)Q¹Ö×0ԟæ? qÃ}LüÊqægNyfÇçß<-›¿`ÚÞìØýmS ólŒöû֍ߛ§¾zŠEþæ§|¹/ó¡ÇE÷xx)>þî÷b­mßÏ ¦ýœÃ~ÏTž›xݯŒqؽ6LߛÑÞ:-ûΑÛú:}ò+¼cC0}ü4.㢛Nþ뾬–û|õ4æäo}s_V¤&z¹´u¾Y^gl·×õenhïXŒAÿâú÷öe=ÎJÚËnr °›<gî5ßlö†i Ák¶?¶gÃ:ìÿ vïۘv«Ã ‚Ü\[â]îÿ;É=®†fy#'xÝT§QÓ€.7Ç žŠ¼Ÿt€…³m0zÖ1Æz#‰Yc§5S@ÐÑQGŠX£ñÖ:b!—àt܍ÆÇWoëû]ƒœÔÑâòì3ÆêG[冴Œc)Æñ(ãø”•ÆpËZ£3£®#QVÍäpµ„¨3»ç¬Ù ¼Ç©è˜MÒ¡ : åi4^hŒ9Ç¢K y³d\“®_nÏs°qʹ íR­©hyŚõÖÞ´2Õ*:XŖІb¸ÆIÊÁ¥6”FJCCðuX‰¼¡û®ƒM¤RõÈBÐwtüK¬Rà.¦Pe¿j²QچŽdÑæ¢Ã;|Èe7ã÷5傔ý°ßÙiéj©JËê½Z—´lÛ±ëÞìf Ñòq²R/ڊ¼oÙ+’Æÿ{©DŒ´àÚÆáøTµAkº¢'‹‘útEGzÈŠÓÜYOÊÔkݦÐv¯¿œ9&é€XúÿøÞÇó?Ï‹ñÿ‡ü›~iùÒù¹{¦\Ú/ÝñÉWõøçPWóí­ÿõÝä‡hÊYþ›e˜“Nƒ;¨þ—s¢,C‘Š 3ó ,}þÿÚ}þ¿­=¯ëXóƒï=ìÛm<ªeõܧv3nÿþÅeö¥þüo}O}ã´ló‹6öe:±ÂªÅyîõ7…Ó¶¿ëÃüñüdMû±þÀæoóëð=öLsÈΘ–Âæ`ê’Ü)¸ÜòWجSR“‡¹Rmmù'tbѬok’ M FÿÀ3Ábÿÿ–ì%˗î9w{û}@sª¿gßðºÿïªù¹=ZÞwpϓ_Õûÿ½Ÿ»¬½ª¼¼ýšS{¾û˜çç¶·÷U^‡=þê–C>—æçn^;®çЧ^ß/Ù×Õs·þþËäµùC'|v_`{^ùMí;+ç÷¿fí¸¿gßõÅ[Ú2—b=x¼‹æyÿ™‡/zaK0¦Y¸µ-Ó¸„O^}Æ=÷¿K=}ŸAÇ3œøþ7=8,«}Ùû֎ëÜúØs>1Ìàû~nk¹øM^¿ÿœ³ïïeá‡uÞ?•ë¹wœò;mYqµ‘˜oÛÛ¶JsÜÿԐÃ? ûùžµã~ÎæðŸoËN”×Iûk†<ýÃ[֎Çð™_Úøµ¶,äØ÷墶lå|û{´ü÷+çÛÿTûÞµò:þ‹Ÿüh_–‡ãëóè<ÇÝwÓǜúÃö¦¶sÜÂyïí˪%o>øŸÕr‹'¯}bAþ‡‹&'—jòÆ»js’{P/÷4yÈ·-·ªÅjpãMÐÁ§­ÿÌ{¹{q5é2Sõr#g‹ü—+¥—冩Êç]Ötï^×grÐdîASµWWM¶r[˜5wwÏÅ>æ|o‹4™w÷iå|îcnt'««=Éxˆ¥çw9kBpSä ːw¼å¯UnFå‹ÉÙèB IöS6Ւ¡Ë[^S GM{_B°)Doå])+¢yÍkj‰ôåf·È‡’¬-ù°)š(=E=tM|oM”;T¹ÍÎéù~ÔÂ2!„*[¬zÿ¯;Œf—;֔4k»Ü ç1¾•gÙ#ل)Iþ?XÝo)mÍbl.º8ê$Xº §Yû«&A—’–rÒüø®˜Tõî;Ä,å&Å$Ñ=-R¦F« ÖuÓAŽY×ìC”Ê,IF.AC‹NP¥>róøÿ“å[o¹ì}•ÇŽV‚²R¾º)d5V«ù÷ƒæó¯N ++ªÆ"%(GWuŸ49—«´2igRšIZPÖ¶\¥¡JyÚ(ÿ'õ%krZÌ®¤$mU>­ÈI¡Õœä3A÷¶¤Åvä´ÊdÒàŠX’ÿ”4·¿“Ô9œ4-fƒTG”H$í–”vä¢Nƒ ‡+E³Î‰¤èdƒEššœO²i)Ãöt¦ƒ$û]‡¶ï¤±d©|«1ßµxÙT0:CÖ"ÕöQŠ´ü$T³–Œì› UõÇ ç‰œÌ)º¢Ÿ”¢3YJQŽy<ߣ¬2ëé¤E,å&MÇi h½fÝ/+-JÛ»lC¾ŸåÀœÖrLQçôª^ÛCÖ³G' ˆU/ò|h5‡‘*ГBÃtfYµ®Iš²|KšIÌr(!ËE@ÊXôëM›GA?ª,u,Õ*Ç®e¤Œ‹œÎÒ(¥ž²T¯Ô|rmÇ¢nBªCۤԖ´¬•ÕÚ»4aHÁʞ§hжåhbÐÀ©-2]‘Ñ ZѪ¥ÿ€g‚ÅþÿÿçUwÚò¥ós—Lãîÿâ¸Ãþ{ë«õ)Î/ÿÿ»·ÿÐëûÁE??wÇ4§ýÃ;ÜÑÞ÷9Íã÷Ÿ+¯_µßwôýj¬Y=wõ´žÿ녧ÿ·Ön}îýË=€ö‘o¹ó-‡ ýõÜí·Mߛí¯ß·-[¹ÿü}SnÂO¼ë5 ù ùà™åŸ8¢ùŒ)©8—rh‘#Ø} o©uŠWrф?R²9Åâc{fÕ÷ª‰vI ”«1:YA–•kˆ‹ãçd%`  Eÿ‘,ãÿxàùžÿÀ÷‚ÅñÿW¿}ÏÿcùÒù¹çµ<îï•×mŸÝÿoÚXúœÂüÜm½æpéŽO¾jG_燱÷:.ÿ_óßæ Èósëößß9_À±ëÆõ¼dÇÏÝÙæˆÎÎÏí·×øþ¡;Ìæ–/ ™¼zn~zÿü…ó?Þóû‡!ÿmû,.ûéËû²ZzNý[§eÛýHÏ`}Ïq[[çòúèËOí9bH=oþ×Ûþiނíyómµ©´e×´ïé<ß|Ñ0Aõa˜£ }ïÿ”×IöÎVn¦ó\ß¾§9›ò¸ž×àži?O_¸üÇû²˜ú÷.iyó5§þñwŸ8ä5¨¶ïgÏ©¿ò¼ÛÛ:÷•×ëo<÷Î>/@´=Â}S}}çÈmý{> ǰaïñø~ã–- }΀˜{Y?>í禅½Û\ ++.:׿wôºñ{¿Y¶öïŘûönoßÓœ¶ý]¯èËÊPžgî=îç)¿xÞ_¶e©Ø^Ïkß[y®ã׍ëÜðÈ«Ÿß–Õ1OÄÓ\®ëûY]î˞œŽá¸…Û>4ÌQ€ÝjùómóÈ[ ÁÕ6G¹Ó)»lєö^'%O!U«iÉ«IÞÉ }ÊÉW­Î`|r%yÍÄn5Á}vQî6]°Ég#·²En»½ÕÐmÑé äî]g>!—”‚N)Pä_š¢ßɺ]©U‡qÛ*kpIn½]ðmlµ¬Yîà£KV‡Ië´qÚ÷a,uÏŸå°²fh·5ëˆnëŠ3IÜι1-ÅÈÊMvš-Þ;cK•Õª 㓦õ·&Õ$·¾Î—,‡%;X4±»•rÈ:è;¯3 DyßxÙME¦ñ«–—‹²Eـd۟lLÛ-.-£’Î"a‡1â.hÎ|)9ٓeOdÃ)÷ù’‰9ՒbâÕ½Ð9Ù䬦Í>JgÙQ͆ïuyk£×,ù9µ¬òNžjä`¤‚—=®Æ-• ó!È}¶¼¢Na卪³ƒµyéeۜõ.%Y}-Þe;Îs!ÿô`´È4s}ñm*Šþ¿¥¤­NÕ`ä --_Ü¹KAêÄÎz"¦A'·Ð†fjÖQùÙXoä#R~:tß&+mÆI™F²CËiÖþ\4e~Ò©-r•r炐fÃwÙ¼ã+êÙaL;÷ú¼(Ù÷r6Iϋ Ð~Éçwzþ?ç?õ¾Ùçÿkv1ÏßúöÌ5;Ïß%Sþ¿#¾}Ä·‡çÐ0?·uÊåw؟|ºÏ#('ÇüÜkV~þïϐú ü“gÑòjÎóß-ÿ]`~Ÿ:ß¡O>tN{¿æ²znöù•ç¼kÊmxêoo{ ÿ^àj_vÙ4?ßì<‚MËfóöy’×Å/ßô™¾,˜¾lë^ãöNËg>ܗÅáùý†5ãñÎÎ1x}+‹wÊëž?XÿWÃqx.Þ{׿]ì7Õݹ Gû^GÉôgí+Z¹|T^g~æ“qX6üÎpÏÞãñÍÎMøè>c9ŸóÕ/^֗•ØG¹cÚÞ ¯ywÿ¡˜¾ìÑé÷‰Ó.?çsÃ2;ü–°÷ø˦xÞcý7ˆ8ÔÃñ{-þÎðÐûorÁjË®\3–ç]7lxpç9 oÝ{׿3|jÚÏÍ ‡¼¸ÿ¦å}?¾žòHy½}¯“îïËâð;J™êï ÙðåažÄáØïZò;Ãë>0̓hú¾¬këÜ$¯¾|tÿ-Hç²iËÖï5–õ†/®o_&—ž¶ìÒ]ΡÀwÙ³âª]ä±Zi~»6WWöò(e5I–Ü,—U+Í&·ÔòŒ¥“pùPå®;ésŠ<éí¹Ü¨'[¬>È ++äRîçå¾\Ö vò ðt™‹kœ‡MžÜŒ¦ «ºQ90yô:MœÜJyömÝHV7²ÜÌËcQ·)·Eã3SÒçA}rYõ”Ïå&{«Ù²+¡èc£>ÃI=I™Y}|’-˓_Ež9¥6¬>¸Ú¢u­ùÙ¢<ê_OwLžå¨¬>Èٕ(÷÷µ´¶ |z@ú ‚fٖD|œ“1ËÓ¦Ñ{dËëÇ䇱‡Oñé›ý­ƒn‡~ÿ2Å0l¼û¹ï}µÁ€ï»aKÙi¤¼ F#D’“3Ŧl¼7%ÛlBŠ&¯ê¾Sk֎{ùXИ€¨áì6£NÒn´w?k¨~Jɖ”Z`{lq#I»Ä£ÑIêª :LÄø\\Š&P5œ"µ9í\ ++Æ»Ô\ÚØŒä\ ʼnrN¾×H«1 I¾œ“­:+^”£©Ök<‰¼†ýt¨EÎI¶S‹lÃD •7֚o¤Á =F©­!¹·JlQûRC Sû¬l,ZïÇÃèC©­%¤žnãJèÿà{Ïÿðü¾,Žÿߝw°|éüܪ)¯ùKwìû†–ƒ¼Úo`ׯyÖÿËã¿Üs Ԛ۲+÷óõ—žÔç²Ó”°mYŸsàuòÚqí™õœö6ôÜô«¦r˜ÍM¿Ç´ŸÇ-ô‘ž×ݒGÀ?ª6½c£·ÃÓ8uS-Y³Õ›6ï†Î¡sek“«NQCÔ¹ëJ›þBÓ°9W¼ÑÄô:4]Vé|֙ðtB¿XsÒ)’ÕÙöJ:=G­E'ÍȚ ++@g<VÇô˦sð¦„ìjúo]òxÙ®N9°jÈßoS²FðkÿL¡ê‚¾È¾è$yÅ9_Š—C±:y¸N^!k5eùO'ÍÐÿLÆ/™óqsŒ$£Ó&$ïJÕB-Ã<%ɕ6£ì„ÎþWMÕꌓCŽ€tò†6“HÎí;±J”6×DL²,e—5 Bв6:»ˆ—‡dWt>otp¾—”ÇEïŒfb³:A›âÐhÞ/%md±•c‘½O%­ y[þSQ§5/G«ÓòîsÐÙCŒ‘Õû2ÌÓ±ÓóÿÑ_ùÿ~röùÿ‚]Ìó·mÝÊ¿ ÜܞmO–×å ‡ýmû]@~~îÖi·ÃwüÚÙíwÝü’Üœö£;úó«çžæžÿ/;£ç´Rlíùùâ½výœÝô¼þͽÎésúÉ¡÷ßnkß;]^ÿÚsJ±´e7ï5þÞà_²ñÎ~œÆõyØö›ò¾íÜ~Yš}[vÙ4ÏÜÖG^õ}Cù sÞÓ¾w½¼^^6Þ7̱çz»Zù­œ×ðöuã¾Üô‘a{Ŧ~|—´ýÄÙyô¶í5.ÛðÈ«Ÿß–ÕqÄ÷M¹¿ÿ€m}½*m–K0À3éÙó©žPg'|:瑳òt'ÏÔÓ´|éžs[[¯Îy÷ž}ÃëZ?¿ «æç¶¯Ö÷µþˆ'¿ªõCoççnX;¾ÿÒŸ|Umu~îØö;ƒÆzû5¯oï‡çç>µ‹q=.àDy½àÛÇÝ⬓÷jŸŸ_ðÄÞãûß{Ø·Ûø‚TËüܙS¬ÀKvü»Ï·÷³3ósëÚûÚ?}à«öû޾_•÷7´ýߨûù­k_ÛÞwѯž»ª­_ûä÷¿öŒÞ'oŒúÖ׌etÖü‡û2ëzßú†)®`ÓÇ6ÜݗåaÞÃ+Ú1ê\‰'¿póg{Œƒ±}üÀÅÓø _tþƒ}™-ý{Me|ÞÂ_¼¸/ó¡ÇÜöe帉k¦²;õ··=0ÄMÔ¾ìKÆN,±ï4Fãg¾è…=¦Â˜pcûޏë1üî=Ž!ØÚ—4•ñÿ„Gú²{¬Âüš±\ÌÕC¼EҖ¥Ë>ՖéßÎÙ÷ñ©ïËá-6båx‹»ÚöVŽ·Øw͸/³sE¾gjã?{ׅ/ëËBéËZ=¶ÏÙñWMu{á‡ÎùÜ0þÃôeOLçÇ ¯yw_V†ý÷¦æ=³•Ùµò:þ‹Ÿüh_–‡ör̺ñ{ï¿å臇ëQîutÇÚ±+íˆÜÍ\`cÿŸÜ=Y[cÚµšúºäO~ÑÿÖÎ\ ?M®õÕ&oÃ0˜—íÆ(+.ú®¬ÚÔCÛH’õd¬Vù¬vöio’? ++θÆ8eí·ÔKë½F"ç<İZ¯½…¾gJ’ÿ¶¤3Iû’m.­3Ñj§¥Üë¸"ÛÓ.U_´+Ôù#©—«ìi•?ÂÚÓ[«|¤Tç‹ü¥—ý”?é%ʝ‹¬P{5¦Rv­Ê®$MãuÊ/W³Ü¹¦`ú~yÒË%Y—órƒâL0­ƒ¶&#»¡ÁÐ:=š R’úŽ·2-Ç ;ªÜïT)0ç“FZ§â¬Y»ÀËbÝÙ!9(ÙQ–¢ñ½ŸV»ˆ]•ïë1ù>?õð)Ü*w`Z¾•ÔAÖðm§ý·¡ø Áݺ[EV«ÎM&¥XêÐߺSm•Ò‘rôCð:ó›Ö»H)m¾³¾?Uª¦j89  oË |­Œ¼åµ8bÐHê´Ó^»oåžÞYc–j«)Éÿh½ïò¡$kËRlÅh I;•Ö"­¨Êµ}¤6#[m}À.:x.„Pe‹UŸOª†ˆ·éæœV¨6H¹ëÌqlÇr¯¯=Õ6 ߐ¤Öæ¥ÙIKQJcÒ>å,E3Õîâĭܲ.‰¯—ÒI²B ¨íž{…¹á¤ú‹N£^¤>ÒØ¾“i«»œ´d} …–íÍ.ãù¿Ûú¢{üBjª=ú¹Õt?>=k´ï]>`¥|•ÆÓ>ï³lYþ!Ózõ‹‘’ÂÓð ސÓHNS©O‰òI©9ir¡d]¯Ælè•HjSCäì´}{FŽ\KÁèâ°ršeÕ—STŽ:e9µIH3(z¶Ú*ÍUÛMÖ©ø’l3UY‹4!]{Ìz!Òz’YBÖ)…¡WR¹.Ë}³\ÜÐn¤Àäôúõ©ÎhÍùÏ$_•bͲ#)èT~E£¤öjnZVÓHíù »ÕÂ'¤ÈµöÛy–Ûé_ôÚ*Ç&»_ ++ýÿ<,öÿÿùڋ—/Ýsî€Ö6Ûÿ¿ªýnÐûÿ/ü‰ÞÏìâü0&ü½òºí³ûÿMïÃKa~îýS¿æ ßrø·‡œwv~îâµãúüÓw¡õÿÇPæç®lïkßø{¿úƒ·¶÷‹¾ÿжÝÙü×í"^à}íó³yÔ¿à%;~®õ?§èdʒ÷—Æ lŸÊáðÿü¬Ö/›Š‘ãÚºv<®ŸþæK[e³›ÜóSÿýç?|VïÃÖÄmÙ{¦±ÿ?Cê0½ïô€%ëüéËû²ZzŸëú¶ÿÚÇû­#Oèù|újï˜ú°·-Þ÷%8ßûÓ{¿¸Æl}ì9Ÿúö}ßޖ©_ü÷<£Çòæ¯ô< Æöe—î&ÃÍSý{Ç)¿Ó—¹!å­´OùÂ>ëá!Î`ˆ 8vЇ˜AØoŠ!Ùpçi‡õü Ö.ÍÏ mû¤‡ý5CœÁ+ñžµã~~çÈm-†Äùz=¬_7ÖÑI\ôò¾,m0Lû²)ž÷ذlˆ¹u7±÷Ö#Ϲ»/Ëc¿ÿT.§}îì°,õeG­÷åŒGà_ y$†ø™=֌çÐE7ü×=Π–^‹qF^õ‘¡ßˆ=Y7moãÝÏýx_Öû;¤ N12Ç-Üö¡~½1CnÎ#£ûòÚþpÈ¿i†º½kŠ÷¸å7þ5.ëûrÙt û÷{ÛÎ1oã+ñäêÅí]³¶/+¹/{ßÔ&ˆ3ðiY?~ë‹Õþe«=–«ûM¬µw†XÒι¿Ú ^[Æ~Po5¸QSS¥œ‡¾J½Ì·þXy[þ>µãoŸ†¹ÈlÌ-– &—d¿ƒg/ù{”µ—Ms€Ù>V: M'&ÇXòÔ_²Žn±‘mü­Ñ¿ð©ºÐóW·>A¹§i1¥)ÖÌÖYc œÓ‘Ù6iùct8¸Ôf“£‘Â)Ê7 ¾Ð^ø"78:J<ÁQ»ÁµË7J“pI3I‹ÉZ½I÷²uˆÇvŒš[L{ÐeÝÃ~®Ôo=µ›]ôaJe™6j;è@~3”ÓÊùÒÆ1û¾uÕjuŒíM«£¦Pëñ^ö ˜Ö5?ÄXHç¤yÒ´†÷¬frÓÊrr[2–«4Ð,íHcòÐO¾|Œ·ÕŒNûRu–¶˜§cÍ^<¼ŸŽ[S¹ÉáiG­&Z«¾ÇÈì*vFO‡VŸRŒÚZ´¶æ–o@7§QGùÇ9©dï¥E{},²iÃZ‹rhNj­¦(ÍBÚH S•SZc+RH²r'G틞_ò¾ÔŽü—ûòZµÃXڇ&( ȹ°êiœ'¡h﹜¾Ú¤4duQjPNðš5† J½IUiihÚ» 18F>¥Q UcPJÔðù¹Ô¹–!jŒ‰k÷þòQ)ÏvÍÓSÅk¦ ™±zÓ 9“ŠÕàŸ~-Ò@™ä¥dr‹,ڙ\¤’†˜”g ½îO‘k‡T¾†=h˜FCh•«`jAQr¡ª-€ÆU/Ÿón8Gd—vÃó‡@ÿ?ßûxþà™`1þß_wÖ³–/ÝsîŠ)ßÚåÿěÚü|ÅÉûÛ֎ï¿óEçßòäYpó’qKó^1ÅÉ¿à͇<Ñc»­_šŸïˆûÙc¢«¼é—~éÑÏÿ³OÌüÜý»È#¸iúüš~ôÚûÙÈv_1åøzxǁm~ÁàsšŸ;fš'ðü·õ¸ý輛Ÿ{bŠÞy\ÀÑ{/¾¿t\À•SŒõŸuo_×sñÿÛc~³ ¨I>}{_sÔ­;éûÿ¼•[,võܕ»É!¸iŠE?ñÈ!‡  ué¼~=àj?äûs=æúž)ÇÞfڗú²<|o¿iÿfÇô1+%Ø2ïl.ÀíûŒÇ°åη2,æ¼xŠßÿ a_4 ͪsН¿ðîa.õý<`I^¯­íËʰŸ×OmmÛ¡rqê—MÇþɫϸc»0Äq?ÚÖùNyÝóëÿj缄[w3aÃ46ä܅Û?6Îُ¯ç3\ynɃ§Ü‘³sKö\‡+kÓܒg?´÷;û8ƒ4´‰wLã/Îùê/ëËʐïÉ©ÍώA8j1;áâ©<ß¼°ÆsKº¾Î>¾ä¨Uÿ«óN^ÕöEÇë¼ò“û8뇜ŒW¬oó¯û•1bÿÞÖ©\.ü¿·Ý=äA4½þîšös6‡àESÞÌÙ<MmiãÂë>З¹aïoåùfy±Ý^7,Êú¢Ö&VÎ/xǚÅu~è½}YÍýŸÎ•ÙqÚ¾üм޻ï¦î<Îà¨i?[8høžÆ5Ü>ßl>æ¼’·üØÏ ãƼ™—Leýšíí9\Oc?§÷X³¸½Ç.xjµ¸áP4=ȟü–xVãK‹Æ…jT¾¨jž<+Ìk´v0ÁËÕWcá}ªò^Є]õkŒÜôÈÅIþ|z ÷Ì3j›ùÚjʯ–¶OVÜ¦˜dÇ<Õó‡é9jÔ°KãügµÍ ++&7%-–<ù>¯V ^C™w‘k°ÍÃ%k^Ì¿¶s÷’ã‰õ)ÎIèä 蝥°l‹“^µS¯—½ª:0BG^´ë0«Cx’IJ} ‹•C/:õ¢40ÍvjuÀ€N=èôÚ)'š¶Ùg¸2ȵChEik‰Ò e×ô²'ª£šªì¤>ÂÉ%G®Z I3„ºÝå:üߝrW98uh‚4giò¹iüQ»¢.>ÿ_ĕϝ}þ_¿nåçü˦qûýÑ/ØŸ¡tþmóãóù·_sꐟ=Ï9Èõó‡ýɧ{“êüð¬©_úÅ×üð§‡üòùþÜ0ûœŚ•ŸÛ]½òóù5ÓsËÁü#··çp[eýûMëùɳŽh¿ èI$ÏÓ=ô~lcöÕaRí>ùèÕ»~?sï]?k_¹vñvù˜þÃW÷ó³9ùoûr‚>Oßýä+û³oý9ç‚é÷”oîuNÿžÏò3§ß öÿð†ÏŒÏÅ}_.˜žûßúÊ-}Ì{LC.€ûöÞõ3ì¥Óó˜ù§ÿe_&§V_gûÞ}6|×Éã²a΁«Ú÷>*¯3?óÉ8ääOnÙo³ãï¯Øk×ϰ­Þõóæíí{ÿ§¼Nzô°wöeÕ/ÿ`å1ö¯híd[{þû©=ú²0ü®±ø<}ñ/œú•þœ*×°þœº÷¸/oÿ;/.•!‡ÀnÆæ÷¼+ÏpûôÛÔìMÏßYwòÂ0Ž~×~U[çùZf8çkC.ÿa΁›§y6fÇØ?¹z×ÏÌûîµëçâۖéÿן»÷¥ýYÔľ½Ë¦öòoìO>8<Öºäw }Ö>îË?ø~1ž1öÀ3ãú)œW¼Ý+í&÷øœóÝvo¿ËœÛIG(;;>ÏYëC hýÔG§ê ®|QïÄuø½>´¹>]žO¥uF%¹m6ú¸àt,kÒä֚5_ŸÌ†±äµêïn>Ô²Âs„ÓëV ++¥:;.¡jÚù§)šn@ÿ¼[-FùŽf%—â“;ߖP_ªPjXJЕ*¦ _Îòܗ¥VäS:%€Õ!õ:2ºVYŸ<ƒè³DÔ¡¼)ê½»d×çw¹JVJ[¾¦?Èãˆ>QêèuyôÐgª5ž}|6Zi<ýò9̧1ÿRPò “uln2‹Ï^OéïrŠ˜ìcûÉ å²ÙM®ƒ˜c±mzwyÚë0:Ö[ž‡å|>ÏYK~琊K戨:7¼fq[ç6C¾#u'zZrQ ++{§’¶½¢C«f¯(QÇ1ËCRµú`hµ-Êó‘þ®¡¹í½Ž€ÖlèNSÂkÖt)M|/Ïûš £è'œŽc·òD¦OVò€WÛpw©R)ÿOý»›þ~dõÇMZ0ÎA°‹ßdVÊɱû6™‡4Œ–çß¶ßj4ó½NÊ }_zQ×4ÿIšº¹×$:+Ãô{ÓÎsR<Õ¿iºÒGԇX¤±Kym|AŸùݐéÀµõÈI#ðrÎH³ÈúӒ·^®r­wšM¡èDr2k抬§]҃ÒÕ9[¤q·ßE¥ ÉuµèN³zȪŒTi×2yÕ¤gN-‘iZ†ù ÛÕ«]“Šþž‘Œ¦Á(ÃïpÄÿðL°ØÿÿáþÚח/Ÿ»gš|ç8ü‡¦÷wŽ·ïý¡Ëóö1Â+÷ß<ōoýü[ëÃ>ô¯^³S~ïMëzÿqú㟘úgçX¿cš³~6ßø“í{+÷?nŸ¾G?"ü¯ûg˜Ëbù¸šåcq¾Ûbµô½ÎbQb.C,‘FnØTuÂ4¯ÅJ󑬣£1kKŸÿNüO³ÏÿaŸñ{çñü¦çò#þË>÷ s„•ù93}þÐfs‹«O&¯ž;~zþŸOíy»³»­-[yœl™¾·<€ÿÉß+v56jÊw°‹ñ*ã|–š#@SAéxût͉@ü?Ï‹ýÿW_vÐÙ˗î9wÙԟÿŽÃ8®÷ó§Uósï˜ÞéŽO¾jÈC]ççVµ÷7ÊëÐo]ûÚÖÿï¢órk2±ßÿ¦‡|ìµ÷ã?1åÎû½Ïèc¢K=¯×⸁Í/ÚØóêUg{lÀ¦¶Ló²…=6=8älr‹ß¿÷¸ìí=ýÁ1ßYÏs×s™¯”Ó ðÝ©åÕÔþvM\©ì!‡1w¢Ž8hók$y¢L-ä?š¤)1[ÒÀš4ø_>ކØCÐw4N?VgŠ<‡j³¯I³-&«S–gm̚¶ ±øµ¥™´%¤¢SŒùAËš¢³ù6Ç×?eîIÝ¢ÒÿÀ3Ábÿÿÿû¿?²~ùÒ=çŸæÞyþ¿«¦¹ÐwÎ pãÔ'Ä·øva~îê)_ÀÎóÿÝ?õï{Ôõùÿ¬sóüï:oøå ‡ýmË#Xu~ÁG§yÝ×½úÙÚæÿ3šwàê¶?'Êëß>îèö¾uy~˜+\sl=åÐ>_`ôòþ {ï|ïam?SªeõܾÓücg}Á¸—æ;+Ó1œußÉWõ¹úŒísš=1}ï컾xK_–†yËzçñ»xÊ£ø­#OèóªëX޶ìê)¿áìüöf¯±fçø»fÉ÷ÿÀká{\Ä~Ó÷>yõw ˆ| ++WLsÄÍÆh\Ֆi^Ä­=ç}YæÕ»®mïÝòzãW~ùwûücކƒ[¹¬<§àÓ¼ñŸyن>×bCއUmþ¸ëåõò²ñ¾aÞÀ!¶ãžÝä’xÏ÷1;oàþÓü?{ׅ/ëËÚtËÓ¼G­Zi~ûҖ"¯kÏ~´·éqþ¿¯Oq0§/\þãòa~ÃuSYÏÎÿ·nﱟb‰¦×íãûŒ×† ¼úùmY5¥×ѱS¹·pۇ†¼9åO•6×è0X¹?):M¡Î,8Ì1gÚ\X;ÍOWõ#1íy+rŸTtÊ8O._}Jz_›BrWVc-!z£3ÆëX[/ïh7œ/r?PŠÜ¹–ªs۝D,9½Ë¹-ÓÄ^Áéü’Nîbä­åï«·Æè¬{ÚM¢Îõ%ÿ45Wo²—ÍF¹#7ƒüÓÉ?\Hvè'´®æàÂÿ½ëÙ³ªî} ¦oi 85ÔÙ8ÖV)m…ûÿÁMqh ++BW¤”¯Pæ'-”R$dæ6²dB€dÆ4Q¥( T4QêR „ÿȰ¾+PÀXædÖl¿sÏ}î÷çýúmÉ Cz~äúœç¹÷ÜsÏó¼÷éýs\ŽT«ÐCô¨¨Ä¡1dE5i/Òx¬§e<ó”ÌLaùaK$3Å5;:)[˜ƒ™Š¬Qž4ôE;¥eÓ0«ÿº×RÛÏ>mÝ/E;ŠQU3ÐfL!{Ÿu¢]XM% 5W¥GŸSŸ1'1Q½@E›¢T¥­T“K%AX©Ki£U%J2×Åg×ZŒ¢ %o•a 0… ¡«wØêfÚÆÅT\Ñq)>…—¶èT¥P¢ÃE8QBJ]‡Å¶11Ã{•÷íTù‘6„­™joØPåCRÓãïÝ-°â¥ÑeÚŽú5©‡‚Ê]&xD ++]mSï(ÞÓÄSgšòöq»‚;);e壒ްº… 0·*œ1Q™Jº>’5¼¥`uú–2öaÎb›ç©kvG¢Yµ1( ++b‡Z)G*Å oʑž|Ùy<?Æhé1Ô$Y eªŸ “Ó›!)Mq]OùýhӜZÀƒ£ËDRÚAڂÏe7žMž€W&›Œ]xºïü8¦qz¾5R§ª‰/G)í5%*Ô4>fýø<P"¸Â-Ю=O˜*Ùÿ@ àÍùþ@ à@ÀÿÿùÇïœ,í÷vî§þß¼qç/úP9¯ï÷î-|áÓq,Ø~ÓéÌÛö±ß{Ǹëß3ʜíœû=UxÉD”>êÕ÷þ¦ðüµÆõ—•ë‡ùüǕë‡ùü÷î3q­Ïÿñ;TøüÚ¢ý-aûºÅ%Ž€˜CýޮƱ^²÷º’s09ÒóˆVSð¾—¼ZÎç ú½Ýåzâ£Ï9õmÿRâ |‚V—ë‰Ç½dßîMå|ŽiVï†Ù>ó·Åu¥*?MËw8ÑœÓÐâŸc1¤×–ÁU Yfß·¾q¸7¶ßÙqé™o=zH§ß0_~wӚ[Ï{m¯4·yߜNÿM/>}%ËRåà_YÆp8Ž;–¬}¹réó嗕ûþÇ©{–2/\åp}á½SÍÆ“^uP¡R”=Yî#þú_÷|毛X—EMvø‘XF„¡"›ßæw˜K?¿ÙlÝàg ™Ûnj Å£-ïäw?ÿ±Ý5OeÍ-yÓìÎ.[ïYñ\•EßÖ¹]›' V,¨q)5VàØæS§^³òù"3±äö@ øß¢Ä&C¾”3”Æ+æñí¾Ô/'{ôTò;%“ •ŸsôžVßXØ&뱆Q ‹ôH)Àœ!–·&:·Õ9RU1KØ3%)óN¥˜â]iR ++@øðÁ˜ÄÜf£‰Mψ °’Ò*Yjì“C ÊQÒ3Ê6fƒA·™" ¨hY„6žÖeÁF•“IXJZ•§’êÚRýôì° K;b\gG©Î° ++Ì_ d!hˆ˜í,s™q}±ŸKT c2%¨“¸Ðè¡qžňƬ2Öj°AÀ÷„Ï8‘°PÎ V eXÖó&sÞ¸H\öˆ;R‰(6 Ê* ++› (§½¢Ù‚–‘†Œu| UbS…¯)ԄôÎxªÁn-M Ñé11.EO-eOeâK=8ï„ª3ˆÁ‘S0k²¥Ü<ÿ?•¦£0…‘Ú-CKQSq7Lf2+kJGìiâTŽX¦ê¨´U¸ÄGŠ(qøoö¿‹ó>bt>*_u1‰]àm«i·¿Xܒ;Nü`ŒÍX¿„ùN¢b(4Ýgݸþ™Â'ˆåÇ€,[mB™ú’)a'hÙ2_ŸÒôQIA(‡»”ËøšÇ¶°ýñ´Ñäuýøü5Ã+^&ÊgÙÿ@ àÀÀØþÿÂëænš,ÙÛQö•)gÚՇ9ÎÛg(ÿßqe?öf ~³ô„š'ÏuûçÃ|ßÎêÚ9ú'‡>ÉyË(oߎò÷”ÿî²﹟÷Yí·—ë‡y?lùÿnÙþ®”óÆÛ~Ýo§ë·üÕ1Ì 0Öô{7µ\qyw5=ß¿÷3•óÑ ßÃJûÃ|‘¶ŸÿÖ_λŸyÊ÷{ûîÚY²W­+ûÿAÅY•w0õþÿ¼–Ãí[w®å¼w*„ñ5 é¾U\õµËu|7à£×pŽÁ.¿[¿åî{uî¦g™7kŽÁÑvßy›=‡k/^Þx—.eހµ¿Tî›:çߊ¶?þԝçîbYÇ)øB±#9ÏÆçKå‡(–Í+cø"ŽS–oæÜ}1jnó ¶Þ`sRô¼ïÜΞ¿ÛVsâ)ëØf·5»üùe§VY¬9ï+²©9 —ÍîüuÍg,eÀºÙÔùÇx.g –}‡ù ®æ^\ÖìrÉߝþ˺ûžiópÆ5›aYªc_Üd§/:ÿiæ>èʧ˜1{¬¿Ñ•3‘y|·5_º}Ɔ‡X–*ãî"û0ŽÕ/Ž|¥Èèï gŒål¤yßyÇÎ#è¢g]ö´ƒëîa{ºNÏííYÂ< oLÍw8N69§á…-¯æ|S³,ö³»Êø¶à¸èÆM/sNC]ýåú–pd°çKUVsnŽÎîÞ+§ýýO±,insß4µAw5~Ñ·®ù·š ±úîâ6·k¿±Ö ­¹w܍aíÇ›eü÷Áx¦K›SçP¼­½W»áҟ3ÅzöÝ]³ºþN\p-˲f{^ܞ£ízif}oz–ÝÕÆ'üàÀFËù4qß.¼.R¦œ]®;7Ý>•ÑÙ¦qu³ÞH¹¸4–bݾ]PN9\`¼Ï”÷ ++?]N—ý/ô‚3&ĒÛvÜßë•ˍ2¹‘Í()šÙۜŠír¹ëÙ²WH CE+À»Úd!¡¹ÄúSÎ0=v{‹dJü×AS¨GÙᒧ½À˜b†‘(©´×:'¨J{¬–v1=´×K–Ι`hÖÓ¥§bc˜‘VXoQÁ2,!lL´ÍŽ9ñ¼ÏõMÄäRÒ¶’S0µý_Ì^Ž’7c~¦Ë@/Ú<ÇÀaÕC´V%x‡Ã (gq™ÆR]²Hê*òÈUÀµÔ“)ȍLÛkÚÌL.b|ʐé1X;áL¦Ë eÂXàÆTöÉËdgâރ¥Ü„´‰ ++›Ø*F?îùP”²-ÀÓª¿CgDÚZ‡‡`u«ŠQ¼…éig›L‰öÈv!XÒ“ª)õÖK´{ ØLõáÐ'åÃC˜ ª8WŒ’05–ø™”ÅÈa O;øGðP]Ñ®´ äªËa‰~0w¡r4àÌáËÍxýòTîoïÝQò<¯È€p‹:—!bM¦L†±´ü?æœÄ¢Ý͘ÌÀ»¯)…÷%¾ÄôÕçUeÈö¶‘¹Î»ZùᘁŸù±o|’sø[¹Ü;¦ÉC¸¬ÍïpBæâŸ‚côá}ËYæj¬ÁA¥ÍÏáxô›«ÿ•ç?x–Ýׯ0k°£åâŽ5à ºàSÏlÞÆñ6³ž3¦É‰xIis Žë?ÿ‰§X–#ÛÓµùΉ¸½øÀÔymÏÃ9;/úË\Í 8¯ôwõçÎ|œe!ònj~5‡pWã¿Ç\]lý ˏúÄK,³5¯ãåmއãvOÃý¥ùྃ7ÿœeÙñ}ëgwÏ×0¿ÿ®b3âÔ¿ó¨Ñ+‡¿Æ‘¬i<öK?¸éáÊáW<ö=s»û~}û¹,ÃqwMÃÅWÍ׎¿µrñûË mþ†yúÌï߆ãä§¿w;ËbMÙ5ŽÃÿµkY–#Ïûž±˜§Ww²ÌýíœÓùÄێ8ÿ™"˦>·+›.«¬â1d[}iOËoúèák÷T™ç±ï›&Çd¡öOÉï‚ÿoüæTk\ÜGúhé"k§Šø¿ÖRÇÏm´ÓpΉþO)×T¡ˆ»—XØÙ¸€!àZŠËÀÅ èb'ÊæF!:CIþ’rP#{±~$Î4®š†K\xÆÄÈW{Fá¬ÇøX̞rÓätk\ù©r‰•X؞ÊÑS6À+\åY{ÊÍ)GYèâI²§TmðŒªðèëy¸Kæ{Ê\폻Mts8åAŒn\\Ji£¢W—JE{Î¥H¹‹þ!‘—éjƒ×£fû~ë³cªÐ6ŒãRn¾À±5nj)ûþ¥<¦Ð'ô£ˆô©mŽDΧÐÌ0Rˆè䣗£?ãéI).Þîé‰4OB1E”Mö£HK!xáÀ–<WiC‘˜J÷RðxÌ.FµÙwŸ ++0+dZ·Ãã§åîwyKŒB .ôá»¶(phõA<_xP0ævå]LÖÂ↦ÍÒ0<¥OLÎQ0, ++ς“¹Q°šPTGñLÇÅ*‘ÙœJ‘çâBz„}T¦ÇÁCìT‡ÍñÀàALN‘ñT@eÊŠ¶ËšvЏ©â†ö—CtƸ¸y0ɖïµñßÿ£|ú¨Éïx¬_Û· Éù[O%‰%@ àû÷µÖ…@‰3’õeßUøÿ@ @ ¼ù!ßÿ@ @ ãÿ¿ðÛ·ïœ,í×8âáz~_oñÌëí}¡Õ8›X?ïɏ<>N~||ÁÆÇ.Í»jM´]ãêÝMŽA¿{œìåÙ,K5®ýÞiêÝý°õ·yÇi7sÜw ‘¢Øîvßäúe@ @ ¼Ö˜®ë¤Z -¶?k\½¥*jLÖå»hù?åÌȔ˜A—6dÿ_ @ ‚7?äû_ @ ùþ@ @ðfÀXüÿÅû^ùÐdéÌÞÉ¥~5Õ¡þÜû¶œ\âöµ›Ñï-juÐ}ÿŠUcïB¿×o5­ÞûŽõ\=Û~ÝõGÿäÐ'9¶^¥~oGË#°ðÓË~_ê\+­û½'ÛõKôãóyÊ#ÐoynÙþ®Ðyg<ÚÿU¹žò<·wÁÞrÞFèswkgÁO¯z¢œ÷ý®ou¹'æ/àZìTË{ãiKø¼·ú·:óïßû™Çè|ˆFõ{W6ý?ú*·C¥7û½Ï–~Ã±øïÞ^ÎëgõvÌíìyöàÙ/q>ã¹Æxj6΅°²õ¿e°åÛEf\æ|£s;ÏˆëŸã\¾Ö?¬è· ++ÇÏŲ`8ßÁƦû«s7=˲èXöJ‘QAôO=³y[‘›Y—Ë[ž„̓íw²,:®I?:N¶ÂY Škš_XÆðE§,ßÌzÆXkË?Óò2œ³ó¢°ß¸Z }Nó©ós›Ty¶Èæ7»œ5X¹œkÙûĺ¸rÕlñ¼Te¥®(ì2·ó£Ûglxˆe)póŠl&ŽºgtPdÎGÖó¦f³‡®Xû2ËbÍ;1ÒtY78ÿf®e¯2ërɡݼ ö|‰eÚ³=×·ñ ×¹_Yd„ãÄg¿u+?*ð}ýæ/yäñc¸F¼ªmnmzþÍ̕–ùää…'@P0>–ºÖI×N§‹œ7)G§=á:jTâ^'¬]±LsXØ[®³n|T¥.¼Ò*é0‡=5ç´IK;çƒâîÆ%s@ . A Q%“þµË‘È&âË$aÙ§}vÊ&¬íµÉTã>*…»tÈh'×÷ÎgôaŒ*qáÞkåÐw޶«#sT>æ¤t6ÙÔû|ôXtj ÊúÉ6ñÊ ,j|ùP,yw-šÅeQuž³n<† ›*(‰ ++—U°ÊÆd‚·)« “šPô2£5Ÿèè`ŒÁZËfünÆ[PØãS,àæ0 ŒÌÇä2>sbƸƒÃ=öðdɈïL0úPÞ¸›jú8¡9ÊX:“\ð†#écÂ}è_c6¼¶ ÿ±1ÂjÖ6š8ç f;[… M zÅ©ÁTc,Éè1P úkmµC,šÓɓÃ\șå_Úèhu7o ++N—l7ø2 ˜¯M3ìh]NÕ¾ð2|ÅXïS >àhJ×ca@Vöÿ@ @ 8 ßÿ@ @ ãÿ?¸üGÛ&Kû½K ++ÿøf ~³ôæ«k×ï·>ÿHã2³÷{Ç3_Ùå~oQÉg†ã²﹟ùÈNõk|_ØÙå|Ö±ß[ÝÚY¶×=À¼}eû½{ËßW\ˆãÚßþÃr>Ÿ´ñ¿ºyi‰#ðÁS;¥ßkp¬|üˆÿ,¼ý`pþü9]ûùü@|ë£_ùäã|žâÔìîüQÿõ§ëJ]Øa‡õ-î`b½Ãù-Ná­¿œWƛ²òýÞÖÒþZK~·íÄOa¼Õ[?§»~þ¶³b;+˵ç´±ýûÕçü‚eÞ1ýØrqÿ/zß–i˜~Ý!]›_^xæƒ,³‘eWÎéæo8Öà³EFü÷¿½c݀c ¼âþN8´³Ã_êc»^šYßkžŸ5·ÓEb0àµEáÍfMLÎàÇ#X°ŽÃϤŠÆ;*‹5HÔQ¹à•sÄÔõK¤œ£É ?*Æyb^瀅´§…‚Â;\ǵ ++!hü Óm…n¢sÊXt„D²Å9\®\J¸ÄgG×@M$müzâçÇ◒(×?)P3ÿYð»d¬Ž*dƒ ÷¨è V´X@qã³&F¶¥579HRi ZbAIÜ_=UƯªŠ…ÃLôrmH=t`ØF…DðӌuFžþ›½ëÖ«8Ë÷Niùn  ˆU(D $ÅýýC~G1 ++!!!I°¡ t돎e†X0¥c;ƒ#:ŒÔi*± 6•Œ¨ …q2cÀÐF"MÓKÀhÃXÐ >Ïîžý¾{¿ï^ÿ‘–}§'åž=gÏî»ïîÙó½Ïû¼è–D6ã¤TJT¸N³1¸#ìšç Þ8hãBêŸtPaÊ/&,^Øx8ö€Ö@Iƒl‰ö®ØwètKn;ó’)Ü:cn2–;Þì ”‰Í¼1­ðÿ_èC‰m†&0w…F¯v^Za­Ø¢C° ++l_­ ++:àhCbrŸÐ#'½³A[Wp×ht ׇ¶¡Ê|j£p٣⏙r¹q[‰ŽD˜‚76°ïQ+AXº–hx“âÉ|[2ø6B-èl#¡ÓEôýUÂáÚhño0š1âGÑVŒ×žêJ-Ç< Ø<ò2 q ’Ðsô@òc‡yŒ?¬4p“öZïv_Ü)X­`ÀrÍ1ç´ãPªŽyäÃÆ1•[¶B8/Ñh1E?œ]œ˜YèMÑ ÆÊ$=ÍïðH¥q7:/’1DcG/Ušº0vcxFÃzlĔ‡Ù|Aêè$ã$SÆ£‹è‚ÓÆ¬¿¢"p¶Ë«çµ±9ö#R¿¡‹•€ZBj'ÿKÇhÆfŒ•ÀÚÁqÁįcƒ±$˜5iS®Å¬ øˆÁøcl£9Š˜…AG¬8 ?ð˜íc5’˃ÀU’`å­Á—ÑÿÝ*MÜdp¹¬ADذe0–9Ëâví`4"L~,ÍÿߤI“&Mš4iÒ¤I“&Mš¼+¤ïÿÿäÊK¾1½ôÈñ¥ÉGGŸÙ ö-Ê~~‡ó÷Mð<ýewÿˆÉü|м€Gؙ̀|h,üÀÇæ¿žý£R÷Æ·§z†q Ósé7üä%?ùD©ß÷Æ%]ò‰þó¢ÿÎkg{ã»&ºóSyû6÷ºö/<ô¹Òù`U¯ø•‡ýö+OÛ¿{Ü%¿½–¸þî9]=gZ™ðÁk\¿¥ú™§úùÃDwþ£¿üSé|ZöÆ/>ªÓÃïýÎY¯>E31~0]¿ǵ.þZá”ÅÇTצaÎÀÍÕ/{ÅyKŸÉ~|³ø±‰®Í7ONèâã/ܯWž¾õ“7eß¹RÅ÷zqºo4gàççôï›îÇߞÆþ³,ã ¬qÙ÷º½êû¹‡oܟÇ?ØìwÎ>Ô¥8îûԒçrYô¹ï[SÿÈáwåû.!ûÇcéßUǏ|yEÆY¸ñ¶T|ÊM;¯þó\¦bîÃáÚ÷aÿ¸Iº¦¯÷¶-+'KYȺ¾·â†9 ++He€ãªƒ îLóDDû°¥ú–—>µ|Aö«Ë¢ë‹RÙ:«ö_xDñ¹<Ŧ¤ë«qüš¼!û²¥-çÓóˆÃXöò9ç—2•ïëcO~óص_Ëe1ä¶ì¬öºlÞº½Ù/ Wä¼zß[ç­Ë÷iSp&gÖu`ÅäöG²¯Þ|Þc»9ü«µî™Â‰(²M,¬|š»¶.ýÖT¾ÄÝÕw¾tÿO.¢‚û¸gN׿U{O. ßðZÅ>,ßÿ©sKYÁlž…ƒqkZ Ö³¬}¥p0Ɔ9ýû.þR) Y/'TìÒ÷º1÷Ïy“Ëöӕ]ýɛŸËeAf;Û2ÑÍõÛYòí\CîûØÜþóæŸ‘ñ Z—ûêšuÍ䃟Î|Ñ羿zTµ¥½Wve1û¶cº¹ò£§¬{¾à"ŠÎæMtúæ‘\‘êü ŽE{ùBW–Û¹£b-MÞüé\˺ÔÇZLÇ7Àv{ýû6•Ë‚Ïe·Õ±]ô=×öìiÒd”Ló©ÑõIؙ1ØHh דö°±È×X$ ¯¡ÇÉDúz½Â*'´Âš¥èUÊ*“˜)y¦¤ð>9þ´Š‰Ž*j«°‡˜‰× —ÊärÒÙ·‰7ʤ÷µ iUL¼µÉ'ÙÅüî,ú˜îž‰JÒ*­U"y¯µQè2 ¼žUª@o¸Ad$ß½Ï$âˆÄ[tV’JÌ'—¦Cƒ#ßHԌòA gvKŽÞWƒ±À ^à B_4.!ƒ''N*ru¹@,ÃEokŒÄåh·"ÕtõšôÆS˜¬R…Á¬ÇŸ"9ä ]ítºTC—>=‘ÊG²bYmn%›z:ùža*ŽÜ\äÇò|«³îézƒ½à¦è;ÿ5¶A6ù&±¯âZ£CU9cc\0ÔllO¡OX¡;´˜ðKsˆxe;eè…⌠ºè%½xR €Í̚^{ã¼7ô^ëÐCzŁŽiȆƫ“3™6¨I†aáÞu>ÍHï²ÀȐh­r„)úCÙº·Ñ ¨•CIr6aM0CǸJoh< £ÇóÊKlžÓ^$\ÃÉ åÁ„´Cë¢1Ä5Âî遌hªAÝ|{¡+DÀö•FÏÄ[† œÓÉF$ç:–Øíc[íÇ «ˆù+þy¢¨ ++Z²4ªøoÑ:L?׍Óÿ#_¨sÕBa’OÂۉä…“^Ä ÃÁ¬t\>9 žp ǎðBÆ -­=† B'¼ïÞ P•#0ÉÚ´¢Ø‚S àA¨„£­ãùøŸvÓüÿMš4iÒ¤I“&Mš4iҤɿ´ïÿ&Mš4iÒ¤I“&Mš4iÒäÝ }üÿ…_~ÿ£ÓK¿¿bÏï<}ýå¯>Öéwƒe8NݱiYá4ó½ñà ÷ILèi·.|³plÉÞø}?<•ðö„K݊ãÌïîü~âóÞõ ++Ž—xñz(×<¿®â{§âù·ðùýzâ tVá¹[*f{á?¾7a~]×Wβ}ËO>”ùü<ÎLíOxþœôx:…èß‘ÚOlí©¿pü[Ï/q>㢧óùõÆwWœÿÏ_wvª?ò>VyÏ:|`m:}˜ßQqÙ+.8~ácÆçž›°Âä<\rÚµ96€A©ì@‡ÑüO¦û>‡c±\—1÷2 üšªÇaüÿîŠÙ^ö§ëö•²˜1¿Ÿ­œtÿú¥ë^Éeºà¹w ÄÜU¸•+†iœã¸þ™Ãçç2cr[n©u.÷«_Ìe¶ë_Òם8võÊof®>gó}÷T¿m_¹ù@.ËùI' ++#õù—§®Êú´Êeœôê‰Î¦×ký±¹Ì•þ½Z±ìâ÷Wv±*÷a{¸iò¢Oá]áÀ»»>ïÚÓ¯ù· dÆ–çØ‘ pÜgV>[8÷|îÆ:+'7~¨àø]nËáTF\öåÏ\QbbÑ˺ڇk÷]ö™Ž/·sçœnîÜþ»Ëþ=—uqOÖx‘aŒÿ–Y¸úv͂ÿ²êìÇç_ÿtÆãë‚ã­×ͳ?k27 µ>ÃžÊ}¸üë_•¹Ì»‚ŸÛÙÄ[G/)÷…‚¹?P±åÃÿ~|Ðoœ‘¹+•"×¹pã?S0ó)ž‡ã·æ^•±óޖ˜‰Í«Íäed̽*ñ 9®éccŒß›K™Êun«±DK_úœ2¿ãÃ<¡®Ã<…÷W»~ô~é›Sñø»êº5ÌEøê,\„›ëºÓ0÷MÞmR±åJî‚4£s%[y™¨Y8/¨œ(kÂB5V'•Ùã|tk1 ã¬Êa‰.J§x=ÿ"Y®3hËÌÞ #®IÒä¼KøÔht ¥™#¬XzM´ºQA+íÉT«‰}5+š‚»¢½ÖàãøVfõ^Oäsě%2K·’ nŠÀýD0%±dNÐaŒtØ7‘KpýpR÷Í@É&â¿Dd#ø2r¸Ãz]sû虏›1W‘¸caD€"|d÷”d¤–Ó2z¢Ú5™ù"É·,eˆ)Gy%!Öoå¼Ï!>5°™"3ÂÉ@82Y¯,^QÚa´Ä$Ir¿È'1¦#uÉvXn… cÚM¢8 ++v&®:’û1ho4?‚Éö¶ò‘E¾Ÿ ‚ÁüÃÉQùÔGÅM0*ƒ4†Ð,ÚýØGœ6¡ÙŶñ&7è¢'l^’DØÎe 9P#Úz‰s}R­ÿ µì#E,ùîœ4ú$®YSVÈ­‰äNhp"úa¨Ä?ÓJDÁUn/“Ý[™ñ"‹º=ª -!‡TÃ4Säǎˆ¸Ï08¡äMÇöŒqštƒyç;Œ6”aÛY ñð´)MG# µÅðMüºK¡)`jÀ¡dŒ L4jDÞÇ ‚f:nuˆóçÈà1N¸²^v‚vm±%›"vE‚hvCÛõP6î儤Æld$R }¤kސ6œ¬)\†Q/!Ñ´[J\>ÞҘ҉/1Ç ŽTAèsÍYhus\°Ä ++á±F‚ÅÓã4žN?-”HÖÎ8ÌB‹ Ì0N#< À<ÆHJ¬Byí‚ y¤"<É)a-¸ÙJR¡[ÔäMðŒkBõèH/Ö1ÈùÇP ÕMµX×ç”ËNš{Žxw.£Âb9ˆÁwñ–ä—°ÕôÒÙ6Z 2ö_§øŽ’±JœiT…-×rê‚®sB¨(…¥1—ÓcºK† †qÀªt„Ás…b0 žRÔM Ve8Õ 8"ü=cÓp‰%Û¦â¸®Ô ˆà: kÆH 2–r2Ö'Â,MËÁñƤï¸ÙFª™bÿ§ >»D¢ítÇoÇøçsŒ’w øÐié%izÖ3ƙT̖Öÿþߟ]¿oú{³Wö›Üûž}è¤ësß]÷ÒSãíwύy-朿7Õ÷!öå/V½XÊJüí'f‰q?Pcs‡ãØEºï2‡¾¸ú@ù–+ß:ÔøâáØê×úßCñÓjÙpŒôÎô=3:zié³Ü¤I“&Mš4iÒ¤I“wÜïœ?hn”é1æ—þtžþn*$ ÁøË©èSÖ †á þtBNfáð^øÚïÈìÀ_?¤u>àûצ,dù°L/2—Ã`L;ZçLýÎyú¿ýŽæŒ˜‘+e†ßäHt ;MXƒæšÈŸtÐü½5²B“Ñ%?èM[Ov ¶“¿(ñ·턶³Åî+§ùCw%M!8“hL oş|‘Eµä_1)}Gðc#øH9/*7BÃÿ7iÒ¤I“&Mš4iÒ¤I“&ïéûÿ?þį<=½´7~KòãÕïÅ~Åõç–ÿ›Š_Î-Ÿó¹Î-ÿdÅ÷çz¿=ùºGcÄïHí߂ãœp͞‚Ù.9Ís ÀC8VÿËßÙRV°×kævýæ–ßP1ù×W×û†qà;fáˆß: üҊøð¶›ž*xnYò«Wìü0¿úg¸Ð§ã· ”Mç75ö⪍—¾”±Â^6¬p“&Mš4iÒ¤I“wŠÔ؏w^ƒŠi/yBFÅk¨H׳5†‘ Á0 ++€‘^jtLÁ> BðÆfÆj<=ÁÂhbÆ ƒ´8©%ZBÿ®aÀCw"±ÄÌopޱ7L;€SŒ Ššh}“׃gž9NˆH^;æ¢×'ÑR¯˜WÁ8ÆOEÂ!ň ¥.qõSƉ/4_>ºRËE?~ÁOÌ?Ρøï9:ÒEšL‰÷(\ÿ÷o¾/£s‘ L¢ò¦"ŸLØ Óg–4t½£aLàà˜‰!é0ëGäÈBoŽÀ}(,…EAÛøê1ãÃI˜s-¢¾ S® kÅ2Æ£#Ù;Ï-‡§ËßÑvˆXàÈÃdˆmPÎÿÓüÿMš4iÒ¤I“&Mš4iҤɻAúþÿ;~ú·§—Yò“Óq½ñ̟»1ñá5Öÿ|:?ÌÿwK?íŠ3¾Wø\¯øèéS>ûͳß,\f¦W8܈XðO\–¹®\썯©œbsŸü÷é¼õÌíêŸÿÆOÿGâäØ_9º2ÉGn¬Ðƒü§þÓ]ßÈçMè÷ÒõÌqÿ7]”x$ùù6Õú×üg2Òª7~eâÏڈãÒgOùÏÄGàxý«3ð Þ7·ÓÛ OÁÄø™é÷– 8®}pqæò㏖cÉÏ_sÏÿáÏ®š,¸ _x÷ês®Û³äþŒ›2Çó?§+»þ©[çÜDá[]9ÝNœ·<ãH¼2ÖçÖcCo=qý ¥¬ä³ßQù׆9ù2×"/xcîŲ́}áò[Qñ"k^þ‰¿-XŒ‚q8ÊFã4¦>¬Äñý­ýNæNð…_nåžæÝÛÝïû³Ë‚Ëx‹=©ÇãXûí3Î/œ §ñäœn|n8p̝ÙN]ámÛPû°ö;{7䲎Ça×Ñݽqú5yŒ¢.üy+ÇÅù󗼜m\¬ÉGwú|㔫_(e&—}"Ý·nŒrž?Sp/—×y0Œý¸¥bM–o\ûõ\dÆ~lª<Ëæ­Û›¹üd¿]•oÕä¥çç2[ìåˆ:VLøBƓt¼t¯W.Ða¾‰mUg«÷žÂ7Qt}âÑÝ}+&þIᛰY×gΟ·¥ò6J“&Mš¼ý’8ƌsLN´u%~4ù“RÊm鸴ÅõÌoí„g˜/]oØ!xdô¸†±dñÓ¤ ¤×µèI¾&s&e·dÚб«ÎÒQ‹÷‚°‰ - L'‚6’ó…˜N{ß#I½rÿP8<ÚG¬±»&Qö1ÙYOòE¡SzmlÙYÑÈmf¥`,®PÂ8Ò8<[EV6ñ¥/+*çBʑž¹µÐ·ì VmF!¨£“–|î€.œtx¯*6‘¡¼è¨ ôÒy£L0FÑãIú»äïãž&‘}¡$¤º,݆d-Ô ñ&á`ôV2¯;Ó¾sð5À}iɪhlÇ£7]’’W2û|JF҆4ŧ´÷Ný€yõ4†ÅE#Rèuç/-yݙJÁsLæ²NcMÊN‡†u}"qo2­ÙéË…Ñ‰Ùø¡LO®–B aôNc08¹5q&ñý N*CÀ@žÓˆ¯ŒHI”†–XNÏ@ ++’æÙL"ʙãuZ÷HχA¤^M䚜ÒÎÀ@ð3—ø.G‚Rh´MÉ5K9V%W ±Êq(ɅÀŲr'¼Mœ«ÍÿߤI“&Mš4iÒ¤I“&MšüðKûþoÒ¤I“&Mš4iÒ¤I“&MÞ ÒÇÿ?~ÆÓ_œ^zäøñ3àÿO©¸ò÷~ä¤ÇÓù(ÄD‰ W~WÅúß°kÌðkùè§çŽ_Ssø ãÍ<rY(üw›jNÀ½_YüÒT¼ù†\î;îðæýê1ý²éxó‹j†ñæ9çÞhÜøýõy«&/¹«`µKν×+—â0V{¬ÖyÕ¾ÛÎé°ÚYg禲ѹÕï®íέ¾b–Ü€·×²Xíږ¿xk/sv}XZûwÍ䢜ž‰NSÙe›3aT>ëú±ZgËKÞ¤I“&Mš4iÒ¤I“ÿK™Ê˜âI¤U¤ï Þ@/†ðüŠéSü“‰ÑHguæmt_i3Ä åܛ£2[ScPȔ(­÷ø:²vZ{Œ" ƒ s%zs¬‘ˆžƒ¬Ïh[êö ÔÁÈÏ=C|ɔïÿ¿~åðãÓõÕ+üòüŽœ÷?ì]{ÐÝÅYÎQ”óåBhŊ5ZXBav‚RÒ@Đ*P¤3¨ ƒ–™B[Ú*:Ãt2£´P- ++-PÀ‰32J‡K!FÅ>B›ré”JŸgw{¾ä|'ÿ8hjö¡úýöüöòîåìîû¾ÏûÈgOÏghãú½ ÕÏÿЋ|3ŸŸ¥î÷ŽJþ¼Ã~û×Wÿà#ß9teº/ðôÿð|ì§Ùߞ®Ýuj?ù9Õÿüë?õBN³Å{}õ‰~kêÌÛO—ªü^½³ŽYpJõwîÎó^Íwzý©ï-̤û‡ÝÓbÈçì%{¸Ó8¥úu¿uÜi›rš+ÜüWÍ}ßñfm÷æ®z:¥Yåâ¤óùÔw‹’ÌnÂçÛï»àù|o¡]n_öÝþ ++>§ÿéìëï}çG^ã5\¾áœìïòëí˜1ú¾ci½ÓŽƒã.œ…ÏÈ ¶—X%>ÄQµ}W;ä™Ârÿ=\å9웞y(Ïu³æéAä6œŸÒèG¾ò¡ùžÄt~òÇÎ}‡²µÖåÊã.yºÜ¡ˆÜ™[€3hÝ-—¼ZîIÊ]Hæè»×f Òn¿1§EŸÇÄÕ5þÅ©[¾sWæÂ%æÄÌ:æüüÉÛrš)ý¾½Þٜ¼õ•ýS½µRÚáuL,¿mFNÃZ—ÒB»{ihhhhhØwÎ?SžҙÈX/côÏ½äD¡ø!ïîÃ\Ï?Zi5é‚Ãÿ ùõT‚L8ª&[Iª• ++Êá?t'Ղ VhêÂÈçY-Y.¶Ñ…Õ@àà#°³”&ñF欱Á‘tëʇDŸð-z™KïL©?)B ÙK?}|ŏ|ô N¥ k¸d¤{•"]Ϥ]ÃPìôw'U¿%é ++1‚Tžqᜥ ++Rý[:¨gÎzG_s ++œât >׍'iÊQ(ßû¼ /é” ޗ>°2Å ‚Åi”þôé¹£ ¹ PÑ1āH²Í&³?kIÁÁz»DlOOy:Ö'Jȋ§ÛhIã@©;䍗qždМNÃÜÓWÏLñÆGá|éPN dɰtuRŠÁ8êb <ÆðäDp¥OÈ0AïøØqr`KM©0î@näùÕ39q t9Ïh=YD0FЇ8c¨‘6#J³º–™£}†ã„Øý{:ö£µÇM°UBeQcäDƲI1ºrQE51|îöC8‚ß‹8S0AL-ÆÈZ7ûÿ††††††††††††††}ýÿGÍ5OížÚïÝSyû×^±ðõ¬O׺ßûój{¾åìLd}¾7ýގª‹Ü•÷~çtè×wÖ¾°vvÖi»˜õ—7×ò×½ÿ¼¬›Ž²Øâ?¾nôÍõ½ao։N­»=°¶ë¡ßüÃñ¬/Ízò†††††††††††††ŸMŒ°3°Œ°@~~ÍØF‰ÿ;+}¶?4{q8 ++OUl( #9 (¥iÀÑÙRì{`”ÝI+Ñôÿ ûúÿW¾tѲÝS÷ï]–ü•©·¿þ@óñì#l¦õ{Ó½Á7ð™ûï NÊvÒô{sjlñ…gžXìd¿èÿ‡í6Ôøíó]pVÖýKß/~çüþ·¾]üÀ‘ÿúêW~Ê ¿úhÖÏ+Õï=^}ϙ8ð“éyd>ËRþŒÉ~Ãø‚7øÜDòlLí:ŸCß^¼ˆÏ­Tø¾ëò_óè/ÿŸ;©c¿wpò¿þ2> vüNеîŒB>kƺržø£çÒs¯D¿·5=§oõÂçmÊÏ5êù|­çü‰sÒ÷ƒgþOT„Ï}fþ>Ò˜±Þe)ò¬ûàÚÌu eáÿÛYë:Ìg°¨ÊuõsWƜ抏ýöÊpš\³5§åXªc½òœš—àš$³ß¢<¿¹*Ûb‹¯|ªÿÔ\‹ç¦<§¶ïX“ì-¾€Ï…?úÜ73g(¼ëû]ûÄ­Ë¿ŸÓ8ú’ßþô.M]Ò¼P¹.ýT—©ù ö›ÞÕóžùË_-ö$…ûðšY]ß\<>=ó>F§²]ÈIf'às³9gSIó¹}‡LïÚ·rËÇ¿”íP¤È>ý¾†»§]ødæoì¸3_ÃGñYúã™mTDáʼ-µýZŽÑÛ/|¾¤™4Ö͍aۖƒöÀYp]åàXµý½?_xu®gæV˜šò¨éݘøÉÝå<7¹nNy^Ì<·Ê;2ŸZŸËKõ\Á~xiѵ9ÍN†7ë¼Y<¾hn™Ç!—7g$ŸACCþƒäC©|òWÔÖ å‚v*Hº”:.²ø‡:ã¢wZj#C`än' þ`TëÀîô8µA!ïUŒŒ,½>ñ‚òŒb.Œ3Æ3ö2Ãd[¼uÎĂ^É>犏¯n ++_ÏQº–Éz¤ô¾6ÇܦBÉ MÙo–¾ËFCïaüpƀgpk¶Û»(b Ú±œ´%Fì“,²Ph'–Güž:løˆ¡¿½ÁV 2޵Ie2Þ:c¬³vƒ˜à«ÒŒlï,²`ly啱ŸWʆ<’xÀL°:ú“Ü™Ô7‘ÁÔ#ÖËS¯IS7Ž‘Â…’ØI†Ì¦ã©Ñ‚~ºÆâ7Ô Oïpå\DºÐ‚~ÈAÊM‘< ++@'& Äƒe£H¾ÁË¢÷â–A``£Bá°.‘®­BÇYzD›äÎ ‘30:úZ ƒý!}Û%ãÏ{ªñå.Ð*SDp lpÝfebæ’1¯½†Ø›âЗxù5…^S4ݛéƒÌ ݦ•‹ )î2g:ƒQЁ:¦ßó$G‚0V©4LR¨_p&¹%ÓIÛà)D&SônŽjHQ̃·b×c˜¢Þž#HHJƒÓ‰¼ÍŽîȞ~îoVÑí8¹-s‹¥0¥ðžåïuÄì@ÿ9c© DÍÐäˆ=³¤3@´ dKÑb"Yæ¤0Ž4'5Æ8dÀ ™ÜÛ¥Êuòh%—ÍxìÈ)hjPé2É‚I,0qH, ={“QÑ©ƒEœDÔ«b¡@ »ˇưV^  †môÆÆPãôÁ¶],Ðf짽失"¤¡À¬°ðD¼HÕ,G(’±IÊkl ¸è0 ¼B‰=kéÎ,ròè3¼‰+t˜Äñ¦8kёìÿHòïį€(ª¨5IЃl¿v( ÝLÿpö…ÆÜ×.¹}CúÈsãAC²ìZÏ>3 ¯éu΄T=®§øÜï¥|*¢m\G%ýßÑãšzt‰ ’e7™c/ëôQªh'ñðâÎ¥GŸÚ_^r]įF—&kÆUHœ˜ÏøNZ­ðŸ&&ZÆ î(">Ï¿œu˜\¿°DˆÀo¬§’è!)Æñ-9Œ y-¾…ÿÊ[®‚¦ê’?‚B°\žÙÉÌ?2-X #‡LL£‡‹¯`Û!IBÂíšþ¿¡¡¡¡¡¡¡¡¡¡¡¡¡a@;ÿ74444444444444´óCCCCCCCCCCCCCCC;ÿ744444444444444ü,`Àÿ·Pn9n÷Ôý{ïÙ0ÿßæôœä_‡~ÄOZˆ®ß;)='ÿ؟žüþGË÷É׸ņyøvV^µyûk'><ñý¥éùr|æ¿õõSž²ºß[R9ÚæOˆ•é¹~¬·1}jž¼µNÃ'§¹r–ÌìÚ¾|üÄ»2ç›™—oiåŸ;uËwRš¢Ô󨚶ø¥_º%¡E›  {%?§³¦ãŒd|sÑ)¥­pJAŠ?<‘¬Šø(’îYcøDKÒ*”%[¡×ÑIrȑUБóÒz§#ùGrjZŒD’ŸV¸ä¬Ó“x/I ¨|t8rG–NäQ(ð§ç9€Äъ|o9'vE´•RÅÈü¹íPE|×h;à›³^¯ìÄ|›Â‘í0Ú`}(\sF(%-Cƙ$?ò*2,œ †L¤N–˜oJ(I^7J†|šÎ8B‡ì„CYN¸LUŠº¡udIuš 2Fí½²hDî´‰·ÎáÍDo,¤95i #úʹÜÿ*ø"ÆZù.Éñdðä`ÕÈȲPÅx|ÁQ¸‰ ’,„šãÓÊdÐäÁ4,­–$ݔ8czÔEaL”Ø|LËä}e޶ðBø¨†·õÁxÁ`ÏÏ÷JîÉÉçÿeÛç|y÷yÝï½6»;Ï-œX÷‘|V¶ß»µžGä³§çs,ÏóKFðöç38Ï¡W/ú¿/œÞ¢ßÛoVwnÿÇÅ þ+=ÇBÒÝ/°Ü£&nº ñó«ú½ƒS}†yø«¼ú»òð?;sªû‚~9ßò¼9ç¶KÒóèÃXï²z–žóõUù,-DáH_T9Ò?9¾åk9MÙ|¶½¯ò®¯¸·Ü#óÙvÃìÑw Uù^:>¦ O¿ÊgéÇg¾ctõÿ½—/?,óô‹rÎÄBX;þ…’¦\.oÛ¤´Wgä4,ùÞ¢¶ý{·®z"÷©*\üWÔø§õ¢JZ¹ÓxbÜÿ×0úNcGåy_ýÃ.ßiX‘ÓžOýv>—¼xÄñ9-–~ØPË[ú‹K^*iEžÌ}²¾ößÛ¸6§¹ÂU¿½Êåâñ­÷æ4LâÜ·õ®ëWŸ‘ùö…/ý°9•Ç8g¼¬o+Üÿ%FÁ´Ù]=WØK_ÉÜÿ¶pøßQË[1¾ñþÌáU+·}vWޓŸÍ1 ++”ñ¥î˜=xïâ#2O¿–Yfë\zgæ™ã…ÿðô’ÒÖò~ì–Krž$Íc°¶ïòûÏ|±»ÏÉåm¬å-ìörgSò¼oÖ íðrŸƒÑ”ÒžôÞ¥7æ4¬ï)íµ:–þdÿSÆóZ€Š¦´9“ò¼mFN Þ´-VCCCCCC»o G»&ǺM{»t֗ Ş÷–弝8× ã Xìñ_à‡eœ ÞƉ<ê8X*6JLù5ÿíØïdõ*…dÀ)Y—3¥ÅўAOpúƒöugmlºxÎu‚.Âçx gÈÀ° Žq.?B§É-oT@»Hh]5òö ݁s#C«^RB±WØè²ŽŒC J\ˆ3CF1(çxϰOb<ý8Öh—xô±ÙË1+P3c—>ê<¢V î– rÊ݂3V‚ ++vrâú¯ñLR Ö¢”Ë#9¶˜ÆsÔ9öÉÞÿbòýzR»FÝǤ.äØs“ÇMÀ@Ñ4ûÿ††††††††††††††}ý¿?øå›vOÝ¿èÕ© ¼aÞG.¢>Î5­ß;¿Æ _{ÅÂ׳¾[ë~ï×{W{ÇRìxê²ç=ºà¬^ú~ïúIß?èÜW="“ʽŸÇž™“ü Ųß;¶Æ§ßÕŽàŽ”ÿ°A?éŸùßö‰ôÜX<߯ê¥_ž˜;‘ü´§?B­ÏQ&ŕ7V >"ݓ܀Ï)›ùÏd_àê¿>éN©‡?òC“}-ú½Fø5<<«“çѯ¿÷­ô\KÕï]•Ê¥Þú^<8µ+DznOíÚÀwÎxÏ?$;d¿ØîûA\QõßÃö ;S›/ÃçÌÃV>“ûFÈ¢w= “ß°ÿÄê]žÃþwT;ÕÏ]‹ý‚Èi7Wۋaۆ§RyûãóZ5^Ò|Ö?ßïÊ[©Ïþלæ‹~ÿž™Ý{Ÿ¹ge~79ÏjÓ1lñfʓ_øý9k³Í€–%Þü¼]_]ñáb3 È¾‡ur9۟ûrN³EfO¥1AÝÿ¥?T"§uí{xzW—Õ¯¼ïÁbQ|+²Oÿuß·/ݖÓò½îXïñÚߚ»*ۊXårN©u¹òøó”Ó\ñ»¸¦Žqëòïg; ]ìÎ߃ïH¿æ¹ì®‹sž!Ûˍõ¶uï}ú‰³¾‘ÓTñ™7½ë‡Ÿ~pyMnßöªß¶—X“ìFøœ¤òè#tü‘gf{ ©‹ÏÉu3º±4l÷}ˆf¦´í_+¶ 6ÁÍ3ºº Û6\6£[ÞøÊÊ‹¯Š)¶Õ>cùøâlŸLgg Òn¿1§EŸevÐôNfËþei—sÿmKý@{÷²æù”U™››«Ìžý•åÛsš¶ÅޤÖeØÎb[×~þäm9͔ñòÅjòՇ½\Ò|~oZ­çoÿ`Ó1yEf7W™ Ûg\_Ó~}ìÔ­9ÍkÛ~HöB$ý‘·ÉV—Ö½Ø[øN/B#OšÅêiEè±³14¿t3O؁ÎEz,ù2†Õæa]օ 鱑ÔI£Ry±ÜSœiïT`þ j^u8´é44¼E ~P"~#u˜É¬ÓZ©£§/Ւ( ¿XP1´Æó÷'Ј–j>ÁåE*[ô@Ò;ړ2Îø$¢¥©*lÙȏ<úh•ØøPKWäãñ‹È|Œp’ÐF!šŸÒ€Ù|•vÝTÿQ- Ò 62t½ÂêȄ‡‚1*²‰–vΚågUŒ)!åe©ÝX7u’&Á ÕØÑBÛI:G›m±¦f–Áëƒbg[kkƒi³¥žJÚ¤Ðd”n(Xä)±‹B%5u¨Cgk”M Ý´óŒ/îŽ4––%v7íÀ©´Ó&:šÚY¬Š–zA¼£…Ž6‘èV,АíŽÙu“lÎU¤U·rnh(šo}¡œu.crw]åžôÔ*Ø(’<@VӦԉKšE£S RO°³’VÂTS9°Érɼœš`HCÞRCœ#›c»DËhÏPòCŒâ ´Å–Ø€I ++8KKjB ƏTN$3o‰ML 18äJ{y­14MæSÀÈCNµT #L‚ÏÝàw™rdóG6Íå˜l°ÿÇöû>E¥wŠyYN É/“ ++\±æX °›°BàSGEºµ´"Gó0™=^ÃÄw5ÕÿÂalbpB<&íyFØýwzpz¹b؉Nމƒê¡2R8-ÿZóKÇك qÉÛcZáè•íh>BG¯’‘=þĊÀՁ歓tʖÏc€A´Q•u`¤_…ð¹g†8Ô@FrPtú´cÛLeƒïq AüX 0P8SióÏ.†L¢ƒX1¹1^¹Š†@ëvgœç÷ì)tžcÂàBŸÒZ r€b¥“4‘Ç"Ôµ]¢¬Oë—H:šKcø«êC±›ÍˆÂ˜à¶ÇpâÐ)ÁÑjÿÆZ(cŒgXd ™€´îà6âHûh¿ÆÖÝ$±bj¢1iQ¡» űÀþEχ½Ñ‡£éÿþÿ£ÿö ìÿwôþjîî©ýÞ­ÕN~W;ÿõÕ&õ˜‰ïXlKcÇ8ÌÿŸùÀh·?ý´<’ž{!û½'*OØ®öö‡×ç»òùeþ3ÚU/ÜqÞ¦ü\«~o^åZ›{âAï${x!ÅXï͚Ï0Þ®¿;—e»o#‹=n¶ÿ=Ÿÿ¸çÂg{j_øÙ6W^¾O=µîCÙöÙ[ò¥)mj曫ÌVŸ?7óÁ©˜ß;¡¶ëŒ-—¸pÅûûgkVŽŸtg±o.ö¸;kÚ0ßþS“8Øvµnhhhhhhhhhhh؛0™×n¤ÿ”66ûx‘¾Ÿþ$Îz-bi‚ìƒôHœøV ++r ++%Œ toqÁK+,­õ™µ¡ >þV €gÄ‡fà‘HD®Ç?\ö1°J$o ++#ƒÓbÚ»éÃ%鯄:;²M>FZE:Ð j7>Àäà¡¿Ð³wõ1{Võ¹ïDyZßB§]pH)Î÷"cZ7$Èg oKKK¨ ++ýtd1N³f#Š‘‹¸°Í2ÈEh˜!Ð6Y¨[Pð£’R_ŠÔªT3ˆ5ìwß¹Ïó¼ïóôÝDø]ñF¸ÏsŸû|ÝwÏÝßõ»®Ðåt øtLùþÿÜßxqøûÿô¹£¿ÿOopSuþ¯j߸ ÷^X¾ÛS´¹76^~\Ô÷ùç·ú>ÿX95¾m¿rö·«¦~Õ wíš'î¸ø§œëm«ú¼¾ÏO)mFnò•›.œ¬Zî©æ´ÿo÷Sçö¿ÏqÎ/-;þv_Ó¾ÏWí~Ó몶zý»Ö¸­­~eËëÎ?æ¼ìÛè8kû}›ùÛ=V½ý+ò§çÕôá§çç ++@ ‚—ô•¶ÞîÿúN¥qô3ú\t¡p1Y[ K¾8 ++TíÓPŒ×tIÝðqËZå€(g4Á&(YPmô¹é’Jø8 jâ Êë“H˯=ã!þ¯œs™îH?€×bIa§ÏCUЇoì4"^–oé^ /·Ï¨ocX•Š— 4`0Ò3€j¢†çò‘¾oëRìÏûÀ@*êð+Ð<Åg°H2e Z9ÔT8Ʊ,¿h€ ++ƒÎQCÞò°  É‚K„£VÆ"fRfÜg!Ž ɖdUð˜•"NàK蠝B?H)'Gwþ¿@ @ ¯~È÷¿@ @ ¯ôùÿo¸ïø§—ör֏ß{Þû*ÿ_÷ª'Üp^ÀDó‡:bí1Ï3/_Óyö‚ïþøÿ<øû̟W©7ö³æ xì¿ãLÎQ¹W}¦†õf5Žþ {ç]TÎgøÎk^W—œ¿°´Ç{Kç”óþ}O6oº…{¯/>kÉy:¿hdþÂì±MÇÿËk>ÄþxÊW¿³Ç›?ފ»'سMÅ̹û'5­€‹¿ÞMœÃ ªÚü–S0ìW7¿ù{ÒÝ3޵兹ëvpYtìËödkË}·¬Úƚ¦æ¨Ö‡sn¼ô©Z–¹lS›·aOº­ÎaOº+K>KLJŸýÌWy¾U½ßîæ“¶arëÝ]Ž×yCù{§Ít¬~ä>Ϟt43¥lA³aß¹³Jàƒ»ú4—Ãcý@[K_p,ç¤JÙ)Íßð…ÃϺê2Ô¶l)egÒ±÷¶Õ»8ïC;ÖWx°­“ᜐMãݸ\píºïpYÒÜ÷‰Rç{èXò“ÿRʜªmô²Ûõ%.ë¼Þî™Û/{€ïç\Ík9µÍÑ#ŸZÎy&.Ö|˜]ãÝó¸òþì¹çº¶0Þ=Kp̚oUï<Ëù)WŒwãòâøy“5¯¥öýÞҖÑy-¬ÿ:ŸÛ|éc\ëuKZ[>¹ù§ºœž¿«›_æ¹Ï|¤Ç¾ž©Ö¹eÀWoº–Å®²3oæ2£¸ëÇûeÓ½ú¾ÐÖÄòÇùZ-«Þy[Û;iØ«oEË=Zrä9OU?¾ê‹¸³Ýo؏oހæÆe×qY®ùL4ïÏÓvî9°z—ÂÆJ ³ªW™ Jç2H°ÙÄì2Ré?UŠFËX štTÑÒ =„¨s2…ÜL e0¤é]N;OڋdãcP´C‚'\VNˆF'¸ˆåLõ%8õ¥àÜݼ¢ý z‘Oi ¤CptLà"ý‹±ö†‰ö*¸§O¦óË*jp;uTÞÀõr†÷Ç ï<ÛFåòjï’/lîU—ó<Í/Ž9è0yV°™‹ÅC¹xäÙP¼àt°a0'8ƒ¸í´y¸ó4ð•+^sÑý¼áÈ ?IúYöÙEgúm…#M^PÞ:LBçO§Áf‡qš£I°–ùԁþxL9:ˆÎK¶ì¡ãR½±uõ,Üzë¹å¼ó¾ÓùG õ«[ÿðëEÿßxÛÛÚêŸê 0¿´ç ++:®ûɛ(ç“K½±Gçt¿Ÿêp՜®þ×_tX©?fEç˜ÛÎÿè-±¡¢öÜÐbºþÀ[b𘿰íÿÕm(çK;O/ñEÄ3îÛµ®œÏ1Í»¡ô]4¹ã‹U×Ðsl‘¹ ++£¹w•ú@Äø·»—³v¡ ++ã£¿hmæ^ÊFó vµ±¼|rÃÍ\fj,úöƛÖX¼f¼Ýå_ã2Wù¬±x6kÛwrå'TB?vzA\ý —yͱá«ZÜøWï>û»\·å¦ÆOæ Œ·øýÇO^ó,sB)ÏÈAhZœ8Áãçñt-{ɏß÷{um×XôƒeFóžo1ó‰;×r[’ª±á-sºyæ.œÔbÃk'wÞ]u)ý ÿævå;—ÿu)æ¶ÜÛÖÄ ï¬k"Ûº^V—²Sèø‚»Ç3‡È÷;µéDž»q)Çö!-RʶµçôÜ{6<Ìܯy}>Ðbí«&O?¹ó¢¨¼r|6VøËöÔ²ÌmùÅ쮝ÿxÿšÊAð‘ça_)ÍO8¼ËŠÉƒÞÁc¸Î£ꗭ=ºrê¸|b^æ49¯oëzØOãɹý²cø~ÑZϛætÏú0wá¦xwÍéÖÙďÿì0æ¨:žþ·sß³‰\æÞØ­³a¢6·²|w-«’kÚüÓï|÷~«‡¯m ¾…hê 1QÚÊùHï6gõ¤×m@À\©hŒJ: b­RÔQ¹à•sjbñÅMN†~æJÌÒc ‹ÒmÑwÞècÙÐèB!+1=„%éÿ=BÆ ++ÑÑèukËp\˜¶(ª„N÷—+q8s¤kº—½Uޝl̖Zkhk‘4‘–:žƒ8ín‚uÑ;…ð¸ ++Þ$üÒêº7÷Z3Äõ Ê…îÓՈ˜—s‘ŠÎE moü9c]…”—£{Ewr5ž7£UˆÏ"Žj}Ø€*w•; Z9Óy-þJ§S‰¯R¡ E&6f†f°ˆÓåÁ<ð°Ô¨SÎá ºBc©’ñÁQK,uÆÓC8- @M}¢éM5n# ( ìKåkœwZ|yTŒ—úb]HÙ>ÆØ€Œ`@qhuchš©‰å鈙&QÕÌz¯&64æšzE¿ÇAH¯{>ʦ…CË+Ó6‰v{~&Ý9DäSÇ14P6‘h§éÁSü 7„IE ŽÚçK_hÁæAÔ.£OeãÚ¸)xÌ!N_žšwWsLs!$œ XiÞ;¬u¢@ÄcNÕaéÑ+‚Ö;=s˧q:è¥Ê­È”by/•>2—dßå·Ây£Œ?di% ¼gh…«\´-8 4ƒe¯Z§ = $%ñ@ @ /7úñÿ·½wÑÓK{²å[_»àO.-ñódfõj¼yX€=ô†ùÛZ¼êçý\å „ÞØî–ë=UàÖæÓ7U`}‹ùMÕØ2ÀøüKþò¦7¶¸Å2Ûû%μÑ]üXखë>•/pÏ~ø7¶˜õgþjá/Jü_;׫¹ÚÃ|[ÊùMÓ¥¿ÿ_å¼OzöX*ãðy:ÎÖëw–ñÁßÂÏB<øýû¯å8|—O}kã|äÐ˟æxº®~†WÌk_RÊæÓ±îGGsü>æêgÈqÕÏѱt÷±Ÿæ¸q¶U-N½oΆrü7×¼ï£Z<}bçqo¯sY㱗”û!6üO钚gî#ǛS›£•“ë¿ÌñX•9:¯Å©Ïÿ›Ë~ÀeIsߗ´8üǏ^ÉuF¥¸lcã |ïΉ§k.yûß[ÊÖÒ±j§¾½æ’W ÕÆz8—|Aëû7}ü‡¼&­ç1s!1W@ ^èb0륎U»¤íÏ躨­3Ákãi×eRЁ¶‚1GÚÕZ…´t$Yëä¼q1s†5mbžà=eˆ)9jŒWQ\"6j–v‡ˆf&ª=(HxjªUÁkj–µ OÀ.%p gðGBˆãӮݍŠõ£\ŒÅݰöÚH+Âwº#t+hEºÙNrƒo®³È)6ìñ@б¡Xß%ð‘}0šD«•Ú2‡ `.JÔó¹-ZèXq!ÒS ‚gáU8—˳Hc…5©o D åiEáŠÃS !ÄAÏ!-Dýé@Ϝ*OxJ4»ô…KK˜†ßÂReº0ÑèÑӊI …«@´H>1…ÁÃ*]L]ÌÎSM4$êUoSǗò4iôdëª ++ØFq”ž†Äÿ@ @ xõC¾ÿ@ @ x- ÏÿÿãØþÐôÒÇm|諎Ýqó¶Ã¬Ž‡~ûÐç˜{\ol~áVëù1?ú:Žøõ‹ ?_ƒo@ӟ[ðÝcÍ<üœzc»š†Üƒ{Ž|ùöAÍðç»lò¿fž¼u¬#ö³R6šC¿e¾[Û½–ýóúU¯jš]=ƒ–ÝÎ֖õ“ ïd½:]ùîìµw=›ßµì[¬Wç_wuéóh½º›Ç\ݲüa.³†¯{´õáC~ôDÖzs•뿯iš­œc«œá¶ìjs²ì¨õۙ³¯k8šfKw\ù®N덹ð³¼è¦k¯=Úr †µ×ØOo´NÚ¡MqX mAÏéZh@ ‚ß=_µ’ŽÚÃ*0ÂNCÊ ++€Ð[SIû””qô;$:‹-º3Îç\Ô$‘b UÈÁûhlŠeûkR‹:¸@•Ú/Z°¼=W–öñV¹·ºŒãéŽtƒìÌ .^p&‚?îtD‚ƒ4ZÓpó҆)ºâ]WûaèæðsöÙQýÔ£˜Bö>Óo :©EÍNp† ++”P|‹ zuʁHê9²2’Kù•¥ 7Eﮯ³ÙיDnƒÎ™f'ù„db¾3úF_onK#”ŒH£‘#q=ït€!Xù#N ¢ºŒ‹Á@Ód[Úë‹zfÊÔ=¬þ>}#`\è?‘‰’!Ikh¿ú Ãº’tʦW2o?ZE<´h‹ÒÐҠڒ2‚MµBÌ(}ŽÓ…Ðå§XzT¢õE|$—Hü_ @ ‚×úñÿmgœ¶aziolM‹+OÕù»¢éαö˜ç9N­molßÁýßÏ_ÍqèLçW·z¦êðm<¸~зïûÍOkѼ¾øw…¤\oì å÷ˆ-óâ+‹>_Ìt~S‹›OÕí›hºƒïᄟ2¹7vxiÏ)t,øú[·–ó:ÇÞØ½­ ÷^_<ö’ƒ~áUýúôÿfWžBá|ÏÞÁ㣫–ÜâÏöÏ»¦ù zÇÄ#w€µä®ic²~rûõ9c9F~j‹åÿ둫ØЛÀ:zÛJ£y+Z,ÃäVöž ÑUO·r¼Ù~p÷¥Ì›©jå]ÙôÿòˆÜÎh«ÆÞÏÊÁ nÉÎzºjfîãmžÖýdûÕ¬÷ØÕÙk÷ûè]̜ ++Ⱦ”²«JÙh¯»E3ðn˜Áo}ã#,Ûó.ö³£Aã1»¤ÜÿX¹ãÌ¿e<­¸74ÎÊÒgì­µ¬r1.9¸ëÃÇþzÙ³Õ?Oñ¼¯žÁ[ï¤6\»î;\Öùà=ÚtWLîú{äužn[Æ»uüȧ–³Ÿ‹Õ§qcãp¬Úý¦×1#Õµôø ڊ«cÅäî/V<Ï}8«ñ;žÛ|éc\«Î#ûI¾›ŽOÎ]ú$ó;|ª‰3p?X“ñ6:ÎÚ~ßfÖVŒu}Þ3àƒ÷•ë¸,GîÃÆö.˜Ø¾¤+Ë<ž··qöÁ;¥qwn¼ñ3¬×X$•àØtMOÛ¹çÀêSê¹÷¶¹]zíé?.e&jᡁà7x®ÅìJV‚¦jvý=[ìÚA5Ð[GÇêµF[x¥¹ ¸¬¡„ÇÞrJaƒfƒU´¯€~Û¬N÷Œš’mé$ÔÞbˆ*™¬Š7 ËQǨMD8Ø*U"â6Y_ÜڂÆ[„苞E”öK.êC­ó¥-ÙSåþ”¦mÕûm”ÿ5$jÀUM¸WR}”Ÿ‰ÔìQt7`D(¨´™¬ÙG28k‹²c°ˆÃðF‹ ڏ 2|ꎴ™7±†{g‚_(¦|´;ÏePàe}¼'†¿]ð°è£•FSí=m ƒ§Ö,!ÄÏéfÆé¢ÃTC'«Þà¨8;µÂ馑¨Š^"†•j¡Q¤/ý¥I¦5c ++¯ÀÀ$¯ˆ\jÇZ´‘s´aÌGsí­*Ú£Y[„4锅|&¿†J¡p¤³xDl¾r`«¢HƒâèÇÔZoJ W€@¥‚×i(Nš(‘¬-ºcÆw-ÍÔ¾iû ÚA€©a º}][£âê`5h¬xV¦Â9¨ãZµ§Ó/TNÑRR>À•ÆØ ¬á-G¸q‚=R´é •a!®˜bõzÐÍxìá:‰4–ý¦K¬ß¥-Lz\ÊÞ)‘_Ä síÄÿ@ @ x @¾ÿ@ @ ï@ @ ¯ôóÿ¿qâ7·O/íÕ|ó»èXðómÿSôüU ½±ÓKð°Îÿ꒫;¬ó¿¤åé~iëüû€¼ú]åï†õÿßRêAî֕ ~YòùSȽ±}-§~0?¿ÓÍÇM.šÜñEÎÃ7žs„Ÿo¹ïÞå>È7ÿûWq¾¹‘ó€—´ÜéáüýÆûeᅱËrâ|óÅoìúú‘C/ç¼x«kžºÐøé¹,Õ<îõ3øÜSêü;:Î>yçÌÇXóÆ7¶<ç‰;×>˹öJsîô¬–;½aÛù_æ2S=–ÌíÆx8ۜîºá\û³fðp­ïçn\ZÆÓ¨X}ž,םGÇÉǜ·‡óðKzÚYú°žŽU;ß{—9ÅówcÓ^øÄÁë¾Íe¹æ›ß~p·Þ†sôU›¿U“§}¶æÚ×\ô»ÊÖɾ4¥l^ߣ`çqoç|zU½ \ËoεßÒÆeåä©wÔ|úT½"æô˾ÉÞÑ8εŸßÚ²|ờ9¿Ý¨º&šæÁòÇù—qžÏìªÍ±kâéşæ2_¯cŸ…Ñ9ó§ÎíßoªÏÂì±Ç»µôçú=OÕ¼øÄ×¥¦ùñ¶ÙØÉeÑòZÚ×4ÎxúÍ7sμ²’3/‚—ûÉѝIãÝdô½‘‡=WžTTšj º æÍ–uùºi̐<¯÷4™úÎÛþo2]þRiŗ{ú­ XžµË´ST6&<¤Ó3ä “ð@möEs?P۩ÚvæÈ&†2~ Nj踺˜zœMÉÚNÔ@bÖtŽÆÏS¯$ôc¤ýžÏ‰î¡å8øìsö°öÞïíão­où`’u=ms“£C¨}¤zŸ’stËr‘†œs¢Ò0}DÐ}ÎÔ5o•BH3Çt#‚Ûá¤Ñ#Äæ@G\ׯKo!œnmÀ4XCo窏mv¨Ü)HЄC…ž:Îòìd›#™’ê£úÉÚ¾hcF£Eä5ÙU!ü^•Àq_ëõŠî©oΛnþ$Z ++Ÿ6m£0×!!FßY_uè#v‡2“hSL¦Y²TN!Z²_¤aB  AßѲ"S(ëh‘mJ1QÍ.Ñ`¨&‹õ§bäÈ|O£¡©¥ªiùÓÊ£½B«†6P†$BíÙpôý½PPð‰ ÙÖjÔÕl˜¤yÎ}K †f7@&ƒµx,©ì0²hާ?iO8²n0uÅÓ¶ÁÊ Ys‚‘6±Å†¡­ƒel°«ÈJdJêÕX¡™ö~‘)ð³"»È¹$/ ++!ªª @oЦuüµ/å뺅žý¿óØ5ԋBBø@ @ ~ó!ßÿ@ @ óÿ"Îxqbi·³žýˆo£ëè·ç̯ùí\·sf_ž¿þ¼€×4?ÿc¾>÷¿JÎ-­{yøO쐅ŸûW¾Ý¸ù"Ÿ´wú×ø~֑ÚmùñÆÇLçç/£ëÆW÷¾Ÿ\êviñk=âß8Ž@ÛÜílŸ$ïà>ö¹^J×ì÷oý"îg®[ëÏì½Šó æ ¨?op=ðožýÁžÕ|?Ç4¥3¿ù¦Ï¸ueɏ§Tõ¿Œßžp{ëï²{Ï.yüTÌ¥ì ¶ù÷éZ¨×”||:UŸýÍ?{çç½^âlØÕê|pãÊm5o`˜˜#nÕkG>Pʂ­ùθNäñ{öž…/Õ2_ÚÛÝüùï»ç’=¥,…þ¼hϞ°ô§%&Aõòê±]†Ç+”¼zÃcŠùðü_ikn0îà¾öÞû·®ªq֕yØÝâ–?´¬”¹^ν;¸l¸¯ÿƶv–^4³”Y]Ê6µ¼Cr絜‰ƒ¹óÎmeKþö’Ÿ—²¤ËØ·öùåŸqõõWeì[š­wn¸ò¹²¯¬/ã;¨a0—ݦV磛-e):ùÁ'Áo4ØÏÛªûšs NäÙN±æ©D9áþOGÝlLtt!œóÎáò¢ùlT2 Ñf:êËiÜüö} –ëÉÿæM:dúkâüpÃò¯MÒ!Æêcn‚‹±ÏŸ~dB9vgßmªX;8Z»¬œŽ>7ßvèþÓÊGêsŠ5^†Ã;œ¾U%]Î5œ´£‰‰Œààõ=›”BªEôQY«R¤ƒ.‘•£*çsj*'6œG–D¤–Ã'‘÷8„ÃQŸÀQ«@æH!p’9Ώ§|FÚ9„3øö“Òï›Y¯5¦þ¼FÛ[kl`rä¾Káˆåˆ½¸ŒšwÑ#µcrQkåb(Èè±CÜ ++V>1zA+†L}°6¢–zOVÉ9iÄr­2½ˆÐca)tD™hCòh0t›ƒ. µvŠLÝ£ú\Šˆv êmêõ/¨ È´¦–Œ“iej!'ˆLÈl‰EÁSBŽ–2}?Ò@©vj*&øï#ʂÊ­*Ÿ9êÃQSè´álˆ´~‘·/ÚHƒ³øD‹4·Hà—ñ˜ñHH´ìèŒÏéى?#l$ØjKšëþ|—TCFf÷Ó¯#ü¿@ @ Æøÿk¿½í扥Wüá5s^8£p a¤Û¹¾q¸³³„¹XÞþTæ®o¤ë±'g¼Ut΂ëvLâ°¬q¬s÷:搝W¶Ûi|çÔ/ñ#Ö T*u;Û¹~ðß«–Ì~“ï{Kí®k<çxžWã~Çë®jý9ý½“¸È{t;›ùypáGŸvø‡Ìó+­¦t®æç×ѵüö…OV}A]8Önã_µåþ‚—þç{+Ÿä²+Úÿþ˜?«º„±pÈ'÷é^|Káù.eóúÊ®;¦hšP¸àú4 'ê v«×ތ;Ï.¾ ++NW_…s›ƒÚX¹ü`«ŽÞá[_»yECŠUnzÓÃ[ýê³ëJYòe|¯´±rù]û<ºÖ»OW.?|.¿Žü©®y¦pùÞŸƒܗ%t}C_ðJÑôªØåÜfÏOYSt­«í­mþƒº}ó÷£Û·¡iÞ­½ñ/JYNŞ;úøúÓî*|½®š…ûx ¡½ÝúŽªéW}?öµ½3¨ÍWôþ¾G×»îÿDzOzûšVåCÇ}s´pù¶–=6©6Ÿ@ ø^ӘnžÊàÒc‚¤´ç(H¬ÖÊsžŽP6Ð!Ä{ËiáY»””5†å×|hš„ãy|æE题Ww PCî鞯߷`W= ®Ñ‘Ì™ÈrˆôÙáhè‚Qw1&Á…j¸x0·LŠ‚¦Y®1Pç3N„&C².Yê¶JÐ}ôÊ;@&YAƒŠDÓ¤Þ&è¬Yí÷Ñq-*%à_i=šV[Ъ^ƒGµtˆV¸Mg[²hx˜˜a ÈÿÑ«†Î¯T+n…&£éáQ]ÎÔìA†ƒ’± ·!;7™ád–ÃtýL´ŽýhdÛè¨ü†m¬b{8§ö‰ å|¿ö¢V1`D4‹4ÌYÃí"èœÇʈ "‰¬‰µoá•á”ÚÂr²!Ó=^*hYÁ˜41ô©e!Ë3¾l³…O0-‚àØ¥…eû-ù Š/oªž$WàêÏ0™Ÿ„ñ1GÄÕS}ðäõV9ꨲT¾3ðl¡îdOŒ`á-F–!páÒNg¼IxRћPtÛö§³0‰?ÂÇ釐úàJ¢ã§…ÿ@ àÀÀÿ?å¨wÖL,ív¶2ß>ç?•ãõüߝ„ç/±Òàùg==‡ãÿCÈtÿê#þÂW?·—ãóctÝÎMËþ3_û,ëÿǬT·sÇP¿€nçæ‡>^ŸzëÏâc–—¸}$0aúýÄØÔÚŒ•¿¯åÊ?=ÿåb“jì:—]Gׅ/ç%޾¿]´ ëϑ<_|)zñÛLíÙáñ?>»ÄÊGWãèi6Ô¶ßÖúyÕ´Õ%æ]çTbÞ¯oñþ—ß¾ú).3,ûˆ2nïR”ݲúõó®J{3öóþ|Ó_¸ù¡SYâÓYú•ÊÖ5{NԚŸÒy·é0,ºaûmXµ’ (@pÀüi¢Ã¼UPÄO>;D³CËÜF:G"žN¶Êdµµ.ƒCŽÆX çL0>ã!íïA¨ºl £®UŒP2pÖd–[Ï1éíÅ|ìûDÍö‰±÷)ÛD1úÎÑQÊò:šd3e©Z½ÉÐPА»wÔ­è) â×D¬`a¤þšÛSÏtD„·RÔ.· z”pfvXú†ßí¨ù¤"óغÁá¡Ý%çF0ЧLaD¯í2އÙÈ$9d ’Û¦‘š+‚¦€ã0Hº­¬Kú޳Y¼\p»OšfÂgÌÒTѼq¢o4$œb¹¨$ù|¤˜@`ð¾W!û” EAök:Á»^¾‡ay&ãô{¹†é'XxÀö:딠ó>¿¬Äÿ;ªžf38ú֤Ѭ#­L‡: 8ax>ƒÁ: §:5´LRÞ|Á¼ß´pÀÆt;oð¿3@G`öÖM_æûÎûÿ?èG0•¹ò-tÍzsÛ;ìG bèv¶s=ðG8úG×=SòÀ¿àä¦á>^ÿ¿Ûò´Ÿðæï¼Ï:ÿÔ¡nåÛÑÏ ¿ø‡?.~V÷üPÿyÏØ;ëx«nûƦyð«ëÿêÅR櫾üÔ¦ÉèOfV-W8óÍ­Ï«v^™KY¨šõû¦ôú±Ü~õ¹RsáögMm}ÙµxCñOPºpí;Z^†KGO¿¡”åêƒp8¿_ˆ¿üåښ@U]úµ‡öÆðÞa«_(eѕ÷^á÷ðÀÏ_|k͐K?gñØÏ¦kýµ‹^Êr,cßsHo ö„š; *SÚû€Çw7]ç>þ /e!”÷^™ÖßùOß?µ”¥ša۔^ÙÅۖÜVô%øŸ8©ì»ûÉ9ðFÓÈô•Ø5­7ö/_½¨–Åjχ›Å{´ä?‹…u%çÀ5\'œcVîþ‹ƒJ™«öÜÂ}ž`:¯ hùŸùÄYõ½\}OÞmëuåèÜû‹o†³¥½‡ööÄåÿ´æ‰¢cUYK»§ôÆðøß-}½–ÕüÇ6ÿ‹e£Í,9¬®>$‡ôê|ëî¿.u†èJ_6r?‡ç*8¿­—G--ãË֗÷–ڛ÷®|®ø‚X_lýn{ïo^PsxΩ ‚ÿ_ô4ćä7™~ρíå[Ñsþt0V:‡!²žMÌ.ãÇ4ý µé´‘-ýª£_"QE‹Û™²9!<~}䐝1):_pºê&‚¡§@ciPjPçΙêK–5©½ÛF¿#ƒ¢—×Hªàè5 B•þÃØ¨²kÅfÐ¥¥ïD^ Ã¸Èg9!ç|T ++2ñ4,—²—S¿HA ÇóR_\¥òд÷1Se£qUöÞA ßC5ƒÊËT%âl¢€ƒµCrºö—ôÈÖmBèËScõÑè:ÄáBÛV­v²¾Ké|JPl§? âŽ!‰_³xƒ²ͧ½£ÎBÑ=j‹$à–l£r0P]O Di`Z£ÃÄ"L:ZEOç}\©U™3Û»LuÓÿl`®RqþtšD8wæ26ä$ÏN1õڟ“þ×(G{´ @­ËM@“Íûƞž=5à/izdH–ë*ÿèP¨ ++Ý Hä®h×$dXȄ֖fáÚXWÔKf-¯¡Q°ÏB ›ÐŒx]!çí6ÚÓ¬Aï6bvÕÎgœ8͍Þsa}?WhI¡»ŠSÐkŒ:"ׂ£ñ"ޝ¬îÈhjôdϖYOV3²OÔÓ@[Šºe±A±4‡ø\ Ë?€}‡õ’z9>¢¼ ð!Óå°\ioà-GÖ¤5ï°_Ñwš¸€Ji“&2~tÑ£dš71«ÆÂ @¡—ÔIOK&À]"АÀÙ¸#°óM¢‚¤?–Ž¢u|¢½¢µ˜%AÀ“éàd‘Ñ ZçôSQÓ¤ZöQÁ,¬~Þ ‰“񵆯÷p3èýÜ 0-ýÄð%›ðÿ@ @ ãÿç½½÷µ‰¥w\ãïŸî¾Tâ¶ÝH·sÙ$yÖ·Üæ'þû´]…ƒT©§#0ÈçoiϏçóß_L× £s~Å÷³£çÏnüéïÄùÔí¬j±îŸùÅï1ŸŸ²òÝΙíþxžÿúæ§ðþæ•%¾éG˜¯o¼û _—'Þyçy¯ÞÝVþõ»Ï¾`û³•²àûùóá|ýÆÆKròs[ÿuÖ5Ÿƒ5£s‹~3•CžßÞ{pãÊmµ¬j Ìà2 äÒ/Võ r{ñ—®_°…û9Ü?à~o]ïl¹ðÕR]áÖïh\÷E£»ï-|}ôý¼û<ºÖ»OsY±Œý&¸üo=°¦ðõ&¤2önóXôÂÚ?á2ëSéËÜf—e£nÿØÉeWs{àÁ8þüŸUŽÜŽ|s{oùèñ…?Ö–¾<Æe§ /‡-z¾”ùª³0«½·tô´» ++®«À±}e_º¥rëÌå @ |’ø”Ŷӱþ ++G%OMfú*§9Ôÿ#DKGXèœî#\eÙí:LñÆ"Ã:©é£\H2í)j¯Ø¯"RßNß*žFœèdVÏÖµv§êÉ844~V#n¼dtW—¨p„æ#¢Û„©\!w} JÈa'gMß HÞÞÇ×RÿØ%$öQHlHn½çc22‰ ×Ó×{K Ü{G3W ++D'ët`/:{'㳎Ú8LFõAÑÞÀ'Qc)à#í£¯ôÝ zý«: ŽÚ&SÅ@UówûRú|*ÀFãè:Gô·ôëïÿZò÷ð ¬KÛ)ÂÑC%ˆ Ô9Ÿè/ÔïÇï“d°/œ.444v¥wd» ÈZ›~' ++ {Ãp—}þ_ @ ‚cüÿȅßùÆÄÒng[‹3?qïâÓ ++Onu·³µÝŸ½wÅNæÛ£ÍS:ÛÇbºúõãkìy*œô.ƒvÿ³÷,|©pÒÁ~u— çOnm-½ýÆÂ¡æeò@ @ð1 úD|šüfš®…u!@ #Yzþ)dê!T|T¢ÏZâÿ@ @ 8 0Æÿá±»M,ívö5}þ«Oý쏋Ž·SÝÎ5Ӎàæãß;îmŽÏ×:Òý¦0>ž¿ÄÆêðoçøèÍ([ôÛÿÁñù>é)uüüp]üáw†Çà¯ßO þ~ï,º.yɨâ›Lñ?ØÑâÂß?eáӵ̕÷nn¹céŸoqè«^;òêÓ`K\øM-îýâÑSmÕ¾W%}Óa½÷5ìK.ƒy#Ãbâ7·~>õÃ5Ï {ï‹Å®¦1°bô†ÏW-úªµUÃUÓV?YµèküúA\çt]ñís^.qö= ûübðšya‰ÁGÐR± ·÷çt}åÕeÿPâì•.ïÛt>œº¸¼çS՛¸µ÷­»W¼X´è{Z{šÿ•3——÷¢R¥l— שßÀíÝJיÏ>xw)‹uŽ64‡ŽûfÕ¢·Abð@ ƺóƤÂ'&’AAÌ?åø?Å÷åª×†J´·ý1î½xòœ³CBt:Èjo\rÁ¸˜¬E ¶å¼ò(„Ü~B6²3Ð]o¥mMÖ*ð§;uÏ!cEtô°BætDlge ¸¯•§±dOG8UBCBrwç\¦3üž³æT÷rë.(¯Óa?úªKï]á‹ÌœÕjë©,º ~d²ÈÝÖT/˜àŒtÃÄmˆÿÃÞÕÛY”÷ÜÖs“qÄ+3"Pq÷ÝoÊ´0~4†ðC¼i¢ E¹e˜)£¶2S¦`eøpÐґR¦0 ØFñ«bZ¨“v¢?Jjã%ØÚh Çþ~Ïî»÷æ¾'÷ ÂdŸ™ÃwÏÙw÷Ùg÷¼çþ~Ïï¡­î’¢“rŸ*ÄE{ÑÅߛN¦§=~.±86–?€:—p¿ˆgbø?¤0PxÎ ++!P9^Ê5P—Ÿˆ¢ß/ùø^ax˜NŒ– ++ÿªcµ ŒëføÍñDô޵¦ìÖ¬gÀ˜4ë#¦õS*!F *8ö”ÝS Ü‚2{Ñ3 >A n+&PĀJ Q´ r±‹.¶c­/¡Îë`8¹>«© + 0À¬‹¹ÆWVÁ‡XGxEÞc1~§œg•€¤NÕs\w¡¯É2·Ç8-†K´À7NƎEAXàG3b j‹C€aC!ø±è¢Ç€Ð֊¤‹U/MÓÿoÖ¬Y³f͚5kÖ¬Y³fÍö ›ÅÿÿÚݯßúâRמàêeGmZ-ø¼¦þ®ù>Ôÿ¿£âÿ{êÿêõåÿx®# |MRkÇjËË¿*|Î™ÑĊŠ?¾ûðÝrݰ^À|«ðn¹`ù/xÝyÞ7J?Wâµòßû_^÷¾ÃõÖöýlY´Ô‘÷}`Ôßwn]ŒsqßÿïžsœÜ—0œœ8¹òN?aí¶ÌG°…0-5Ù?Ž×izzGn‹¥VýÆZþÛ3ž­ùiÛOî5¾&ÀaÒFümaã㙏àJíøseNã9‡TœÿoߐÇé:Ÿñúí2ç«ñúôëÏþFn³>÷ù¡j¬¬ú Ìl¹§×öϜƒ\K`¼îÿ™Kú>Ïûá)¿QbDeŽÃj铼×ÇuÛ 7¢Ë}nõór#²ÿI‹Æq#®¯µ!θä¬ÌPAç±Ruø‡Üˆ‹Åg×àµzÛéûnDñu¬Ž 3oþhæFÄ2‡K–̶­<±¯APüRy~vz[æFUô,jL®¿w*ÓFÛ¶,îãå¯ây…7áB^¿­£ÞŸS3»nȼ ]¸-wú±¬Ÿy㝥-æ9œ¹´Ë}úÝy,X£Üvò’Þg}qÍz.FáÒÌéó_ŽÈ\Œ®pbÎ[ÒÇçÃw­}¬Ô<(kty塬›Y•ë/ð¯æÒöi›â^yìäËr›+~9TÖh<‡ãŠº¶ß>xÝ.iKÆå9<´¸—·<úù»òÙ¢|ç¥Kúµ]µý‹·ôm¹Ïêþ[5sdùœ6±})4kök·ZwÚ;+Ö͹6 ëky)7´¥¾4˃œ2‘@˜óA ++"w^áM‰åèMbÁêÈçašÓG ¾Çk¼ÞdAuí¨×MQkbšÔgŽ&S*•‰I©èAAÜKEÅ\Pê|;‚Z‰,5b;.Y"}Ak…9âhéžVc& ++M¤1 %yª–+Ajpc:…§()‡NèTʊ+‹ïD*[+JJ¯XÔ³Ô¦½s¹'ê5‚:„dz—s îˆîMœãS¸™Ö]¿%LBp8Ìß$„´02ë|Öï¬bôGTÓ6LIÅü­ÑÔ\‡'=<¨=Ix*QÃK©1)´D´¶£Š;¥È‰‹áMXŒ.%–(}áÆDg#\á+x–‰®‡¡ ¸Ánëó_ÖQ‡Sˆý«H©!þ,êŽKr{X{Ä«[DSÆ÷¼'Fž¨‰žõ½3,]žUäµ {_ʪõ„ŒŸá âÈTr1I_$¼½£?CJ&"¥Ö‡`©^ÏJìä°btDhqߔW+z¯ ßM!ýDœÚD>HX"•µÆ:ãŠù̈́39ôàYʨ٘¡ž>…ôYÿ=Ám¡Ä!8/bZÁíƒ%¤K¶ðl€-h¦ÏÿO7±L;bŽ•è eGBžì(Õå ÅøgØbCê¸ã \á-ލ1ñ}]—X¸žk çaª€£À%OØ«í^æÔ‘…€8ïõî_H܃_•‹'±B=˜Òç³]Wa~},8æŽ!õë1¯~ý¸zèÇ‰% SŒþ·C˜„ê„_¡™N“(Ç`´IŽô‘HˆNyíµ#%Áì(ÿO݌‘6ü¿Y³f͚5kÖ¬Y³f͚5Ûlÿ?à©[ž˜ß:š˜’¿0WyÓÅÇýDðxeÌhâFÉ«e>ÿÑ÷/kΧþÿ¡5ŸøUï9橌íkæó×ëG¼Å/J®­M<µ¸ïgO]€’S?¬;p|½¾ø´Wþƒ\ ++ý<"××àuåÌrÉó·ÉúÑėjžòyo=VÆïœÁ8¯¯¹Û+vür=ºn4±KržOâ¼¾úŠ-R§@'¼Yå ~ÊA¿ÌzZõõ†:›%—y^Çþü¶·ÈõΙɢSÀùžó°¹3ûS ûsåޗãµþöÓ¾™Û:ó¦·W>ÅÏ®xWæa(gsÛ.icÎøçïY—5”÷™3±£r4Þ;3™ùº¯ypqÍ5ÿË×m˜)m!÷yЁ}ÛP·àK•kñŽÇ/:"s;Táa,ª: ‡Yê60·OÚ6/©mw®}0ëh“5Ž–>Çk¬–µý(}üŸùTŽ©>‡ûxés¼þ€]@càrɉÿ4^ü²+mE çîs­ÏüÍՙ»ÂZœÒ¶µê$¼sç—em_ÖOþž™™×ƒËc™ªzëZ—ýÂ|Hi{¨jD<}TY¿dÊÚ^²¸Ç¡ÞÁÒº§†zÇKüçÊì¬Úv¿©ï—¶â—[«ÞÇúGO½&ëh•ç¾r²ŸßP aT×ýmWžÿ­ÒV4 >wÀìçæë$¬¬zþÙº'‹NB©å‘óú9–µ;^óÊ¢%bòý¶×±¬Ÿ9æÕY›À˜ì—e5æ×͜rWÑ&(s¤žg?ûÄú”6›ûüJݛë¶ü…¢[`²?·‹¯Çsˆž™£wpûU¹-…Æ!j¶/›äãÈía;løÝq¶1m™X†çÅüþŽÙÞ!ðËïaF8³Xîø™Åœ‚h êÂLVÇLaՅˆ§"s}¾þ'RY™)xS$t"9Ç6v!yÜÅò&ÖTì’Â?õ|tÙiC%g¥]²ÊDäñ”ÆèFKv¶JŠY¥Ýó´4>ˌsÇ$^•ßð:gš+cJ"܍‚ÀjÞS\áñÌy¬‡eŽ.U¨<ÀÒ?1ãr¡#zåDÌ:õù 7¦Xvù·Á"X¦™S¢oK¥µ`uèñÿ#oYÓc‚Äa)Sw ++ÝJ4 ˜bë;ïB >¹Ñ¶ë˜|çyùÆ]`žl2®ÿ·Óø¶€«Â¢ç$?:c.)Yp|¬¯åŒu¢3ÀH!¬™tllŠ}î¾z¡á¡X~ìÜ0ñ0ÀNH6J!àƒŠX|‚Â"•Ð+XIÇxäKüà)€eÄÖV&ȾÆ(1™@w…£#¡¿hD»‚ó€ FÈ]Ž#+z23ܸ–úòRχ¼'·eós…ÓÊم…òÁSã„Dê¼,#>Jùz Ää¹ úEEpO^¡‹0tˆUÌ돑Ù)§€Sæ¢ÄNbí¯NÄHXĀC[ô<ÔR‘±âݒ5¯fkR`ä!r(²_ã!öšèÞÎՊÉZ4™‹;ß¶!cËJlùbÁ4߇ך#Ög\]«¢ï~QՅß4sÁMçîJ ûGj û³ÿfúÑÒV4ñ—íß·}çÎsžÌm¦à–+¤8â;ú͝öÒ6;Ϻã5ÿ/ªøÿÓûŸŸÇb‚Íxç¡UóÿË7oؚqõ®Ç&+F|úuïþ~iK¹mj†ã«fü_5•ýŒÊ÷;³bÄC]ÿÏÉçÆcç'Õ¹uýß·€îCƏOZ4ßZÇù­/L?œ1pçò¶×úC,ûÌGÞÞãÕZe¬w?i;¯Ý·mÜYڊ^þÑ5^6̬ÈÚö5ù~—VÆÁ¯þÌÇ0‘¶û÷÷ûå ÓßÌm¶`ü+—öŸûä½ç–z.ÌÕ½ïZÒÏýeǜûÜfJÛÝ5&>pÂùYó߅²~?®ñù¶o}F—6ŸÛî¨|™_.]SêÄ2÷¬÷±‰>»éü'K²î[êX†5n­\›agj-‹3ÿ(·õœ‚õs«f¸½h÷—>—.íãúÞOþþ÷öÔõ¿ºž5ß¹ñÿ‘ÛŒËë~]ÝÿçoޙÛDйY³f͚5ûµYæ¨d<’ì ++ÔÏÑÛgyC¢‡3–`vÅ<JiŒîþ\Ì8k¥ë¤½NÑâ»YðÓ.xò2lï ¥-yÖZ{³î9Ë;ƒg?4I­ª² /†EíƒñÔNðÔè'Á‡d¯YÏõRQ]¡kKÞGǁòRêóëȊ ÞG¨¾ê½w&³6;¿>ºÑÁ”6Rʁ„S5ëO2ˆœZí1‘¢'‡.âA2“b˜åbŒ©Ç>¶ɜúã0ê\—^iC/É$âA¶Šu ,90cõ.À¸]â”H  v= …88·¶’ç0¢ÐÂé 8œÐß)’©]Œ²–x~|Ÿí˜É-½~=æl‚K Î[…G·Äò &Ì÷úÆ'LƳÖ<¨°BžµêYٞµFŒÇcV©%R±ôùœ©ŒÛGϪ¦Äþ¼Df\ þȯ\ïàyV¿„5A¸gùþ$Ä6ˆð>±]XÜîæOSìARB´1X/ͨÀ97 ˆR,!pG¾ÓäÔBðß`¦!"ÂqW‡_« ÿoÖ¬Y³f͚5kÖ¬Y³fÍö›Åÿ—Ýö¦?™ßÚçÿƒ;n÷šSJþ¿Mœ¼]€k+¶¸§.À¥r}˜ÿyÅ)Wžôòû3¿ ëF¥Æý0Ïså¼v÷²·ËõÄþïœt3ïû“­ÿ#¼EÞÁû&ûûóôoÿ·\×|ÿÖ%ýø÷ä),›£ `¿.ם¼2®Íyþµ>œ¯Û8šÉ}É-¸êG/½O®G^¿¸âõ›>øÚ¬;ÐÌëêšï|ËËÅÎ;ŒçÖfï;W`ëý}WüӋsõQÙÑĖʳزþhÑ;‘º 9§ŸøíOþtæGx5š°õ¾ùð±?=mÑÏÍr}¨S°Cú¯E0›#þö™Go(m.ãÜo¬þê\T×ú¯øƒœãÏ?8æ>kÛé'¬Ý–Ûlá ,«¾?gûš3ŸB•<÷»k< ù—Lö¾ò7vÔºCþÆ5¨}°¨âÎúÉýNÃëÜmϜ˜Ûláhd^ÌïàµæS/Ú)ûìæºöÓ3+n*Â)X+}’OñÝ¿;퇹ͻܧšì×aÈÃ8Hæ0^ßàŽÚ琣q|íóí?Z~}æh˜^£a}ƒ«è×è]]øºÌѰÅ/ZÚ÷9äadŒÓñ:ëqskië2Æc½ßkq}Õ9ãs|=·9]ê}Lö±tö‘ÓßÍ\ ]x4+÷mCÆ}“ýºy‹*¿áÂÏNo+:ªð ê^\ïTù\¯}pyå™ yàSLW~Ñ^c° ªÿ\Ýãßµö±¢aPx4ÏÌÑ>8õ¦Ü֕q^W5†|Šõ<<ëʕg¦ ’#Ö¬Y³ló°= %Á׿çšvø:&’Êœ|æØ—tÆYݙÏ\Ÿ4òñõjA̳Ç];LÌõ։d똩ªµRÄõ4k×ã1Äf¹óA(y‹)<»9|Ãù.t {‚“šÿbÂú¢Y¼´`ˆ]`Ö®·®ä£/”ç¿·º÷̊ž*|ä£{ò<õ Œu³}<›ùÎók|¿`sÑûœå½`õ‰!£ëkYü¼Ç¯çi«¼ÃW’þÝ÷í FLåЍCàÔDO¦eÁItŠÂTpŽš–±€ ²hŒN§ì<~†æeO9j `ކ ++)„15ÖÿUŠ2!X"l‡òž¨D „Yö teÊøŸ/ú#Ëfy ƒ6b£¯+1Fó›Û±ãþóøt ž 1ûÝ0xðÌay;Ez%SÂ-5‘4= Z{!b…ÑS¨ƒX0ÆÑ©â£„c!D25¨©ï©±œ¸%dž_wˆU<?ñÐ@‚OˆG¢ê¡<eøËÈ]ÄÌ}ÌKÉ8}€pwð0÷Ï|^UL‚'áÀû9g@Ö&@ÔQfÃc^ ++;Pc^D¬’ñl5M°‘‰èGì, ˆ”È \NŠ 8 8(¥´xC”yÒ,¼E”òŒá¢‹p ‘>Ҁ¢B†®e3köFϓ‡/„1ɉƒ@hx&ò;™ÏsŠçËwŠD‚ΏâÛ½rZþ߬Y³f͚5kÖ¬Y³f͚í 6‹ÿõ±¿xÅüÖO¨šï|éòGWeüÊ/êqì!/`T5´ûç·—|å8šØ.¸Ôÿ?ºæEÿé›+ãÿ £‰Ã¤Ÿ!®~`mCÿÕÒÏÇðZþÓ7H>··®?Rñü=uNª|„7=ñyþf4qGÍ_ßSçÿª%¿ô¬—ü«\wQONs.üex}û3g~oOüùÚÊù÷{Þ½#ëôùüT¿<øºµy,Á–6»€~Àféóxvâ'¡`©ÏTŸ}èÀó3v«Eޏr ¸nSî½Où‚õ滛èÔÌÎ[2>k\Æ=÷“>ÇãºWTí‹a~ýAuS3»n(ØmÑx¸¶êF ±Û­u,CÝúûäs'àõÇûŸõHnse~×Ðûz¨[¿YÚ¦è³ÇN¾,·¹2‡•/×àµjûoÙ3OþÇuOÎυŸœ8´îïU3ï½*·¥ÂÿØQuV=öқòžU—ßÑpäf͚5{±So˖Xíj®õ¯ÌùÁÉù.XbÁŽ X¯ÙßcÜÎ3?×I"t³‘bª30GùpªdñJ„p‰—yá©´Navt&lmy”c§–¹Ç‡™ÚR¿œéОX]À£dVsw¬XM E*ú;R3ð«JÞ·£ ++¿ÊÕ´d¡LW¬ ¨.³±_—©³Ì}øvT’æ¯uLJÐ ²…õ!XV0¸—!í8j¢™)g-GŽœïNÚ§ÄÂé&ò!„ŒßóPÂþ÷† >[5#z Ÿ í,ÚÎød#«¹¹Zì{ÃÉ÷¦M/ ïÞQR=ÆèœÃ ++"à¦~3¿_”pÏH¦ –Ѳ€FÏy˜Ça-D€—Þv¬7ÂÓ­Fs8¬Æ€EÕ.èǖÁÓvB‚EàQŠp;q],94Ø^.`u0 .ÉÖÐ]áÚ(Ƶœ—åÃfåÁ…™«…ÁCjƍ¥Åöó>ק׎8+} ̸¦Ô  󳓼wøZSÁØ3¯‹K^N„ƒÃ#ºð/°WɒŽD¯'íéa=ÆéSì­vza ++¾eäâÇHd.>‹)0µ?`¿Á=‘<ŸþÀ4½Ha’2Œ0ÈG²¢•ÀZ¶WLbßI¾ætu@gðša¹t—x#a^ė: ++o]ñì]kŒ]Õy« qۄ&VB„«6NŠ vÈ~?Ê£™Öm bÌ`0&*›Ú˜PG²mùA[J¸ÍCHu+ÔZ©˜Æ˜€–ê*¦8Áƒ¦¦5¤` HÓoíoŸ}ï̹3ýyÅ{I7ÁgŸ³Ï~ž{î¬õ­j¡u`¡ºÀº§+ÐK»YÓ³Šönƒ ²¸aГF^À;"`g‹´­hß¡:ØX̙¦@ÄÁr‚å-jŠi7ÒóÅ ++õ‰ ͼ6yÆëJ†ÆûŠTþ¿¢¢¢¢¢¢¢¢¢¢¢¢¢âp@ÿÿë7Ì_zdçӅ¯Ëÿï-qécãüGÊù'œ~)ÇGÝí¬-žÜßÚñ‰‡o¯,(Güï'qöü÷.áÿÿJñÂ_~Á‰?o5¿x‚xø©%§ùØxøë ÿâÁKÿ¼¦ãOëKŸï„î,/±ßm>{âgç8¦´÷šãWsÜ»”ùàE%FýªÑaö¶GR*»aJӟvlûÕ¥ííØöۊ ÛÎÜûà R8í7O=—½ôñ·åTöPO#p×Èã9F=Ç~ïIý‡>R®ÓŸYòsöBñý8ßÁ¼¡AÞýW§¶\@Ÿ/ËË0ŸoEÖ$íD›ëEÐöîß\â´Ûqá{ÊÚ\6zÙÌìÏùºyå~í¸p֊ Öl+sÛÖŒLë•]9+ë$¯¥ÙÅ í³{ºnp\øôI4—¦²Á:‘æopþú5e-ÝÄþüQyæóg—øõ¶—þ+e<ϝ?3{w¤˜ÿŠŠŠŠŠŠŠ1¹Ç{±ÌÂÊâoЎ¹ŸÈb¼'hr®YZªÁ8/-Þ|­¥‹á~ aU 9+:<)„tQƒD,²°ž3Ø'¶2˜‡ŸÎžÆûw˜«eO~mì{᧟=î'Ò2Ÿ‚·éSÿ®ÇÓ2Ò*SaL^Š£¡×CT,-lði)Â"™s¤ñB¡K "æa’덨z8:ÐÔ;ú¤¶IókMªA&h",ì Èmˆä¶€ˆ}ª„ú‘¡vÐ#ÄDQ¦)¤WgZÆÎ!±„£ºíÿçÁâd4tj€= ++ K˜Ô?b²Ü'Š'hWhŸùæšA±ø&¹FЮB‚ “\äJ4ɖÖe²j¡A:ØВ‚Ëí`jUF=†é]J3&ÀC³vb¢<¼$Šö£òÿ‡züÿ7þiÆÞñ¥Gv®+¾Þ7c>—ãóé8Çiƒp¼eöé+˜oWCÝÎöâÿ?çûòù<ü‚ÂÿóÅ'¬?ÿÜ>?ü~þK‹¿ÀXþs&Ò¯ì±:‚Ù…w«#X“ΟGŸÙ·#éd¤ó7?î±¾ú³ :VG°°´sù“ׯÌùgn{Cº÷×ès®\Éqó’=L‡;§”\ðíþ©éºÁ¼þ)e|Ûñý›RûÒï.~öoLûcÖhŸËæ^xåè‰w7z€œ{>Ç`?û‡Žê]7ÞÏ~}‰_þâÇÈ:cø ×ÜÖ,(u®¯³Ÿ½è÷žì0?õï+ô9ÿÀæÄaޛÊö/‰ÓNX̼¾Lv¨ð`8º™‡?}`%óóÊæ½³Œõ[G­z†õ1s÷¬9ƒ>‹^¸ø¬Y³±§x ´ýæÍƲùPÖdíż¢-ikö”qY:ºà®¬\öHYûm‚‘£›û}þù/u¹,dëëö–u=òô¢[¹,æy__üv| ë9b£…˜[ô9Õ ¢¢¢âWMœ9ˆ.‡¬Ø²ð]ƒ|Úa ¯|t4³‚;€w^EòÈ7Ñã \! ++>ÐNb¶uÐ6¹â§|á:1¨…g› ^<µÉG«¾¿@» MÆÿ âÐ$ò|OÀå5ñêC}ñáïo1L!ÅU[ê;b‡= î#R8<½Ô*N*J¤QÞÂhÀ ++:"ñaGéÂ`ӑ¼œZM£¢]°SCh°ŒHjnà,o-MD4ôÊL/…È| h6iìÐX?¤†¢WX™¢…rÆE K|3(z!vô®FÃ(‘çAÀ*ÝiDÁCì=’x¤ §&E„R;ºÒØL€6¦&‚q6Æc–Mò‡§a‡B#FDD9Zb`gÞ[Ê1OëHÃTÎ ++"ùµÓR¥5HL]¦®êˆ´ït;àû%uÚÐBÓ)oè-Á·ƒ¶ï|,:XNB׺ÉófГ G¢‚Ì·âéßf‡AùK&äÅÁèC<Û|ÍûÑÓÌökCLÒA jĘóŒ¼_½=&Ï¡A3År²@Žþ§˜¡e+ñ£¤µM+Ÿ6,š«Ø)@ù4ÀÔ ‚CWp<ϟÀ¾R²ÉÃq¨óºTþ¿¢¢¢¢¢¢¢¢¢¢¢¢¢âp@ÿ쥮_zdç†ÄÛµyþsJ¼ôÂyŸx4Çþ–|õàùž?8ó`âçµwÝ0I¾õýÅ+¾Íyo)üzۛ~y©säî+ÿ›ó‘ ɜédñãÿSÊÚñãë ++{þ¾5'çXïÇ?RøÍÇÿrÉϲW|nˆR¶æþÅìÏîbಭ¥möú¾ê±>ëï=&˝µãÜÂKx.4Z :) QƒSaÂöbôûõLÒ*¡a(a’V _ “l_N‰4OЁ(¨bH‰BÔ8­Nã[Qãÿ+*************ôøÿ¿ù5y`|i·scáÊÇúöߐâ‡á…ë }$ˆÃ_W¸îþxûáN(>mŸûE%ÖõèïßÂe10?αëˆë¿ê¿”È~õÙ;a‰oûÕ¯,1Óמvk¬ËurþrÔyþózcæÿÇ)oœ$?ûd1Ӝ¯`PžõŠŠŠŠŠŠŠŠŠŠŠŠw à—Ö)k½ƒ¿âûµ‘òÚî{d®×Â෎”Èh/…7ŽÎq—‰ÌF®e’AÖ9+š\ ÅÿGøÚ{w…ˆ8v³‡BˆÖÓo)£”Ã‚s0)¿^h-‚—^g…1Zp”{ˆÑ#Sf,\Di¬¥v;8dÐÝ|Jàº<% ++°‰Oß.RV/¥ Ñ£3t@[!£…‘…­Nc¥ ý Z¡ÙtCIèi `]¡Ùoœ÷ÆÃ7$†”K »@¿ÓÕ*À…gçiptŽ‰Ê»Ðèr>‰¼I’õŸ~}ÃmÀà MÜ4Ò0hYj<%Ò0Hc ü:"F î!!h瑃ÂÐLÂhCÖøÿŠŠŠŠŠŠŠŠŠŠŠŠŠŠÃ=þÖk—=1¾´Ûùj‰kÿÔy³^æû躝݉ユ>Û4ãeæÂév֗|èŸ=xÌáç¿¶øçõáï¦óÿŽ>s^ù½‹ïŒ¢ú—÷ùê_òdòÛ÷:v;·§ó‘‹}æ™Ó™üö…ÝÛzú‚ëäƒ.á8n~{úü¾{ïöÀŸ„Rç @»®9~õ³ìÅ/s¼ÿÕ%ÏüR=õ¥¬/àxÿÁz†G&ñé_—êìÅ¿²Œuۋá$^ü7Æ÷6,ۙýösn÷ýSš:Ï»mų¹,rف4.—Ðçç[®x!•9o¸;'ñÛïøU;/¸ƒ×„ŠýÚ ++ÌϖÙ#¤|ݦ4Gð¿⾕?f/~kÙoÿˆT6ا[Ñy´½Þ*sÔörØ=¥¹ßç·®zŒË¬äyØZ<'Úþþו±^6ºð´Æ‚Ûy}*ìï¿3­Í¿ÂXßyÅÞ\¹»Šÿ®-#ώõŽX^rQ\ôÄw$ûû{Ç㹣짥£ÿþ)ÞgÊðýJ}8}˜v>ßÏÛ<.#i\àÃñêח²E†×ˌԖoÒ眧¿w—ù¼^)û¨íïÝ$þþ¯—uöàßÿáOûõ/4ÖS›:÷‰§>Ë^!ÂÊú𭨨¨xϑâFé žñ`—2Ÿ÷AÊõmèì© ôº˜r'ÏuæÐµFZgœ¤›{j=r­{¸¼ º3A0€RX©+al²©/-½¨háéž ¥¢« ]æ/jӋ˝ :lÙ%‚€•§º†zç ++Ÿðy ´¢ëµƒ‰¹×œ—À#Î8š¡\î ²Â›ìÔ1xX͋4~4­4 È/ƱÎ2‹y ôŠL—{˜ŽMׁm´‘›Z„UárA8Ó{(J¼ñ˜\ê›Ó³€šM¯tkOÓŒW1Ù¾KՋ¦‘´È~®ь¸”ÃÝÒ«ŽL©Ò½•ýã©-¹ È2 …ÇÚU¸"-AꏄS}@f'è%¥UMfæÆc¡ÑÖKùªl–6TQtS­E³Ÿo†*¦µ %$ô31:KÓôˆ ;ž…4>T¹¢LÏ5A)zHi´J‘Ð"zë¨\8:ê•èéœÄŒJëé=Øxí!óÀ«»wŒ¯8MYÈJ,ýdPÆH+“lrÁg;ùÙ(Cærßßè Ý òŽîŒQADý‚wQPÓ5‰~N¨¨µÏҘȼÔÚÑxŸ”8 §*£„h%ÊèhF‚ƒ@ :j©ëÑË à€˜rhv ì¡ÆzG¿¨PRº´âˆb©4ÞÎÑ6éS´¦Ñ@ˆ&„Î|ùdÞøR:`uÒo'¾Ý*‹ûu‰—õo-ù ¶¿8ót<:Ñͱäm]À¶Ôßé³ôÎsÄã£dæÛSYâéG÷ýc.³Ì›ß–ÊÀÓ¿¹yç.€­d*ÛUîuÕèf±.@›Ÿ=Ü+ÖY3ó!¬™$ÇÂüÔ/Ä¿yê¹Oå< ++9Ž|ná÷ÛÞ{R[~‡>‹¿µìù\–ãÁMáð·~ûªý\ÇÉonú÷¯3—±îÁ*Ç×m+±é?¹wÅsì;À¹-‡;kÓºú:}Î=m߁f©lg—+GŸ»—uÞrÿDêÃ<ú¬7—pÿ¢ó<.Û§4kãÍo.gÝþüÉcÚr}¾,/ç˜vÞ¤²Íe,{?{Íý»úè^Ùe3Ù#@EnËÜÒ÷·ŽZõ —EÃqò7Lâ°²xQ´=¦—y¿xôhö°JñzÙ9ܬ³‹ž»é. Ùsag_>‹I·¢œ ܖ Ózeã½Ìp3GmÿÖu Ö|°.h°·ÀHy´½Ž-ý;{tûÙ? Ù®t?øiœµï»w7ÞÜÎMåyóÀM°ŸËL^g§5םýŸýçT–ÿ\QQQ1™¿áœÉÎ:Dÿ6<‘1*NÛûnûX[é{±¥¨=ÅE¯„ˆîÆ­*ÄYS™Ï1¯pGi4ʬDšc“ w/‹|°iï@4O ++ö܎HïfH—M҈žÎIë­VôÅ*10ˆË÷‰2¤&وo8P×éÕ"Ú!úŸz‡—Я ++ §ÓD ™yE) ތ|“ï{`Lò¾‡ÂÀӔ÷¯]Ž5§R ÇZM‘΁æ78hæ`®@íž…·ˆ‚§^àÁóxš{ š^šƒ¶TL YhOËÈÒ@€ÓE3i(=œÒ5V>­^Z(ôVc?néÝÀ vwPÎGÙ̯ °ŒHÿQ„š ð»´*Cð@†õˆé2ˆ¦AA‡%æQ¥é£Þ+PÅVe†³CršˆÞɨÒÂÔ?{F,8Z½ ++ÉÚi°=v/-?¡°BæEx_û `:º'­zrdß|i{¿ ++8ÖÛæ9dÒ ++4;4”†ÓÇc8¥F÷m²€¿Àá¨MP`;ÓÈFìD,º¬4Œ#tyÎøºßÓ†—<=hÿ˔½žŽšFÒYì"ªO¬š<•¤Ö5¼ý€xö’×Þ"Ôy¼é¡•¶´ó!øwXÛQփ¦ôsKbí((LzkÅҗƄ–m²t| .¢òÿ‡züÿŠ}÷m_zdgcñ¿aξ³™[tt|y‰A¿eöé+˜WWCÝìÿÎqþ‹Ï̾²›ãçQøÉ+Ox9_©»µîßï °£ðÿcu¯¤ö€#ýÁÙsþ7×ÎvsL|Û`wiÿ܃&yÀ+¨þ¡ ?6Á+ŧ}öS¬;p.†ngjêW[_Ðã²Çê Ø›}êyø¸IG #ÕõpSÿX}{øÏkÐíÜX¸ä±>=/ö3þè¤ÔüÁk¸sYá‚Ûšƒ­e¬Ûº‚cÓx|>çʕÌɃÍêyɣナ}¤²‚¹ç…Ó½|×Ór™³ÌÍn(c¿zôgSXs2Ÿ½¡ôkÆ]#7šƒìaê„þîï,ú)—9Ëm96•­£Ï='_ø¬+0Žyâ©E°jtǽM>æë/M}¡Ïú›ÿ„Ë¢ç>ì)^ú3KćPÆÆ)\¼©_¤1žÃž€·[<Λ½É«í” ++Ìý¨à^|ŒÕôøLɅpèÌ-oGÃ1´p%§‹ XOº4»2žN :¦àa-ñô¥ŒLځZ(BH݁C½{®ƒ´tº"ò˜ì#´-½€|£/‡`]ïèâŒÁ ++Ad(§—8:üVô)Ë8ÝÖ*mé kFÿPÆ¥|ÚY²}´Áò÷hʇ®@ç#9B“ð=îÌÉý4à»!_ æÐӏÞjÀ/ÓÛ/½àë魐†Ÿ†¸Ð¾RŸ$(o£­¡9ˆÎ‚1ßûv &öòÔE0®ZÁ·žÚ ++²[Dƒ÷CO‡¡ø ÉÿMËF&Í B²‘T‚‘&&ôˆšÆ£[a£sÊ;Çù¤ED6"ñªCÇpS(&ÿ½k¹¬*¯ÿmˆÜf”1҄R ++¶²ß ++”R)Ny9à8Î¨È ‘c¤%))(°µMIú€„Á'D*L3I‰´cEŠ€2ü#jEhÚµöwÎùïÌýš4¡"ó­äÌãì{ÎÙï{öýÖ^‹šìh.d30jÌà~@±Ð†–AVnsŽx‡«¥ñ+¢k¹¡J;%¯ŒMÜžW³uÝ^èÆGAGô4D'ƒÀ´½ÞµÕšƒe<í“Iú@ëÑÏ¡ûBfŸDò«™¡U|¥ ÎÆù8” gd´ªï§^7}¾xçäáŁávù|-ÔÞ'ƒ_Ü^Ú¿çÓÐOu…f¦SÀ„§ê9³»ÔáÑ:Y|{޳ɱ¨¶;‡&¿ÑШDÓ¨ ++´ b~E-•bY[KµÖH÷øÂÚNŽÕÊúÀ³IÙÀ«GäS3cÄøTW®…öº÷Úðã0\¦¦F€÷ïš[[1>ý2>±nÕgŸÀÇ\CãŠ@÷ø€Znv X0¡àh^o¸©Ü£fÎG†;ÙIâÔá8DQ ++´´óä(a˜'ƒÎ0ªÄÒÀ·ÎJAO¥#¦„°ó™ÕÍQ¢•žƒÕª ÃÜqEϵ2& Ý0  “ÑyÉm ê“Ó¦äޒãÐú•.h$¡«“ISÉ@u’QÑÔöG§ ¼3fG1º*”ÀWîBŽDm¶¡ç"í¤!@Å:8Ä®ÏÑ{ƒ³mžè—6qÜ;;è,àuÑ<ð(ö×4áu!ß81V(GáÈË)›BûŠD®r™½È“£‚Ö@…’zjÕø¿B¡P( ++…B¡P(¯}èú_¡P( ++…B¡P(Š]süÿžøS¿ìÞ霑Wüñ½‚èö¹03}|Ÿ?ñá›Ö¼¤ñb¯Å±òÁý*¼zòÕW¶ÏÏÏW?~ÎsoJÏnõÀß_ý… ~(÷•ƒ?އ\/Üݘ;¼ë[Ú|ºf ++…B¡P( ++…B¡˜ÃNûœl̍‹_“KÜc¢ì¡M¯ÜP€±V'×ÑËÎ÷œøWP;ï•Ô³œOӐ»pªC†ðqD§“ʰ–äûФièGKÂà­Áø9&ØdjÌqÛŸïp‚Z“ˆ§ú¡£!7޵}<Ü;ŒÕ- ++Bi÷ŠÜDÇD¸»ªÛÙPMӖM–;°"à4þ¯P( ++…B¡P( ++Å®]ÿ+ ++…B¡P( ++…B±+`Žÿ¿ýÇ7»sêî£ûš†ô´Îÿncÿiüøã…·oÃx´|Ðð>ü¹½ÞÓö Ô¦Ãß~g¸ÇuOí½©éð—PƝV8ùøKŽ{ãך¿18¿iÐÃ>ô¹??¯/эGWÚ;êó?0èáŸðÂáMϟ¢ãÑ Cþ{ö /¶óÞò>MÇzg½ýE£mÃþ€}o9KtééôÂ7y}ñÖ>-ѐ_µ¸O[{Çêû»´*Ýçe?ãÀuߒ½Ɗžö}{öםvdw5gæ´ç¹ÿáüï|¸JZê¼é·íÙ×ûþvÃ÷eo„«’—óî‹g/þФ…ÚéîóïÎg?!šü±Ë˖Acýž›ÎÚ"ºû®Ó¿¡Ýs~Ý}ÑëŸ_[ÿ›­ Ëq¬|ÅQ²¤võ¹vqß6çm[v•ìáHNÊwü åÁìÖ;:ü({?BËçüù·zïëŸzøjI+Q4ò7/ë¯{á×ÖÈuÕwí·eÏ>íÅ[: yãƒäóˆö¼?Ãqú“‡È¾S½\·²ås~ýü#Zùæ×ÏfYŸÏé=*‡íð‘=×KÒj‘çí³¤¯³Õ[ûeÙ¿b¼”ïÍÃuÓ{[nöÄLëàß:¡YüçEÏÞvzï‡.îÇÕewñ¸¤Õ"}bà!ÿáâ á²éž'û†ŽÄqùÒÓ•´Ø•á¾aïКٓÄ;€n«-Mü:nÁqÊÃ÷Ü&i¹ëƒ›&®ûÌu’V³”A<>ã¤‡îºyR_¡P(~–è¹­%%šn—ÚÔ²‹ãDúrºÏ¯2 z1·eðÁ^HÝúä›þ¸Ë…YlÖÆzkÈ£t2t †jç^9ãá!Ԉ’„lc-dãkÜ^Š#;>”LhÚýBÍœ…«H¡–ýœùÉ/äGn–i4w=Úö7ë íØ žzߊ }y¶†ŒWž3-W†Iê8á1ßÔȆKœŠð>‹.ˆŽP+rÅ©m︸Él*Oõø2§XÇÞä1‘xϾ„; ›í„^‡O£t¨~ǪK´1©.§Ò•µ քy…Ôu*íÇP Tå/Ñœ ++øNO’{F9ÙÉ:/öܞ&6—™´ðQ}¦ù"„À1‡Rào4Mۏ€Ž pò遀aXQ(n*hÙ'Áý&cBJ´@&s›2Вh/ÃiÅe} Î ++}3*ʁt“ðÙÚF<;3\+­¨Ù‚é+³Mš#æŒë\ù1´paÇÄ ‰b÷c·Â4:I~fÎc¿‰ۜ‹”仆S=úmíë_˜|ÛÎ@³5£ñ…B¡P( ++…B¡P(v ÌÅÿ÷{ÝqiçÔÝG«†xþ•‡|ÿ$‰¦™qçMì+Þ¾ß?uþÑf<Ú¿ÅCƒüÜæ_ü‡çwяG«Z¬p:þ/ñÓ?ÅqÈóÇ}»ÅóƒK¸ÿÿ?ì¹6Oö–qÓ·>Nó2çÏ$ã‘iŸçý÷<ßâù6„E£-í¹WãX÷™S¿Õé Z‰5®^Òçi:.¿×k¼hö_VHš‡\>ðþêÀ3ÿµKË·Þÿå4 îÂtÌþè!í;Ÿ?çiIóQž·ïŸ½xö„k%­‰³>0<ïܯ¿ÿ`‰ç›"1潖Î]ẃ’æ’ÄK¯lםÊëîIâò>¹§h+þëåsg G€?Ù¶´qk/ò&þâ©Û%-E¹nÛÐw~ñ¢m’V’äeåÀ«07­ùºp¨$Ù|Ê÷}Éüə=ÀI>Ÿ8ço?ö:=I#ñîg†¾yáìÛ½¤%#u½²•o~ށø¢³ «^wʺ´Žs±ÛÀyÏS‡Ü üß]wÉPŸÓœ„¿\Ößóö·¬‘ö«¶ó§?h¾~ÿ›—þº¤µŸn‘f–õuöŽ+Nïx¹ë/Âÿ؀㬭¿µ[Ç0¯ýPŸ—~f}7ÎÙ®ì-û3§á8ý ¿±Këêú qùÝäy.)_8oZñ^IóÎËóŽÆÃÚÙM³!ÈóÎæ‚K¿¼Ax!é»ÛZÙɁXwïZ¹g(¶‹ç/êË0ÍWØwàqLó>ÔÒ.æón\ÿtÇWèúĪ!ŸÓ\†#öèóùÎ?ºè»’V¬<ïсo²föä…[àº2lžã\l?n¿–Vû1¶yÑÜuŸ=PÒ\–´Õ­ïÎÇIX4z~IßîwìÄm’’Ôõ%Ãx?iö¢ë$­vsÖÖ=æÒÞ~€Ì»®ëKàò{ÌcݜÜñbŽøQ¿´èw·JZöRöû–ÌÝsã’V²Ôٓoä¤ì}£è¿ŠÏ°B¡˜ÆÏ ö¼ƒ~=ÛqÚ9eÇP^r_™¡{ÌkTˆÊ¹Øš--£6d„Êe’ Ù«Ùçf-NìŠÛFDQ"oãÂXe4±âK¤ô5¥Hl(…6öU{d„9¤RC‹Ò0 †J¾îPI†ÀÙPMÀ[FµÂÍ0Ñ.àÁ$<ŽñuÏú§Uz-™jc,"òíIêÃe¬NŠy1ú?.­ÚјÞї›P68&^ç3£Ñ•Êf5'/YÆ31%g™ÑCf·`íâÕÌ£LÌèH% 5¾„uu‡ØhˆŒSÖs‘sW†„&(|Lb,ÓTƒ÷@ð›Î (¾œ\fÈW²^>2ŽúG£9´JëÌ\Œòÿ™ï!ÚqÈ¥Ðژ YÂû=éq×¹ú FZëh_%”Ö6÷Á°\(ÎÊ`­C uqU’p-uïÐ]!/olÂª6ŒR—X)ԆLXvxË`2ŠH®ô蠜0+ >És@‡ ­ƒÓJäû)zy0”’C­²r<Û£]Œ^ڃMPL 3wÇòYÈÆ.Ëç°¢èËO{ŒðħwmŠQ$÷ñ Ÿ“‚433ácژÇéýíÑG‘;2.éj«£ (¢ƒáfÒߚ’^äÜ,Ç:*°='s,cˆYjÚ±¶ü9R(0A4;§(üé8qºÃÆ8<‹LℍXÑ`f–#Q+}ÅTT©$Ya†`oʔ)Lú.ˇŠ8=Óº~xR‘4T/[®ã&ÌÇ;ð¼0¢¸gz®†A¯æôcnTd›VKõäTaðpŽ#—Ø‘Ôáä"cvv–LuŒCzÆ-j‰ƒÍòᝦ"‡q"Á ø˜º¾JŠ ++bRp0jü_¡P( ++…B¡P(Š]sñÿõ_~ü};§ŽGçOøüq¬ÄϽžÙsîü¤ÿßê!žù+ü‰åZ?}u8ð ¿úãÿ·6/=ÐÎÏŸß2Ä8§÷ÔoöÍOÇà_šˆ—_xcg·’¶a𠜎ÁKó*|iÕ÷vŒm á6gãžØÅšS»öé_¸åŸ–¸°«rݝC¼uz¯úƗُ~ëPöé=àsqè³fO¼Fb¸¥‹>?ÔËK‹/|Db¸5H,O¼çÓJ\xþ8í'ÎÅ;žxÿXör—©xëšÙc¿ qSÛbÔ ++…B¡P( ++Å®Ž>6N6CΕdœêr Փ"ƒ×ø’mòR–’ÙdÏ ç‰;Ç]H9Tª¸BS<“|u1'ãs¦ËI&¤yú¨WܯøÆ‰¤up¿y2XÁY:çåP’M)à2µ¬Ã"Š!b¬møÌX\ϑX€?§áÒH^Hϧž„‰ŒfÇ žÀBœˆcä–* $zdØw)ÝÞþ5(È~4ä+tZ½öÈ«……*Ã?ª5”jiƒHãû„ö§íÖZ©âI–¢,d»æíc@7`®cIXA­Y ++WPþ ¦h)ìá©ìÑÔZ¨ˆaI¨@gÖ%…²¹INKû7=ùoÿ+ ++…B¡P( ++…Bñڇ®ÿ ++…B¡P( ++…B¡Ø0Çÿ·íœÚ{ƒÜ¥wZbO®P( ++…B¡P( ++…â•AÛ;bS²&Tnw·6“C¨‰»ЧÎw¡D©/ŧf;éyuÑì"ñŽ£NÄLóØ<¯~ï‰Ë:ß<Óù®ÝÙîGoµ‹¶;#iýuNè>½‡¤•ÎÃïÉáyfMBÚ§ÌÌùíñçm[v•Ôer¢W(>„Gã¸!œù h¦,ÏÛ<´Á´wÜ>CÞõ£·%úÑIN´ÿûÈ ¢-èC§;xÄP†u³>-i¦J>7-™K;x…èúÎClŸ–v ŽS¾ç6Ñ̝×Ù3ƒ/ÙªN{L<Ò¼/·C‡v»÷S¿ó½=ҖOø’íèu¦P( ++…B¡ø¿£Ó˖–i>ÅîÿµâºÒè/Ž¡„äÝÜj¢#}ø˜è ‚¥c¡¥Ü’ðRH•´šè̝iĈQ±.|Øʞ¥HkÁd+>H]¹¦°æjs‹t‘f„&„PñÄÊõFµÍÐEš¿¥é ‡{Ç4³ƒ§ÞÎÞt6¦l4í]sР %;,J éè3-¾~–l6W+Óû0Ed¤š Ò±äšSÄ{¥¢+ÖbÝAgD*æáŠR¨Â–«ÇӍ7Ã+Ô}£dÞôOÙEª¶yêì™B÷Jc¨îf--éUç"½Ù¼÷¸MHxBa^#ïT#«ªyhbÝD}»QÝË4k†Œ´¶ólª&[‡•Nm–‰ué,–0tMŒä'P6Î:”¸p±Ñ÷ƒ’›ŸwLO–^¨O‘:”/ç‘Jxx¬s¦"ƒ…ž„¼…M»ÏfošÿŸC¾S ÍC3 à9è­á3Û׏|¢¦q­ÐU ¨ï¡4!>j½g¸;çÖ;h€j,³‰+!ÚG&šm²[R¸Ï¢±ô«l™2ìõÝD-ïF×ÁV ¨tÏê@›#¨)¬=QŒæ¥Ju>V+U-GM{Ù¥©¨Ÿ™ô>¤ôžu½b0 Ƌ+);‹51Þ†nÑÉ}DmZÚN0ZúÒó”£ M‚ë"}‘a4j¦–H)í^‘R‚(z ™÷…¾©¦yÆ¢x\Èân.†ÞžFè™è²’O´GÕø¿B¡P( ++…B¡P(¯}èú_¡P( ++…B¡P(Š]süÿ¿ùÈ#wNݑÿéo ++OÞÅqç?Íóß§'Ÿûæ ù¯ÆóOäç?9xÈ¿õùsì ñè¡áó'¼pø³Ïo\]4º³ñÂ_ãœ‡Îøëö\g:nû^Cž.ž½P¸ôÎYáËïÛ®»Ç{øÑϵ´ÔóÉg†=w}aí7„go“\·|¸ç³‹}dzwâq/ûވ#ì¶Vøë68áÄÏ Üýuß?ù>¢nûK—~í춛[Zð1´´ñP¾wûK¶¥Åœ:^K#_þö˜Ç„÷Šp÷7|ù?Ø}嬤ŢzŒ ++…B¡P( ++…âC㴓ŸS™ØGÑøá6Å䊯ýç’Ã_BN.¤Z»2p/„&1K\À5þ¾m{^lÍLC&‘­®Ì%±(¨!ç?´lÅd3 ++ün¿ÈÑUî•ÀBÒ»@*¿Á§ðïRQP¢7(y²!._Mˆ¬nÔ@åL­x¤åvŠZ½÷¶zÇå#êޔ‚ûáñ¤ö·vB-.ôÝÞo¼K5˜‚ú/f¦ãô»’j;†ˆʦužwÜKPê#nè>¿Ãúÿ¡üÐÔú÷Ñ'—õëԏïNnëMfÆ£Ë&~ØïÜnÿ¶.í?À×®ù·ö»ªa·´´å8Ö?¾¢íÁGV¼äå#{ö¿Lïù¿}i_öËïÞ ûú]*rÝõËæ~SØt—ü¦‚ü.rÓpݧî=W® -mÃð»Á7þxÍӒ–;m‚ë[{Ã¥7®—4vږö÷Kûë.»ëŒÇ%­¹nÕð»È川ùXŸ'~£a]¯¹ÿM_=tç–vüPöÕۏÛOôL‘º¾bø=è¸Mô0€[ÚÃ=ûÛ.¿}˜®ýÎ]¶Ðï"‹FoúØé×®Ü.}8·1 P( ++…B¡P¼ ++×è+·¶Ž«1q]‹Õº}¬±xœÔA(!$‡…uÍø+&îÅÏKJkSu¡Ô~=op3—CˆXV»ÿaïúcö¬Êsß ÇÛö+TÃÔm¥?¬ç÷Áq5ë\Õ-´å+à€Ñ@¡àCÔ¹fšø0³di6²U`(¡™,2a#Nbp¨DeP? ++"Ãf»®sÎó|/ßû}_âL´÷•<„>çyιÏ}Îó¼Ïùîû\W0%.Yêε°1„¨Úº9s‹?–õX«sUT¿ãÉA}Ÿ{ÔQI[ƒr™Ukr$0èÖªÏ_»òpø®¯gÀkÿ¨FÊ ++›ÂÚKwÓêؐ;ï¹.ÎÊ¡Å\ÖÅX+‚71`Ùm”mõ`9걖OèˆSÁâ’H³i ’F߬U)êˆÕ…WXi“]‚&òà2WöӓŠ‚p“3 xc,‹Q¬ØB!¥(?Àj±lÓ§­^qs¿'÷¾Ï.º®‹y°@oÿáH€»}fß|…•;F0á^²;Ĭ±l´š4¨‘rÇ¿`¸L{a)™,`¯ã0C ++²$^Î“‚ Æò‹AŒ ^µÞx¬þ$ÿ_ @ ‚ÃÓñÿ¬Þ÷ÌÌÒ#Çüxüc~Õç¿PÏ«‡ƒ='ýŠçަÄùµŽÃÁÝ}.üêƒ×^Pö$o†ƒgËõܰâ§Çn+ñÿ˜ÝÂÁžybüOϓÿOç¾|ÙÎG+ý;ÔÂÁ•}[۟|ù¿µ8¾­¼÷Oõ÷Ývë¥jY ++5&]÷",ÅñžcÛ¾hUsWîþkqÜúò jem¿Á®Òãñ÷ýöæšÃ]Ë ¸³ôïã8N=ù’ÇjYÔõ¾½¥ŒùûVÖX½Î:Ô>lï9ñϞºêw¯¨}˜(÷}dž¯vD-˺ÆÀŸš'oà¡ÞÎñ¼}¥Œ±ómwL¶²Ôì\Ûk4LN=q]Ëhñø #Zënne-¿»¯sü¯Ÿìtª-ö{-fæ @ ~v”˜¯vÑÇ`ºÜñì½&¹=“ªGbÓ9foTò¤Þ7“?æàË=ŒxRÞI1Y:Ôz爣2fL ++ÌâÎh#¶Øólqã.v^«öV§ÎfçP»å)Ɩ O¾woJ²¬É’OÎ÷òÿßÒÙkË]$O‘ ++HQþKÛdÐlÂù@QR«Ì@1³Ý±6JÆG]bµÎ2p‘!ï¿"Ï>#öŒTû(‰³ÕÙu9Ý-æOJ¬HÉOxñ^}È)OÑ$¬‘T°ªy½M0‘®Ùd’ù3‚Åÿ{,ÊÐsc"<‚N1³ÿEµ!ÇÀÔtŽl¢Ü|`:4í³Áp±çtµÏèþn(¥µJÕï–â–4øXG¥àtf0 ++`L` cL=“ÕÑ{̃·¨Ëat1GLR%ß 3AVq@Ní^enHžrpœcÍÖave Ãê…VŸº &Gt6¸‘ü‚ê·¨ŠN…ÒÌXð‹¦yA k£Çãu×'*:&ÿ/˜;?Ca2µ™k1‰ÿ @ @p8`:þÿðuO½nfé°í¹f`ù؋V<[÷·k;ÜÙÇó×<æÜ£Î8¨ü=±Ö5_<úÁÊk§ÒppûâRŽ÷¿å7¾Ðòâp°¼ÄtÇy6”ëÏÀqÕԪ ಠ íÙùžÊè yoZܝåž*ö°‘7üàe?.ç­6ïíyÉw_ù¥r>+?,-õ{ïî'{®žj8(U/øëÚôÒ/ó|öI[üŸq畇\\Î瘞íy–}✚3 TÛûÿloç68ÔÛ5ùé–÷ b®qìO-él»ÿæój^€±mÿ}Œ{nƒ£ºûΊçÖ\ë[^ÀŽRvŽK7ª–Scñû{[–ݼ¹öÁéևåóð,ÖÞgß°õ+5·ƒQÊnêí¼äÞ3o¨¼&×öNX܍Õ;¾¿jw-³­½õ=Ïâ8_Â5Ý\9yÅOÖ¼Ûø+w#Çg˓'žÜò%š-w÷9ã¹Oõ}xïѽåR¤Z¶«Ì©·ã8ø‰s4ÎGWýy×ÑÝØ¾âõÖ| klm¯æ¦0¯cÒ_Zí´>×:ï*}ŽßŸüǚg¡ZN‹[ÜÙ9Î#y½¿KÛk{ÞÇÖ^™/³ó:ìíëÜ:uc—K«¯¿±¨³ó¥Ëw.l“² Y²Æ,sÕFw‰bÝ9uòÛ5љ°” :Þ·½Ö.Æã÷jdÿ9ºM,Á|m?š1æÎ™”"ãÍ1Çà)–«èTŒÇÊ%Wê”÷[gLAÌ@… b‚¯`•b”ÞX¸Ë£G*J¨=¨20GXGS^3ŸŸºÙrڤıð¬){†‹1EQ?Sòça„1ÊLj‘ŽÓûæÿ?÷Ž— ++åù ø¶¯t?»Õ9pø1@pµ­ñhÌ<ªtR¤A!0JŽî[†Ú- UUö µãƒÚ‘M/sF…Bõ_:F¸µÁh%£[ ++»çN#ɝ& œèƒj×XçK|nÄTÝ³ŠQ±sqÎïEƈG!¢íêÁ‘|Œ[ÍqqªÄl •1¯³­9"¨Ýæ’Ûb9)ësIá%þ/@ Á/?dý/@ Áá€éüÿcïØtßÌÒ.ùžo[ÍU'+G){¢ß°sê×ÜñÔòџêó}oYpá}5×9;@ @ /zÞÃ\öÙ]vO¯ÿ_rõqOϼg8ø›~ÿƃKßQöæfòùßÔ¯ïG÷Ï/l<ÿ³ïQhž¿%ìëËÆ¹òoïõâÇ÷~ïîyûOßµ©îVQW^û]ý~ëñ}Ìz;gîU@ àX“ÏÅSR¹H¸mŸ² žÇuÐkfŒð-ÌÅ QÖùsñ{Hþ¿@ @ ‡¦ãÿ×ýÁ‚Ëg–kKœœÜÜk~²æ'Ý › 8ÿóšËWÿ¤òyk=\S®_Šc×ÚW}©j­;5l(\ëã|þWôõ<ŸÏÿ²>¿`Ç~íó<´ÍÃÁ¾r=ó>ëÕy>Æ{& ÷ø)8NøÜoÞSòtŽÃ¦5Ï€ãÞ|ÌO ?¿ÒjáૅsüJÛn<õë•gß蚋pe¯U°ÍžU¸ÊµŽ¹æ ì™'‡a²çšÿ£Çþô5u?„R•‹}{ßÏ˗í|´–U®É…ƒ}ÅÆÙ¹ô_ÛûA]߸ôƒ5•ûýµÅγqüh߅߯eÑÕ:Y܍ƒúÈÙߪeÙÔ>ì-unƱûƒgte±õ½ØI~þóøÌDÍÃHM›`iÏÑÔþO×<Œèk{U߁~Þ·rkÍûÈ:Ô²Õ}®ÅsËÏ|´ñó»Ê}Ïý¬yÚ5îþۋ-űák§Ñæ^Ó-¸fNüS–tun»c²æ„¸¤«?÷ö:gíÿàI•/?5;÷•²Ùùò'úö¶M­x})‹ÖV݂ŒpéÏäÄ¿bÎ<ô½ŸßxÅÖ'ZYëÃî~žßqü»¦êsdۜøX¯uñ¾#×·2Ÿœ¼Ì@ ø™1¢ žsJ¤KÖåTâl$Ëäf>Z•“²øù/dÞÆXE‰KÅ{ÊÞåB"U|HQ{å½UTn×dÏǧ¢7É&Ü“Ư½›ÎË ÑçöÿT  `€íâ~& ++vPµóAwÚðshÂSFݔ°bQ··(ÑÚcb`r¬0ÏyíbäG2®¡Úâ­.‚ð984 !{Q)÷ِОbí1Y¼JÔ±Go· eh„)“RNø‚Ó•C=™˜ZqlÄù¢J&ÃE0É¡íX¤ ,œ¢”öÙ)›àI¸&WÞr¯h8FÂx¯BáA1q²sÌ9ØÚRv:ë^ê#M¥Y´ÙgrÑS †Ù'®Ösž¥%¶Ëé€!mãŽûjL·pºë sG‡ ù˜˜õÿ¾•3ŒÀ¹H}"qèoüKc†Ð(hµV™‚ ° Ë\â©&AÝzLÌ@xÂÄwTgPT„ð9PÎ>â‹6»nN¾@ú½0™ðsÐ9€ë‹v„¦´>µ U "%ªmgÇçŒôú˜¼˜Nݘb¢ åŒÞ9Šr•±Äzj½ œr|ýxôl$~Ïׇ@a&ÚÌZbäs‰7BâÜ£† &‚‡ÃtѤàèòáa®<¦»ƒU6¨ìÙbTŠ’*Fâÿ@ @ ˜Žÿ_váǾ;³tØb›7à8î™Uëjœ\»áàšŸÜÂó÷ìÝRãÄ>“åzƏ×|ñèk|U¥áàúòw†ñ|SúØé~öÍõ¼ËÃÁ®R?ã׋N}õ¿—óQáúµ}lþŸïùõϕ<ãíppe¯=¾ý̕5À[ؓúvÿé’U¥]hçõ »vW¼ö‚r>y3lìõÍßpð]%Þ¼A»5öÍúOx ÖBf¿fÍ/Àù÷݊cå?ñÖr¾ØYc̟Â1±é¥_.ç}Ò ªéþðÃüHõ³w5&þDçÓí÷¿;×|„ *ÿÁ] ;»¶üýއk>‚išòûû²q.†ËúöÆó>pTwßYñÜÇj™oq÷]Guþç|¼b¢«ó¶[/=PÊ\ ++5~¨ØÂ v>²óèRæC³sý<¹ ++w•:gÏUXÞëÔoüÕ µüûm)[¶¨³ó¢©E¶æ#ScùO”1ށãœý¿×ò ++\ËÓ–û˜Ã±åÉO®eÞÔ²vsï7^ü_¥ÌhU}¶¾ÜwŽMÙ½­¬åiìém9gjõgj™³Õ/›‹?™«pÅ_lù^-óml×öÏÀé·]ò•V¦«-wNL×ù–Õ²ÔrN蟑³®êììò֕û˜WðŠ×_Xs#øGÖRvûHëkß­OÕÎÕ½-ïü—_«9QÕ:—õy ÷ýeÍý@Y››çÉŸ³'§.ª9Þêڇ Ý8œóÄË~¥åi4îŽËz[Î|ÿ¥ßªyI×\ 5ѵ÷g·œ]ó-ðœÖ²óË3ù;,[²©òDŸê\ÚÓ÷}ëÔÛê%×q“”ñ›Äqê£kÿª–ùÖ÷u‹¦ï»ñêZ–cµs׳¡”Ât¿uV^ϒ7‚óü9`lNwšã3âÀuœ¾çÃî48ÃÑýWEhޛà­ÓøE…Ó…ÍlTÎâ2]â‹xË3ì©G¹ ++¸6{kø5FiFöápuN.b<ኒað­ÁP&/3ž‘M|5¸+±d4ÅPR°-¾‹{ñ­Ÿ´Î>Ã)¦ö£Ó ç§~tJŒ²$kÒ/ŽÉ YqÐ{íueUà¨u±ÒÀˆ<“[SƽôàˆgÏèçÇ -zë}ƈÛX3q Á±&„‘ø<Æ* ·m³i®¼¼á Úby­EÏ2gfiiÓGŒ#S |‚ã-ÍSŒ»ãÁÁ´Á³‰>Ánf%`Ü/Œ+¾w˜Â¨ +–Ä+9…`nˆ¹Ë#Áøb²̱ÄÔü×ð~¦‰àSˆsȔ| „w &@Äw &Å:E ! `:q<Ñ"`8Œ 1|…`R”ñuJ9¯< ++1Çbjãl™ŸÁˆýèüX^`j¾â’v>Ôg?3d×AƋ‡µ]®>!¾õ™ÐÀwKÀûs‘/¾}<X•ù†1t—+ó ++pG*s ø3`rÂâÂY¢øêÃHböp²¢ãÎGíA•´çx3Cc0ª ++•Á°Û–W;S?0pœ.Iöÿ @ @p8@Öÿ@ @ ˜Îÿÿê¾ÍÌ,ÕÉcùhn¯@ @ ‚ÊOÎÒLŽÄPöDIþ¿@ @ ‡ ¦ãÿ×.ÙõôÌÒ#w÷üVXõðÛ*WÀù{ÊyrÒ}x©{{åšr †ƒ½=ÿÖóõO*yãüëËù}8NøÁ½?*|~*†á`YýŠçަœ×:¯<ªk÷¸ÿøÐ7ËyïÒppM±gœÿïÐ|~wn®«p¬`ùÿV>?ƒë÷öüokž>ïr>Rp]~ÅOÝVuÙ¯‰£»úW<ûþ¢;©SX9ÊÆùÿ–÷¼{o:oMÑ/̎íVÞAÖ¿òЁ‹ËùS§;7;/àÆyxêÇmçÔ%ÿÐxu-ûXßù_¹|EÓ)l¬eáe}ßøñmß­œz˜¥ì鞛ò›ŸÜüh+óµì¶ÅݜØüøï¿ªòíuózO?îã:ŒçöctÇßþá×wS§¿Yu;9î÷ïy÷wj™õõ¾gûwËÛ¦.½º–å¦!zg©s6~?@ øeù¾¢sÊX[çbœæ&$?uÚ:ݳL;|ŒäÓ²ºãÓÁ†yxà´öd°Sä#åì8Ø ++çšfëø~ÄoPn¼t æá"ƒ¹Ùàw5tüh³qûák„âh¦ñ·ás†©HÎ.oíôuèP2®° S‰XùÊÏHÅ5ʇQ7B}ÉReŒr{ÎðCã©®—¨µ¦HFmACm1ëçÓ £fš7¹è¡¡˜:pŸ’ʐôL+ê:ÜAn0ʓé—âÑsä‹Ã· ÚÔ¤_ÄL!;©Ç8$–ßK¥r”¤R—'¤â˜Pn$cÀ#ï!éÚ4µÿ<0sóýÍ hRȜÔÔ£.\Dû¥oօ@rÂ4-¼¹4Ö e»uʺ¾)8?dMyÂL½ÅŒÙ¼€ŽñÊ´ haþ?ö®fÏê,÷M˜}«Å6ŽÉ~PGG¡œÿsn7g·t9èÚR ´Œ¿–!NDc0X‹ûɌ!Bfql‚2‡‘A0à¨K ĎAùè Ì2Ôë:çyŸ÷ë׍ɵ÷ߕï9ÏsÎ}îsÞ7ÏñºïëöT ޅo0'JÅ%³ ++Ÿ Ï;Ój$×ꖿҏ³ê³?ÓÕ²—V+|Qï“˦¶ÞUÛR­–Á•‡ŽÛ–ùV“>™V[àªÚöe|ÞUÖ>Ùµ¹ö܂Þþ¿˜uá¶Vç ¤öܦ¾ú#w®i5ÍCŽÍ–ôu®¼ûŒgGuÙ[Û°×nXþÜo©>wÆý2( ++…B¡P(ÿ#T÷(gq%ÛNs'×kÀ‹x±1„à+oõ19¼¿[‹—Z ÞÛrHÅëKˆÞ܇.Çgž±½uElÎ,5Ÿ ++K»‹Ã©Ëz–|ΤèN¸ÄºñâÉے½µ>Dƒ»™'.Y¼ÉÃFç#.üéð‡ ɎlƍxšÚù¸7Ðâ€ÿM8›¡»œ-Ì ,VO |X-™68oL%¸aµ,d2Uö gí(aOc-1yœD’ÄR¨[/Ñ»ì­L\¡Ø~Õñ7VXÜWµì\é]Ì5÷=rÎÙÁˆdšßm 8P…$Ý:ÔkÆe>'¡[/x YŒ‚9»/1»\X-À°>@Ê΃Aóëɬ2 aðÀ"10NÓô؈‚ÙqYcÄ¡1‘ý‡Ë²5 «]Râcu¼ˆ~¦^Ð\ĹÄJ8Z_ðÇJÃ3Eªë`m §/•Ø8u:F88©8Û|`á½Z [ÖÇ4Kù…B¡P( ++…B¡P(ŒùóÁ¾0³uöà=ŸÃüð¡Æ‡YÃÁƒ=÷<½.Àpð‰z|õ·¾å¾Êۻ臃‰zœóq¯í¼´òð’ËœÁ»{^|ÃÔ7Žm<¼Oݏ}ÑãWKkKÆÖ¶CúºgýéäÓµÍ9qµmißçäÔñ·t½o|ú²Úçáøl¿cåó­-ÅÆí¬·ý/^ÿh‹QpIjÛêÚçgðYùžË¾×8úl› z[Öl¹ä…ÚVZ=Ç9ƒ]}ÜÃeŸùç­ÍI/ô± ?¾í¢©ÊÑÚs7÷q§]szזítޟó;gêÆ_­m6¦6÷Ûû؅ӿç7×6g]‹k8¹%8káäöK`»˜‡Y}Ÿë§Î?ºµ9iã}¹÷ÙDÜðýÖ;_¯¨}¾ŸÕ/N|¾Å Û­QßçÄÔÎ?km>¶ñʼÑÜ?Wº¹³þf[£CGsß;váS½¯¯>öìö\6¦ùsAïMøüè3g·ç ++V·¶-ª}2ŽeÍó'QÛĔ¶'>ÛÛ¹vêöcZz­mOõëðíÃ×îjm£9„¾íž?þàwG50šK{_?~óÕßim>¶µ óFã-ŸZV}Íÿnóõåý÷ê7ìûžim¡ˆþP) ++…B¡PüTAÞ'ˆèDþ;IÓë¹ïÁ©VÞ8›B¬¤·Ø †´v..E_¤2ðx£ÅK&ŽÁxò»øïhm¶É9—£'Ëx‰Ž¡ø;e—ðpN–ä~޹±>e±¸ð ,01[—sÂ8R0 ÉàuÜ4ÞÜ Ãrc–;n|ô‘`Å&1ž<~WÓÞ1쀽åLÛێ+÷.×@„zN«±IøW)s Al½Ï ++ uØkY±¾Ý‹Á3óßc`n;ޘ¥ù—,zåüM´Ó쭘jfëpð0)ÓÊ©n¼jIÍ«·Æûáà”žc_²û°sëu\ß1otÿ’×—¼Þ¸i ÃÁÎÚyðÅÿ@‹#0I†]>=yÒ?øµ·>ÐÅäá`Vígo]€]ýýsOzÓ×y=S†ƒCª=KñYtßÛ¶Öü+è穞k=n÷9×ëÙˈcf? n[¿­ÍËøÆÏ¾6wÔ6qך`²4Nûwëøä­ÿè—×Ou1 ¹qáÛÏñ‚G¶ßÓbRlÏ]yM{þyrê¸--&­µmblç—Ölµ5;'{Žùïn]ÿpçÐñÏ kŸkðÙôñ3þ¹iHgç µOÖt¸ã/xªÅ2øî¹Íu‡ásé³Ç¾§µI7Þ8`õϬx®k“Öö`¿îW¼õ¼!¶Ó7¸öñç÷\ÿ¶ëÖþ˞+ƜýŽŽl1¦ó˦>6dÝ·þʶ¶œš?·öšëv|üÝ­m¤™ðdÏÙï[ðZ¿WÖN½K?`ZL·§Å|è–ÖæL{n~}nŸ•Ï-»¾µÅ®m¬“±|jÃMmߋmsošÊõ+ ++…B¡PìoÜXBHÎD¼oâߔ’!çš3iwS˜lÝqÖÞ<^×I¯2¿»Ëùv£5oϒýˆ§Ç[¶onqYŽ 蜙Ú9eSœü™mÌ`_G>·xcl”`|ñcˆTÎ×Û8ŠÈÙ¸`Œ«öùëØ&ÃBߏ»?†Øè%8Sþ/ØJ|;“9ôÊEcx±f¬3^@þA¿xK ÑòÓœª¨H†)0j€Ì²q¾À#ð@)ц„c`Ï0Ð)É&æ·£·Tp—ÃŒmNÁŒüdst¸±†$ÀŽÇ|H¥e†UކåëÀ¨—ŠÁáÇœq¼ ÅŸ0¼É8c¦ýúGp¤;§Ï¥²$á]65F›¶`Ñr}O†­°Eð®=âäcÙÁ™iqx÷–Q½¿-Î=ÓÏ®¤ öœ*‰Úû9áN)0žbw9ĪI)`€9Ï,}Á¬%TMFY`gz¡3BÍÁO>ý¤òû —ýcàèCӏëæÊ`<ö¬Å¦‹ãPþ_¡P( ++…B¡P(Šƒcþÿ⯝w÷ÌÖáàöÊŸ…ÏÑ[7ŸÕ8ߘ‡ƒ·÷\÷’˜÷dÇ͖á`¢r¡7áóàc ^jùÙ) +ú~ŽÛºù´Êu†‡?ùÑwÏÿõz]X`i½Ÿé;_ý¥­:–×ÇyêÇïþô•ÿ/Ñ ×ÔëˆÏâ—Oú¯§àÒppyåXoÄç”'Þþoõzrèçä>ÏzÑ‹_o×öëýkiço;µêTý‚]ÓâÌÙõz2yÎÀô<ôyÿä¿Ôb¬kœÿXƒÿ# 66¾ÜÛ.ÏûüžÛÞøÌÆyMk uœø¹}M„ß9jb[ÇϏrÜkŸKñÙÎy¢ñì)·¶ÃP+à¾Ï+þzòюgï8ê0wdËÄÔ®?iœ¸íâ–M㽿pSã¶%7Îÿò俦yì ++…B¡P(ÿAî0…ÈW>r¼v”žkzj|i)†<刏$*³Ç[6uâkêq“?÷o•1‹-¼JòYbDçø/ ++±gʟ‹à^OétC-xOιŒÇÅәyòŒç”¡‚)Öø,ÞErä¥X¦Z{+=9ϱkR7m –½ºÂ;½3&cì×K» 3ë“$ç|4É¡g²ú¸`Ä1߽ʸÛCàŒ`£8S\L'/˜œóÉ¢çD~îÁ°-ï–2ªÀ՘…€8€?°|;æMÉyk8©Zø&yé-&á*)ŸY¦r»@>šYúð•eJ>n*© ++ ¥Ô¾"ß´™=î£:öŸyõhƒ·™\Ïûâ<œÁ)¦t€ø~²3Ö ++¼@iƒŽWo¹é®júcH²éð^ÇKc$Þ Iþ}hX—L†ÜT½x"R+‘§Ä ++v ú¦ðxf•û‚Q";[æc›2Ø‹ÂyœýȨ›’—N¤8ì9.({bJ?ü¡sð¦„ì¤J5`UöÐýÏ%£ïœaƒ,kØZi‹à;12ò€p÷˜FJ{½Î-ÃèÌA±!«¾£†±Ñpf8/ۈG`¡ ߬1¾µZ€dnlA|m°ˆ™%Š#͏5 )Sì 3_@\7˜+$V5 r„q„ÀðG¯§ÀÈDž¥ùÿ ++…B¡P( ++…B¡P Ðó¿B¡P( ++…B¡P(zþW( ++…B¡P( ++…Bñÿãüÿ7üã’OÎl=˜Ûç_»øéå-Ï?Q Ï{_xïu«šö|HÃÁæþþ%»8¿Õ»6Õ|÷3ð¹qjñj>¿ðþ¦}O]ü£^_¾¬æó[æç_4wÔϞyþ÷×OØý[UÏ?eg†ƒÕþã¾|ÞíºÇý+úœø7<û懪þ¿˜8Ö×/Ø3Ÿn}ÃÔßéûw:ýó«­ÔÍ_i'w´¶"­mVÿÜÆ©ËniÚÿζúq]€ó¿ù‘w6€Qíù—Çúþ ×}§Óðí¹›ësÌ¡_—Ïmšú>ÚV{þµ^7ÿ+wlØÙü_Rëók}sëÚo6íïÚs×ö}®ÙrÉ m}Œíê ôuîÞÒ雚-_éý~ÉԎ»Z[ŽM[`õܑï/}qûÇZ[Óܜ3¸²×q8íšÓk½g²mÏíìk„C&žiµ"‚ks0u~gâó›ö‚]­-šfË+½ën¼´j=8WlÓxª_ï³Nno¶óÙ!½¯ÿãW&km!4ͅ5õ¹ë¹¿páSMÁtz o>tdçÙ÷L´9„ÑxóûuŸ˜úùcÚ÷ùöÜ#ýºï]£`ioß5 ++6õ¾^;µüLëóøy£>×>zøW»6ߞ;eZý‚™Z z-нµvökô{³O™jZ ±ýqT( ++…BñßDÍÇ»¨·9‹7¥Òçˆ3±=ûê¬ÛŒW^[‚eJza»·ù’Å+Uñ1u:ÿûӍ÷,—î˜ÞÙrՙ·ÔךVs¾Ö‰ÑWõíæ®(¿ŸM))MbÞ¸$x§ô|–o¯ þxSÌÉS ß;—©­_(ώG™n˜çîš Ô=ˆ&eŽhº÷žãµÖ·^ÿø;å¼Õ¦ÛÙÚßÚaÎß)üùÉQ„7+þÍ_Ÿófc×í8w+Ël³ªÆ˜ŒŽs˜_õ\ù¹‹ØžÄÛZdÅ.ó&U³a[âbΚ½ü5Žs°M Äîb3ŠYö²ÝÆqº‰ã8®Þ—«z§pŒ€q–۝;eH¶`sÑØecÕst|„ªqËön:e>ñ^Z[÷ē߼è—Mýˆf݇jYŒ®±©Þל¼’c'¢jjY<ÒߎwÁË_鲬ÕóаºçÜϱ Zñºo)ºœHk8}c5²iÖèöËð܉qÜH¶žçwõÔV©I!‚ ø¤1øõÉõk‹ßS¥lU´No-ûuñT‘?d.{HôGGDûC¾ø2_MUæmññ²õâ´ÁV¿¼òºè9ÈS.ÞãdëDyC®{hÒø|&DLèæ+5Ü­CGxìՆË97¾Ù€ÞÑÁKæ¬(`–Ä_°*FˆxˆiXÌÉÚâªu¥»± ++6ÉP¸®úäLjm ßŠ?=8öEb|ÇmÍúaõª?öûØ*AáùOÀ‰¸ÿcv™Â1ñ«"¯8¦a‰ã*`QM‚¶QçTëïrÀ ,4vÍqŠ÷ U '0úHÄ Ÿ3úK– ++,@‡âaV{ÒRq\†ij,šQᆈðŒEXòŽ:¿Þ;9§ºÍU~¬Ž÷ƒXÓpÎûÈz.­ùò_ý«Á§›\lŲ-¥ÝØ\õ›Æáª_SóÉWöν¯ÉáN¬Ë#Ãr±GòÑsN5åÒñÙçOãXÕä~¯­íõ¶õ³,Eîó”jëEû?QÖÖi‘ Ö9,»eá+,‹%÷K @ ø¿†–g?ú¤K©€èuГ ++”kžˆ`ÞYãmÃàœÉcäã*¢u ò/*D¤¬oå ±ó™¼×Šj(£:&îûµWÞ[‰2Á©€‘”7É&´‰‰óW¨˜w?§Âå r$â3pÐ}„ºVgºˆ(õU¶Î9½zÏ!ӛ×­*ÜôÆêqj.©žÛF§ú3M¡¤Ðë’ïî (Qþ›¨è˜§êÎk1ÉqM!ðD`¢'­¦Ú1¢âù'v¯L©ø¬ ++^%⧀µ(G?$È0u¤ˆP"9ŒLó'ÒzµŠ&TKÙýx÷3X`üqºÀ0 ++ÃáE*Éÿš†2Ù@Ñ`ˆÄ&Z>èÓawÝ2^±m|θ$e¼këFÆãmU»¢·£ž­ƒ%2Ñ8@{Gtd‰êOäR&À ÿ¿@ @ ÃüÿÛÿù‚‘Ò£;¯V®ô-ǹóØK<ÿåüFß>ø‰Ç r©¯óTñݱ÷å{ÖßÕԞoøè÷T¾öÑÜêSJó&Å‘þê8¾÷§J;ŠO8<ýÂý zÃ+¿³rŒö½/‡ÏœãÆæ,³Ê–Î8ÿ¥†_¼ðD ++@ àÃÁ8u$¢%G·µ#¹ýÛx*û©¼„²T®"›è>z#9þ5Ԉä{7†¢,tT|A)jžt J ++CFå‚WÎYe0:È9R¯T¤Ãk*ƒ@LþŠ ++hªá¼Ñ1F­BdjVâ3Ú8\³öTº#¹Hú®s ).BÅ`Bο-þ@ @ &†üÿ×Ï>ñ‘Ò£;ûj=ô?·aqSß~R·3¯Æ|ö'ß<Ÿsó]èvvWŸûõ >µ½‰ˆÝњ³>yÉg~RÎG¥»%üa³^ßõV‰#Pý¼;¥íÆ?m~¡œ÷.u;ƒÕ߿㵇é|ÊAu;;j-ñ÷ó ¬¨z^ö‚½ù´iòÓËcs_kš_ÚÛûÃFæ¹þøÖš×~U¯Ïý»J‘ÝZóá/Û½ü¶"3J3Àî¢#]px꺽Ef£ãvûjnþ`oÎýlOm™{à±þÖ¦êö‹~ÖÄT4uà»ecó ÜPæ¾ÇÖo-oy"Ïo[åuXqÿ•¿àX ®wÙòÐxÞ?ð$Ët`›­®ó[¿ë»Yf2ÏáДÖf—8æF–…ÆÖ÷›ý)Že¯Î½‘c8²e]Ž«s]Ë~é°:÷ ÏjkÒ³ìÕþV6Ð{œÛ9×Ìýku~O=¼â¥÷ÇwÜVãP.Þ÷­3˜¡åkØUuYÙ¼›yTæñ›Ú®ß¦G—ÿËrâ>§ٙ8®›ºŒkÒGŸx~‡Æ©sÿTíst½ú£¦´º,êí¸§Ü3J•ø@ ÅÇhJÍù±r®GÖ-çëUÊVEëtðv(7ûÃÎ%ÿ¨äfJ†¦Š÷Ŭh˜KÙÙhx=w‹Q]ðxâÖ¶dX{ôOåéaXr“1MãtŠ Jé¨ †…'±Î;Ô Å_›=Ù³Ò”ôŸ³N W»EçNQyjÛøXrÄs0X”ÏÍyÑÌSÖ®±¡w˜[ ;—M´¬Xg¬* ,V6aY££=BÞpñ´‹%K˜ ¢OoK”ØðCŒ”™nÉù¬´Ëšæ3ôÉXîà”¦|tC‹3er¤£ûâ|Æ8´Ù’Ç‚‚e§g,‹KI—ZöÉ©LJ`IC wz´•'J)•‹^Ï`Zí±¹Ð»ˏeÏ´ïðпƒÅ)·^Q·{ža´Œ}c¼ó xó„Zx¥IÄ)@.y,vLn²s‘¢ ++(M+â0ိŸMÊè£c¯`ÛâÕ¯(̍à1¤Bïm˜½¡4vŽÇûˆ±¹YJÕ·”þ‰%3ó;¥ƒGŠˆȰ‰´ÅHö±…8ÀåŒÍ’“†V¸)LÀÛE(à^‚yqZ¼¦xZCÚÔX@S8xŸ\ õbÙÏ+EÆÃn3âÿ@ `"`Èÿ¿àŽý3GJnòùÉyˬ?ø£ÂçŸÌ¤n“ÿm;ž™öŸìÓ ®ÛYSΏäèvî-~ÜóqœôÞ¢ùtÞk»-5õ§½^Ϊ#0Pý·³žŸû^©/rêë<0ŽÏþþvìå3W²L+;ԫK;òiÿÙÌKþ•e6²ozkiG>íµ?¿&7þ|ŲCãøúw©–À=¸e©ñ…oª~ݯLÛ°Ÿ}ý:±ù{Õ¯»¡·y&ËL`ßû ¥Ý<WŸÞøÞ­SìNãÄl©ó›vߊ'[÷¹µÚø‘‡®:À2þ·ª¾Î7ªÏ~ÃKŽ-22Ûsk‘]áŒZcáÙ¿|ýùÞsŸkj»/¿v:ûìµ7;qÓ0þH_?óCPŸ<²þg,óšÛÝ:e¨Ýš`2ÛsaW]aziw6Ž¥îà8¥ymo¨º ô®<™ã¬æù-­}^sæ:®±àcÃñø°ÙÜ.Z˲ÕÃj%œ÷ç\+Á”Ú @ ÿˆ/Ýé¬CVÖj[®t¥ÈíñãñhhUÀ”Sät”¯£vÁ9rÊjµÏ‰|ÙN«E¬÷DEÛâ&×ä,Ä)òàWw ++>X…n³/9ÓäώWu4äô¶Åwšì1ž¾mÄ%¸Î— ùÅ3D¾œgu6‚@}íšsÆ+òM&r(ã¤*5Ë­óøÝÇâ}ÿ¨Ä”8eЖ ìØÏÚòäÛTü×è½ØØéHW§bãï…>DÒ”a?rÃc¤¢ Áá:µ´0A'M½˜LTcP$Zea7ØYµ~òìȍc(ØÀڀ¡Lq§a=ÊÒc=µ± ++í)cžâЦ¬sÆ ÖÓ43 È%oF³°D‚%K¬ ›b³hzêǞËΣ§HiõZa£)lªIÃbNþwóàyÑ¡`‰‹1˜¼ Æa{´1ZŐ°±é^ȑ6±¦§ô ±|äÏOXÔ á:ì.L˜B¸”ȹhíƒi†<¦…µ¦Û7m>\ˆTÀ“Ân¢$ü¤È×o19›3ݘ˜ŸÇˆ ãf¾ß1¬©†îuºÉ’ÊnRÏc0½¿Àöè3ˆ 7ªÏ˜¾ËU`ÊÍI|pàÃÃb¢)Óô%83¥|XdÉÿ@ `b`Èÿ¿üW‹Ž)í6ù×wã˜ñë¹ç6ùó®åÏ'Nþëþn9òMHƒ/@ ‚ÿÿ,ó;¨ t¢P“è|¢žlRÞ¸˜½ Þ:í¢%ìÁ$œQÎâ2m“¦ðŠ˜2Uˆ¯ÔF\KL¦P †)lÚG“‹6=Q>ÄàU¡ü§ËŒ§ ++ÞÆ`œÓ^‡h)FŸâsˆû Xñÿ @ @0 ïÿ@ @ L ÅÿÿX?RÚí_ëù nÿäO Ÿ¶¹ÛÙXÎ߂cáóÓÿ‹ùùˆÏo^½þc—~ú _`VªÛÙWxÑNÄ1ãœã[êó)ó{*_ڜ7ÔÊr>¨Ø×™6NݾÕuŒÑ\wçێóï-y…eÁ37ÛÚÚΞÚÔыªá¥Sµ>áµ'5¼{Ñ6|oï?‰ãº/y©­ûæeó@ ÁGµö¡ñT.ϔ‚ŠôKÐ\»O«£OT©/»HԔÌMS8B ?,1¢?K=Iƒ.J½½vTyÏeåÐkæ1NK\©ÓI ˆZk“¡J‹D$hŒvÎjª³“ŽÊCZïHµlˆRSH­  KÎb¥âZStõ&çI*}ADÕ³…Qe*;uV…C1hâ²ôÀˆÿ_ @ ‚‰yÿ@ `"`(þÿ»ñªQÿÐíÜÔOSþ¬ís/äúð:v;»jMù“®œýv9´ívnÚ^?÷§ÛÏ£óTJ´ÛQ}¥?×/øÔörÞ8ôÃuÖOÀñÄ¢¹¿)çmðÝN*×ǜÛ.(çÇùÅÔŤ‡IŸ×w½E睊¡Û™6µÕgöáßÿu9¯IÏ­EŠÝùo”ó–®ßSõßpíi¯Óyo¬év¶”zñ£ó6V=g=?÷=>ŸS·³ðy ó«>7}Λå¼v®Û9ã˜öüٗ}¾è“‰m=…8–Ï\ùL±'Z˜Dù³Š-¨ÖÂ÷¿°ªÇ²@¥U!›Vd”?±¡·yf‘Y8bG«óÅqõË,óMŸoå;¼sæ’çYçW,.û`3Ž+~qó_ðÚ*¢‹„ì¦2/j|ùžõw±ÌfnwhœŠï=¿‹ã¡.ßÓȚ>Sé“ éÁ¹[‹,Ù&Ÿc~­3ñÎ]k¹Î„²ŽeGõµó;<ýÂýE¦­SEö\±ó ŽUûþð(–9Ź—¹œö×k§ŸÅ2ßäl+ºü ŽÅOŸß´ËÍ¦×=üÕ{Ö=Ë5/´JE¶±¿]‡U½Se™³¬Ë)S‡d 6³,©Pdj˜l!ëb}âvçNnÇ{wòúY–ë2¿ìÓ³q,=8pG‘Q]Ð"»µî‰Þ;Yf=·ÛÔßÚzžS?Sd^YÖÅMjwÌL–ÃûìÇ5çâg¤Y¯íšcÚuøí”å¼F>5zÖ>Wöþ…ûŒ¦ÙgG•9œ‰ãº©Ëö°Ì'ïk¥ÏKöÏ¿±Èe›MnÇ[:ã|Îǡ¸¼?§´ã-êí¸‡?T£Ëžºî_Úû7÷7²ÀºìžÜ®û¢ÝÞÙÊx¼oô·ëðóÛ®y‘eÖK­àý(±–Ž ++çˆÞò1XåL²¥ÀuÀ¹Hà&PôcJ1y£\ ++ø²‹_ýø!Fc²¡²à߀Y›¨|Ö9PIó€9ª.n¨˜7>{sÔ íMÌ Ÿý¸ÑuðÉk|4)«©7C…·“KI{g©@¶Ê¤>ðñ½Ž¯ÃRZ{3•jօ<›¡ØÑàÅwf(S~Çã Õú¶žÊTã; Š@©`µkÊT[¸ÃDg‹ ++Þ;oE ZôcŒÏ×Z*q­¨Þ:&KZê¦î3ƒIo)L4üqͨ³à¨ŒsL$öšÊ–ÃZ&¡ïl¨8ºVЂ>+é;&SÕpçaZíÉn95ѠР惩\©î¨gr¼ÑŽÆj“ç ÓµðLoT5”ë±ÚŸ ++ÌȨ.•9ÅŦT;ïè2~…Íz£â|C31!¬ôÏ=ýÝâ9À¥*"ޒ­Žž9Ïi±|0òé`±: ¶|N¡›KÏ\õŸÎ\Ûŧ¯a†x,o̲¶XˆíƺÀ—VhŸx6V6N/òìÑ.`+ø/(tßÀiÓ‹ª<çϋ€Ud¬Ã: ^>”Ñ<> Ðu,9|—5 ++kO.<ÊÑž¢Ê;,I…©ÆK#®§”ízô½g¡X˜aÂá%ÃÅ£‹U²Ïm¶m—Ķ܁cõÃ÷™\fÓugÄëfáX÷ÒÜSYȶû¢Ò‡{6åý<ÂÓ¸Ì)1.Ïio"´¶ô‚bk~jûåHe:Ù،Émé9Ó&·mdžÛùþƒ—u“­Ù^·m/¶ææOâm‡$ïŒÔ¿í3ZØ°eñÎdj—Ú9s¸ÛßúXœ#¼ŒT²—gNkÛrÚO禴&â^A•*UªT©R¥Ê>Þ«´ç ¸GKÅgÛ~2{UÂrў€m÷Æ ++šG¨Œv9¾¦a*XžIθ ÆÍ ++˜Â°E“žYf/ƒÍ$­ä`aõÃ.·4HaZÅ-<ë“Ö9 n"ÀtäÖêó*î·Í6Ø2VōüŒ›‰Ö¸ ܈ƒ=Ì=¶Ò㛕÷ä¶R¶…д@ãŠÛ†0½“ ŒûjͶ û5ü7,4˜p°]a9¶{´Uت¨,øýt?£YÏÍ>ÓÎmÃý1 u´Å-íYØ£€E©“¹·ûU‚›BVÁøt0ám;~Ó4^oâ]ú=Z†rÌçÎZ+öñ^饗}º§ÀFg5÷ulkocʹ]"€›Õ´¹ÑÖ{©â&®!îâjwb¸I"=F ƒZYt›;ªŽíÀ¯Ê¸c9ÈÆÄÊˆáE½Â 5q“ ÁbÁÐ8“Úâ^"Jrƒ\cm¡‹-ë6·$0¹žÊÿ¯R¥J•*UªT©R¥J•*Uéáÿûä?¬œXÚÍøõ7pÌþŸùKr~Ý͜fþqäYsÿ+ãù¶Û9¡àüÇí¾ï¤Œ‰†nçO'áÕ¯$_À­…s{ÐKïúwž÷A˜nænߎcøãoûˆÏ/QOÁwÛ±.žÎu+ü‚þ<óJ[/ýÁÜÄaP:á¾Kg´õýáÎ+2¯^dþøšÂ1=fS› aɋ ¦ֆ‹^HeMHun(ü㵯¼ãޜ›@%=åS¸Çǟû£Ä›Ð6áýŸ-÷»xtë ·w™ç¾(öa0¯þú2†+Zžx Ü_œÒà‰]?¹iYâÎ{™9"~ Ž3ž¹ïŽTæbUªT©R¥J•*U~½±f-¢?1ÔD@ׯgüÎÙ&ò~5y”.’¼ñÅÚX#tâ;­ ÞgM£!gñ¥×¦Ñ.$¾ô‡tA5Æ ++%sz¯ * ++º4Ê:'é@ÃÖxz9Òэ”¤.“/ÝbäJ)T£­$̨½3¬)‰–G_ #„ÊX¦’ :IÙZ µßrþ‰Y°ð)MD¸‡ƒTŠQо†û¹ŸÎàØõ ++Úih”*º©¨Fˆ¨è4éùÚ:nщöG#´ ++ôì¦ß‹jHê'AãàØCgDœÆ¼†€ßDiÈìÐN9úÞÐÜrähеŠ?k =­Œ‚ªjŒŒ~ ¸“ª‘¥¡2ŸC8–tÎÅ4ã×Î+Eç/9ñ,¤;ƒ§×8‹ÖÈÆE—`cÅt‰³¨ÑLüXpdé% Cƒ„xNºŽ^gћ¡ ôYÓ:àŽøA¤¨¦ß°á˜`¸9ӎ«àÊT¡ÅÕq Ç *Öóu(y´Wh+†o<¯Áz‹:c…qk8èž+“³LÒ„.¼«@ݧHýÇ0úÑ[2 *úI™¸ÂÐA,]ÓDN&TЋð@²J¨ø•*UªT©R¥J•*UªT©r HÿßyÉë'–v;»Š?üžqòzñð֞sL:o”ëæøpý~õ;âùE8æ=ðÞ­ϗÁuÇÅF;f÷õÄóÚàü‹ã΋XO°Â uç£¯ý-ç'Ÿr!²?¶(Xÿ'·?³%ùè[“°þŽek~xÙÑÏÏqÖ6îÅ/~^¼Ž|ƒãýò§²ï{“®K1û°—¶,ûáŠù)Žœ”yý±ânŒeƒãºÝ0.>Ûĸnc%a¿Ÿú¬Ø¿Á±ÍW_ô*UªT©R¥J•*¤¤8ˆ0&„Ö:׿‚wJšqqÿ†'eà-S¯ÉbLâ3O ^Òž|„ -`R_ú_glE”¡}Áz†zlÈ|pÖ ßc,èàž®á=<Ìi‚Ê+£*ʄl®ACЯ™ŽÑíœTÆ«·¢íÚi«YVì+üŽ12ΐe¡¼48©$úN&†n¼õ ÃÈø`PsÂ2è%}6R…¡ÒïVÚ0îcY2¡pÊ2¦(Z©‚¦Ç>cßi+#/C£M΢uƶñ4'Ä›̏~ŒºOâ Tü¿J•*UªT©R¥J•*UªTyëKµÿ«T©R¥J•*UªT©R¥J•Azüÿgv½ûü‰¥Ss\=rߞÿüi)§šÅùKã¾ùí×ÎÔ§'Þ¸žÒíŒÅóýquÉY·ðͅoæ¼êºÛY]rœŸºèÝ¥rÁÂXJ´yûãΜÄ¡ï°ßáÊ8Ö×àXùÍ3œÊb*bÆù;¸íÇwî\>šÊ¬Mñú_ƒµ_RC+’ÏÀ¬â§ÑŸ·ð撳~ýèú»S™Î± ++ÇJûónuž…ã’—‘Êl“rÛ}·äüåÏ|"—å|ï#{‰›xW¼ß‡pœý­ów沐â-¾~Hïº7嘊Ù_bI™¯ûn>[.˾ [‹¯HÅ ñºU8~±ùÂÿlc*¦þug´}øÌ9o¡S"õo^ñ#¹xÛ9ßHú݄TöÙCÚ9ºâöUi޼ó©SJ[úc1&^÷ÆQynƒÒiÞOÝK.Ä¥¥ÎÏÎX÷㼦|ºn$–Žc÷-«w$©SßW—5ñιÆû5ªQ©—–œ¿úàHªSéܖ3ÊÚ~ø/–ÿ<ùŸ¸¬Kñït ºü¦u©ŒIœcÙk%×fîÅnY'ËGOڔãPæ8›W—gÌòGÞyw*Ó*û×ÄvÎÙ¸ ø´|ìùïljý]’n,z½åk¿ÿ“=}aÎ+1MïýÒ);rìR›ÚâËúÛòþO¦çTgóêRçŸL=5—¯ëË¥J•*oAùÔúõ†,ZæAÇ32rfñnµ‘',œ”^µy˛€÷ÿ¸ØuZ’á,ð/B˱6ڛË:Ñru-‰×–±å¬Áë7x¡bÚmϸp$ç’Ë jø£ÁsÚ3ԝõNóz» ¥Æ£73Wא…‹7ë¤ñÜ&ŽažMÞ‹ó¨…D^ÉÀgoWÁ”ßR)˜,æLG»¼"DŽ Ö)Ϟ¿h´`8;瘷]+ÜÚyôZ&O|s£Sν£¤©œ³{b^õÄßv‘L­U;> ++wbD44€‘ý ¾Þb$É6o(éÔP±ÎǼë‘"î]á²OÈ·/s§•1ç·T̽§ÎĄìÆã{‡ÔiæfÇw²$¹Ü3EœÆÈà$)ëLUÇsc52©ƒSŽÉÝcl<|OÁÈo ûjðÌ(‡ÙÉÔñuÀôï¬H4ÞÏTðãâ-N߯Irá¡ß"ƖRx™b2&Y³Œ@Èdñi¡FDÎ6Cú…àÚ|yZ’'‰QÔ £…Ã`3ü¡ò¸†Aæ|Cb¶²1˜ž—LbèhA9ª“'òO+Tä©Ã”¡jZë¼wãr2m¡cŠs#öYfÜ£·€b½8d°RBL-BŒŠ)ú,[€»C  P,»FæuLJ¾Kµ¶¾ ¿aq(Ñp1YÞG†˜D-x`}s ¥k’¾2÷ –«žNÌq(©oP/"”|"åùíÇû‘ìWñ.+þ_¥J•*UªT©R¥J•*UªÒÃÿ:ùèg'–v;WüqÞCóÏIyé¤ëf¬zÎ_°Ú…»[“χngNÉE÷ç§¼ç¡Ì@=KâùͬÿÕm¿ày-êY:½­gÁn±[m„êvVÇóЏxó´Å‘ ‰Ã?5Ôûýx¾ÀƒÓëç Ü?ÔökÁ¿ñJë…îfܛ;öÕßþeÄÿ•lZ\›øßß|àüь±ç³â ++sð)G^Le>cÂO•~¬½8a×ÜHŽe;bcó›Ç]7›ïŒöÐ9+žÍؼJu^çkŽ+ÏصÒ"aå× ·}[ÿÂúi.mH}˜Ëãá‹JœÃ§ï¼(õÏúœ+pJì;±rñåUmìÄ&ñ¶Æ²ÁqŸ›ÞŽYÞB_æ`íË'ýV*3/^V¸kž¸g8•ù̃ØËfáX÷ÒÜSYÈ܊ OàžMy\¸w™Ú9½íãw<±daL³]…Wrî+ǟ˜0vÓ$LxAÑé×­{4aì^¦>$}0ƾuF;·ç®™ËBëç†Ú:ûñ÷¯¼ìà‹ŸMe!cú‹Ëºë ùØP¯ìÁoRë<·W¾Æåÿ4òHÆô3޾½pvVn9/õA·ý[V8 çצ2c\êß]…#±âÑoËTælZ7¼åèÑs@©T¶±¬‡þœ”3 hùèé7¥²&·ó†q‚ÓîÉ<‘Ç,Îà\–C[nï·töY/¤˜™J&}ÙVæè´Ñï}3óòXß8­WvÉ_¥²y:ۇze‹gg>SækŒ”uôñëN}9=¬±6«T©²7ÙK^2üo9fî ++œ2oÓ$¦Ë/ÇHdùÃa^;)…±"ç¡;© Uà3…o°DâCa9bƒ ++u S3n¦KÛǻϴ’Ê ++<ðñù€I1ü†ùºpG/ù֕ mˆÄiïˆK¢zå3–Æd_®ÑŒ`%…âw†Î؝´f_ÅȊ±Ä¬‰í´lÇÕz…zC‹má÷¤)X¦OÃp:æk<{NF¢bÚ5–¨Ÿ÷Î3ð˜g0‹„…X.`dé„$xï„ â`o1ðŒêÆìfLœÄ<2̘ǘ ++f@Ã÷®ÄkV.µù`.º¬8™"°øx± ¸fñP¼|ˆ+ç± :ü?ð. ++:{áÙq©ñ—û- ™Ns<¨P¦ä€#ꎕéM′_¤Š`$BÌ÷§—‘zA‚â6l±kݟ°ŽÑSsB:üMŽãEÙs(ÆyöRçÜxÐ Æ0gDAm¡'¨<Ü ++ZÈph"ñÃ1ᝠ6‚"€ü<©˜D‘_P˜¨ó¸\ŒÁÅLƒ|4™ü|à4Åh}6z?ÏÏØxƒ¾âÆž¬¨ÔÅÇt#@ƒ-󸝩êPú8c–-ágª%aó ÅásXŒÓê"“Ï<bôù¿Ïþù&až§¿þ¯¹êG‰ \ºNE^§ ++–¸~ô£×¥²àšrúqlV¸ÕÉ'^™1ݒ—ñiëžOeN§ë¶MoÛrèmËnýì®™ü¦¿€ã±o/ýI*³&]wElç_â¸ðg_üVÂë[ßè¥ îç\Yðó~À¥-êØìƒïDÆÏ§>B?Î?6ÜÖُɏ¬{Õèuʘ¼Møëƒc½òÏÎýYÂäMŽ…ðZѝsçŒ<“ðs™Çsd\NƉ˜üšÂýøÚ–57.ãüE·o^öž>ñ#ÅϾ#_Rð啣KnËþò>µåšÒ‡Ïݱ*Õi[¸¦èÄUsW¦:È± ®˜Þ«s"¶>s/ùŽé½²[Ì¹#]ë^üˆ~Œüõr]?Fþ\¼npÎÉYe­<~ãUϦ2eR ¯çý6lY¼3ûà»ñ95ãçËï=úÄq wyÝ5­Õ³S^|ej*Ó&]w¹ßɏ¼Ëâ~}•*UªT©òV”<âøºÑønÅ+PjaÉ²Ö ++IäP² Œ¦Ó7‘g©‰ÜzâÄŒ¡g6=ø·Ä„#$4 =¸ ¾wIºPÄq5ƒMôYÒýŸÌ !B}®•!æë 9-ÞãB|íYoãƒ#C¶9ÜTã9* c |e$ŒØ8ãI•ÁNJ‘¦ý­H¹ìdP~¼xo<“˜ýÄŠ€ÏŽI|ÙÀ7¶&z›9:Ò÷pkC>EˆŽû1†BÎÿÇø’f‚9ítŽ<óò§u:ÆHçaCpü]ô;×øð2ÂXK¢†ózÜüìñŽÆ@“,"›È7^eޓŽ1 \C-¤öáæ¹žA±D0¶ÚDށ·¼»R½{¶>ý½ÜІS£%UȓȐç10"ŽùR[o¼`Ð'&É™âF¡÷ i9ž å,ñ­#ë·‚Z0Ÿ¡!$8L”$MJ“C+70Cbàºð‘ €ÿ†#Rs ù0˜aΖ@‘Z@î=F€‹†¤¬5ŒºÖ¸=É ÿ¯R¥J•*UªT©R¥J•*Uéáÿ_u³.žX:µs×$qþ·•ó{Æx=ú¿ž‹cö֍çfLç¿W°»=ãì*Øøž¼€e±~b ;wώ¸½VŒ "æx6ŽëFçÿw<4ΜyO^ÀÍ%NÁúÏ÷j<ߐЋS°g¼€±â'>òÐÛÿ%ò¤B;íÿkó_;9úz[Ýà¾Ï,ó Oö@ä!º%VúGßH÷eèXŒClÏ"ŽÛïÝÏˀñ¹}Fûû/~þ˜×2ŸBu¦Ä~ æ\ZÚÚÏ9¸½Œ÷%£C*Ç+È1úO(~ë+UŽ ]È>û{Ép}Á³?¿9aÏÜðJ8ê‹Å/¿ŸãpÁºû9sbٙ8Ö<2vbŽWy ;Êuýù6Çq$cí+ï¸7óTj˵±ìÿØ»X»Ë³|–ìÜQ@”IeÕ5…Ñ®·«ßÿ?CD’u¤TÚ¸íZÚI•ÚŒ„°¸dÄ i ++‰hXÒeš¥l,+Ú *›A[µnÌU„gÃÊ`Ù-He¨ïó~ßùîí=ç^g ïC~·Ûï;¿ïÿ¹÷|ç}Þç9›®oÿ銏ç8”®ó*º~[ÿæáʍ¨ü‡Y§öæ¬_Ë`n›ë~NŪ–{¿~|qáWýŸÁKàõô ++Ör_.¦kÕKk¿PxªŽo_k¯_ËàÎÓ'ʦjÜÚòùû¹‹'é#\_¸ÞVÿ… “~½‚}MÿaýáŸýéR–*—fë Žy­¬_¯ :Q6•‹±{bÝ¿½ê®R–«Fá2a_Ÿ9oì`åiÔ¾šAËàîVÖÏ©˜sj¯½~ބjýœªe Þ¾(Zæ9z1÷r²HWI+ËzÜȍMìˆED­CÞp°ô+•~S;Uð&ᕖæMˆ¹ê×½pï‘8sâà`O˾ÅȦ‰ƒNû¥_¬1r͕û›.¯vZÝS”;MüxêECöˆÒoZΊŽÚeÎ!ÆxŽ/R øû5¢§&Ø tšT5vºY”ÐMda~zƒ¡"Ï÷kì˜íÍEÊÊñȌ¢×i«|¤ÿ«¸“rò·KÊ6yÇl@RµŠj§$ŽÃa !ü ûè5’ù¹û9¨=“5ò¥$¨÷P÷G08Â4 BÎÞFÅc ++ôdt4 „4|ú”† ~8¢ºŽuÑ3ª¡ºñ ‹L#q¥€‚-k2£ÄXivK~;=E§ ÕÓ·àHóŸVo dºk쨠éÂ.PÖa+’&™õ&v§ ©õ!&Z]Ï»»Öã£bšÐ 8ÑÚœêOÏQ+†^Å䕲¿2[tÐ@]QÇ¿ßi6a£BÔ@\QðoЦˆ˜Ð[z8EAU€~ÿ(Ko6ˆh=Ðb+üºÂD§ÞÞ _0T¸)Åw€Š M@¿>ý*ŸëZfš?ÚQy♞¦äÇ"Í ´O@Ç/÷hqzSù3ÿ@ àdÀDü×Ç>õÉ©¥ïê<ß<Ûïyvy‰…¡ng dž¾H×ü×F–Öxäwž.yûFu;çµ<ç½ß›Œãä9Ðý ÛE×ì+Îü:ÇÉ}Òݹ-—¼?NþDËñ]}ÿسUƒ¿êޝ!¦]r‘缏¶Øfdða<R(¹×ÇņÿŸ½ëK|ÒéÁ«"H ++¦7GÓäOòW§~;¸°»šç et0G,SU@U“¸!EMžæ=EE㤯…þ'M gbǑé,ã©uj<"·?@߀Î*ÚFò*ЂxDp#B´”ªA#É.NŠ¡kÈ%è˜U6T“)nÎPãБ™wZZ)h‰x+f Š ÌÉ¡™SØH  ôaTo…êdt*!_q^#] å¨Ï!ÑÖµ±õ”À‡ñ¨){Ø °&€WÊ2ÏF¥LS`a)ak¾MÔvb >HÖ'”›R¸ T,fÐ7x+rX hA5˜‡ ÐTh÷OÖ 8žtD¡÷e²v’ƍ+ ò—èq $þ/@ ÁI9ÿ @ @p2`‚ÿÿ؟§-SK»Ìwî×óÛÅ|f𼗼¹äÍÂÏ®ÛÙÏè»èÚûäÜW ++¯:¸ž>êY´oçǙÿì¼ïv>Ýxô_Þ÷ ¬ŸçŒ·ÝÎN®§ß·ogÓ®;å¹9ÿPòÕs_ã/:¢Öq^@Pq²×X¿ÖÝXãÔo¿ñšP5Èör;ÈW¸éE£Š.]O?ïñæ#÷W;Ö?QôåLåyomzaýºtwp{wÓõð‡W½>ïB᎗ü…ÁÞ{w·¹îÏCØ×8î7Ž_Ròb¨ù··<„]ÊR(Ïíj¹ý9 ++›&åz¤”E_½ð¸Nhí^T¸ø:So¸ìhÓ<6ïªï–=a]áÍoi|û~í¹Mm|bÛ ÿRr’.c/ºt›éºù¾_5Ö*Oÿ‰Iüþ,¾uàó Mxè]?„ÜýPÕ_«>ŽÅ³?þò.}¾ê¡…Ò—ÓzÌ @ ü¨`þ4”É‚§.Ȕħ_xÀÊoÙ'SÕóš–ûƒOZÒÁA‚R…^C­”Ó'I‡ Ψف®ný½:MídÖ¿vÎÁQ,[E/‡8Ù¬ù´É C~÷[Ƨl’wÛÀœ ++l˜ìë¦b€š§ÑR—5t©ý sò`š'íSR4Xн5}s´(ÔhׁO½ÎÁûh,t$ˆØô™›zæB„_„z M ÝWàÄã#¤ÍÙepэ§©ìŸÝ¸è4s¯gs½^ßéø¢ÙÎ8}ÂDÐF ځ!P5ÊÁUkñJ ¹•AšAZV“àègA Ð&t™³-4ÕâØ.ςý"-…ªZš°¡F×5'„п¦jobCD:è°Æ'v1È$p–֝J¸K½£]êohÚ\4$dz-Dõ  ¬õ°t“yïCÓhmýQ¤¥Ðªú„$ "U‰ê•!§à‘ƒUÀù3aë;Z¨…†˜Ñ¶!2hC©‘Þ.JyÙò~óìÆH]S »ÂaURØ×Ð#ôp,Ï8!äIºžŽ^¯­‚ÚdòàÞÇDS3D·˜¦ý¤î¡­kF’ ++£4io]xa ++ÒcQéÍáöUŒ,6h©k1!u{ÒN§kyBµZ%þ/@ Áɀ‰øÿE »žZÚí,k~Tç}í÷V–x6üö¶7?´Ï\zΞê Ÿ¿iâü [|þx¿½Å|¿ßWï/Zý×^ö^Žógeõpç©+^ù‘Ñ.ñ|Wãù·6¯µMOߖ«ç]՞»•ŸŸà³Z?^ËbÕùkmÍ=¯r ¡Âeñsƒãù‰Ë„ÞüÍgT/¹ª+xË{Émmñõþ˜ý†6¾uç¯)}ɦêÙ]ÒÆpìü5e ÙºÒ^ñØ»ˆ®íîêU0–xþ§gð’ÛÙâÝý¾o;šßØZÓ÷ª^_ßh›³‡‡®ýV)K•p÷$¶ÓK\âe®[_ú½Ö.jšÿ=ûÊñêµVu Gú€¯<|]Ѥù,eø9¼à–G¯|®”åTø_mœ„Û}G•šì=8Ø£íñ6†åãç}¥ð´-ãÛÒÆþô}·ý[)³>Ê/@ ‚w,À€l—ÙçQ©§õŠîD貅^|?:Å1e´1`DäèÙÃOé¡é|§ó†ÖP§ƒ \6Î" œªf_öÁþ<õÀ/± l@¸2ÁX¸êÑùœóá.¼ý cOäðw-ؼglP4𠒎P Süp>h^$þ/@ Á;rþ@ àdÀÿÿççÿÔ#SK»ƒÌ‘_{ñߞÂúk!)×í¬j|ó…ýÞ}¬Ã§sîmz{Ÿ?÷ê¢qÃÐ!ð¦÷søòŸ|id{ѕ³¶p÷¿þÃI<í叞¶S•ƒßüØûµÜ–¶öÄs] @ ÿ ÐqÌÚk´Ž%Ç!™˜‰]@–ˆ!ªd2MMD¾ºŽQ›¹C«”öÙAM9ÿ¸œ~Ö-ä\„”8w"@aÔ"Ý¢—g¡WÈ«8îüó}ÿùÿðÀó¿ì@ @ Þ²ßYô} ü@ @ NLÄÿ—í¹ü©¥ÝÎËM}ɑ³6^~¶ÝÎÒ¦Çþîïûsë£ÒÝÎ,~=¼ê_82ÿî;C·3—ï_I×¶ñ‘Wù~†ÀãM»ýcÇ~ùœG Lîvn¨ÿß­óøñû¿»è(ß×Îu;—3Oa]³¯8óë|ß'z}·å,:¢Öñý âpg-×s']ë¾´âI—bÌ¡áÎí­O¯ný­ï”2_uöjõ7Ÿ¿¹”iJ~ÃËìGÿ+ç—׿P¼h¶¸ìPë÷Ê{¯+Ï9“‹ÖüŽ6Ö?™¿¾xxSsŽrÙYtÝð܂ ‹W@®9[Û\ß|Î5¥½¬«€âö Ý¿{њïײªÏ/÷>o<¸©hâ+ëJ£3øÜÇÏý:]GÜÀ¹p³-ü³yž/¦kÕKk¿ÀeNUÃmõëì??ƒÎþ³{s֟۱ŸŸƒ/ÃòïþÜÅBY%oh@ ‚·ð©£Ê¡xÃë´riÄZ{§¢s9@^=Yúüi’KÆØ”lÈI¯gK5¥"¬Ø=¤ÔégP–5ãM°Ñè˜,ŒÚ³fxgS€2¿ ÆÀ8ñJ³SºÐ´§——"?o¡ˆX>öÑ-zë•Îô˜BO/rùqW:Ÿ,½ZCtÞD:ƒ@Ÿ>;¯]ŒHžÖ Šƒä ùw©ã98 /€HG«‚cG{OMÐYý ++^%(Ú{:žDˆÎS5‚Š”I)'G-³n=µhlήÎu¤zLp>õ¼<s¢A˜lªç€ñN+Ì9M7†Ç4 éyéÀ`閃¨}€ø½Ã8Cॏð>И< †ÚzKHfh²n?t÷­cªÞZ©D³bƒ¥™Çj4e-?§h–©‡Ö*r AVG㣣Ao<*Ç@Ó®=õá8 önp¨›ô/M¬ê­“òsQƒ›Oë@=N:Qhý´æÑGzIä ‘i³P›Täù~±'(»Êô*ZŒ@e>;Gë±ÿ©kžæ([ £:<:ohæKÍ:¥D€ŽxÆÓŽ¥ÒV¥etXv8XZÓà,‘¨ö xhPR<Æn­¥j°t‰V"Eš²§·½7ð–PÊJü_ @ ‚“ñÿ=Wmü§©¥ïêÜÊqVb·-üÕëgÉ u;ó8Þ{]{ŸœûJñU®ÛÙÅ÷ÿÆò‘ÿ⸬ ¾ÛÙÝbê8öþ×8þ¯uìv5½ÀSž›Ãqþ”•ïñÖеè/㸽ñv¸³·ÅóoÿƂª/èJ,y?s5]ÿ±ûڗ¸,DWbÉEÇ|…ÿٍß,±k¯K,ùž|çgÒÜׯºjþJŽé›lu‰£ïš×¾é®»Îz2‡ ”]2¿èšTúyG›§_¾ìP)‹ø ++K @ N˜'ú€øqð‘/И£uRC+cµ^+çé‡Q.$„³CŠ`#x«À’ÐNš½‚î%M'$Çõƒ²ëåÑ+¼Ž1ÙÒ¶¶ÉY£ƒBª:ø1ÃÇiIiouÕ³³*èlBÔ1¯õFqçsP٘HýÆ FîîXµÏF%CãËt¼ÊA{cÈ4 ­} ÖÅÊ-P1$ÁnÐ9‚ Á^¦uÚ«¤=u†jWßÓ¤š"gœÏ™¹µkE]ñ>Kӓ]¢‰ùCÓìRåÔ;¨ÿр辢£ Íl ¢M‘6Ô@v†uµ­£Ã-ó[ÚÜXÄù ^Ü2 ½ò=‚I¬KH“cÁ” ùÁ3ÿ@ à9ÿ @ @p2`‚ÿÿ¹—{lji·3Æzp«éš¿oçê¢?çc·êçáǹ+0ÿŠÝÎÁiôÿ66»±=ïùöÔ6w;[˜C¿®eæý'߆ê?Èõ÷óÿoŸA¯ðø¡k÷Ù­/e!Îý²öÜêûǞå2crÕµã²Áº}¯·ñüë#×*9É.ã²Á9?sF¯/g/¸¶ä@ƒËöžÖëËþÝ£%oÀE_r.hù£‡>ø¾’‹ lio{ËX7>öE. *+.›Ãí}„®OvÅÁ’áSßè y ++K§ÍE@ ?:À÷!A¹?k³Þ]ÌÑÃæÝ§“õV9•´²¬÷æ œÜ5俬Î11?ã2ÈèÞ)JTð&á•–Õ MˆY×¶²??G«A‡ÊۉçÆÇ¨ŒSÊ4þy Ôn²Üeê/¹™¯SÀ?ŸNÏ/G¥{œö[¯qmC­²§“¦CþÍ#MÿPÍK NðXtvÁë`5µœ’÷žV!xÈfZ(ëè ¨1u)Òdeäк¤\s¦åâ;ñJ“Q"€Z±Š:½ ++k‘t Š©UZdšÎŒáºAûB+Z-—œ3YÑsÔ$- ++ýGsëi½i«¹Äuyj:Ó\fê#­MoR‘öm<烆>¤§ÌñçÿÞøÂÔ=<ÜÙÄgÇ?®ååüµ•··@ @ ƒ¾ ¢#7ÎöžÎåP>pY«lL&xK§õLçøû œ²&›a, á aØÂk|Ýa¡ ++‚Æ—8Ñz8âí¢ 6øNˆî9z&£ c vr‚RƒÇ×/J³Qœðÿ@ @ 80ÿ_°åþS§–v;ó?|ɑ³6ùl»•ß~&îÿÝÏTžzêvö³g;xþŸ¹ôœ=ŗÝÅnçèp¯žÅGsåWTÏ3üú+éÚ6>ò*ßÏ.t;³š/À쏾çïqß+Ô¿¿¯—}ÓU‹~À÷½¥ú/ázúó.hÜ÷…FÞ,÷3Õó:÷þñKŽ^s€ïGkº¥-¯áâk–pþBv&wná¹¹“®u_Zñ$σ2UÏ"·á]ë¿UÊ¢«Üß?¢k…+ù:eÏe‹›‡ýo¼p˹\f•*9ÝÙ½~;톒¯`£+Ïý{W³gUÞû$8ž·Ÿ.i"Nâ¤vP Ôsîó-Â:WFºZ°HÁ·P·* ýb¤‹фL".4K—C2fH4' 8™8üˆ&Í)à+å± 2Lu+±Œý~ç:÷ý~ç:×9Ï}îëwý®ã涺Ü<8å‹%^¡ÄHÜÄèX†%ó'î[ú)kŒÄ¬Í÷]ƒã{_Zó#)óNžw8÷Ýöä¶¹Ìù;±¦ë»9í¢¢yÞñ];· V)óJòHìÄ(\ÉXÏæ¶,ı驓Δ²d$^áê¬Ï7áXó[«\ʒ”½-?1¿¼i£Ä\(c¥lCîc5ùÊæJ™sÒ÷%ù>ÆxØcÆ%>Š‘²å]LÉpÇò®— Vž)e.Ê}‹´íw[Ÿ+eEgë»q|KrJX[òT,ž!Æãì.6d|ðì§¥L;‰}™»`â¾³ÿ©”EÉaqûì¶Ý}±ôs@Ævq.ç8üxÅ5’ßSÆ6×yŽÕûîÚ-eÁKÙx×΋·¼]bJš íœÛÍÑë¾¶âiÉ}‘!c(»jv{ߪÁs$Þ$U¥J•*U޲´ÚäÏÖNyüêšFpºÆYÍÌã–ù¹£NÑú‚ßM„žÚšˆ—‚H jTLÝí|ðI¥Ä´Õ„5ã%cjWLFn Þ#~‹’å©À„ÖxˆI>*m[Œoƒ—f uMx~ƒòs=¹®µ7IJ&mlŠÅ—¦ŽuÌõw-œÇÿû&Ú@\±o seÅôÚÚ*­˜mÝàeMHžÄÚªAóê¡Èä~0S9Ó§'ÜÈTäÌ^N®ñª ÆG<Ó4™û¼i˜D;Ù¨ù&·—dñ*Š—´p?:¯L,XcKX®‹‰¹âí«(/|d~v¾êd²`ÓÃR– ++oáÎ\vŽóŸ67 ++¿¢.m9ܵóðì-‰=Y)Û¹ µµ+þyóC…_±ø´¯ëÆïÊ36I™ JúpL§³aúó]|lëJYÔrßóù¾Ñ~òG´}ÿ“'þå‹2”½Ü0¯µÁsö?wl™BËQ¥J•*UªT©òk’ì×µV5Æd¤BÅš‘*FéCwšNVò¢ºZ¦oï2„`£ÆûÒ'j"9Ýdç3neuԄóâO5oNtaFñIã*£#þCØ.ċ\2ŠnW£‰[‰x\C «KMR)æq]‹iiø4íC(|h£¿Þ:¢YšŒ}8ڒÏo¬wv‡æÚ[Ëˆ±¿âÄmO ++6_GÁZ¯ÉϹÇ¥?ùë/H»TÁhoœÄS·çËRlá2ËýÍEw¨kû–û/È\m:6…Ûou‡%¿l°_êŒÁ ÚòK>ÌE·!—ÆÑož óÛ½ÇÁ›Ö(eÿÕ\ç»q¬ùéø? ++^•¸„Õ3`å×ÏÀ)wOÖËhÞ8›ËþǪGïü\‹y—²ûç´c4Ì ÷x§³Uƒ‹ßÄX'i•*UªT©R¥ÊeÇÆjïµ"9É̜Åk³M¤í3Ñð=2ÚØ4&FãSÔ nÔɸ còA+Ó8C8¹3^7 ++Wßr¼)§ûQÃ÷¿Ê¸3‡\BÿLðJãV«ULׅ&š]:h1à Äu³ï$Ö$cd$²›Gn>2_zM:M¥#I,)ÉuKÚÊ  Œºl0RMÎcOCL¹ÅãÙÄož08ä:$idÁÖ7IOîK2rlú(^CXº§Hž—RáÙԎlœJ˜uf¶4(f˜Æ>A“ä.´¤ÕL Æ%9˜X Î‰.©wtÄC伅 a I¯¨ ™-YþHü™dT#™þxuÒh%L$ñ5Ô|lcŽ"G)ÚîWæÚÎø}ŒlƒÁí9Ã4ãet>°ÖMMâòÑøˆ{1fZg¶Ë€KB&tÄC9ˆžS•ç§îÿ/šû™iÿÏ=ÙÕ§>±Jâ¥=öùñ×+—¿ùî²Wkú½óÛ}þ¿ðŽÌ€9„ýüD¬ú)wå}f´.LŽ‹¿òÌ ?)Üò…›|e.ۍcýƒw¹Âïe¯ü {háPߌã’ýxLás/ñô»æy½¿kã%ƒ ‹ ++×{š¼gͽ¾´ãBø£G~ðхÊeUªT©R¥J•*UªT©òúž$û]l °uÆÆ92åþM ++‚œ¾¢0ìcO‰3öìÎZl¬±E ØÌó{ ++6ÿ*Év42€Û¦`4wØÉ{†ÀìtIl8J߈„3À¢Vl¢Ó¤~%ã¹gOÜ{3 6êhˆ8qGìíSŽä­zpºÍó09ïm¼b·x$lÝ-ªFMTÌ ++‚îàŸÒT@ÃÑê@¶³L„àƒMdSh"?Z¨œú xeBæ@ÇùŦÑѐ§.¡¾hò·GõxÇÜÊdæè6BÏÞ~Âóø“ûÿÀÏ`ûg>“Ÿ•fUü•*UªT©R¥J•*UªT©òú ÿÿmsJÃÝïíé0ÙË^ñ‚©o\¿·37Æù«¹×/\/ñ çWgÜ7ó,{qً…çÝö{ßêøØ§âVt¸€ûVú¿ù¼ñxî-c…8Ö;ÐÅSw JÀ]Ùyg¬}HtdKN‰c 6`ã÷¯LRæ žÿùNW[c¦”5‚}X:C¾€]Ü»ïkRæ A¸ïs;—üÄ4͚੝`sÖëïãxß.yº”%ÁL¬kÛ2ŒÑX˜õu1Žÿ¹ýҟ¶±‚™ØØ­9­äªðþ_•íáV§Ç‹-؎Fð?Ï÷} ++ǹgn‘¶„ %~àò.æâC{¯x§Ø—ò¼«»\ Ãù nÉíü;ç?{ªÄ+ðc\.;œõ9/"y.h·ö˜ñ'KYiçÞ.GÅp^ƒ«;›¸âæMœ‰’vJ®„ѱ÷wù6vüՅ?‘²6þãúÜb^Þ{ǖJ™–ç]7 »rεR•Œín^:c³äX0¶ÄÌlŸÝŽíÞÛ×>Yâ?J‰åsÚ9¾ýÎ÷=%˜—¥ì†¹m;?ºûâ'Û2ÑõÏûm[Ö NÎù3ø­VÊ>™õyYÖµ¾EâFÐ{¹¯ÓÙ÷o¸ò1‰ 1NæÑÎÜ¿Q¹`gÝÚrþ߬|Fb”BÎO\¥J•*“åWÀ÷}$ÒËÍÅÍì큹ì3Ó´õO%•´K:²UÄçDò!FrL+í‰D11Cµ âŋÌm¾lf“M."›xËWNU0mºwÁ¨D^iºé"1Õþ髕%¬šC|ÚæTö’âÜ*oðӅG«ˆðMÆ^oÇúž‚»è±*<éÓp¶¦ÁÀzíTæBo3¬G‹™¼½A “fª{&o0r>x´üêx2nŒjN|‘1!4ÎBVcTÆÉzÜ,}j¤7Ǜ™Ñ-Ñ{ü<IlâóQw³¬ã¥5Àl ÆÊš`^TQpÈœ75“L]Scr>‘š}Kh²%è¸ä'Y{¢×Ô¢<¢5¡n¼ï ’Ä$çÊ Ê`½%²:Zè7â:b¤ÑqGô9ÆØá$£%íÎr0|C¯*ñçô4’‡ÜC¹}£‹7f[WR:cuôÁ’'<ѹ`Ø ++ „I–ˆhŽ Ì¡õ›¾Â±°2«óøªREh:¶úqęÓñÊî[‰õL»Ïüø tðDðÓÁ<ëˆ|úš&ÝÎ}âÄÅ~mkæ¬Ïv<ä}ñ!¿lž÷âÇÎzÁB†‰©œ'‚<†Xì-3m¬a4Sh3õqú`3±‹01eˀ‰ÃèÑ‹GùìŒfO©hÆÐú¦0àHu8Ÿ3¤ÀU5{Ä#ÍÃc%À9[´éXg( ™+‡ãÔÆr¦Êº9)×Á«1¶ãHy°>b:p)£?Û·Ø(—"®?K$«+q|f±gœ ·»¤ÿÏçq-íÙÑÜበ€}@Ñ ++±\±±œa}ãâdÙDüN`2Äñû€á2\ê£#lÊ­Ñ\BÐe,Û\±¼+ÏÍAõÿW©R¥J•*UªT©R¥J•*¯™ðÿ_é¿û³é¥Çön;µéüýI¼Ë¾ï,ñ‡Ýï7»½~ñ7>~žø‘­ï÷–wç—Ü}êâC֡ߛÛÕ¿ìß<*ü*ö{ãïàT^ÀõÙGHèU+Þzoñ*œÏõÓwø…=oþ&ÏÛìÏWç+_ôk3O€uõ×ùnO~é„u<ñ+;^ƒ7|à­¹žê¿¡ó…Nå5XŸÏ/g¿¾ù–=ù¼NèסÎçú†§Ž»WpÊõ{×g_ú0îàPǏøî?[v0Ÿ·ä;ܑûõ ën>÷aÑs£Åïykǵð‹¾CåŠ_wé ˜„Øév“`gÂ$tc8Œ;ÎêóOŸÞþvÁ¨Ö‡>ÖêhÇéゝ0V‰}cçÓþåçŠÏž ¹ìmY·£1 Ïç²7áØwÛ¹ÏH™wÒÎ˳yŽÝ§_ø]±5ëÅ¿~h,Ã×sFcæf½ð_<0ÿásôÅoýÆÙ­Î†¹gÍoŸ÷ÂÛ.ø±`Lá–<®³µ,ØôpÁÄD¿µ¹Îcq|ô_7ğ_¿£ažŠGç´ãpþÛO—2W80ûÙ&Gó@^žë¼†ör󥏗²‚7‰ÝóÆ>'eƉ>×ÌoÛù÷_Û í´.F`M§—uƒÍŸŒ€JÒ÷YsZ}ói¬îæÂ0îà[¯wpynË,›w¾ôà }X™û~ŽÕûîÚ-¸ƒP8)ví\5¸çæÂWimýq¨R¥ÊÿS^|Ý¿ŒB;"wõHÿltIe'x zRlmðQüãô¥ñoÝý>Ęsw ËÎV Þv2t¡ m¢<6ô΅À*ÍôÛtˆ6Þèì€Ld ++KŽ0³ŒÓCêT“™¶"4ç ðD$X<¿ñ¤ú¢³Œ(Š˜"ݼÓâw£·èm ++ï ºíßËÄl¼ÜâÓã–Gñ±ÉGŽÑgHpD‡È 6k¦ÜãÒW"G¼Î3kIè–G‡$“|îݏȫ>1=;]Ö ++æHt†¦yy#ñŒJ0Q¼ Á¼ˆnÁÍøÃæBÈ 5t2º*0åÈg ÅAãR(ÕÚ@¾»H+nˆôúj-À,Ð́krVúÒî—Ë¥Æ9•ˆ iØ'¨ÞFŒ°¥åä Üpʳý¡gšxè9‚Ošó´'LÓdOzæ¤Ã¤ÀôƄãäöŽžj¬‰ìb±ÉVߤ̇‰eà¥Å¢1q/–ÃP †ª¼#{ênÇó¬‰y¼X‹hiÄ_7Åmì¼b,>a6$ëÜÐ(Ü:óÝaöwÐÐ!ŽAã0k£s%çUNh†cÆe-bDaœÐ·%èÇ´¶žcÇcøÚÂÏÀ, —¯Ä ß절h6ð ++‹Câ4„‡–OÚÎWní±’8zÿ‰Ÿ"ôu5yZ ©ÄW‘#Òe$ŒEEÚ8¹ ¹j‘‹’&ï8aQ·©úÿ«T©R¥J•*UªT©R¥J•ß|©ûÿ*UªT©R¥J•*UªT©Råõ øÿï}i͏¦—Žõvd,õ5¥|2κJ•*UªT©R¥J•*UªT©2³HN´5„Ú*—HXï3'`ȗIÿµOçìgTq“y cÔ£¥c–¼¶Ak—0Ãy§SÌñU®Éˆ2—j(i¯B`àˆoRÈQäûÿ¿üö’«¦·³?)6vjœÿDÌó;Þu–ÄÌÚÔï=›¿ ÇíߨÅÃìœß¹»ð„~ù¾p!ŽSöÜøÞ|Þ:‡ë»ü'¿ð{ÿãö5ùvuüèO\”ãä¡Bßïmè¸í—´Hœ¿2ýÞg;~©ñÿ»ëO;øáïç|¡QýޒŽÿ*/À»f·ÏݳnÉ/òùÈ~­™×¶s*/À1?Â)wåøûhÚ¿7÷—që‹ÎZøRŽóWÏýäÈøÿ~'îù¿ýù¼‹ÐÿG:þ‚©y ++vñæWœ¸M8`7W½½ëóÖÁ}'I™±}v×Þmƒm_‘Ø~›¤ìÖ|ß¹86_¸xó>áÀ*•Ë6ϐoàюó`÷¬K”2¬„ÒΎÃãðì-IY*yvÍÀAÐïr¬ÝÚï‘’×bÅü‰û.“\Îh)[ߍß?Ä2 †Ëeò¼Í%°t~«³_|jðDm¥Î¹lt~ƒ³»ùwÑà–̑Ѥ&È8¬èÊV QÖM9¢«T©òxŸûr‰ëdbæúfp2n-ߙsÀZßàm21o4^ôÔ œàx„R¤Žö ¨ž5%þˆ{DûuÎ=ë¬o}KÒ$0C:ziñþÉÌé-Š=§u)ž0oFEJ(X ++V`¼"­ Ïüáè$Gޡ܍Èê(MQRÜ£æŠ(ø+…5ÕÈ0õR)ó%&qÚ ÎmU˜™]æžØYlþKU¯>㦝Ïpáì*×üB þ]æ©‘aæ ÅÇ]Â>õùö]—Á0Ÿ<¬Ç–M‚†á"Åpyª D¬sޏT¥6<­ ˜‹†Ò޹'ðp0”È\óîy¶Åá1ᤝ&6;Ôƒ›ãÞÛF{ŒFÎ\ކû‡ç]áM`kJR.ѲÇQ¿HM{YW1t­€_¢yCðPÁ/ã¨1^|B: ++žàNÀcJD ++÷&Š‹àyÁ¼˜D_35°d¨>>«|DË Y‚‹aþø4ÅÍ^øK²;ÕcPþ¿B¡P( ++…B¡P(»æüÿ[Þyî-,wMôiÝþ¥»ÐçŸüž;úÏ(~o:¹>tÙáϊ¿Ú†0Ñ¢o~ç ¯íyî»OóšÁ—ý›Ï{º•ùž›|Å }¿åÀ͏ö<÷=|Óŧßò]w½ùìMóÙ®–vì¿:øà¦ý¤Çí;i˃»úÑîóëþÜ}ŸßÑR¶Û)ß®W¢i}h\‰æó»èê6†UX ++…B¡P( ++…Bñ¿‰‰Ï~çy¦tû9t…û¹s­«9¸jv%ÅX ++é'†òü1åTM­¤™Xëb±¸Za;Fo˜ˆÃK~f3Ü•É ++ ÖúšŠ±’'‚ŒǚIÃȾ–Ö6›`ú 9ï»È?ò‹äcEß|µ†ôöªí rÚ|“Å”BäX©ÿ_¡P( ++…B¡P(ŠÝsþÿwµñ“ KÇ£'$îöFlË~¼ò„ÿoøÇÕNÇó·øÞéxþ­ƒ/㙇Kœ|ŒÇ_³Ó8ùE£²ï¤þoXß|øÆô˜ì£‡krùÙÿÒãØsó·oÜ¥^á$&{çñèFÊô{þ¶ o2~‘²k„ð1lŸÙÿümOÐs‡ß6Ä_òšóZÌy•ð Ʊ<„¯ß¾éÁÆ5ˆ±]oېO~Ý÷NúHãXÓú÷Áá¼K>»éëœ;gàž¡÷`ÍÓ½¬s"Öm™Î~òÀ_øãC×µXçl:'âÒaÖ̞tmç/ôë7ð6¾ô‰·|·çFï}Ÿãt¼wÏUR§·±hÞt…B¡P( ++ÅÿDÇ"Ÿr’\÷É$cKM¢Q…ùë«wƈ0B¤š@)ïMÉ®„œ¡LóÍ[ú~EÍÂÔÊM±•"☭LjƒÙÖ²ÏÞ8o,“ÆGCQ€ÊÃ\Œ…Ê”6ÚD¡ \Š/ë6•ä{¼?Å|¥s7áß`›~…¡Çí/,Ž46œý€„}³&DKޱ+†ê®Â ¢âA­Ô…¨ÎАÔ(J°ŽÝú¬–:WÕJ@m‰:TŠCB×lȞ;½oþÿhÂÚ;ꑠØy›c±¶Ær˜§7ÐnX 5» çzƪGª5¸”“,cã]¡Ôµtí6=Á3°}¨wÒ¯WÑ3:ý;gáE±ÏRY_薥HßO<&<5*Šéèý±½¦ÊŠô´mÕÿ¯P( ++…B¡P( ++ÅËjÿ+ ++…B¡P( ++…B±;`ŽÿÅìÏYX:]'ï3°]5»RòޅÒ¢ÑVÙÏÜYŸÿܚ–ṳ̂žOíùA×nýì†e-—«šËJ¡P( ++…B¡P(Ši0F›žÇ0P]Q–Z‚6eg'ßø@F?Ãjb:IF…¸”˜ç“©]cʅá<žqÌeê+?2Æb¾ýÿìw¯œ¶ÿïb¼—o9âç=/µnâóW÷+-þß:7-û/Ævõ“¯ºS¾”PÆ£{eÿ¼‹F7 õø#×Ü×bëëyˇïoŸÝË·ØúäÚ7†2”­›Ýtc‹uÇ8HÙ ++)cüünýý?ŸrÏ#þ/ÿȼ:k¹Â³÷Q—¢B¡P( ++…B¡PìN¶¸³n(Ñ×'ú¥ÆL­êÐ./ÆdçL‘nDHmHф@1Xò8«fµÿßwÍ~ï¤léàËßï° ¢õïbÓw\4:GÎc Â_”Í—OMG)û°œG†Ã%×^Ðtò“5í¼Ó½ûu³'ÜÜËJã=¯ì—7€ ­Aê\‹í”GÿÓ¦“E'_¡P( ++…B¡P(^Θø›M¬ÕºR`ƒæöwu*6Ìü˽€Cqaԓ²ä7Àœpj¨ò{ÍT44¡Æ³ ©1åT šSpë"»ê0>×4hPð¶m…½Y™ÝÁ  ‡…‰œ8€äü—j,ŽÅ¨–ˆƒr.¹ÚŠþX€E«Œ«![ïC%— ;ç­ÁH ÉEæ€ÉŠ+áЬÉÙâÌà1+¹ ³>b$¼úÿ ++…B¡P( ++…B¡Ø-0çÿÿ«¯üÔ-,Ýst±ø¼_‰íÊW„“ÄÏïÂÌxžý¨íg¼¡ñ¼®ÜgrüŠ»Vž)û£ÍãÑ5ƒŽÀÁo?ì§²?Y?mXÌýga[vÏõgµøÿˆã¯ßw®þƒ6ÈþRë„wÀú—Ý}Ń¢/©/°iŸIýŸ¾p¥èÄÄzîâýW|³íO©âx#û÷ÃvϺ¢k˜KBý7 íü­óŽÚÎý5¸¼hôì’ÉuÏ{ÐßÜy®ñî•>PóàŒåëþMÊH’²;†~\4»¨i02£• c¸yöMWI™«¥•]>è%üÞc—.o| c·aÕ0'îÛrX/+MûàÝR'ù?;æ”o¶²Ôù c){=Ûù7ëk< [{Ÿã Í›K­lžf±~ÐÊRoç—å¼ÕضþÙßjóZsãnÜ6ð3îÿÕM#2‡Ø8ÇÉxràÎ}råÖ6¿ÞçVçÀùøúí›dŽ‰±õoµœ÷çØNbeã`˜Ú¹"¯ÚùÜkÏ|Tʬí¼UK&c}öìU¯oe1µóN^2i燾m¶ëUúÖ÷'†²iŽÉ ó¸" 5(¾¼x҇3ßÑ·ZY±mÌ>5ð]~÷±-ãÆ1)›rΰþÞ»çªÙÆ«‰›r°–Nœ½~ïVVrЇ˜B¡P(Š—$N9×#¢xÉ.LËLÁñê™Ï¾kKòÞÖ\]pžÕ5ù yÛñ’jRt…GÒeœñfš«muSì ¯œÑ£^/þhc½5fQ•Ԑic\q>F¾4–LÈÌ ‚øj=]¨…¹à™ç¾ÆRÄ_‹ãµ½t¿7.Wš_ÜÁ>(¯Ñhs)¤j Z€¾xW“I9™à*ÅEã“C÷+½Âµúœ1*‘¼ã䳩…AÞ8S\Ý%23¼O0Kj™QÝÁ™Rð[u¨u;XJÁ҉èìÅø™y¾øì˜užÙæñš›úáRÎf "æEÔ㊠〠tŠb$ç DiP;¬Á’‡sF¼÷ÿÏN [m(5ökX ž+>ôß3à˜žK‘¸ö+§ =ȶ¶cl1¥rð1Ñ7ÿ|®)<LitÃí۝ GWMXSͳ1Ô*ëÃb”°\]íd|ÃCØM¼¶GƒÆ³ÑGñº|Í·d y?›f^Áq6a9fدÎa%ÌÌÅØc¤ Xâ©·ßːÙìûz bÿ™ŒfÔêzp°4ÐÇo"֕v^ý‰«ÿĹ}X¹X\Ä0„9Ç0W¹n&Ë.˜låØê¹+ãW ֨㤨ÿ_¡P( ++…B¡P(Š—?ÔþW( ++…B¡P( ++…bwÀÿåòŸYX:Ý)<æÆÃ_zNËÁWýx´U8Ì·a[ñ̽?¾Éi<:pïÉñGl÷5~¾Áñ›„G}¶«fW ++ß>ԀãO“úÉ;_üÆýîÞ¾1eÿ-²Ÿ'½é¹_†û)Ÿ€~I=`[ö†¥ÿ%<cÍxt²p¬oa{Nå?ÉþXì¢Ñ*i'yàŸÿܚÆegz†áñ}8õ˜Õ;oCm\ö†ñ›æÿÏ œûu¾k"ÚÜÏûêp½Ënky ++­‹¦ñÕ7.žŒÍE;Ó9þ½Î=¤¿;çÿ/Ý{r½/^·þÞÆÿw”¼øñ¬xóÛ÷íÿÚ®wüÀŸæñ¯]<9oããoø¥¿Ñ¹ìŸÚ{R6Íñh¨óÒ[Înu–\¯þ¦a Mç}4CÆêûÞº²ñøvž|Ë:ÛØóŸèÓÊZÜ9÷g=õ›Çö²žgò¡a­þ˜¿^ʜusÿü°ÞÖϾùŠV6áê›Å“5´6^ôT‹ˆ}̎æá’Ïnj9(C6m¬¿<ôo:nàÎa¿çÖ³ne“˜G–LÊþóãë¾ßô'mèù0‡:×̞tm+sýz->egº•“˜`;ñ¡/|ºå÷4I5- ++…BñRù¯¡Zã²)Åæ¼&SØü´ÞČ_ 3\[¦¹ÂîêC±™©µð’ã\®Ì–E23Nu¯™.Sez'tÙáÏÊ~¸s¦ãoáƒØÖýõ)Mû߈T$yC[vËúû[Yãf-7//À?Ú¸ÿ>4n ÃyÓq'í>ð^Æ´—3s|t¶}ˁ›íe¥ñ$.Æyóì=Ÿ€K­Î›†óž[rÁ÷ZYsþü3`®[s_Ó÷÷nü"–ñ€ó·]xC/«­-WÊy;Ï pÝÐ?d¯3›ÎÅßcÐÍ×ÁkۘeoZ[VKß?†í3ûŸ¿­—¥ù÷c;åØ [nƒœm+[*eäþ_ðä·?Øb J_8yn¬_·¦gu¶•].} 'åg7tíҍ¤ìÕ²Ïrìag<Õs ¸ÆÙ4¬Ý°Çڇ;¦—?ÌÃt‚kæÅñ…Ə ¾wép_½óOÎúA+›Ä6üt¯¹óÆ(,bLžßëÂï4îL mþN“5(˜GŽüµ–ÛÀøvÞ÷šô}:ïÁViçfl—\{AãÜ$Û¯wùÀ«Y;ûÄ_ö²ØÚù ++©ólïYrú¶–÷ –Ó2ÄgLçDX:ð¦c.ò¬yà€Û[Yðm͟3äƒ8mÙ©wmówǰæ¿ô‰·|w~ÜâÑ=Ý8{ÑÕ­¬Z§, ++ÅËä-{B½hƒ[[miüæR´’MÛàïdŒ!ÇÄTÛ ¯B…:ÜÅâãõ\¬6[(tîgºÆwϑ-Ò۞dߒðo Î99´‰zïç’álIèw¢GðÃ_¬ Ñ2>ÃpEWC$Û<’«[é‰+t|Õ(­£k-82ªù·9:’…- öÆÙ=G~rN¡û'èK_cæ±èþ6‘]ŒÉ¶‰jæ¦d¼œ`@Ld£ÇÀœÛx“©Åá0ÒnÉØ&!ܳ?Á%´ßáå#K€(£ ++Ä 96”{'»¼„DFöį™MM/¦–ù®b,ú ñÉGï3Þ'B¶Âß%Qou¾@J۝—2²ð)Oßç{ŠG޳j÷k:Ìt®EHßó5˝ £dbâÀa…I{vŒmÀ+‡•qK¡µëˆLq߯í^§IŸ×,²B×®ˆùcùPnßHÒóˆÕnðÀ€¶µb‘¡ Ì ++‘§s/$žLu™€èÈúöäÞÓ#\1zÕI’z¬.뙃 2y|óÈb‘b4ɲÇìÇÄö‰ñ(¦ìRÇuˆf»crz4'Öÿfïêƒíª®z®CÍ}6*ý€–Ö4"šˆûûCHf"†@€@ҒB/@iĀhëH‘Ì´Îı:̀SZ¡@%Š…ŽãX㘊iš–L ¥ˆ@-X×o¯}÷=y÷åýÃÈP²~“›¼}öÙ_kïór×Ykýց2}]sÁßuzÚqJáÄ!¡€SÅß=ÓA Â¯‚hId6G$&À#=Ҟ7§#"9•4 4UÅFrÏkö޾{ÃrNÏ×`Ÿc‘j0?iþóíÌi¤h g¾žãÁ¼¯Lù}ê <‘´3tò°«œ›à|PŒú$+:F%4ˆžQ’fBžüv¡ƒŸè”Ñ=‘$th­.‡4#ª‚æË£ßÑΦDH‘èé7VBzÊJ"‹„!zZ¨#…àŸw±ÿ @ @p(`hÿ_k6Þ1¹vfï®Æ ÷GÇ_¹¬ÚÃgô{5ûõ‰Ï¿o ÛTsîW¾´Q¾€¡ýù@^À->¿®ý?5»Þ‚zK±1†¤\¿wSó;8Ðþ¿¦ù)ÈG°»ñ ++üé/¯š¨ü{ÕÍ6UŒqñ®sngŽ=¥Ùvxl³9^9±þ®3•gnk³U~dÿ†jKW•ã`CãµÁoo2ŸøÀ½Ì¿§«½õ¦fÜúå+öq] ++lû]ÓlÔ_š»Šù½ <ÞæR·‰>÷ŸtÞ7¸Î¶ï.ikX?±í¶ÁGÇ}Î+k˜Úξ£Él”ïoSi›êŠ{×}Ÿ÷]U›ê¾¶÷뷟û®+i&agoû¼nbï•ïϳ\ÖNÃÈöäOÓgùÓó™»NeËû7ÞÎÔ¨Ý{uës”Ob[óñåŒ8rÈ 1b_ÜÎÞu /gN?«ÌÖÌÈó¹û/ã:’u×Ύºs?qÅw¸.in§Ú¹Ýðà9ÿ1àûã¹ìj2;béƒÕ¶]9 7”vSsú­îØËÿê6®Ë‘÷èìö<ò^ì+}‚ÏðmsÆÙ>ŸMåk$.Ó¤?êbØW´pÌ×pÞ09¨ƒrpž1åÛ¸Ið3ÎTô𐡝 ‰Ñvƒ. ð]+BûIÃ+€s1…ààŽDJ‰£­†kC¦oÆ¡ö:ƒ[2døNØÓÙí é¨Nƒ8~RGH®!Á‡ö«\q#øé”s?Ê[ðÿËQÙ夤ªùy*Îð0ðʀú%ùÿ@ @ 8 ú¿@ @ ‡†þÿsþ5³'×ö«¯í¨?ÿ¦Æ+¶dÑ1Ìÿ§ø:ƒ£í7õø^ö·OÕœóêÁowí3ïü ++û¸‡êË}ló‘>këú¯W~3]}Ü;ùÿ&ûy/h¾À£¼a÷•vëÐn¯¾»ò†öáß×|øOßó·÷ø¿¸Žc¦Ê‰>Ö{ú ¾Ç@ @ðF@ᨋªä¸Sܖ՗ÝfmUÉ`µö…×.dº`½ÒÙÃ!?gIÅÉÆÑ_>YU {ÐڀÌ<ÂßF°†]DLBNڂÎƒI1èBÿH­M›"îÎ:äœÁä˜@í²‰! üé3µm<‘>#\Û} ++•¿“&dào-øíLˆ:¨Q ¼x ÄƒÃ¾ …î.›˜&auÖGZ,Ft ´ZS/Î9þ!º DRpU¨ü’* NÀUb;¦âpœ*†ÂgGã:’‘ò±‘¤šBíh.`ö³ÞÂu?S­"ɐˆ#b3h@O»“I‚ˆ0Zej˜<~ìs¬w×ï7=þÆSÞ÷/5¦Wõ{ۛ`œ¿júô‰/\¼“¯[Óï=VîGüöž ~®ÄóG:^ýÞ¦rÿ"úÌû‡÷l+|þ$ø±š§€ùôÇló7üÞaW{4îžßWLÍE¿»Ía4~^‹]ƒßØxÕ?üƒùŸå:[ã¨÷ÍÌÿ³î¢Ì7"Ïsw›ËÆ#.œ¹ásåG¿éˆá;ÉÜðóZ»óŽÿ.ǺkͱÒÛ[|ùh¬û-­Ï•³žãÙéÉâw ­î‰Å_¬<î5þzeÛãÑXw~¯25Çûâ!ßüAbϧŽ!¶µ;mï33ë™òÂÇ.@ =ÏÝG!©Ù|íµæõ8/¦a݌÷Kdg ++¤¹ ¯i³žôwj¨@ÏO +++(֜qÐì‘9¯H'ÎÁ“bnS¤Y‚Ñø¤—êœ\RaI‹'=")˜™A!esvÈР /ÐٙAì;iÁfr|L±¤»°`€.Zˆ J}çHÇWŠ&€$É? ¢R¿ ˆs^›Jž¼3À{däPã Ëù0ÈW1™÷ (§°:’Kv%¿CÌ#u¹1è~C“NØ.ƒì"1D•HS¢"éí9"±™Á’ %;H‡OƒOÁQ^jtx ²6¬˜Ÿøÿ @ @pH`hÿ¿ü†øéɵ3{×6Ûù'çïYÊ6â@×W6žôóìm|ßï_w‹Ì9¯íÀ/à<úÌÝv×ylK÷±ß[ѸíïÙvLáówÆÓý/”~ÎD?¯,=×½6tÿ‚ÆÙ`^€Eå:¸ËçžúöWË|”Vc½[œÂï[Å<÷p[™Qøñ¿ú¨ÏÀ#Íþ=ÊÿUëóØã.x¢rü[®[=k0ï+ž2Šë}.nœægn¾ì{ì‡`2Ûâ?3Mlsçÿ1}.ýþ§îa™â·5ŒrüsÞû©ýöµý[ûÔ©?U÷£ÆMìjÜù/>·Ë¶ÊlKésj>þEfgÐçùϯÞÇ> ++Úuý ³W޳oƒuµÏeÍdùž 'qO,ϵMÖ÷ϸôQ®KóÌjëû³‡×0Ç¿ó‘å²¢ÛQÿ…»JÝÔ> ++§É5ã4¹æmùv¼ëü§+?¾çñ^~ë n4×ü m¼¥ÇÕ8]û\Óò0<ü ¿]9ðmm·£ññrç?Û|>Þ;vú^®‹–Ïà¶#†ãÝõV®K 6@p Øé«0°6^§S×fŠtXF'£ÕŒƒr¾ël¼BâòBæBÐ|]yðÙ{¼aÖyT›À`n<}ÉAry¤/Ï>eo`Wuô•P+úB© zt)Yú6 ¶xm2ÈÝõ–/~ðIÙ&mi|ÈÕѬrô$5“lŽZAћ ;´† ·£žiÅ –hOô°“é¨ß•Np÷%_¼îI8Yzä[ƒ |.Þð$‘€™:úBJm¢®yT‘W¤ñ}´rò#|„/z±»µ§Åfï³NÁQÿr ˆ0ÅÒ¤VEûç¨K8ÐCTç±G?IBy¿arÎãsòlG/vèf7NJ‘¿Þ„Xr¨Äïÿ5û/Ð.»r‹-ð^{æÅ$nZµHáH=t9Џ6Qß+4¤sÐIÌÔ?AÒñ‘:&±©Aÿ{”ågƓºv}šH°ìàUL5ƒNLõ´ªŒüÊ©D½D„"ÐléÀk4£]ˆ¸ ­ËÐd,­”vËá|“bW͇žú½›=÷§½ûk• ö{×¶âÚá7·¸ýkOªùæ­Sl§ÞÑúzèÎUÛ«]¼Ú9W·þ¶|€ã×uÖÕþ»©µ{ùgÖ?Á¶á\íÍ»›}tóçì¯yÇË;K@ @ ^ àûœ7)G§=h÷¥¹«x.ÞæyÛÔêԝ5waÀî N5ž·Q^Àµe¼‹èó£-—þ`PÇ1[Èë;\¶—ëRå ÜVêî§ÏêGòÌËlÇ4¼€›K;ðû÷ÌI伆¾æX|ºÈ¹ÏÚºþëÌè5×1ßb?Vú+ž©¼€™ûo…žÖ2÷Ÿ÷‘Ûmigð‚ÿkÍu1ð>웆ðèYúå|ˆà‰)u{;¼€§ÞËÜZñx×>8ß¾wœµ®ÊìäÆW¹â»g߯u9s;沜:â†Æë(<}@ ^ 8ÒtðH îjþðnŽ3”sÌÞ¨ä•ûßœ‰È˦¸Œœì±röºìƒ š:VeäW£Ap‡Œn%—92©#ºQ.$î¹µWÞ[/jíÀïGešS¢6È6Ÿ­›ÑÍù†éö Ê’vM¶!§pš(Û´ •GIêØ?܂.‘Æ‚ÛøŒÊçgKz•i_¢ƒ¬¨ã+çžq&(I#"ÙÑt"͉„ž¨¨ ¾|%×”u*Z“\ÆI()¼3VE³ڒ2¾5+Ò`wŽ$H²Âú‘q/Ó÷Ԙàqž‚wöÛ+ˆïèx RÐ$˜ª¼¹Ñɉ©çI_À˜ 6¬gʁv¶™Î’ØgËþñ&ù¬ ++Ñ!rÖ{+§¤Î9øh›"ºöH ’ûp˜[Oì‘ ´üƗ§hU¤Zûò«HK¢-Š$ c”Uç‚@WSª9öè\Ú*k× ¢} 9:®Ó¤©€°Ï‡'&€AÓEz ++,¶…¶N£Ó‡>IRô\€)S9’ê Òg–˜ !XIðç6âñUgÄ>ЕŒÛH!J`Õ$Q8G’¤¢ÅŒó\ì;úÿB}Í͓ôknùQ}~Yч¶àúmÿQÑÛIæý^¿éÛûŸŸ[ôpgqý°¦.xÞ=ÏÑS×ïÝwý|Q¹þ!úœsϪýU_®zÓÉÝö[õPÅúëœÆ™þãÏW½PYÇzö榻¿4ç\ÖÓ@BÀzè×Qw·üóì½ùdÖ'ôLÃÃ~c[Ûò[—<ÅïN¢Vòߋ@ @ xs¼7ÒÙل×;ê­&å4XåL²%˜tdÒ«I!3¤hgÒ cò¤û¦ éVm-¨øI­7¤Ž{Rg•vYCÉÏ:ҜSpŠ´À^þèKr¨½‰È Aã8|òº¼¸ÐèÍàÝIhïð’Ç©ŒIrµðí=€ÉÞ#@Ÿz¢!hõ½BT9ì}¿Ç±¤”Çd­V¤Â“žH—§‰&Òòi¢ ð/³Ð…±ßӝÊÑmÆ¥XÞ¡)äoÈ6#‹±œO¬äð1khðE¡§Í´ï%Æ÷ïñҀ ++aªwJâÿ/@ Á¡€¡ý×›¿=¹¶ß»å vþ«ŠmûVú,Ù9çØßÄ~oIóõ>ñ…‹w–ëњ±ÞgÊuØÐ?<±ç/Ø§Þø®ÿ4üØÏ\XýíµËl³ç|ì¸a뗯ØÇ~)°ÍþÚæ“½nb/û¸§èÙ.¿¨ÙÞ¯~÷Åûkހê#p{oœ>«öþÚalëw՗{qó»^9±ïsœS~Ç}E³õ¿:ëœêsžj¾Ye.ëJŸúîš7Þ°ïøêÒ'üØß6gœóÍgS}ÿolòZúäQw°¿Ó@ oL4_r¯l`Ê6ªúäkw´Ú¨P2Ãûjo®q ++9Â1ÞDíHÓ(mœÏêCÉãžH9ÑÚ8Ÿ,¿ô7(á ýhLôð7%>B+íC@@ÄøA[m³O*㵎 óA{xÎG‡ ›R À€I8»XâHÙ1Nþ1pÕOƆ€8g©‘Qـ@g4BC”V0H›DZ^°¦ð /s$´§‘¨ç\‚O;îi¸ ÂÐvNšu¢r_øIô õ§D[I3Åâ?ˆk°‰d©ƒ‚³?lþ1×ó@û€0 ÚBZÝ¢àv@ÒELL$0JÎi,d‰8]Øþiuθ„üŠÚѺ _º)…”C5©ôåáN3Ï42íÉ#©Xb'¨Ž–… @ìÿ@ @ "ÚÿÁÛ6¹v¬7^lÞSñº @ @ Å‘“Rìÿ@ @ ¼ù!ú¿@ @ ‡†þÿÏÝðÕK&×ö{/tòöýÉGáÿï“7ýޮƅ7oçüW˜ÿ/§±Þör\~ݹj{Íe_R Žõ^lu£ùêהº©óÀomsX5±f.ç7™¹üv´º•ÿø óõ¹šË~Sëó'¬ùóõYËyÙooü€×ßÑ÷8|Nœ#~cËxÖþõ9|RÜîï[>Äó¿ù®¿cž?ÎÙ0ÖÛÐÖ÷­Û¯{¢pù)ë£2@ @ 8$pɕWZ£üð]P…3”^—Á˜Tʖ®zÐZæ 4:ë sr!:Ä x"@Ÿ´Î>»ˆ´}oÒ»äCpƄ¨jNBM:u¨õTÁãètD¸SQÛ&cWÿ¿þðå»'Ï}¬÷Õ¢Ó.¬õ¬ û$ñÿ@ @ ¼¾ï´Î.xÒúµÕHEཋ>xkLÈÚ%¼[HÚ§SLHµq !€M~VùÖ£~ÔìáÏæg‡?‡£†?Ç·N°ý9ã-½’~>ºSÆûc:eŒõžNvö÷vʰ‘Ï–K…÷wÊÈ£w|§ [ü¼Nö÷ùòÅý :eÌç;eÌçÄN>ªSFÿºSÆüü°ìP—:e´Ï2î=©SFû“;e´ýà°ì1ö‡:eô¿¨SÆü¥SÆü}X¸ÿ´N÷ÿF§ŒûOï”1¿3:eÌoY§Œù9,GÌï¬NãÝ)c¼å2Æ;·SÆxË íWuʸÿ#2äÿÑN¹¼Û–3æsi§ŒþÖvʘÏe2ú_×)c¿>VÊ?Íç—:¸º[¦>Þ-Sºeêà·ºeZà5Ý2 ôwºeZÀïvʚÆÛØ-Óx×wË4ÞïuËÔÿïwËÔÿtË´aØ)ãùT·Líoî–IÀ·ü{×fEq¥ç ++꼐ƒf"** ++èîªîªBDbPQg ’'€á!êŠ/‚¨¬h⨠¨(5ˆë( D—à ÑI|ðZt@ÔɈWÄ1îªúÞ9sG“õû’|»ZçSÇ¿«ëœS§N×£oŸSkw–gÓ”7qº 9 ~·qŒú·sŒöÎfX‚ß\Ža¿ù£þÝ Ópǰϯ9†}p ~÷r ýîçúÔ1Lˆ>À1ä-æüâöz˜cåÎDÍaèÿ(Ãô€üŽcèûŸC¿Ç9†~O3LÄ3ãþç8†ü?pŒú¯0L‡§¾Ê1ô[É1î_Ղ£öXË1ä¯ãò_ãöxcÈÛÀ0Mop {läýù6ÇàßÄ1ôÝÄ0M[8Æý[9†>ïs }>àíÝÎ0ù÷Ž¡ßNޡ߇Ãq ùs yŸp yÍ “ÿÊ1äý•cÈûŒcÈËd†¼=8F{Ûs {íÅ0M({s y%ƒ_)Çà·Ãô<|ƒcèóMŽQ¿+ǐ¿Çh9Ã4AÀ1ž¯9†üƒ8†=æüc˜~€8œcð;‚cèדcðÿ.ÇЯ7Ã4¡ƒ¿äõû¶`AóC?Ž!¿?Ǹÿû “ÿäõOàí=‘c´·’aòÿãüNæüNáýõŽÁÿ4ŽÑþá “ÿˆcÜ?ŠcÜ?šaòç38†>c8¿±Ã>ã8FÿœÉ1äMàí?›aòçs8†¼s9†¼IƒÿùƒÿdŽÁÿŽÑ¾ ¦ùá"Ž!ïbŽaïK8†ü)£½?áúLåþq9ôÀº‚cțÎ1äý;ǐw%ǐw ÇhïO9F{Æ0-À~Î1ø_Ï1øßÂ0-°nãònçí»ƒcÈ¿“cȟ<«]ŠÛ¿äæ0Gmç£VåòËÏO­êën+èҁ÷-pǰeGŽQ¿ßÓC·ÎC.CÁ}9†m¿Å1äíÏ÷ôà÷mŽ¡ÿw8†mºq ãwçúÂ÷ôàw(Çà׃cðëÅ1ô©àíïÃ÷ü¨rŒúÇh¯àúŃÂ1ø+Ž¡¿æï  ¿áòäòâòŽæòp yßãòŽáï ïXŽÁÿ8ŽÑ¾ã9†¼A£Oâüów ¨?„cÔ?•cÔÊ1ôÆß9@¿r {Tq ÿÁ1äÎ1äUs y#9†¼ówà7žcÜÇh_ g€û'r ùçqŒú—ò=?úgǐÇàß³Cÿ«9¿k9Æý×ñ=;ìUË1ô¹cð»‘cð»‰cè7ƒcè7“cÈ»™ïé!oÇ4öq š WŽÞk%=#½{–­,‡ÜN~¼ªrÊÇܾª¸qÒù«)‚ºËšõ«ëa¿Ûv´_Sùc?úɚ¹hGE窵´¾™*G®­@ùcûì¹näLݯ׺zԛ½ ÃësaŸgÏ?¾¡ú.|èì ›¡_ía—½Q ++=4Üÿf%ø=Ñ|É[ô~{êäLã4Èo?¾sc9þÎ~uZc%ì8·öÝÆZÔ{uW&zOÝüéÙïÐïŸreý»usâIx¯÷%Æm©¹nÜûý ßŠþ·•¢^ýÍÇl«…~Sç­ÝV ¹U[÷Þ^ }úõ?u;9ÏÚ^ƒû/ž¶ÿÎz´»òÅv6À~ý;ØYò‰O¿´sʗÎ~ãà ++´O_±þ£´ëç·wþx.øŒþhÝÇ4V4œ¢v7€ÿÙ7öÝ]}ªŽž¹{þ¾ðGwW@¯ù›J>é<}ÌџT@¯Ã¶W5Ó:þòY·6Ós|à ŸÒ{d9rѧËpߊA‡|FÑíû÷]ñÙ²"Ÿÿϓ'Ožµ½+3¡Óó·9]ªã‰[]ÎÅØ¸öuÍå9l.>÷ Wf¤«×åoäclÈÙsÕÒ*—sQªÔžU¶Œ¾ÑÕÖ¹¼Šî³¦¢ÌBÛú®aÈ;¯ueqàꘓ7¢©®»-3ö§¥‚l.JêÛãÖ¾ÖÇúbd?¥ñäɓ'Ož6œÎÞ:üƒ—?²y>õ¹Xïƒ_¸þu{=¦üç}AށeV:ó¬òµwÓõ$‰ çҖ|îú¢Í;`´K–dõÿÙ=wÚ¼¡”E™¡¹XøòûF­tö „‹Ùߕ+«~´jµ+SÆÅ´²ö \ÑCšFg?móWe6gm2©éÜ»]Þ{ ÊfXžC?ü®š·Ò²4.¿´¤¥Þ 7º2£Ï¶_(çúØÕÍ6@(¤teKsž90€&` ͉wdB´5¤&QG¡ÛÈÅbzÎèu¥áàx°Q¢-¯˜"¦¬7„¤èþôiǖ€âèÑJ4Ž§ã3’%R{Ӄ©ÁUf}ñ_ÃÓQãñìP ++©dvLø‚Ü®LÂiè‚੊| =†'Âp jJ¸+Y]k¥1ÎIŒs¸Ci”²JJa܀Kb]iàÆ¾ÆNò~4 9 ++ù›¡pù€ž¨Æ* hݕX/…OclÂ3Dƒ º!¡ÞŽJ´+aÏBï€Æi8Aúœ JJÃ)¡jâÎXA5<øO`yáÙÀ8ŠAÄ)1å\ ·Ñš¯Ð1Yƒ ++†tô(LŠ$õ%££0vr(/=w=rs ŒêÆr g0 :6ö\,wFV0^ºó¨l ++ÜY°ŵv؅ ++"Hëh<¨ÚHw~4 ++0¤áÑÁã Gt÷(Œ|pdlû±=Oâ@Óû'ìº%¶á‰¦÷ö…nÐÚh Éî|[J¨uö=Íÿ±wIPMB‰$ˆq7Ú%éG;«gH/X¤ %Œ%¤KCª -蝊¦W–h—HŒ†a齏ˆýÚ®(« LHïNEŸÿϓ'OžƒI\³æa‰eÉK+ÞÁÝ­½7ïyü€‚æ¼éŠ×©S§N:uêÔ©S§N?2 >¤òŒ”÷›TGMXK碎8š`s2‰@§*¯qQq î³Lì[ˆPè½\—:˜º_[¥|ÎÉg&ðO8§fKüÄLxöLL@GD—‰×±L¸v »ŒñhA{d¢ §1™Ã?;K<̈́F­G£¶áó y æc+x¥33Ž˜¼ñÿ:å¶`‘j ݉íYeíb˜¦óÏÿ+>»fÞî€Ñ5K‡³í{Ö=ô–r^KÆ#'¸ÛÄ¿à’ ß+çvkÇ£Û÷†½o/çòŒë«—gùßó+ïs°qq<ºP°¶OÃoí]ן$ם÷ãÑöñôï {Z>Â×ï}é;äzÖ¨§`ÊÇýŠÙußçu—]WsÇ!Ÿ\CmóxtÕ²¡þµ{¯’oÉyÜùò¹ëg~U®GÞ骡žsO|Õçx=+‹~ž°|øòþß[û¤\×΍Gï“ûOg=Oßp¢\7üÙÑîãÙöÊuÇ~~\úyå³ù ÏËuŸôÒÑÛV í¾ú†³î)üW¶`›wÙPöôMCY¬‹K}’W‡o+،Zé‚yxY{î/?ó‹¥ÌÆòÝäSmü“ØŒï“ç¦c3ºÃwš_x×Q%G¤ªy ¯‘ç¦ç¼jù ÿ§ßðöûKYp¥/ïi:03»öF)sº~Ã9Tôà*ünÞxZƒw¡Œoɪ¡NõGgþ[ù–•MáÙM­½ß~íÖ³hUŸŒáfü¶ßs›/e!TÌJÁƒÿÇqÌy–2¬Rv±Ôù ++~‡úé·}³”å\Ú+y5‰=¹åÆw~[ÊRÁ'^:šY6|3:ç‘Uï-e¡bk®^±øw¯“Wc¸ïc3_“¹ª¼/¼ÞÝôë¤Ë6—œ›„[‘²;¥ìTü~SŸó˜”,YʶH{/ã}|ã1µÌ”opÇ7¼ôÀ]_.e9¾\ÒtâGž[ڳƖçžY9Èï¬Ù‡Õ²\úr×xñowO-ÆpÏœ^¾Ï¹è ¯gV un]uxY§°ŒKÙÕM¯ßý†]_*e±Êv÷Òa|g=ö²Ÿ¬ u]¸bÑ$>èšåƒŒÎØó£kY(cxi[3·ÍÎ|¤|GĊ]twé £'nþÒ—kK黏ÜVڋªösÜÖÛïhÛÃåû£vEç n*õì Õ3JY6u ۗÏ}·üÛÃkY,}¹º­ ó©.½rèˇ?¹éÑRæbßÖåsß;7V¾iÑÁNìÅîW:O¬å`S^`Å ¤µõA{¦?J¼*°ÏÞ;oˆ%Ž¥#2GRÆÆ‰Øà‰HôÁb»Ddhž»}^Ù'a«G\b…íšu|µâoH.¡u¬ðx§8‚YÁÙgîö˜Ä ûCº÷ؽ9] •FAò’W ++ÿåz;HïrÁ1ǐÑBò¥Ÿ‡'-}A‘5€}™/jŽÓÄ$ŸX…wŠÂ”&~{À8°7%;Þ±AÁ£S„³"#4ö2Dw/\Ð »AìI ·Ð6”’3ŽpZ”ŠÅKÜcW‡w«ŽN%ÔáÍÁJoV¶B´[TãZGRô¬){¦ÀkP?ö& °ÐV6 ++Ý<|°%ó𰟏¼W¶`sƞ{ñÿ+ƒ9°‘ã³zÀê¶¥¿>ºˆê²àˆƒ×#ÖT#H&çáܑ¡aÁùúÿ–w,P#ŒÀ…™jžp¤0؁@®&ùáÞ"${§¢ðÂRO17–LÅŸËm&hØásr@†û-Ö¡Mšà ªCTw9- ßà)ÔÏ< ++AQh¦ž„'.@%ޔ>Ô±¢¯æaŸ£yv<½M»¹¹µ8®”Kç€YâԌÙeÔ%•8q¡ÅÄP³<ë@ÑƒÈ݆$PÃ+43 ›IÄtS˜÷Fà㣃ð¡PN~4Ç%õ%˅’åJ^B¯-ÁßpìCs3$H³…Ðo‰a›>5¬mÐ=®cšˆíè _È<+îÍsQp¢;ñã¼,˜ÄX¼0ýyàóÂʄ¬Ç¸3aîx. 2.XšªOØ;ÈÇPÕ0Ázü?Hö9Lp0ªàc"$\à™ÒÂ3¿ç‚©Õ9¡ œŠ] ¨4‡Ë—!_žq(M‚o–7܄•D9 Uc¡òbàɖbÐe&ƒƒ˜s8µråà™ ¢3š»Œ‹eì#àCƒ¡cÚEÑwM¾ ¸÷Š# ’‚Ïc©UŽ‹%Ô+0_$–H(€s¼B±cˆ ++í°W8‹áåÞPݰ ¡÷P`Ù° z‡‰ ł†Çœò¥oœjœP4g)“dkŸ¡ÜhMaf$.®ä9'"µgª¥à¹p‚Iš/1æ¡×øÈ,–KêÂÊ­³LŒHTT,­žÉÿÐÎF¸ì¸\xžN2…“E‡ÐK.¹"_§êɲ0ç1=„݁+ ß2ԕÄ׫¼ý¸ ++xnŹ vÿÿN:uêÔ©S§N:uêÔéÅ@söÿÝ[W=¸°t<º¼ùóïëÿ?Ó®þëG>Ql”™öö•íú»Ö?[ìFZG—4›ßë÷Þv\µ'åqÅû›´çomõõßÿØó5¯_ºH|Áv©çOð[÷ä›î{¾3èϱáÑnv×¶5âÀ¯Y¸¿Åìk·/68Ú×>óÈ.¹žcZ:zªÙù'mãïivÂÓþr桂‘hr±=^Ób&ñKL}Îÿ–QÕÆ]mêÏ4ÛÌìúk‹ÛØb·»´Ù]o»î¬»kYÅH<´Ùkw>þ3Ÿ(eü’+ö̕ÃsêºÓ¿PdiM±=;/=çÁón¨e5cKã•}]}.ªj.~ôOؘN ÚÆMí§´7Ýn®¤Lüî¿uE)K¡Ø3×K{ã·ëá#©vójÏ<¸ÙH'íæ[šŒn½±Úði‘²[š}ø³ËŠÿ¿Jْ¦#î%[¿QìØ®ŽáÉ6öI÷õòÿl{è­,et鑲™y6îõ·–2W姚¾Ü{˖oìkÇ.6uڇ9jÇ‹]ÙV߆ڏ=zgÓ³I›³Z5Œïwn>³´¼[ê|ËVn.¶ãèëøž™órÜÕæ¬ŠÜ75ûð×nÜòÍZæ«üVÌ=÷7W–² _®i<Ûò­7½¦Ø£c¥½évìã[Ò'>ðæGêúQcV·µâw8a¶Ø£Á˜¾¸wêÔ©S§‰½¼sΓ½>è9µõÉfn±Ç .ºàtöt8°Š´îZ\1:àíq‘U™~¿Î¤@ï?K3¯Ó´|㚠++{p)z-d¥t¢­Ñ:¯p7þ«2¶M*Z4‹M²ÇEì@"­ÀÆÝüK²¸ ëä= tµmz:Ӑ«´ó)ÌÙQ³§M3‹“B¢ÅÓgHÙÖqÓB‡(û±KgE#«ü/T@Õ1ûäcü>‡ÁÓB®öŸìóvðO*öfßì¢Ïƒñ ++íc¨©Â®ø‹“ó¸1ÇA¶xZü@”Çf3R”莳t ¥ MՙÝÌÎ7UB=è>‹AAòMÚ`zC¾œiô§k.ŒŠ=À’¡T, ߘ:˜^>šŽÐøä"ö˜t½Ð&ÏÉ¡ú—Pcq[ 5~Éþ|°Ù2/ÈcÈ\íÇ·OŠœçû8`ƒœè]¥«n-ôÝ_·ÀÄåq A¤3µÏћÍ¶<¤t²¸—a5€*+h ¤è‘0eœñè$X&é}|uºý¿S§N:uêÔ©S§N:uzQМýÿÒÿâ/-,=`tU³åíÿ¯Úõ {O9®Æÿëñhw³1ïçÍ"vþ=ÍÞ¾áɳ%Î;DÚóKŒ7ã‡:ãç$>ÆèÆ5'àd|þŽfûý©‡{~ÊʏGWK?Æá/ÝÛlèÛìÿ^ìù±Æfe ÄïízfO)K¹ØK¿"í‹ß%«Ù:Uì—GKÓíù—·ØóÉxö§šyҞÿ@³OƬ?Ól©;¿uÜO;¹Wóãà§Ûåoڏ]þú&¿Iz±?S&Oß°³Æ[Wúò©ÏþÃÕ§{0³d.ât[øîUƒü7?tñÆ îSiϵöþô“;J{uáË-«†±Oæq\¿ŸXð;¯'cÁkºrñ­§<<ØÉK{Ÿjq÷[¾~ò`ÓÎÅþ|]ó¹8ñ¡¾±Ø¦UåÙLãËdõ½‹æ†œïÇñ–o¾üÚ2ÊwóN:uêÔ©S§çƒÄþÏØršF±_¶~ß|̸ñ<Ù&§åQà͚Ì ++»Q¹U¿Q¿JØü1ýA½?DŸ§Å¶KR|Íù€áYR–üÙ±WQÓ`m,s_DÅt´[« i=lÄP3J•Q-Žý¶Å¾Ì£Wh‹‘ÕÁÐíB9´amblôž$ìk%m…eÆËLI3C¸—gVG«¿R¨Þ¦–k¡äŸìé/HŸ=Ò~ò%€fZî‹b37J¬êNò¸,Y˜¯¤Œñ ù‡ô¨F%×Ñ!¦1Á˜Á~Z÷=‹ô?`²ˆ+àœ•3½Oèà‘F¨*ä«^€¾Ür§]ô |£”éêóþäxàÇd\Âu Wì‚Ùó®­y+6څû‰K(˜‹àìI;ôÕ»JîBkÙ«…wïÅï+=ù?j.A_Ê ++FÝ"ñRçôü}¶¼çÝ}êGJ|©±w®tê¢Wž]°ô²@•°ÎUÃs“¸wW‹ìgð;kϯ¼¤æï«yê0&có£öú𣝿<¼Wê|+~{oØþH-sóó!R§1óõ— «üînr˜Ä¯ÛÔüö'ãV¬tk«?ÿñZVóD^Òâ.n^rî=¥lÀ“{JʦcâÝÞò n}ä¯K™õ¥Ÿ··9tÑ?Î|©æT%žÁµX‡I,½Ëš¶}rk»HÓðvûô¸‹#ä9ÆküYªñ!tΒ²KùqßGu»Eî'/ڛÌOøÌx˜+“˜xO¶±o›ý×çM©9ºÕ9‰—wiëËd,GÉÛ8=?áî&÷I,½›š^ÿê}÷¿¾¬oʗ¾œÜbUÆytêôB¦ÿ¬<¶î¦k¯÷⻋§=SŒ:í ·åIø1×«ªxnóýƒÅ~zpç43¦1±“c´¨\ÀñˆI ¾TÑiy²ÃÌ[4GØ Í§U Ò¡ú4Ӏqóžk¢ÛA˜9A ÂHôBÍ|tLÿeÈ ++(¹ q¿©ŸA‹o9QÙ,qͼÎI'Kœ4Aûʎjiiì+#% ùA%Oœ ++šn×N û.;ŒŠ¸hTu:^ã½O¶£ G`Az8 ð3vµt9×Ò7æZ–Äz(IR—ç9,¡Í °–=‰iFÈ3‚=£Så¸/vâ4mL +>÷A_ ECIÀÆ%Àü JO<'ðuÖÒ}=AôFV-hê.ú,‘•(WÐÏ,r†pŒâto$ӟfò¹„%$Z.-ÌØGuº„ó6¬‰‹ ++&…#6"ƒŒ “Ǎ=ÖkÞ7ŠÃà‚Fç|0Cr¹,]%ošÃטbА31D…ý«ÿyyE µÌ_§AÏ&h=æä3„,ýù÷š@zœ…Äß?”²èAç]€lН<§•@9B±ýÜO :ÿ#›ï}æ4ˆ%JCÍ»ÿ9ÀJEï<$¹ŽSLžQ¯ üÏâ¿þÈ~ùSð(-Ûgˆ/çMÉÉǵ„€ˆ(ÞMo N!HƒûÿÄÇ-#PD¸NY(´4b 2 žà߀ž•œK~LDªeŽ¿@콤°VÆ£0ÊÊ öâx¤0-Uy;`S à+À-–ËW…ÅÁy¡0 ++s¯">&:~ ++Š"æKbæLü%»¸6˜Šì9@ÐP¬?Ðp$¦SïI•‹05øf:C¼ÐËõo6†nϝÿ7>ñùe“çÿ¯šv®ÆùáÀÅϛKÙâwî·ßÿw%f]Õxöõ-þz!æt§N:uêÔ©S§N:uê´È·ç÷¹Üçòsð #e›´ŸÌÓ*ñ떎&Ùù-ÒókFŽxŒßlÙ(³B¤Ì¯›™ù’´‚ŽIøqÛ-eÖ r֒ë‚CµÖêl ¡É—‘êCóü¼×ýÿ;uêÔ©S§N:uêÔ©S§ÍÙÿúó»XX:­o8ôö^ôËÅÝøqÅ>¿¿;¿üê'ŠïmpãÑöæ»î3w¼µØ÷CÆõf÷?áØŸ-~þژq͙ ++~WÌ®û¾ødÆ£—¶|þ+ÞtÈ¿ðºWŒ#xªùÎïac¯Ý+á½&Tã%oh!Ÿ2#w¢®qÄ °„¨ìƒçڗ½b7p»áš”-*w¹ÄPÕJ¬BLa±üû’¿?2&)3¡`„ ÎK¿3øfÀ ò×3%@k“µ90‚Šfr:« xª ÎrQ¬‡$HÃŒS;¢  .©ÄЛà­¨œŠñA¸–E÷0hÐw`ZÌ4ìg-!g†A .ü{çlWUÝñÜ)67mEÀ¦!!€û÷vbKH€CB°¤%BÂ&C*Sgp,Vé¨[é”™ ++°Lå7vŠCf¤ä‡2!}„¨i2&N×w¯}ö}y÷½ôƒJÖw¸@Î>gÿ:ûܜ}×ZŸ1€»<tÿèmž„1Ô‰±¹!4ZE¤uÔÛz¯Ç咠ç1¾äý·e² ®ÜGê~=&ö‘H$‰D"‘H$‰Dï öÿ÷Ü?åüñ¥ýÊ,ÿŽ\tô›ÌkË¡ß;|püÒãv²_ë~ïÔfWlÁܟ—ã6ø~ï†r|ž_³›ÎÙ~ÔÛÅþ¯uì÷îo<´Û=´Øáñ¶ß»»ÿõ5l·÷ÁÓù×NbÿŸÙaÇoýËçÊñhT¿wS96àç|`k±óÇèú½µ-_ûú-³¶;t>sÖÆÛó»Üö¨çžo-e>blÛevâ—é³P¯ÞÄvûTYwªÙ}W>qéæ'tœ±ÛÚ\ý줅ÏsY¨\³;šÍûÁ›V<ÎL>Síöw4vá‹ÿºðµ]y}ƒ¼÷ߜµ¢°à´7mì_j|²‘—Gರ —ã[{ǹ<¾_·¬ù 3ùž-e௹}–½\™|•xÛþÝ=9wôºW{àö֗²¿£ÏO/ª,¿\¹{ó›/NJÑãîc{¿³\çÓ»9;óî5Op™×u|m-íØwÍKì «ÛôO¢ÏU3ÎÞÀ¶yŸ¸/óÚÚY:zúרþn*?ïÔ郲ot ¹È¾Û¦wó2̗;¯=gÍZÄó‚ ¡)îüNÛxÏ:~¦Tàû~c›³£³k™.~"‘H$‰D¿ ±wZ£‚±Á¸ J>r÷ˆT؇ôŽgáa®tÚ)zU.PMBl´U0°[Á«£Š`ÕâO[X‘U¦ ¸ƒÇ ˆ6(mH>1–Ó È¡õÒ{cvžjŠ.EXP©z›vÇÞô!ÁsBÇÁ˜è-Ò –“-îüÿöt¢ð<=l™ªÿú½Gðjéx€C‚Ñe±®G{T«èJ¢)>ô_Z97Ý7š¥``ƒRë4|ÚuìʼnX…€ÚÒ *ÔJ ½w‘ö°è?u=Áǀ–/Í>í³03ÔIC~åÁjº²0u ‡"Y×ñ"ñL€'i¯+Ög¦j\¥Uw~ ´(”¦Õ‰½ƒØÿE"‘H$‰D"‘H$z÷Köÿ"‘H$‰D"‘H$í øÿÿã՛†~ ˜Ú»¿±à®;æ?Yü䓙үþäãùyc9o—ÎÙ̾ëºú„ohu}⍹7°/¹­ì¸×#m˜·¤ù®ûo3Wp}nž÷7ìkí•0ÒD"‘H$‰D"‘H´'Tüí½qÆ;ßùé×mrt@øE“‚÷)!,C倘–²Êá€êGÀürÖpDe¬³…{Ê¡Ã!ÉD§µÍ!) ¦`0 7ҕ»aJº³1ÔÈD|ʱûÿ¨?»sü¸ú½ée=·?`¯ïŸ¿£ÅZï‡ÿÞ¿|ìVµ¼Äϧõ®i¿üôÚ¿x™ãç½ãøë™-¶þ¯ïZαçÆ+.cnú"ú\üšQ5F¾2ñ¿R®û0}ß¾âUŽƒ×5þú’ö»Å•'¯üau¯LüM3ºß'†ãà7´Xð5£~‹yùÑqìùÌÆ°Ç/}‚™øªþvñãVç0Kÿ¸rݝô9ïÉ=—…ÿJé'bùÏúÍ36WÎ~æßJžm÷ä™{Wÿ€YúÞs_®iýŽ­ß§±í‡cäg7ÂÁG_ÀL|Y§ øõ„¾¼±ì_˜—¯4Ç¥okœý¯ÿöo0/?Õßt64–ÂWš÷*Ǭ»È¿2&ž}Þ¬š"I<»H$‰D"‘h/Ù?–8wÇ>/&lÔv€ôŽnÏ·‘v^Ù§ìÏ§ý¥Ó #«= È@;M m+iOÙêO¿ ×¾ÆÛg6´XûàbÙ[“8 ԅ@›"Dߛ˜]¶šzD;Z õ†6–H9@QŸBˆšzRüÔ¹ Š¿IØüª@;Qƒ²±äË -«ÉšêHÈ´3՗¨[Ø3»Þ¿ÒA!vÈÑ¥ u©À$ˆ Ðæ7$Ú?¡M`ñy^­§-3˜ùÈ·‘J΂º_G6 …´)€± x †6Ì[D4á  P™*Rɇ€»£K֋hÀR b‡<!g*òåxÍ Á¬š0Ú¢Óüh—éDÚñ{î šæ%¥.Ÿ@ +52&heK֌¤œMìš1’˘pEÿRÑ{:S¹Ò|ŠeßOŠ[Cýö%ÿ€Ñ6F‘Fºg^üÿE"‘H$‰D"‘H$Ú+4°ÿoÿû«þk|éÔÊ·‡ö3s7.`ûn ã¯4ÆùµºÓ‹ýÖ¸)ýÞÃå8ŒÐG\8gÛɵí÷nn¼û¹ßy„ÏW!åü_ýÑ÷?Rë‰ýêóûþ;Ì+œmâØ|#õ¡Ÿ”ãƚ~ï”Ò.ìÐ'¼uþóÌù·¦ãÉ_BŸÅG.ÿ>3øUåÉ?Õ|.ûàûh]sÄØú»ê¹+3—Åe©´[ù?üþŠÑZÙÆ¾£ÍË0ןó`¬3gŸóR°\çY N<}¬¯ýœ·›|©ÅM¬Úò¾*óßr_®/×Mœàá1þ ólõ=Pl›Ÿ¾¿„·ZÃ~ ëÛ–¬»}+’ªlûù»‰ýxªÍÙpׯ>ì³ðíæwqÎu=ÃeI3Ÿÿ¶6/go\ûìÏàë½=®­¹;§\ð$—¥ÀíÍnù¾úÐJöƒp>r—´¾\öo«Ÿæ²Xó¼Þž“e£ÍωÕìçñíæ¯qМ•ß«e–Ë>ÝêüØÕÿw) Ió=ZUæe¢Ø–i½ÕcrŒÏ?°¡­ÝáügMïîÃG7m™Ê~Îù"‰D"‘Hôÿ¨ðó•f9½çh¯BÔ@ös™6ôªudªÛÓ~Ð&*oL¦æ)“r×é‚`¼Š¦Y3eR–ÿD¹ìµÓ©Úh“ŸÀ^>Ä受8m:ë|PÍo‘džz‹Ìö°½{úµçmN…ß>ßÞdï5 û:Gºþ‡bÛåÜ1Ò%H£œõNù œ­ºC´Ú¸þ.á^FZD´üî§úèNb%:Z_´Æ„ÂÓ¤P»N¹âGO©8ZÐHÁѧŽ«°iõŗÞÐg†éÓz þöTkDŽ jŠê¤Nûˆ[둎Àed>Àj§¹¡;M4þl‘y!ÃßÓLÁo¡df 䚟Â`Š¾•çõZüb[ 4È­`, Žæ—º2ÈgAÛeû'ü‘H$‰D"‘H$‰ö ìÿ×Ì}ލ/í÷>ÝìíG.:úM¶ÛæÐ“û}W{þÍ&»küj±àë·ÌڎãTšÖ»¾Ô3±}Þµñ‹G§Ùjg¯1þïßµ?lgŸÝâ܇íåϖ²Åô9yÎâ-ok^úKÚXŸüìÒUû®g{«j¾?X·d3ÛTµgî’Rç…ôY±IßVóÄnïðIó¶w¬DŒáŸyþCl‹Uå7L‘H$‰D"‘H$z§UmÆãýŠÙ&E;®;³Õ™ê«=š™!gÁßž³}26°éœÕ9€g`C¦cÎh¤²WZ©¨à4aM°0Ç 7ŽláK«©çÕAÕÂ߄6œ*LêÇa•¢M ö¼³ÁdbFyº>Zïi_“†‰E4¾†}_§Š_K.s?[ê¤65N?„àá‹BÛT‹gJ9î£O8dáüQ}N&òÙ0™ät>>$j›ý¤ßi?±ÿ‹D"‘H$‰D"‘Hôî—ìÿE"‘H$‰D"‘H$Ú4ðÿÿîQ7-_:µ÷Tó_Ëÿë÷Vî‡ã·ÒgÖÛsOå¼}Úõ{oí۝ÂÖÅáãV÷{w_÷ƒè3rÅ ?©Çm¿7å€Áù‡­¬ñ¹ß{ªÔƒ8‚ù§úHÍgú½~9Žx/¼ñ;—¼ƒÉ¥~ïS…y6Ìdÿúš¹;Ëñàc¿w×ô®Ýã·^^¸rÁêçÓ»~>ºü˜Ÿâ8¨ ýÊ ++DÞó‰ÃJ¾Ã˜•ê÷^oÌ»±q ýžkç_pÚï~·ä;,ó°­ô)}ŽýÙ-§•ãÆÛi½³öëú9œñ•;1Ì)|¶qà.}ìh.³Žc8ßߗé³P¯ÞÄe)süÄ)mÞGF×|s+ššÓïÆéƒ²‘{¹Ìe®sÀw¼tæÈæÊ0¬¬>Ž YHŸ•Oï8™Ëœãöf·ØŠí3.ÚÈe±–]?cÐޏöã²Tã.^ØM¾Fæ~süÃÏÝάIø:æAžKŸÿ½ë‚7º|ÜÏcJÙÄ Ãóð¾u˞äõ¨ÏË ûvkã²÷ŸÏŒÆ¬+3ñÑݰ¯mã[1ºrVÍ­˜ùº/•²‰s+>>†)øð}\æênØ¿ëËò‡–UNa×Þý-þe˜7xG[—Wžt3 }T<Ÿo5Fã9›þöĚ˱rošÞÕù束äëh>9NçÄÖÏå£ÿyd)‹¦ÆÛØ8Œg¾ziŸËRÍywûnY:ú‘u5¦F1§ðŠ2׳ïn Ã%¯ýÉa¥,w±?w©ó6îK6‘Ë^hßϼôu.³žÇ0½aÁèúopœŽªã[5£Ãiï©1<ª®‰}Ú|>wã•/q™õ¼–æµï¼³¯›ÿ³M£Vò—ŽH$úüPéÍ Òw³3ôˆ\°.¥¢1ŠþŒô¶¦RÔQ¹àé‹YǐY‹^Ö"ý]F_øÆy­Ïð¢¥Wï5hbŽÞªb¤o½<ˆqYa¨íQ\¶¡ä7S*%,u)–¬Y•ÆþÁt½ 9c½¢"YOT6†ºV†DrG€8󙦂^]֑Óô†YRiôÓÇ`Krã ryáµD!nÖi |¹lRÞ8ÐÙõM»èc™b`ÕuÇëe“†¿sɧr¤WŸhT ssñbvth¢€ÛÓ ðÆæ¢îÀÚÀ%šÚ¥Fpš¡Y†#p 4í4›dGjŠ&nÐxqB®8¸`ÃÅ9RëÔ¨í8k“1ãB™6G3A/ÖV夨ZxR+ª¡À ®Ð4,š,ðÎh)yåq÷b¦eC+ÎПMOEQ¶nÀ,£w0ºôNHSÐ1Îè{Z>XþpoÏÅÓ]Ñ̀z – ž[j(Ӆxä¨ð¿×–žøhé]Öœï©ez[EÖrúrÈ´4¨> ¢\ÙÔ1©‹dɬé†ùqó4Ž}×±y͏ W¯Ù¯,®ÎD ÎòŽ*°üLÐ ¸ ÖvueÆôƒ¶vüÉL†ÃT½Ÿ4@<¸¸¥´k£»•cx2è —¿EcF DƧ÷ ++P@ƒº‚4þ„‡¦ÝÜ´–¾=-¬Ë|ïÆø£ï«Ýäôøâ UÆîÿ±gÿ÷BÇQŸhO'‰D"‘H$‰D"‘hüFû ÿ=AüÿE"‘H$‰D"‘H$Ú4°ÿO[tÀæñ¥ýÞ1Íoûˆ çlc?jmû½ Í'ý±s^|[mðýÞ!ÍÿöØ­jyño*vþßû›s€‰}µ¯h>´Ã>ש”BŸܹÌùÏ!²/óÌæíöYö2sþ]åüÿ¸ií}‹ÿ‡}™sbßâm\Üÿmc|‹°?6À‹S¹ ++n¡Ï/>x'—Åê‹þÞÖÞx¿c‘H$‰D"‘H$úe«ù‘ÃƜN.$çCGsv&o•“µ%˜¦°æQè-âœÎ[MG=Á÷Ÿöo9”àl*±<ÎDG'«„@›àSVˆîÉȆ–Üw†üÚxƒ#ç\¦3².»0ƒà‚YªÛר›œɑB2X-™㛄å?>n¢œ•‡Õ½ägCN„„|ˆ!qu€Í¯Aâ36(¼G€ˆFU¦Á!.‘R”ØMlҞާ)q+Ô¯2?bÿ‰D"‘H$‰D"‘hoÐÀþÿü/ÿñ¥S{‡örÔ_{ ;VnJ¿wb³…ïÊù[= Ïï’rü ôYÿý™o2,¸~ïŒIü®mܾ9ۏz»pþ´ŽýÞ!·uû£‡Ÿ3Þö{ó›ŸÀ«[gm-Çm ýÞ)­ž?ÝÎ\@¤sœÖûTãµýó‘ç~¯ró"û#¼Õx_öêÚ#™y *—làß02úùZfó¾îŸÞ]·jËû(e.XöXÙúýÍY+žfŽ \§*uâ⑗G¨Œ»Ì×Í.e€þù†5·°o„ÍÜOfÀMì7qcãØÙã—>ÁŒ;x)sY¸d݅ÌÔKœrZoC»ßkÿØ­\f*3pýŒnŽ'óŘJŸí\:Êe¶ò WíßÕ¹ä‰sæ²/†®¾óK‹èsö«öfææiÃܵÇË|žNŸ­·œ÷J-«L¶SZ{W=°šùw&$ÃÌvo?>{õ‹ÌÛӚ¯»©±ÿ–ù‹·p™¯s}s›³û®y‰Ërmï3ûwí}õ¡••·çcåѕë&æííh×ýSZÅ×yù>œ:†›·úVöCQ™}T˜+‡9[úôÁ÷V_Ës}øÝ~ëðÕ*ãÎòØï˜Ñµ÷ÐQ—27ÓV?”~{~oÚi›¸,ZayˆD"‘H$úUl–@Óé‘ภªÇCg˜}ô©2õœA+—ñ:¯µw*:—ý¯Mï–É%clJ6pb ÏGÐ#ma`ŸÎeKÓ^ÅÄ^e°ic¢†2t–šðl7¦?ØDgæn#½Ê!1½cÐQ'³Ô/f«œ‰ í-xÇÑ:Çg˜Krx“-ga.ö`c™gÀ¨ó NÀ¾›Ôžœu `õ’YÑ8Á•ÔYQ_"÷4EÐøReÜ1C/[pî¢MÙSw [Ñzz{wF5^žP2tü¹ÉìíÁê@ƒ†c74±¥ïN×1áVÒ?oÛÂéæ;¾Ÿ`fTu49^ózòžê¦žpQizf4*UüB²m¾2J[”HÕt3MÇ ±›/ZJt'P©Î0GµŒ4Ñ MÑÓ$P« ++xG ø“Ž6´ÒAWÍ Vªm#ÀÔô@Р|1h¦"&žšK4KžŽ+pé.Ó¦1»ì1i´ØpÌ´;û¿H$‰D"‘H$‰Dï~Éþ_$‰D"‘H$‰D¢½Aÿÿ/Î÷OŒ/í÷6´œç'ì}üõ™QÈìç½±–»ûƕåxU|¹7¥û]Žcó×Fþ½ÄØì§/’Œ ++Ùxç9Y\ö+_Uû'n,qNûKëýúc–$Ÿóõ8Ž ˟Î2Wø³Oý~8ÎúÁ¼œ#ÒÇ¢³‰4è«>òËKž/²˜eWÖû}ýö±¬³ K^õ‘šãý´‰Ù—g™SYvÓPWç†Ã–¿RâJžúÌÃÈyÐÏ yMÍaÿÄ?­~*ÍYamîCŽ—øSÇm[ó͋Xb7¶¥1š>FaFÒËô1 ++Uʵ—œøR–Y‘ûpojËôñ uã÷Èe¹Êx›e$c7Þ>¾Ä„r¿+‡º9ÝO°ªöý„?:ç™, 2ëea]ƒßqòsf‘Íìê\>~ËrBôyüÆfMÊn=¨Ä!ø|¿µ#s—=W8/KŒÉh-wÌø¢¹9A…ÐÆ ÿo$^§¸AiŠßïOÅ?Ù ++…»¥µ&ïyè‹’Rè”û<e±MxûEÜVÑk;ùËâr¬ÜÿáC‹nÙ‹T[³©ÅWËt˜ Ý « ª¬~ÍØQ¼"µ$1™¤çpяdÂq#¼Ðl&^\¦ôǦú$’ô`Þ1¹–Н?µ`ö ¢™l³¤kqr¦¯x€6Ñ-åÊ¢ƒtÍ h-úä¹)Å5ôF'kÞ{x±c‡b =ò–loDu‚LiÊ£/Î ++tÀÑ«™~È.PçF±"Á wfۂ )+8ú%ÝҝC\Î{.-tJz2¨$âN’ú¢;3þ…z¬5ÒX¶ÚG²·”>²ët¶2†ÔO‹®`û ӏq³Š>z2©a^ard¿m4;8kŠ~P«Ã=­Ž!ùA£×Á%ÿríôTw\EݓÎMZì3p+ց ŽK¾þ˜‹¼“H9؝vS}Çžüª§ä†Çæ³?¢mÑpà±Ës«2¢¬bbv/= ++➠++u£r¬YÜÀ*IóM‘‹.Jރ¼xÆ1è–ÎûظG'Ð4,XæÇRԘjŒÆèD,SáFw tå#’ÌþŽYÉÑ×äދÆ`<œÁ,B—Ñ…jP7vzeè5àa‚e`ôO‚ûN[¨ Ï(ÀL >^¸@0#1ïËÎxǼL‹M¬E'#šcéˆ X§5– ++¦Æ #„ÁJÁS #ìCY§˜Qš ƒÙ;ûӈÁ¨AÿPVÊ¢$f«èzÐQó^èž“Xóx`â«SCë†'FdX®j<1aù¡ŠqÇCÁpacòèÈo è9œCïÑ><ž0|+Ï1ÁóÉ àjü*"èPµ˜@' ~Uä24üԚüþ?ð¾KŽïÿþuJ<ÿdœÿ`oû>»þŽ|«–9s|ë]ùÛ /ˆöZnhhhhhhhhhhhhhøYý]xƔ¿Ç6ÿÿ††††††††††††††=“öÿ~Áҝ¥½3vÁ«c嬧_ýéúå8{óæ£y>*«{ëÓõÓûŸR} Nºê¬'²ŸtÙßy]åA}v¤ó?ŽÙ'ýšÊg~ϗ~7ùÀk!Šü5ût²ÆuÞÐÐÐÐÐÐÐÐÐÐÐðó‰3á“C¼)¹¦Æ½«üëS|7r7qM(o•–aHÊϘ6ƒf‹rÕV8†8¤ÄÑ1>ºR·“ZátSڈJ•uÔÑ1zÄ1èÈ%¥õNÿ_CCCCCCCCCCCCCށIûÿòOý£ÞY:ÐÛ·ÚßþæeË2—œq½¥óä÷úö1 þ'Ù×µ³½•ïmîoí÷v²ÿ ){OÏî®?ɟ’sÇk[r²oO2ò¬ef–…ÂwöhÍåÞρwpmÅóVd.4/Dæ-I²›q,yöî;²ß€wº xCCCCCCCCCCCÃ/ ¦rCzKzH#ñí§‚4։ÉøH.nEjNíq²ðÒöï•U™3=ÅË;gHµ•ѸZÑ0OÛ}@!H é¼I\€ù|$«¢R䎴Êã”ñAëdÀÇ)M³½5d#4F:²’>"å5Y?£søÁãC7à"r4zƒ‹E qßYRµ:q¡•A%ÆPE Ê[’» ++cLÄ#}!") ɛªr$Wt¨Û’sµÙÿ~ñѾÿöLúÿ/¾ä·í,è[}ó§æÿè¥óŒ ˜ÿ‚Òy+ý@o8å?ÇÜM7˜yþ,Îo¬9ÍZ6ïG9'`t½ƒgNÖàªr>ô.rßýNÉyÜ£蝒®góu‹|0óú1Ð[Tã ޏ°W½~hé¾™Î{öO¤äLxxÕø‚'^Ãȸ†‘t=ã Vßÿ¾áy'5Ú³_ÍixÄë¤|‡Î*Ô³:õ÷äÿ+w ++ýÍ9Î߃ãз?´‚罏f wEÍ ¿iÅüt_ê_?ÔÝ÷ô£x0ÇMPÏ×uõöÖÄYé|ôa°·eVwý›ëW>’Ç%çÞì­­}»kô±"‹9ïü}UOç²&åe—R†,û\Õù9ãߞ—eڔœô5ã¯:ù;Eæs¹µSÊ ê,s*Çaì—ÚÂ<÷ñѕãEæs;o­yà׌Ÿ}C’)%sógví<ñoV¿Èb.wi•}÷¶S_É2]âE¶ uórÕÃçšcIDÈ<“›R¹…8Ö9–u¦È² ³»yòæÇ—>™eÎ䶜1Üõ}Îm£¹œAç“ìÚ:Îg¼ü«ÿœeNçv^—îÇX˜gï\úb‘Ù¬—†ºyðÌ]ŸÝšóg†ä“3Ø»)Í©Q×ýÉñÏdY,:Û^ÇAQònz¡2æâY®ùèhÖµ7¥Î·ê=¾HþMrRÿîÀqÊ#wÛ"sù~«guú<û¡¾’קйkS9þsÚÄì˳̩¬³u³ºþÿë§æx¦­ÍãWÇhôᓤØLÂ\n2N荞ð|–ar߇º1:vãÙgžP+sßÖçÈÊñÏ|¾pˆŠÜ÷ u=ôó‹Î©²·†Îþ^’éhr\ÒºZçØøÄ—“Ìh›eçÖyý¥{VåØ#c}®sõPׇG7Œ>—e¾ÌÏõU/+î+庶œ;ÜÕù—áŒ,c.ܬ³áNg'=ñ5™eÞåq¸u¨kçŠñ=(ÇA©2w¿1sRvè¼,ÓºÄHÕõ·|ü˜¯ç)#ò¸ÏØ ïꢙݸ¾ø;&YìÖØ³º¾Ì]–ûµÌkeImË1ãÜRøZ‹®Ξ”|{–IçËõõ]óÛO<ù‘üÌ6÷ïÞږÏl}yïò>°¹cSîwÓÌ, LóÝÐÐð3Fò¹µŸè±^#‘I»Éo%¥XïÂ9ŸÞsé\Ä%^áUk´Ð“~»xþo]0Ò ++Y8³¤ˆ;/c¬•ÌboKÞo¼=œÃûÌm],u+á˜ãÜ8áuÊG.ddru´H%N.‘|¥1*vyÜQît$w7S|‰»btõ÷œßž?;a3ÉãQ͔|õx­9]¯w»τõÖCAÁçœåØ’ ÅM;é˜}” §Xò5Fafrg>¯™Gž|`ÚD籁æl0t5¶$ Ø|IC ++5²o3q¹PûØè”H¾Ï>zËÔówLÓnDÀ†ßGævWÌäŽÝ¢Ó•ÁmZF…0»aNz«¯DÍ5»¼ïdÝ^ò·¹ Múƒ‚³I'œ=W^ØÂ‹†ÚFÅA3ì½Âî­¶èbÓB ´IÒuÚcñâÂܑ1$ò3zcGzM㝅í»p:òm‰~Ü­„²%êZ0<ê Ô[ìó˜ ójÀ|ð&8é†<29½ÇP1ÔèöH¼§ ªø‰ûèl7'8…‚¦0ƒ/ãI'‡­¶¾ó-"`ã‡É}a®vua&p6†½b4ê\ãühªÔôÞÛn½¨ÅO"9 ­ñE—ýÙeâͳF ++æ·wXlÐwá2ùŒ£æ 痱˜5P'Ö†ÓóËÒ:AӖ×ceHÌ l’‚ªmڕ<¦BDq‰1󲬽©æ™0å瀖CÏVACZ)¡‹¬· ×tæ/}õ!hWðé™ 0f¸Æ†=ÄPfÝrû$éø.‰÷ЁÜ. §ïÚ> ÿ^žè§€Á̈P6ÄdÄeäÛ _˜ØB‰X œ£2­°ô!FÏ~ìŠPk–­ÇE˜_|H@R]XÚôäQ²¢ùPf' ¶í’L…˜¶´KÜ*4UauG>a°\,¡ÃšÄm0f4‹ÁSJñè¸'çBÂh‡‡$gˆ˜š¸ªÙÿöLÚÿ?öâÅ;v–îÝ»·Ú^®Ü×ü^²¡(3c ·±æ×ûЙ‡îÈ6J©zÔóï´óo©\}¼<÷”/0:1Ø»®ÚÕWv{g[Ív»ëk^@qc±u:ޝ²‰Ô®ém–›k^Àc×—íhÂËlKڜꤍíýóNÏ2þ1+ÉvÔûõÛ­ö©±ñÙÙÆf•Ê÷[WmÇï;tÕw²Lë©¶\Ê~tÇg“-ž"Ëu^]mOÝ>šmAv6à*ûyÔsÅ®b›° ïR$ñéƒÁwQ²ÍÓ ÀÑ[TJŸØï²ý[“ďNÝWJ ‘Ï›äk,¼S.Æâ;”¯×Q‘‚¯ó?yú“dîA•|P»TÊ«£Oþž9QGéßÎþPÍzB‹àè¡Q]ˆªoS³ÿ74444444444444ì ˜´ÿ_ýåß?ggéÞ%ŽvïK|ÿ˜lÛv3J|v?/À@}'/Àâg»xá¯ÝŸíÙJ ”˜óþxþWÓõXÏkýgŠÏÞu¼lԚ?üÈkXcG¦=󅩠q€Ã9ƃ{åõŒæc-h²Ä¥Rk‡¼OÙÆ,#Ç¥a(²€º¢‹Ì˜†MWdš36jFO +ô•Á×ÌKÆìeP§’µ)Æ¢ò ++X£÷I‘@×Z®mâg€ª0VÞ©Ž‹AX…¯ ++ÊØ R§KÕŇ+Z;­1AéèÊ9ŸXt ++å[Êân= šaó)❁ÒèHHÑøŠÝ©•21XêÚà2e0øÉîŠv`֠ӎì@ÐÅä|Áv1ÿï¶£Bí.&;6ô_ÄÂ[[z…ÙwÍ^²ÙŒ°Ð£eÑåh0zÊÁlD| †«EªƒÎzöÊ£DHqá‰Ëê$!˜´+IÒç¹1æÀHoÆ ³ ÑHiY4 ++½£MZ“‚T8(²¦h™’CŽú…ȼ˜³˜†œ!ÙøgLljÁ¬x–v÷PÆkÏ+cŒ—^q’m x*Bcsz¤|Úùg–!Ïï6g_æ±ä›ŽSZ‰]rp¡/<ðèPŒÊ÷΋ ¢HvƒÙíSS¡n-P:Åe“¥?ñqè ±ÀX/¦>—Mþ¸%9‡µ·xœ@aסÃXÒWágRyXÎA2+8R@`NcfZæ Ä|¬A@ß©ÉäÌÓd倲¸ÞñFÎÌcIJ]ò£4ûCCCCCCCCCCCCCހIûÿð‰ûüÎÒ½{ó“M’ÆÇËY³$Ù½%ãÿO¶ß¯à˜û >]ìÞf ÷P²Söóí§¿3œ‹ã ?|ï}ɞLèm߅Ý~í.xøGªm|þ“ þ;óíÇÐÙçÎØÙž¿¨ò¥ÿÒö0ó;Ø[]ëŸssg…ÓýŠÊÅßϟ¿Wå1èçÏß¶þüµÕ®Ýσ?QËõóàgnöéyð·T߃~®ûƒ”Q)oÌ:+—ÓÞd{ñœš;àïç®Ìý³Êe_€íÕÆ~á'Ve»½u!—»h¨ëC?¿üÕIFÿˆ#Ãò§ ƒÊm¨üägŽo½+ûx›íÚûV_€~{ÿŽ™]úy&ê8ôûdÞöÕ8VnýÔ^YfDîß~ÕäėüD–ÙŸÿ¹:O¿ê“EV8%FR¹/âXòزR'WBê_ÕçEûœõx‘_€m»ážßVûÞÏEqiÕÙÊñUs‹,澜Ê]ŽcÙ-§o)¾qª_Éô¼ôëëÚ<ÿV?VxéE–m®¼\¶ü•wrÖß[Ëõó[¬«óóíáã g}(üI¶†÷»á¬WŠoEáä_8…—þÓ·YÈåLõ êçÌxµŽß±/œ7ý.:žÿ-ƒ][úù4æÔþm~ÿòm…—¾pù~ÿY“²yé‡ë³å»×_ø½,Ó6ÏÝíumösÖ/žÝÑ=¿yÁx–éâS³¸qÖ744üD°›xZòuÓ²¦§Ú·C´ÏS²º F®’#<á•Û¡±¿ðÒ ã,Z(²ŠÓøäñnR¸Ì$îêèH毥µ’Q·†¦bïIïO6jÇbÁî̗^øðINii4oJ£4MãxImƒŽÉ†oœ‘ÑÆ`,ڄë$m8C‹·Æc'µT!ÒöjTpÌL£#¼i]38G®zEBvch«Žx@ ‡­æ®Íâ)ñ«ˆ>jáµ£½N[œD·½bì­qÇéßÎ(šàqÚÓ¼mh‚ËvMü¦æP)$4Mûø—ôýÉM@y¡zeÑG¨Z¡ñÎÓnéÈ)íÿ²wõ±~•wýÞXõ(eq™,Y h±<ï/at¸@2µ0ÚA_€–:`(ÜJ:³LŒü±H 6q#$Å(1à˜¶¡º²)C3š8S È*/X {éêèFÕÏçûœsîí}ûÇÉý~Èi¹çùçøÖoÉÀ ‡Lº–­-ª¡[‚eܞ„,çñù„èjŒX¥!â‚–Y4yÅ3ãñè>'K]çy æ¶:µúCŽˆãâHd ØÐñŠ! ›YsÑ10WFðÛXR;¿b ++*¸ì]nÿϯ¢Š08‘É%:Ca»I"E”ë90Ä@ZžA®þÌõ‰D²œ<_d¢PŸ.8º'ðÛ _@¸ Ÿ\ Ԕ\úögŠ<Ѥ¢øÆ ˜Ó?À‘ˍFõ^ É$C=»À¾[¾¬.!É_²\Â$ªÈ×$%ðÏå‰o$TŽnòy& åßb‘Ž(¬âZhåaÅ ƒë9ãÙ3γ ™¤‹ðcx‚È$òt|™E+c‹[áñ*Tð×¦—ÏbÇ™•w¢ñ…B¡P( ++…B¡P(ŽLÆÿ7üî,ñÿϹÓwœñ›×5¿z726z÷à pdžÿÎ!vwdü¿Å]gÆÿßâ͛×.mùüÑç^oŸ÷ý݉ç¿ÐåÎÇ=až8û¤_Áæ§?]»8»iq·Mƒ×ÀøÄøWZ,=ÔÎ7^®[…ãêo½¹¢ó†ïâåۇ¶Ìô9Qê¤Çûî¥-nÊ_Gv¾ÕÒ·58Vœ¹f£vSóÕ;¼ù‹}\¸÷G¿uÈç¾ôùmç´Øoì8o}˜éCð™a\fú€_-×]Á>¾|þm-6»Øï#‹ûþÍôóþÈпw-Ù²¯ËWïx{‡üÌ|õ0è@L* ++…B¡P(G+$.ë( _rüöN»Ý3-ç3u 6yâ×^x’èTñS¸oÈ[>ҏà„!zé›¯Ü çk. GߜG×`Ç0F«Ïít ˜3$e¯Èu³ó&N8W=»æžÆ›0]þɃÖýLí‚=‹û6~üÕm§vú]þ]ƒÆÂɧ]þíÎÇÀ·ë–Ìãq°}˜ŸËó¦æcàc—‡ßòÛwàØuÎúo6NJH]™ôavƒJ€köÝx+óÞý2ïqüh÷µ¯·²Z[öHîıjō­-9w¹ý;äºwã¸á¥ÓŸ$×nZ¾ù윑CnøLo„öc}ýÄ1¾•%×òۋô}-ŽOÚk^ë´ ºù»gq?Ö3õ ¶Ú3y({‡ù›ÉCÙ7è üyét˜`42©]Àõrù¿ÿme95.͂yô¶JsèLêRÌðb¸ç˜þÙÒ;Ø^ï»fÉz͔’ïãihg•<Ö"þ•C)ïæm¯ѕ"êa´4 bo$ÉàŽ(F¦øsåVïÄà"s"0Ï5OÇ®yÌSS½G‚‚gâˆïªÞG£q8=˜ƒ.þÿvÒÔϞ¦ÞÏÆK˜Kw- ++'„ξöý’e‡ÎbLäÇwž9B—bºÇ¾Š(ž˜Éçu6.I¯É0«&‰Æÿ ++…B¡P( ++…B¡80ÿcÅC·N/½Ebd3ãÞ· qµÇöŸr¨éê'Óç‹3nöЗ»ø%Ó=F7{LbxŸÃ±Êni~ñÌ4‘²ƒýê»®kºúÁu¹ùwùð›÷¿ç[[(šíÀÿÆeÿÚ⬦Óso܂]86=ñpì4é;=÷ÏH³Ç`/ú0S“þ³R6»¶ü¦y´åâ¬ÿsî–ƒõ¡‹ë®8 3õη ãòµÏÿÎvÚä]r³æØ+ ++…B¡P(osHL7‹aEè8sqF„À ¹a°:õq÷LZMíy6{Ƈ#i=%djÙ£Ü'’iBt1z“È’‰ž‘åšÈ0ÂV°9z»˜"òóÌG¹}JÄË3ӟƆğKK™÷"<àpÇbqq´h}ˆ¨)‡’mGõ¾ôqêÙ¼RÈyŽ„£Z-,*šªCõÕ[æñ ++ë“aÄÊ¢Ç^/ÓÍ#%*æ3n¹uª©ç ++ìÐ~r2> Ï©窥œ§ž\E}œŒ”bg4È0ˆÎ8>ú“Ð> j%É)ã0&6Qe?9ޓ‚Öæàðlzÿˆé ³jø‚>—DïÒÞcµ×Â[ä ¢ñ…B¡P( ++…B¡P(ÞùÐý¿B¡P( ++…B¡P(ºÿW( ++…B¡P( ++…BñNÀdþÿï¯ý?½´×ÿ¿ÇÊg–ü¸éỼpÔÈùáXó¥+›öy°¢e¨P( ++…B¡P( ++ÅÏ;D»Àggsñ4å¨Vœ!‚/)ˆ EB¥@Á&ǘé§A­ÿPrÓ60ÉR^ ˆ-Í;¨ùP]p.Ó‚>çm®¬ÎáDÁ5&Ô‚£‹Å¬x¦å’¢«5¡¤H]ÑÒd„¾´1•2Y|;h+`Q‹¸;rÿ¿ôàʧfîÿo4æÎøú²µÍSÍbÿ¿CÎoåþÿÔ ÿÖ´üLçÃv‚”]?B<û@óÜB»tù( ++…B¡P( ++…âí³¿OÅqü+4ÿ£©d¶…¡ôÌ tGôØS{zB¦À­4ö÷ÖPÈЕìöÕüõ@u9…ŠMºç=lÍE61š”½I&u:±1,؟w¿_0ÆRÆ=°À|˜ÎŸøûûB¿l꫑&ÙÆJ‡ÐŒóF¬PéèCIh¬øý¡ àÕ=-B ý/ ª­±åÿ+ ++…B¡P( ++…Bq4`2þ¿þý/|azéØèæÁ_ïÚ Ozœ±üj¼ë¼üøÇ‡¯Z~@ΗÇ:^À/àXzÀlóÉ䅣#óð¶^‚OÿÍU͋fR¶@î¿ÇMßqFÊ|rÍ3ðÞy|·Êu;pì:gý7o!¤v¿=CÛ?v륝¿_¶ÍûïöE}û7NÜñ¡Îïó Ü)íü(Ž÷ozEÊÈܐ²íƒg௞~m«Ó;ß¼ÿÖI[èïwóßoiþ~!›Ö¿×ä~ôWüÃ]_hÞµ´þ5¯Az¾kɖ}RVo>„ ã|ÙħveÙHَa\.|þ¡¿í=mkçп‹&núÓVVmëßSR¦~‚ ++…B¡P( ++Åÿ/>1>Þ.bkàª5ƚb»8ñ,>€ÎÓÃÍEy¯§Ï^bäÿuÞr³úÍECR9 ++l5dñçgCŠ.zWl΅f}Éc'å¢õ1ÞM§»*adlx=þª7ø +¡ŸP]5µ¸æaç .ŒhaFuâSXmþ{ÁÞÎVìd\‰%8´;eéˆK&fì~R .lOÌŒ·nkð1ؔ+ã×9{Çp6ڃf‡Œ¶Vt½úàû¼ñ¥S8&±zS°“ C-NT2Òë[oç8`çëÀ¬¢µäÆ;p® k XT+:ƒ¹°%Ç)e w ÕúÌ&£uL)ðÅ£Oœ‡6`VjÁÍ8×>b{[S¶F ônôÉø¨ú ++…B¡P( ++…B¡P˜Œÿ/{|Ѫé¥}üŸáSWŸþ‰£—šÆF·qä³<|A‹#‡:6z×qýçÏ<ôþÿâù`mF=ržqîWœ"|à3ê9MêgìÿŒg–nú‚µŒ^"çÃ^þ랑óÙ»±ÑÛåüyüü£'íåùb+ê¿Uê'Oá_:Qx ++¥š¸ptûОƒ·Bâëü]O‹w¯®ùÉÎ+Ÿhe¹+{Vî3;_aïÀ‰X}îºoµ²P[\~?ëÿbËóËàj«ó¹ãë×<ùÜ×ZYŠ-.ÿäñýxŽO|÷ØÆs(bÔIÀs®úNÇsˆ#pŸÔ¹Ç9å²g¥,'×x+…#° Ǧ'Ž]YÇexqàÜðúsÛÛ¼–˜¤ì©¡-×O㥬&×ʶÉukp¬8sÍþƏðÝý>x|?ÇaÁË`CWŽëÇåÉÝë^è8]ÿnø?Øu]ãG¤Üñ*Þ=¬¿m_]óRϏhם0´sÃę§KYö¾Ë¯âàÚu£&eŸ®›ÎP( ++…B¡PÌc˜52þZ³·%W+ɳ_Ž6ò@m ++ÞýKi׸#é²¹c+^‰û˜4^W%.kMxçex[î!áîèíp}õÕÆ˜]£¬ŒÔfëcñÕ3&ÊDëR`p»„èMÁçl´Î[Æ®®±'=ê®TF ÍOx­äñâ=¶œ3‰ Í §r´¦zkŒ±…á\¢Á§›¯¹2ċÛFç#Nüèðƒ ÉJnwª D—âB5ÁæXmÃõ†n ­»€ÝˆO®Jd—£sÙGÖG)8ŒjµÁ2†Œ&¸àb&ÿ¹HHƒcH – ?ëE«8÷5ùÀ˼鸡àÃ9ëB鿊C„·ú˜sˆ¤ „‘‡ )é˜ÀØÍE ++NbÛ腩̃Ï-ƏeŒÛ–X›5ÝÜqÞ,sÝ­—́ԉàœÍ“÷Á-°;¢r^Í\7Éslé08T«Ë),0ƒ3÷X Ç»LêÆÐÆŒ/}‹ÕÑÖXòS¹oqlӓ°¸±ƒuœut%`õĂ &²€žú|˜ ++Ԁ;%ŒP-\ŸÔ5ՀÅÍ瓋G$'ã³ôÎÁΔ%0|TP_ÁÐ:’%0µ ›°ªd$0Ñ%ل‡¡ÿ„1h>SV°`ÿÇ{Æ"û2ÿ+ ++…B¡P( ++…Bñ·îÿ ++…B¡P( ++…B¡80Éÿù¶ÿxtzéØè#£^ã”½÷­oò˜ÇF ¾€ËþùëmêTÇF?2p¹o=ÿ}7 ¹`ÆFOxñÿrѲÿ–ó>űÑïËó,ÿƒ³¿Ïóёçÿä±ýç7¯]ÚÎGû©ç+ŸYòã–/@ÝÁÇäó3uϗv’«òý=Çßtz{åjö=ôåË&ZYJ#¾nÈK¸ùã-oÀÚÒ¸ú{ŽíëÜà/ÿv+Ëÿÿ8á¹Ç*»åÅVVjã¤ß>´q|bü+ÿj㲟<ä;|üÕm§6þ¿1M?pÇ0F¿wòøË­¬ñªŽŽÈýøköÝx¿”%_[;8~´ûÚ×[Yíº‹e\fÏX0èÞøµÝr\ׇ³MÂÝK/kZÕ¦VgÓ\ü3—¾¶ì¶¦«X;=Æ÷ý[¿ÿœ®¢ký{m—+'ÎújÓU ~jC+ûí?ieÅ´9Ú=底­NK»î‘aŽ>}î -§ fÓú`Žïû0SWñžcûvN×NT( ++…B¡øi£ç,SIÍÅ ¹‘sèÁ5ò…óìKî9Ïxi ++M ¯,/‚ô¯Ö‡Z¦Ôï]$ÿ¸ãÕg×Së½èÀ‘v]B¶ÖÄäð‚ž]6ÊnwOB‰öÙ¦ƒzã ÞÒ|Æ~€$ïˆÖÕZ¬õ¸”ôxJD |&×Ýúd\ö©Äb=›à…èîpÇbq1Z”kÀ+¾Ç j¦¾ª÷¥ÏHÙۘB²6ÅìM-†ùÆz¦£%¬/Z48RASK*ÙFTí ê¶èZƒŸ]¡4ú/zqžtÿÜð:;î1dz™Ù¢›6ò¶óooë£æH ++|,̌Ew¦{ÚÏTWp·ÍA«ÛÄòâêÅí ?éűÝ­½¦ ¦@²' *Íud>mº„ÛâVX¾˜SÉÀ’°Ç t ˜þ.ïÀP¥°T¼ý{&`V±¸ o‚ùÁ¦-eTÅĺåy,:îg*ÚY}Î|02%ð°¬*Sa^yñ˜=Œ'ô5ŒiÂ@4¨Zõa‰TŒ(êÁÝ+µ ++Æ ¸ÏMÁôq0°F»¾ã*J!¢Nf1wy\I.LO¢%ÒwËåÙ?_?Oy*S÷ÿ?YV–LÿNúåÑd¯Ääm¿XöÕ6ŒŒuùãÜ{-?°æ‚¶w¦/À? ÚúGê„!{ùáå‡Ûþ¯†±ÑKæÐ¸{ø=Â1«~íŸä|6¨ϰ/lÿ)‡Zž2 G_‘z¶sOþÅU-_Ÿ Möt',ž{¿¾rQÿ;€?Ú½¡ý€*™m/?ôåТZ.?¾žÚrßÐî-gýeËÉwݞõÃu{¼é•VVR+Û¼¸ÿýÀƒï¹f_Ûwûä§ìŸ¹/½ä—.nûü\»v6}€Ù÷äß;¾ïö[J.mo½}ž\þ7†±<´díË].híÜ»hî}÷+ƒþÁúÓ¶<×öݶÓFhZf^¿â¯Zž?¾Úï?†\þ'þ¸ýî`RàîEsï×ïÇ#ᇃ®Àÿ²w-°v×Õ·%ášgc7qJiãÄ|ù$5…Rpù0ÆÆ L0ðøÄrӈºI$$  "¨¢UHŠKuÁÜ4BEI]ńÿ·̋¡|e’‚Jš®={ÎÜçwß{R[EIñ^ÒÁøìsæ³gÎõ™³÷¬uùB?ü“UïÛ: ?ÀeŽ 2gŸÊߢO<îû´oUKçŸÌõááŠã¾cÐÿøåã¶×ù²¼¾@ ü:gÑ´:Ô´Â._0°Ž´u½‹U–ÁR¹~{±š>F8±´)’ï‘¿Ð"ŸöàÓÒ+ï¤êÞyZY¶=ôe£:–QÓ~u”ZÖ«XÍ*bÖ§­ÜXNâڛM pIÆ«¹÷å|]oò·©xû'ÝSOûÑñªžÇíçç>ÛdÊÒ]þ¬^±Fw±ÜŽ´ÕŸ¶¬{íb$B5MÛïÑ=,u± ++D؏Ñò˜ÄB þc1ŠvañnbBžñ¾¸”Íò‰Úìh5KŽNXè¢æòý ‹(r,}ɚVånûŒ¦ ¡ÝÜ¢k™>úAáTPڛû=؊øíé[AÖLò=ccSSÏßȼÇZ¯ü¨H)Êbqüw5bÐX~©n.)×>Ù`qî=úé6 EŸ‰Í€Ö^ÔŒ«£u.Á™*KŸÐèo²æ ++ôFãú°¢Éð #à4ú¬…ñQ–Ö_¨ÉdjºA³%§úuHe_Z¥]G%[‡ÑÎD€*Ÿ¡èSŸÁèÂ=Nöÿ @ @°k@Öÿ@ @ ì ++äÿoîöý&Zû½§Û^ð÷^y2ç²»Ðï­kùè;ïÿßPò£‰/àà-O)ç÷ýÞÃãòüçžSÎgÒLåzғ»v쐟]ÀLåï×ö‹ô‹ýË~~Ú Ôï]×öƒï¼Ïÿöiôú6·Üòa½¾ËÆéîMܓuËWÞwCˁ¿{ê­5ÿ¿æñ¯i6{Øò9_Õ½îwµ\öµ{ŸûRÝ?¯¸Ì-ÿV>‚l«á»ÓèîÝÔê{w‹ÿóñsÕÏ{£ÜGIò+Æ^ùçÎëª98ÐX<å¥Ïö9¾ËñwÍÏKƸ¥îƒ¯e^ßrà¿°ûñcÌñàÛŸ=¸oãÛ¥M @ ‚ÿÆéÜiE)ßÁ«¢·Žù»ÆëßyOûÄ£ñ†÷½Eí¢ÁüuIú±ì:w:xkk^½‹±åç﷟È{¡5úE_BÙO¡Ô¯DÓ/:ºÙ–]1öx‡¦¦L{M[à8ÚÑ¡ JÍ"ÍGçsˆQÅB™h·• '§Îú²Dc†5´;dÆ@2+*ÈV"u ñ¦p6ÀßÄá@t$ïW62$:KIÿp­+Ռe'‰’ԉ˜‚E½p„+ºšÿ@ à½Yÿ @ @ ë@ @ ²þ@ @ðÿþ¿Ë?ýøû'ZwïÝWôՉçŽyþŒ›Ñï-nÄWÊ}·ãøDZþ4ó†ÊA8£øçÃ8–¾ÿDæJŒ¹r,no¾^vۅÿ^l‰5KgöîjóâÎÛV<Ä6˜Ÿp}›Ko=ýf¶™ì‹íñYÏyõÙf-—ù@iËQ8ntg=É<Š!ò}+fwý;åK§¿’?-¶ëZ}Ë<óžÓ@±-!Û(ŽUÛ~7¶9Å>{»Í·ÛŠª­úeAãž\?ç¢Gës’xŽélü‡–>\EãpËùϪãûú#ÝØ~ížÕÜç#Q鞛µß}„mQ±m{ëûCW.½Ú<ÛFgu÷}è Õ?*6Ï:¬3{—ÍîêûzZÃõçH±í՞‹U¯|à7ٖê8¬oÏÀ™Û¾|xµöõÜÆ»¹rlôfæ¥T™}öôœî¾aÎÊGº>¬»ó´ٖ÷aîH7Ï._ÈsÞD¥xÜOéê[>öÇß,¶dª_¾Wl‡ãÄgテm±ry¾1³«ïž¯ýя+fµÍkÏØ=ù\åÁ´Å&¿n .)©–»Ê³5•·!ílbÇ¢sÚU k” ɉV,àn¥‰+á­*GÇv:¥5®tÄÏ¥}LÖXë"h”£ÉÊeâ«òڐp¶‰0àúà\$n0ü#ᡋ$©NÌd¯hè~B-Ž2àԕ3^3i‰cT ^zþQÇ«Š0¶ðš‘ÑÑ;§1‘ ÃM8÷¢›B§]UD’¦M”:GIë\£ï]9X"Ðý(+xü _Ãa ++3,ä\ïq)’ ++‡ÛTœs¸›HØ ++mý=©"nO£‰ƒ×ƒ®MèÑtšóxcuôÚ£Éá/·®¶ÛÒ8‘ÌûŒÆí†IÍúó)ûHºì/vô,\RЦ'ÊÃ;jŠp‹ >&8ïˆÄ-Gšµ±Àyr=zçð ++åС#¹/ÐT.ƒáKÿ1Ýè¹ñíez@0ë=mAã„+˳áæŸS:ɦ)\~¥Y†š «ºlSp©°.ÂTôô ÏË`Š¥n¿“qìÿó%‹ ¯ž6±ß[Öxåþâ‹¿Uøí´C9Ç6N²yïÞ.|d“ï/˜×8Õþ怳~Ä6ÙÆ<ƒÄÅöÌ?\°­Øs¶Ìì­)m ¾®‡>¾Œ9ñ¢«¶ËçØš—þ ¶yŶõ¥¾;pœýÐݾòÞæbã½óp\ôâÂOVÞ»ÊÆÜƒ“sâmi¼wko¹è±²gÁhÅÜhjÏÎv浝-éÊqÖøWÿIæŒó‰yÓ®kýæ…{¸ñå-ÛvؾÌŦ*¿Û>¥ÌÉ9ÜTã+|ê¶e?á}ºúì¹Y]ÿ~k¿Qæ¨Ë¦ÞwÜ®ËÇ6Pm‘Û¹º•9¼_cÙ쮝Çm{mwÞ¯á<ûzÀMø»3OØÆ¶h½<ā@ ïi^´ìƒ‰+íM0¾ò£éà]áM‹Q§Táª+qÊE« ñìéýt9áœk핛‚“(‰_2S’x,Œ‰“r æ’ýK¦Éó6ÄØG´ŽÙ$ãp:;¼û„¿ªD”w*£¢lŒ*³\‘Ø£ Ñbˆ.[£I舮eãcP6:¸FgED)hÑ'¢¼d : æM¥ƒBs4qúE—‚Áá6ëþ‰=ØÖ9T§O¦ò‹­'JÂhQ™wÄ=§]¥$¤"ˆšˆ¼QõÂ{G>3Df‰’0gCÝ¢túàƒµžšæ ++÷4œ¤Äs§pOp´pKF8ÇFeTà­+„w…:‘Üå0ð–('mB¬‰‰÷sôv…ûì)EßÁQ9'2MÌ¢äe̘ˆ.R?–{ðÎdºÌx¢·ô6ãh/@¡Ï$Z̀à1[¹÷p± ŽhöJNµɺ2ͯä0V ++Π1üRãxHËþôÌc2'ÛÍ{“¢vD˜rIJJlóÞÃ×Áeb¥ÄŒƒ—cJéŒaÉè9z ‡)™•6ç$áÿ@ `Á þ¿aôÈK&Zwï}§ñçí¬ÿ÷\‹ï.ÚqÚќ`u¿÷ö¸ók?űyãûU[ÏÏ;›5Ù²íW}´aÁ-³»z}ÎÓ5^ú½Ã[üûc;æžSړuì÷>¿gWÎK;æ—<gcè÷V4±Ãv|®èoÐÎcËùa=¿Áù'üο”|ôkfïºiø7µ:.ûᚏà8îþ\)ï$«y—ó¬s¬I¶_˕¸äe£Ø Ûhý¼tìõ¶¥Ê¡x{‹Ÿ_þÉÕ¬§çCâûöi÷]<¶ØÖ\…šWpTëÛ°ÖÞ+-ÿaXOïúY¯.zõÙ«ÙÖåT¬›Óù}íÞç2Ÿcîòökm¹pl[uø ß·¡Í«a­½Û‹?'çÜÔÊ\1¶ýo9ÇÁzÖÌÛ6MþÃ5#òáÍË^ØYû®ßú°òžõ¾.ßbã¬A}{r‰þÛ»s¶ VÍ<ÍýÛ«µsåØ±ßªv‰ÛÉ9/GàøóÙ§rÞDôUpS©ï¤3¨7U:Ã}¿ºåiœðüwoë´èØvv›Ÿ7ܳø%¶¹ÈãàwæDLŒCÓö›¨a‡¾·y½dlãÛRä>l™ÓµeÉO>øMþ]`½@ ‚ÿ :­>ëR°::¥ñ&–ÆiçRn£ ¶-‘å@š–Tîœro—6Æ`·Á‘X["m<õ3 o÷ÁR4fŠÖ梞¦Iî͹D±aCz’VJú­õuÇTú~3ÆiZÓ ^—²Âû±÷xÁ ^$7iIãð ++•H90¢oèIît8=ZNzŒhqÒ¡òÖeÆéñ•¼â™#á;ír6†±»vçMʤ‰7ˆ¥+Ê'0‰¨àHN²:R´#‰Cx!VŒ™|–ILÐ{EAd“Ñò`èzú[2©j+Nʑ7‰&'kRÌ9â¿èK*ڏ3:=FŒ$©z*M6­œ©ó2~™\|”KBAsj}Ö9ÆÚ4ÁV¨,ف2HžÓ’Ô&Í7ʎ m@ôsÉ ™R#ÅØ“ ‘ôH6Y‘ØhãÓ xÏV±°ôÕÜ ++MÙÑæˆ÷lÌõœušRs2ÍKJm ¤ Òýsv0/ºœ‚‰š˜ÿ@ `—À þÿØûøþDk¿·®ÅÕ/ýü¢7kœßö{oµ¸ýÎñö›ZÜ~¼^`¿whÛÓ>ë˜ý ð(Šç¯hqË5§\Ê÷ÞÆ~åRìñÐu^9Ÿ¼é÷®™"nӜ®üñqûþ¸æÁ;ÔÊr>¨8³7ošxþÖ›^óÄå™m¡ÆŸïj¶ó~öÖ6 5–šZœuõƒŸ=ˆcöªîÍ¿©õÿî «¶²î¡©qVθǟ8ƒù ¼ gÝÞú¥6,ù (£´¥ùú3¯ý8Ç×ËçRØfµ~¯;ôNæp–ÛòF)s.ŽS¾sñƒlóšµ7·_1ú(ó 8DZéÃ[[î˜qþClKëÛ6»+sí·G©ñuU9 Z[–}[åP\Ÿg[ÂíLNq}‹K}+pœô“ÅW±Í×27ò†ô ·6¿ Ç»/õ ‡€@ à×SiÁá•U•xoJ”̐(,ÝÅ«'‰ÍÛdl¤´Õˆë¦‰½·xñ1xcUÎÝ5օ@ã“õ¡îqÚ¯TÐÄ €ws›qG®ñlë°‰Y“±üÞ>EºnC—âP™¥-ø(Ñ', ¼‹JQ>†Lô– (^ïc¢t ‡Ue!ڂO"c§”…EJ0žvêgë¬!Ÿa•dSÆâ”øå’` ‡ÓŽè< D¦ŒÜ\r6rò…/"Gôȑ:š”VLI-š2œ–Ð"J„'ÚŠëchàZ,­la > G§"µÛaôrÀиq9 “iš)F%ܑj¾G¦D ԉ‚uLƒq՘)…‹Â¨`l0Õh%þ/@ Á®€Aüÿìwï?Ѻ{Ý7M›’¯=ðSP¼4&3£ßKmóÎûünqÙ÷^y2ǹ]èâÿÃûù´Xí!ÿ|?ó ¨ûãâÞW·÷ý•w ö{o•ïgÞã¤}ï-ç£ÒýÞ²:¿ǁoný’w Êþÿ¦/pÐ;ùY9¯‰/`kãß¿uËoÿS9o¼í÷Nlñïó/×ÿ%µó­c ++'påŸ8E>º¶ýù3÷-ù1Fׯ| ++œpÖt>E‹þÎjíyߋ{•ü…”üyWÛ·þÀkóßáóAõ{j¤ë×κ ªñüŸ3öü78_ÃxŽ‹_VÚzŽÓXù(™ÒœKðÜ4̕@}ùâæ•¬›€ÁãýŒq<x-ÛrÇE0ҍíp>ÄúÆåÿÙ}.em«kîÂ^#ƒ2'rð^ý#©·®b¾§kÜÿK¥-Wáxüï—þ˜mÁs[V·ü‹á<Š~Ëq֌˜×òþlÿʙ­â2ŸFOâi´nœ†káñ6~çmßó*¶…ºÿÅ4\ N£'1¯q ç‚ tV÷•ª5Qu/–¶gðŒ£Ïr¾‡®óå¨6'>¼ð|æL°Æò8,ÇÑp×G›ìŠm·ö<>tåò×wæaØgŠm{ʜÈÃ0:Î6‘‡a{kç×Ón'qÓÛ+{tý»üˆ‹8gÅÇ:¶ÛšÏVŽÞÌü *O̟9ýŠKža[Ò|ßQ­ëî<íE¶åTŸ£9ƒ2ÿ•ûã±Ý«Õ7œ#³[{ކs]öÛ³ùìåc~µ4ºglû4úGt¿+ãÓäÏllÏív?¾òEøÊk1àf™È!¿J”ø%^¶Êžd¥3~Í)g¦ˆ­MãœÈó>·;“U9¢#ÇKíBvÿÍÞµÇlVÜå}•ºï+ÐZŒh¸–]ÚÎý.R¡UØ.[.»”[d¹ekƒ‘Ô6!†¤h7@‰hÙDn- z¡¥1Ú¢nÚZ%d…õcm·XÀE.ú<¿™3߻߻ßç?bJvr6»gΙ3ó›™sæåùýžŸIøJFz~ZÞá"¾*xñ¦EêéR’Ÿx¬"¹‡÷5ž†®CKñmÊ:´5‡ä€o¼‰ßùÌ@xTcŒç843y-‚ðšµv—ÉÚ;ËÐd•Ù£}ÀöÂz±‹‰(™ä'tôm}çÉr#Zå ++fAÓ5É»ìð1`ž'‰Ã—Xc˜Ác׀ï#ö“&FÃ, Œ×¨Ê2~?çIkT ö±Ö ++ŸX ++c”(Ë-uü­Æw)<:b“`AvŒU‡Ûf-:ýTAG£w¼û<%]EÍ=XÆØzlÈ0K\ԕ/×Êq§‡kš$]—ýâ|ŽÜ$Ø=­<ìî¸yŒe6œr÷°£ÏBáß1‚è¾ÇîI‡Œi IR³é†µX1¡²¾1ž±ÿíÅ®£cqk@ÓºE½wa¯³cø?ú¯gW fŽY4§‚!«¹¶€¾ž-±åÍ]Ã¯Üs‰QWH`ÎÏ_ ++8‡?a†DΆÎq’³7>'Î7G!~g®>ÊC8ÊÀì I‚ïU †DŽ_ñG¤O“s3Ð-–[sŒâ˜XÆY 돜È`«i¸±Šð‡ŠØCb;ú/`ùÏ4þa ›‰ó÷:šÒ ,íí`KzI`Z뛌׷òh.ƒ%: =M2W0­©*Qµ$<Þ*Rç? Ú¶¬Œm@DZàÐÕÎÿwtttttttttttttì ˜ãÿß|åÿ5¿téh,<‰¤Ï¹aµð̚úÿNðÿ“úÿ[äúi½€õ¯>ôò£wŽUãüõ¤ß–¬ÃqØæÛÖžÔÇñh<®?|ÍQ/4Ô#üӍ8zôà ‡Üxt@ãÈvõ#˜ãùwõ#xh†çÉ}gÕÊ7å¼ ~<ÚÙ¸Ä]ó ”œõÓþÉõgá¸avåËr>Óßa£´‡Úþ‡¾±ê$ñ#ÐõœØì°áw?Pô ýŽÙ{xî®zªß5ÁÍ3Cùæ;„G IÁ¯K{ÎÁ±âµÛO“ñ¿†µRÏ=Ë3ßùm9ï“øæëqœwçéV]xÕer¹Ó/ßNá·U…WݹÏ`×sï_ûH)‹¹p„«·8­­pDã\×_ïÓ®òâ/î[÷—W>]| L.mÙÒôÿâE?)e¶òÆ'IôÁøÿ¸úðêgP¹S™ºÂÕ¾vüéOÔ •s]ÒÚ2­Épðx(›ö8±ÉU³›ï/eÑÎuûÒáyÓþ;ǃ=§ý–7›­½ûò’Ó!©ÊǾ¾tXƒÓ>;›ÂÕ÷œ_êL1•¾ojüï}+ ++×ÎРêc1ú0›açÌPçk·WΜT…”­müïG¯=³–E]êÜ_ž÷G8Îܾ²è50­”=°l˜¯Óù”´e÷ùn›ÆvÝsǞPËLۙaŒ¦}®™ÆaZãâúÖ¿OíÊÒRéßml§}š(›ïƒ°u<ôïcßÿ[]} B÷±kºãÈj1Ó2Y)Cªˆìé2rp&R<ñ ++ãPDW“”²0DL0’õèµ]2?“í ÉÎé5 SY†r1œd)?MUSg^Žq4/ÊFóE êæUg;áczÏìÜVW^/ªæÇ×:Ø|’ÛtÇMöÁÎÓD߅U’_CÀ¤3•‡%e‰^(,wmª‹‘Í ŒM$ya\¼I–ZKeqXÔIofÇI²TËØÔʰØDž3”݇å"Ã¸ð©Ÿ<#€IÑ¢¤µÇ£<µ°­å‚E)?îRô¬ óêژ¨E ÷M¦Ö¤¨à{9}ÉgؒáÄÊ皫Ü2æYµqZ(vS ++ì¾ÎÉÝùüŸç÷^$ÖÚð•ÉyPn< NYëÜþÁ2Z k󊃋¹–ƒ ++1`í²>ñÎC;,Y~¦óÂóÎÓ§-ØH¹sæC§Ž?óÐ{¶Ý2c=fº0@Œ_ώrýh\æWƒ€ñœæb¡›bá9#:$…t>‰LØàð.áL ++,LLZ¼“0¨+p•È+9°Í0±•¤[2gùº¦4Á°¶ñ†ÇxÒ­ÓÌÿ€&¡‰ß|ê` …§)¾þ`0L¾ðð=;óU…‰Ž¯˜Åk‚Ro†î¼*øâÇÈ0ã̖ý0øXœ™Îx…âëŒÅŸ§¦¬ïºþGGGGGGGGGGGGGǁ9þÿs—œ³|~ésLnç¢'Ïú|á]UåûJŒûgq\ú£ßÿBáAUåa>Þb]§óПÚâg§µâ]‹wÿäQ%ÖÜD¥º>{GGGGGGGGGGGGÇÿ7Ä·$:¸¥lœ¥cžv“gÁ*kBvЧSÃç‘èµcñ{X3¯€¸lø #ªÉQ3‡kÉLT q% ¥¨ €GFOz{M üW7Iþ‚ÌTÎZótÊÙÒcκÆü>O õáñIEÝùÿŽŽŽŽŽŽŽŽŽŽŽŽŽŽ=süÿcÇ=µv~éx´MâÞ§ãùX žÿZùÿ ÓñüËäúé¸ýíM÷ú;¾~r‰óty\5çoÀqê‡ü—Ä·ÆÏoj~ïÛñ;½}£Æ£ÏK;YÙû^x×k¢“oµÖK{¦õóŸ—çNÇÃonqØÓ1èw5]ìK~êÁRj¬î¦E4ëUӞŸŽ3¬é…¯ùÓ˞©e¹”½$÷ý1Ž¿yÏ%[j,y½ïù«;í_ñäރ-¦õåŸo±³¯Ycú³u¥EۛZ'}Ös%ÖZ$<ûÜ4òÝ^ç½p4´”íÕr LÇho»|ÇêGÖìUÊrՐ¿¥iü÷ñW>Z4ä]mKÚw°Ë´NüÖfëé8ìm‹hºïl:l×ϖ²4èî·þ}úÞóŸtÛË}›îþtÌô7~~˜/?¸{í³µ¬Æô/™ˆ§þÈ­¥ÌT?—keþ]ζlÕwÕ²Ó[‹§>ç‘÷~¥ÆaרçmûÌÕ¹k8‹­ŸFOsŒŒQ§n.AÛEƒ*ôh•§ ++2` `TL ¡x ++†cé*Š°“‰D%¹3|݆ÀÌŽqø Ágb<˜áõ´ÆYahÐø`){™sÀeQ½Ð¨…’=ÆZ* ‡*Pl§ik¼½t)`áÈÄ~|ïTñ§0Bf´~”ùAK"RO>W½…t ÒaîJ— ÿ ++"zБ¯z!ós&`´8·˜¾*\ÔjÀ*ÆÑÃèvÇpas¼ Ií ™BQ€:ÌZσä6€9‚$@I’ºV{7ôRy¡œÿïèèèèèèèèèèèèèØ0Çÿ¿°ü¶4¿téèC¢o>Ÿÿ_:z©iáoÜß}DtûÃùkšÿgŽÜ°Zx~햌G_Z@çcãñ¿°ùþŽçñv0Á©­ýÇ|óÃ’rãѸÅöÿêEïß!íw&ΌÖËùëqœwç鏽 1¡V@Ó±ŸÖB/Êνí#µ,-„m9®ºµæÐ¥l§”íÏ:?ý‰âû\);bÙ`ã Ïlدh(„ªMpHÓ^¸ø‰¯.+: )-„›ÅFïÅqÆÏ­~¶”å\ü)ö_6ÜwÕwϾ£øL˜\|–-’à¹o÷ú ++¶ÜÓ9œÜw6Žß֗l¯9ªFĦ6WΟ½áWjY(ýÛÞlý‰;¯ø¾”]ó\Üt .˜=æ«¥ÌÙò¼‹›†ÿ5¿·îG¥lxÞAMb:Á§öæÃt‚½šŸÉŸ§õÅ_„AHR¦ZΛ½òŽ’O@åҖǤlûpë¥N&󔲇Û}ç̞|wÍ' J— }˜ÎCpjÓ¹˜ÎCàZÙ‡­)㐭®ù Zî†UϾûֲޕíù::::::Þ¾˜ˆ;.q×Þéú÷X’‚1¥Èë°¿´_­cÐØâ0ú¸ê’'ë±/ÅÖ­ièS=ª”tÊÊIªq£LÈÚ*ñO¥D½œúéƒw¨Šbä&PªœºçÉ[p+³*P¨ÞšÿMÿÜ ñÿw~îÜB1ß%÷C¦ºò9'Ÿ)Ÿpm¶ìtæ6;SÝEm-zCÉ}æ.Ph ¶~AÂĽ‰Øx2ÖÜeã%ícQ|‹Nń[慰s¹˜Y]Óy.^}}“D%Ülö‘ºð†*úVcP(ó¯Ð$•tˆÊZ•"†Ã¯¶´dšÙf4½ÆeN4ðI“Ɛ£L ++nGl-CàH a̹€{ÑCaꜫ.>ÌËàp‘…ŸÌ=Á»)؏;‹µðˎºò ++ Ӓš!ºEsH}É&âFiѢǯ* ùTÔL‘‘Ø ‡qÒ9âfÀàá&2`¿~PÀdZØqF¼{f®ÀüIVÁ2‰ù#¼ò‰úÿ’0‚¤wÂÌ“ÙF•1¿¬Æä¾æ Ðî-ÓØ—g:…ÑP>”ËS×óµ $—ÌÍyŠ)Œö3? ÖKÍé€ià`\ÌhL†H¡‚½gúÎâŒ9J£FŠ`}ánË œÿЉ2`C#,ð£9wþ¿£££££££££££££cÏÀÿã¾WþãüÒ¥£‡„ã$ñxÃò^F~0&C>_¸Ý;pöÊÊ^[»ñhónóŒGÏK=䳯=é—%þßj§Æ£›üΪ•oÊyüxtŸpëp¬Ø|ÛGå¼ó8_ôîñü…ïþ§ðÿ*†ñèšÆ _ù­ÿAø|M݁ý¥ˆcåK§_œÁõ›Úszî°WE§ ´çf©çöùÌw~[øŸôxtFãêWìPçÉù "ê‘úɟ®x}Ûr>Ç43º©ñéýÀ~±Ú§æw Ùè卿ùL)ó•oÞÖü!¦ýÖNø løJñp¹æ“o9ã/yø©KYðå¾¢‡À6®î=_+Z ü?®sü/Ÿ÷ׇ]PžçM(|óÎEò1¬nm¹|vëýUcÁþ¸}†ç]ñã§®/ei—<ôA¸oEáÓ)ñYî;Ilv"Ž[ÜùOÔ<±ø ,i}X÷ܱ'TŸSÚùdãý§ý¶,˜«af”ZΝ½ü¨Âß[]Ú¹¼ù_xôÅß«e¶”]×ü/>¶õŽ+e©öáêVçy³G—:£µ¥·¶<øg¿þoÅFU͊MÍOå—fNÛZÖG¬÷+u’÷?ó†SX8ú¨;GßÑÑÑÑÑñւܛáFEçäBt-¶Ö%’£[;DŽì±Ã3L:Ùd›%W¸u¶rÂ¥¾˜Â9Ýßv9êj(JîÈØêDiòLúYÔ<ÙZ´ÃS¤DЯ·ž6ðÑE£TæßñflwOÏC<³òhOŒ Y–{Rà$\£‡í1®Rਯ8$žeâõì½c›L@}‘xΆÑÙt] –ºõ&rz°½òNŠ ++1*&®Ï:£FRÌBQG ‘1 m ¨Õùla ža'Ÿ9dC칍J‘™èMFß9qHՓ&vw)<::‹™@±y , ++råÛ3 kÒ·Tv¯|½ ++ ++}Ž›òD| ¸R2Ðaz!`§ÅuýÃÏEYyü,J˜'h7Ý TŽ> \\›…åÆÓ1¾‰ÎVò‘s>Ú“Ó…Ccê)q·àeÆÓû£»ÆÑDBܺÂ@¡´ç=)\?˜‡ë2,œ‘"ë%© ¶Ò¸–àn¼^ ƒóœ0 ++†°žÇX²?©Î“Ýå˜âØéM1™7 c^àyJíj΀Œ¥Šå•͇a¢÷ ++VŸEé2géù;:·`M&L!¼ 0‚t' ~"½O Eo¶ ó&`dRàÄ¢lÐÝÌŃêŁ…qþTð0<¯fm%ÎP,AñIHLD‡FðGNàŠì§7WœøòÐë…D?žíiœ ÿž Ú ++ cIºÎÿwtttttttttttttì ˜ãÿO¹Úm™_:}I8ËižSÓÑÿŽO|PÎkãÇ£›&Îpaápÿ‡½«¶«ªîï¶ÐÜ÷+V*©EÌ(šÙßòÑ B¡NŠA$–OåA€Ò6CQ3SfH[˜¶tÊ8NuÚÇ@ Œ´2~ëØBm¦£hEŒ ¤OBÁÊnj¶Æ¡¿ßÞûœûÞ»/ù§bÖ/’³ïÙ{¯µ×Þçܬµ~+Ûá`[Ÿ—¾ê_z¬úLY/àÂþûóy¶ö~éýÿóЫþyå'[zÿøx®ý­}>ö_½scõWëkÛLi[Ïízæwj\Bnm[û؄?zˆÚg´÷ÿö½øÀ?ÑËtñׯ~g•µü50ïëçòã;Zn8ÿʨ´]Úç”hɚÙêëõ%'D @ ~^Q|öÁc?çMÊÑißÇbt>z£RbXãBÇOðЍ1,¹Üm[lBÇË¡ƒõÖFôébÇ͑£ÒE~•ÈÿBGo«bèéÇôc$‚ )i²@o9C \â‚!M£q‚ñøQ ~PÙ3v!*ƒo‰ÿ_ @ ‚}#ÿÿÖwýZXØ:l£ {ÿÿî¾.À|ÿÿõ}ú‘¬<«æ“ë8lyÑã¼?êýükVÿêÕnÌp°b’×Çù¶ôߟ_/à~>óëÔ8‚ñz•ç¼^À±=Ÿý¥gõ\¹î-®ï,óç8´Œ{çÿèáÿ[®ösJŸÿŽ—ÞRøbÌäG(ß²šúùòaÛK\ƒÎøþ–%\—üÎaEÞ¬¬ö;°Ó۟|ø¨[=ô³¶ÄŒóŒ8ðçòL\™ÿGð9MOï¬ë•¿ÿºa'óÙ3ýD«CÐê ̔ñOÃçÂGv_ë8Wﻪ›óç?±ñ¡Ê+`Z>û-¥yþ;>yÚӍsÀ×ûf¦:™îÿäOÕ¶*7þº¢ÿÅã4¦‡]Ÿãõ ¶Lu2¬¿ûÿU9T㸟)kÁŽ/zjÙ µ-4.WúdnýÕoº`Wã#hõ~Ðs8ŒÇw|¶·çÓ·žÑâ;¢®m[ûµ¼î Ëj=S•¡ò¼ŸîØôT«_à\i[Úsœ~ÿå·ºrÜWÚØñ?7]Ç3!Uù6ô{âމK¾Vët|ªçÅØ=uùwk[nãÝUä;ú|vÃßVnÕêOÜ^ôr÷ȝ—<ÞښM¬v6¶avÙ[k,1µ-í…7aûd·'6>óË¿Øxl•azY·F㜠++ÛKŸ‹×K¸­ïù{ßÿHm‹M¾åý<}×UÃÊŐÚ}kzÆë,T¾…Åk)ü`Ùè¾÷|¼¶UmþñÉQ۝7×¶«|_œêä[ÿôÉo®5Tª6ÿâœ>ïªúÌ&Ö¶Kû¶SgWÜ]㣴­z™è×ý[»ö»µÍú:Þõýž¾í 'îjqU1Éïgsj [Ö!yù3´R$t±ÁªH"oÓ8­{_:…tÉæ`i’YPd/¼Æ–lÖÌå¥NRɱ®ãXŽ9&=j )7Ód59¼ž Éá2!…q˜¬™§‰qIÇlÐCd:­ËÌ&ó8n€®˜– 2ÕÖó q7$t5&¯©Ás ++¡p{Ï˙d¾2Çà« ++S²Ì§ŽdÛvÌVd²¶P!æœÑªŒ*—É©Žõ*•å l&ãFªÒXæ¥2IS1±9áanYXÚâifc•gtvž#Rpc!нMÍ'f˜ê­Uñ±ìRŸkþ3˜ÓŒuÂ*8ª(8€ò¹ñ¢‡ÌLa¨Û‘[>2Ù·ø-5«²ëöO­Õ ÛÇÉ%w‚%3„à‘=†¨—?ï;c"Vz…lª°hÛd=Œ¯ÔÈÆò`Á`úxe²…³\¥ ·LɵÍölc>l4ÍÛÂnÎC/|è ó”± ²*,ú)êÆ±Îtyy ñèK_dõžcÁRm͋fê2¶Eëç•æ¼ç™¥™ç³]N/›¯²änsñv­æÂÜ2ép,aݰŠ˜za@ÀZ“º ̴ƶáõ‰=ù’ ?˜¡Ï£sŒLüš†áJ *¢¼©A_0v’ÀÃ(è¼u†ôø†Ãá÷’Yvg¹u¹¥x²`õh¨hI¥/ϓÙ-— ++oW6á’ðš…È]“Áwóö\C(¨0Jp–ÊԃÂGS«Àþl“…¼W4Cþ lTEÚÿHÆ3’zrùåà–¯ùùÉÏy.Ìåyè¸î_éÚ#^ʾÅ2ˆ!¡¥ã ÂFÎ\zœ ÌÑO4  å!š¨ Ì ++ßß='¾àüo•ø‚hóäà®~>ï›}⣕Àøš·{]ß¶ùÉÍUîÐr–¿2ºïٕ·×pÛrïïÇÚ8{á5ÆÀä–çÝÏo<·úñþ¾ ³_ùL͑v®¶m™Ó¶°¶ü5}ÛxžðæÄ4Ï>ŸÿÇÊõ³ñ9jûÌéÅí¼föÀÿn<üÏô¼÷wùʟ”ëü£¸€ßxáK\@ˆF GöñGÿËþ…#<$å&kzŽìåwlüZ¿j~ÿû{.úúŽ/TÞûà+ÿù±}ۅ_õŽÊ{ßñuÿG™c~|ÜiÖ¶àê}÷|ÝÓ³G¼qâÛzß±Ë:™Þ{ÛûŸlm¹r‡Ù·sâ×Z œËú‡Ï]Yùäuãi?dY×vî7ÿQ×8ƒ*¯B3 øKKϜmœêW!ÍáŸg09xêÀQÛ|^…ŽÇqïÞùý%-¾ƒ¥@ àUkD–Ì÷1¥Ø×>°J«{`YD€´ùER&FõBr,•bXÖÄw5ÔߨuEL Ææ¾&‹¼Lµ^é: kthGVVáɺÔQ*õiîÂÏ­d}h¹ûÖ:ãl„¬PÁr)õzfÆ(÷%‡ÿŠÝ%fêê‚`š,:‰·1¬§(ÑÖÇa­ V(¢`LH‘¯m4ìXoÄpQ"EÉßµTƒÂÒ[˚è½õ-þ@ @ ö Œüÿ«.þ超­ÃÁu½/xÕ gžÔüÿz8pÅL?ÿÛgήµØéŸ¿¥÷·ÿñ»ßô@«€ë·•ë÷ásäsý°øÿU “ƒõvßÿñ=>ºš³¿¦øšïÅgÓ×>ïë!Ô¶Må>ú¶ÿçð³jnm]õ—ßRÚSpÆ.;Óê ˜êÛÞYÚ¯5J녟ñÄ5ÇÔ\ŸªŸ}kïó¯k¾¥×Ñxýî5¥Müå@ Ákôáz£èXN§Àß>^ã}õ…­O†•ÞcÆÿ›y9àÚ謃ÎɅÈ|íà¬-•âƒMté*:™­N¬%ŸRV&²Z¼UÎD‹ñYEž¿˜Bq [å³É*j“-¾gM×O»Æ½HòiãÚ)LÖºõ?¨ ÛL0Çl0/ú¬!‘+>l§é6‰ßÄUô&@GM¯6xWb&§r ++Saü(4ækñû]«¨ÐŸ ++²¦ÖÃ%H©#”BqéLφ)öcbm"´£sÈ:`9ʽV)CXCr0æ0BdÍÞ¸TS‚ölÀ©ÌIíñ‹TCY¶èÓÁ!²ü£7—-ÖT)v‚;萏 ++ ++ŒC¿j‚Ö#4”¡(hS6›2<ÖÖà[ ++Âh†+_<ù›…/ÐÌgݼóùŸêsV½xÁ£õº5ÃÁg{n¾¹¼ƒÃÁú’»°Ÿ#¿|ØöR¿PgŒ;ìûŸ[×p8Ø2Éëo¤¼'òR©³¨4Æ];Ùéí„ V½P®;ο9ý¨óÊõ âäàñ©n>|ÛþCͧЦæ0l*}1gâê·m®üƒZ·ü†Çú<Œ÷·þ‘ÚæråIÜÝÛÀ³“¶¶S9·õ÷gÏýnm‹í¾åK»û6Ï^^¹i¼…;µmþtms qbÎ}¿}SmË©Ž7Ó¯Ãïîºæ­—QÕú§LvsY¾¢ÍÅâŸÒv[ÏWyÕòÍßkmÓð‹ýZm9fCÍA±NÕüÇ¦º¹LÏuwåeÔ-ïã”2ÏßÄç̿߸«µå:—¥Žî[ȹ©¬Ýâu*‡ý}—ÏnÿTÝW±Ëk)㝏Ïï»äÙ®­ÊPs^¸¾ó©÷ï¬mÉ×y^YöÀGðùä¯\ôxݓ6T]¬èì|ŽIç<ÖrlLã¹ìeÿÀìT]÷Lísy¿î×tÙ7Ú¾MU†ƒû¶«ï¼ì›-ÇFÕy‹®Ï¿©96Kðùàç¦+_¥ ©ÚÒ¶~Ÿ{S×gÒU†Kûœ£³WLï¨y;°Þºý>¯ÑyK‘9=WÿÓô#µ-ªÚ秺½2Ν¹z²ëó¼ÙSÊ3A§Úöƒ¥Ý}×¾ý¼z_TªÚíž¾ëªamKªêóðÞæÇk‚~@·§×ïX×µ5;{¨Ï/ZÿôÉo®¹GO©; ;S^wøôã-/©qŸۏwê슻+ÿ§¶U/iNÛ7×¶¬ëÚÎôœ¢¿§Ox²å3¥:—5ý3áCKÖÌÖ6ßôrâä¨Ï™j[ŠR×TðZƜ8^¾¶dÆ­ï ž¸¦ñfi­¼ÒÏ)ï‚2©^Ï×M0 [2ñA¾'þÙc¢ ¡ÔnÊ6kCËâÄÃ3§ºÁ9¥­O6—@W«ƒ‹.àÙãsrÞª„ïi¼çX\1xTÛ¤=.’Å7ëFÃV3Ï^ÍHT\cL®ÁéKŒ‰ÍV+¥°Ieì0W›ñG•|ŒÇÄ2Öã¢Ã ¹²\ЯOמ¸´ºæíCÐknµ¯ð¸M*ÑqþN,Âûy=fî1eÚ÷ nf¸1Tc(#”Tâ¢-õ YÐFýέñ…œpæ“-{käc®h°X•Rà V½j†`c] 0WÝâ>ϼQ¬ Í#`‘ñÐ>3PêÑÏl§ZÏÐb°…Š=a®\I ¡ìä eE›Ã+ÕhŽ0 ¨/K4¬–›¯R’•UgX´µóíBÓî1&:&‹Á`°†lÙΦàËðÏ^"¾}äZ‘#Íá _t]©8ócÂX‘à ++z€- ;ƒ^q‡µ¬fƒfXƒ 9ä`R^yØ~$õ-;ÊCuUÅĀx×xäv ++T¡}ì<|e¾¬Á—y”õ„‘©—9Þ=L ÊíËù¡26xt”ßC÷Ífó0€Ùø¢œtL€Ô³ÃÛɥɇS†áñ-/`âeâêÃÊñN‹+ :Je¿r÷àØ€Áü6€_”ÜGÔ#ú-› 1ඏ‘3£Þ—\s¼3e2§;Y0m¼”f,§M*R{xÕL84mÚ±gœ^†‰šB8ô0+XDÄO•PÞ­_† ¶‰ßË0žh‡_Âî+ñüøm…ó ?EaÏØ ªh#ùÁ_êzC¼móÃ÷ðefG` šú£‡{7³n|‹éâ`Æ.Ç£¿–¡‹‡ ++&¨-œ8-8Iœc8“ 5%þ@ @ öŒüÿ]|ëƒ [—4ûBÿÿ’Áº¾Ü oÛ¼¶øŸµ›žéýÕóýü×ìÁÏÿ‰â»»Ÿ¿±üùê ôŸ÷>¨£_pWÿ¿²ŸŸþ§KÏ:ªÔ#ôÞҟ_æ3îÏßoŽ?ÿJ?Á=¬+rÑï¹ôŒ×ý{™¿OzrpJégq>ÂËØôO~ø¾êÛÓÆ«æóìýîãµï)÷†Ï…ì>¾ù—]õ .ï¹ ++¯xÚ¨VKpžo½úÁÿû€Ú–|õO~eŽy¡_zS¿6—>}Ò/´Œæg|°Ü÷œÏñ—WŸ5ÿ’¹´]YÚè/\÷Kk«<ææË¿±÷é~æîæ#O:TùvOvã]ôÔ²j[h1G÷>Ï˞ݱ­¶u~éMeíWãs»;ÿÑæ_ŽUö»öÂï¸bª³%·ß†'k›k>ëc§ºñÎþþ1Ç×6oªòÊÞ¦6Î]}ÁÆ5ŸüÌ^üËé®í¥ã¦«¯ë×üõž÷!ߺ´³‰ñڌ·öòû—«/˜ÿÚ0ûÌG›¹ÙÒÚ¾þå9³§V’k6¸¡ïœGÞøéÖÖ|º‡–ynàºïÄj›o󼦴݁ÏÚŸ¿·¶Å.>`Ùh¼…~éýzÆ}Áî nNýÞë?^y@UÓõ×'»õ;ã¦5O×¶¨•Ɓ@ðÿ}ÖÊú°sñ“Ùú XÄï]½zoKG«öPƒŠ~i×5:ðA7Ÿ£²ÁɎc7â5ÃS@Ó3©2Îuëø"d|v$0£Ã:ÅŒÇ Çd/3t:OV3²TáŽT¼‰Å·ðÌ0ô6&G¿ â0Ɔˆ÷.Kb.Jè=(å4<»óÊ됌µtÑҗœ&={Ê^猷Rºë”êü£ ã.èĘ.GrlyLÀ±úYÐև Zæ4éŽÎ'²nyúÛՍÇ`ÈPK¦§SE ++mb9èùçúäìèÜô/'Z…ôÉZ’ÑÍ0*‚OS2‘‘0 W½%[™ÅZ`Œ>ÅLm*c9ƒ½ôŒ𤉠Ry Np… ­D¥XN9ȅ3,².o†u.²Õôí[¬}•¯-¦ø ]bhS³nq,A‘t ·$ªX—ÓȼûGQµ:h{‹7ÀO³Çús]|€"ŸÖ¤Z¸f ;úk5}ëО‡ù–ˆ’˜éQf­õ0˜ºá~†ßçŸ80±Wߪw0SO†½ÈSHöðvΘ“`³A&5ÆØ0:‚¹dF´„B;uôâ”yåÚ^Ò6–÷$£1¬Kò£Ø,Þ^bZöÆ%c¢Z} îÀ¶Ï ++ëÌø†à-ì1 F™1¡àp>„B0íGMUFH–¬ÃÖ žõP, ›U3PVègì®ÁæF!B¸È€Œ\æ )Y±>^%è$)(ZñøÀ¥y`xlFq«k2†Â2cBÙ1˜‘TP¶s‚è}WT.& iâ+RÊPH €Vk!R'¸ {ÃY_×µñ=–ÿÆ>ÇAKÌOH8€Rv?‹ñ?âÿ@ `_ÀÈÿÿÒ_ÿ{WlgQÞïqrnÑZ*¶¦¢!–@¢î¾û-hcÇV†BZP Æœš˜&„vÒ6£82S¦~¥H;­c§tš™$bÔtÑ!ÌÐJÇLEAù ++J1\¡F”Iü ~õ÷{vß½7÷œÜ?:F©Ùgr&É»çÝ÷ÙÝg÷ì¾Ïóü~£Ù˜Ã~Ê/¬\öñÕ]rý|Îyè¥ÿ#~uϼôk«_úðüöUâG\Íë?¼ñ\ñ·wÎôãóÎsŒä²ï»p{ö©+ý™ë«tL^¶<‹Šœÿá·½ä^—ÜòRFþ½¯^•}øÁôn)ïßYÛµfꉲŸ×¸ì¯Í±ƒÏÊ}·ßóe•øO›4iÒ¤I“&Mš4iÒäHRüÇ)2¦"Ò-탕Üòi?¿ULJ§Û—Ìwtl ‚’ÑÄGŒ`Î&Ñt)KÂ;³À%™%]R¸Ï1v‚øX!z @I”º£ˆ`,ÑBJf}R‚Ëá5EcBò®àßÑcžÛÁÔóÔy iqÊwÊ*vHžÁ-tTêZË+ŒCq©SUÛ¤qfôšqô‚{<¸@8…8ñlŽuèñ Ÿ™¬h51#†2J"q‚&1`à-ñÁŸ(*¹hºÀ¾'VAÇñ )™`ˆ`}–ȺŒ:tÇ`œ”­#²eüvÒ>%Ư˜È@b2úÈ3oóÿ7iÒ¤I“&Mš4iÒ¤I“&¿üÒÎÿMš4iÒ¤I“&Mš4iҤɱ Óñÿ_¿ñ_?6»t88Pùí^ùÏۗqÊÈ«·Fbމ{vÕë_òù‚ý¥†'Ž×çŸwòr=(=,œR»ñYúô=ßž³íµ}—Lý‚›W°T]>1±îތ›}názߚ©…§d»êºŒc·oFنSs™Ñ¹ÎŒG·ÏÛ¯wf<º®` ‡£\h?š›·ó”Â…rق:ç>vÛÇûüÂ‹x|߆·¿ãk¹Ì¸<¹$w¼üÏ ßYÏ«÷hÕåìýOÍ+óÃåö]Wm¾áß5iÒ¤I“&Mþ¯Â˜cá‘2Ñû ++®!~!þöÖA^ôä#Ÿ±ÛIb3F†z¢/e»`ÈöHÄ;¬ÀݑN.aH¡‡ïõÜq:Y¦¥èqÒ»vV‘y\ ÊØÐyF©Ç" #£“I@Gª5M¦Žôˆ8!0àI:ùäºè ÆØq\%¡["ˆõ`8ETDƒÂ÷\^Z% {ÚYCø=•¨D§'Ñ¥ ŒËv¤b‹6“Ó„ž$›*Ng׈'EÀ7c‚ÄTD™K)jÂÒu¤ÁTÄ6dkLЋÆG3 !®«Od;§CHÖ¡¦`c N ª7±Ç6,ÜΆ$ôÆQà¤C·:Â7[T¥+¶ç,ž¹gY~´9B’Ø&J=MÁÔ*h•;€k–·ÅOÁøÐ;Œ®7¤( Œx·IzD“.Uè@…Þæ«<,™çQ ¾&jˆÚOç\`îDùmíЉËr'£S!ö÷y#†È9Áÿë’#Å*¡%H¿çˆe~ÛFFÅÄv='Ž«<›v7›ïzx¢”Îàï„%y28i_Šn&ßéÌóÿý ŸsÿìueÞ`çXüÿáàn{&>ŠÏâï-;«ðÌÛá`i}_°äο:?ŸM-Îóï­øøK?·ì¢|.Õ8‡ïš×Ÿeç ˆ5÷Ù¿}îò¹Ë§á`{=‡Ÿ³â×?—ÏU]77üûˆÌ þfžÿ÷îx£\Ç4ö Ç¿¸K깐練}W®'ê¿þ„^Ï6å÷ Îó=®ùãßS,ªï¯xú?”÷ Põ/ÿÞa(¿øwOü©¼w€NΪýù¶‡ÍÍ¥ŸËywGåÔ¾|ê §æ÷0)[Q¹Ôÿá՗dœíC>~¦r(qqæ…Àïb¾ïÄùG~ot ®5«¾ú¦žã åöížßÛõÿøûÿ5Û£/–9헔÷Fºð-\?ÿÈïÞ[çôïÝÿЫòZ¥ ++¿ÃîG~§”¹UÆñ-49föù³1Ü{¾jâp+þvZÚDIù#Ù´«;fFZIkúul±çÀö _Ó²‡1 \c_‹ú٘±%uÜÄb/_‚ ++ *7Ö ‹í>ó…íÜ;%pÔüv:‘hØXÿ°GwZ`Ê5øè3×v0a7ægýÿñr$Žo<'æ=9Ñ®s[;Y¼û=ß8\tE”kã »‹ý>–9¦Áñ<€gæ/šç|ö>õç¹çÖ!®@ǗŠA,½F²hb þÂò' Öè ¥À•Õðm̕k‘,|뀙Œ_‘ÀEOä@E²!gãŒÝ#~LHïÁKbǧ1˜ ‰;EÞ/–L´øÿ&Mš4iÒ¤I“&Mš4iÒ䨐iÿÿ?rÛìÒa‰'õçOÇS¿òà‰o;Ëd†ƒý•/|ùA+~Y딙l¯~Ðwï^›ý |K=qx ùÆ©å)¾ãÂ~¢”}Ÿuß|ßDzO¶÷¿í­º]úÐí ²ß5úìC|BôÏeÿhÍXõñ ßÌ1ٟ29ØWýóo^²ñ«ÙŸ©‹ÿtbŽ8ñÕÿýÙ÷ŸýD.³¾ùæš4iÒ¤I“&Mš4iÒäè‹Ä\$û8ŠN› ñ’fôOê¢;RÌÄmø¶g<’µöå¼]4)0ÞÁ™àºDG=shœÄH‚Ȩ5TœŽôøc]$e“Lœøï‰ä¯TJZwtġ٨Éh+.©QϔˆÒ†.ÿm”Ø“qñ(LþaR†‹.Ä>GÁ…€*™Òâf \ª±%ÍÿߤI“&Mš4iÒ¤I“&Mš2íÿßyæÏ.7Ø"ù¨ô±o{¾ÍyøvÉuú»_¶á´d¿¼6ÃÁ¥r=ûÿÿþ2ɓ®®ÿølܾÉÁùþø\xÊÚ¯äÇYØÚ/£ùßëk>ýhÜÃõ璘٘ï3¶ä°ï<¾‡ ÛrF.s1÷õßU]ÖLÝu{Îÿ¶¥íß©9У9ދDÏñyÜWTûZ=uSŸ«Jþ·ÜÇÜ÷•ûn¿aV®vµãÙ9×Mš4iÒ¤I“&¿H9w8³¨•øò:Å$è`uôFÅoëù؟M>̜£ml=f™\ï‰ÔS*ùõc±ÔÆäÄú‚Yý²w“\B0(æ”;b.(fÅ[EÜK,‘4±æ¡mÐ.1å>Z‚—}<³¨%Ї 6ÅÌz&ˆ“®^'”8’Ë+Ÿ\¬¾d/Tö„›ð.|D1g[:©#r A˜ÎñNYOè#¯kè;èhÐ ÐË@ E&÷d¦±> ž!É;™Þ•`‰$É²@o‘$¨ ++¡ÐHM=a´¦Ù»(jãt£o¢ ÔuD ‘Ãqãp,¼#áˆô¸´rÚÛNá,„>Ô9×]UÁjñ;COVtÄcèЂŠDvf:±Â‰m—èÜFŸk#”U"äJ„ýzOgÍ0¢Ž`/Dgˆ=H(2¡2z|ê¤9 Dт²ÀI¥8*„H‚ºb ë˜Ð]xNÄø)q¯k<$à%™`{߇`9:&a¢ °3<‘2)£$F£/¿- ;Ä0Pj%ú‰ÃbžUøŠÍÿߤI“&Mš4iÒ¤I“&MšüòK;ÿ7iÒ¤I“&Mš4iÒ¤I“&ǂLÇÿ·ý]×Ì.öÔXìÍ[_ùtæŸ3f8ØZcóÇÜ&×?ˆÏÝ_Y$|~d®]Øÿp>¿Ew>ÊÏ·_®“ÿlþy'ß)׃ÒÃÁÕ z}ž<¸ø à òö]-ï1˜GðÁoýê]r=Ú8,qߣ|~‹j<ÿæw¾JÚå:Ó Ã³~xþ¾ŠkøŠƒñ ä/„N ÷T Âåÿþ\áÒóQ¡½ÇUŽ÷½k—ÊsCd{ßZyÁ֝ûâÏgž?ƒv)©5ûá‡7ž+×;‡~^Rõ9ý Z+×½ ++“ƒ++OØm·^9å öáw&û¾Í©X.õ­Àgëkî-ü~ªä1Ô6nžúöñ¹,^ÀC¢71ßñÚK3f¢ó%&ãü¾­£œz××qÅh\T9G13~#¿pÙ ߓ1}ák[0ÿÝľ_Þõٍ™«®ó1×9œÛñÖZ6šãpé9QÚð;l÷ÖüKá¸Ó¹l}å†ÍXpBߟ÷í^•sl(}½|áô}N͹Fç>{~헷ìÿ™…ÿÎç:—V[Y;µñ£9oB¥<¶[Å_Ã~9á‚ÌÅ\Éý¸µâa>üñUßÈ9ºŒß£U—ÕS+s<—m¢æT¬þòIŸ.e…ÿîÐóz=Wý÷^"eIŬˡ:÷8iu¿d\‡Ò†ñ9ÓØ¢+§.ÿ`.K:ë²mFÙë^В×cL—í8>—Å`ÛâߤI“cH~ñÒ$sì㦏Ä{¨crñ¼£cQ+ùû¢R¤|ŒÚ“yKÅ ƒ²Þ)kÉØEö¶ˆÍÉ®B!s‰ÐØN¡z‹Ÿ>2bÒÍac„݃çmȏG2@m“Ä%§}´¸õÆÅíÅï"ï_ C¡NM ++šÔv^'t±#=úTu–üƒAlXɼ‰Æ“œ­g˜3Z›¼Cwò(’Õ1’)N{ëÉɇ֑.uQ‘:›0ÕdÀ£_ÑJÒÞ'Ûͅ™–¹í4:û2ø‘$¬‰QÚGÆ5- ŒPŠ2ˆÉ`9¹ž9ððð‰9xя¯£fvƒZÒ  ++NZŽwŒãg„<öTz5Nc¥INÚCZQì ñT²*ì­#Õ#³%¢&“!©úÈ­10¦ïÔ³4.ÿ23ãÓ _•Ê|òäJD_‡¼ólf‚ÒX6 4Úe•$CàX’ÈÛÉtİà8ÈÐsL—0;ç1»Ð¹Ð 3P´}Ï÷Å?¯ÂaþùӞyù÷äºÖa8X#¾ØQ?ÿ¶êŸ^ÑéÙŸï ¾ÿ€øÂÿŸe‡Þp¿øçmGþBѓ~âÇÞr²Ä„ìpp–\õÛß*×é~îã/¿}L ++ú_WÛ{÷S‹ŸÉ×=ã&ûïîç¿NÚµ‹}zÁ¯ü§\wQOöÖø…QŸýÆ3ðϧ\ü¥\fBÁØ«~ëó_³ê˹Ìúîê¾|jÒä2ßeŸýފé·ÖŒDÊ}{ê}›§6:ã.ڔ}°oªþüËîûê¹Ì»¬Ëus`2ÞUÛ0ŠÉ¸µ>oÓÔÞ[zŒÄì+Þ&eŒyçËJ¼B0*·!cP~Ÿó^»éÉ\tÖ3c+ŽçxüÌü~ì·ìº8ÇNÄü^qrpß ½Ý½ñª rü€ ++sòÊZç3/½èw±è¹w²oÃ(ìŸwÒ©ër|=1+Ɉ5îò§JlAÊ÷]YÛþk§]ú¥`J\EmÃ?Åõ¹N¾Ìö²°¿ï¢¿¼ü‘uî³ýÕ¾¿û¡µ_¿Íun©sh4à>±— ø\²_ïÌe]‰ÇX?GŒÀÎù}Žúú£ôËx_ÿ™§s6ŸæäàœZö›“çîÏþü`rûÔ|ýMš4ùYÊmÞì».>[1¦&føÛµr>ág ›%~Mú(;~ÛÐ]Š’NÖAOl)èFrñãꝡ[ gg‚·ŽN5íRðTÅã×¢SXRéêK)vôÌÑåΞ°w)<:X£¢ ]’˜ÝßT甝Ëwå‰8§=!èØ»6e¿ 4´cüvx¬= ¯ìçÛ0›“‹^5‡§Äâ£ûyÇ5t>¸$ý…Ñ&_$0}’cÉo¢iF'±ã®Y1"@Ñ ÚEZ±ÖÄÃà'ÃØCôªgè"Œ›Ðo[0 ÕQ÷‘ŽÃìœ'Fš“K°Å!Á¡V‹Zh˜†Œ!è0ŽhŒ7‰A˜¤°(i8³:ºŠé‡öDÃ°`:ÁÀ ghƒ#²¦!TÇ5ÌSÇ0†FBÂlˆêç0k¢âœ>äiÓ 'À(XéÍé¹ ++ÃՌîÀü¿4z“묓m5õD§$Æj`Q™ö“C•8ÿÍ.Ń]û ã-œï1ñGͱÊ8‰`É×a«9>cx ++'¬³.ë±~@ã2#\`·‚·=·ú‰Æ‡@glõ¢#4°|aAaÊý4Ç0€ÈàNwE_؂腧Á±‚B7˃úÀZ¨ÅÅ(âÀâ¶B=Ÿ ŒJH9òŽ°‚@öèG|!D†Ëh­# cÆ 1xˆU‘+®’¬¿¬ÎáQë#ú ¯aJÄʃcMÉiFˆpÝwJ‰¾É2¸&ELÌ(¬Ö°Mhk$hæ­·ccðڀÅEaQÁ’‡æÑ;³’\1‰ °BÏ%Ës!gÜ®:ôĤVüAÇá9V{, ¨Pl’L8Î&¨,ø‘Xèþ—½k Ö«:Ëùœ8|i’jì0BiX÷ L5Tʤ\b“p’  5fbe4ŽŒ:¥S0Ògè Óé3Á6ÊUZg¨ Ç´„B¹5r9 1¥©+ ++ßç]k¯sr¾sòlj ++yfC»×Þk¯½ÖÚûìõ=Ïû¼ÀÂ$Ð>Záÿ@ @ 80ÊÿŸsÕ‹Ç—ö{³™kŒÿ_ß8¿…6¬ðÇÆ÷{ŠùüÁ¼€sÿûÇ~èñšG0ö{×òþA]ÀÔÆNÄÿƒžûäõÏó~þÑ$üÑ Æó÷ÿ=üøqßb]€¶¹ß[9½;þÐ8ÿ -®üP½À’i]ÿªøf»îük¹žQÿ†k}¨^à±Öo¿ü©…\v†Ú¿÷ƒSŸÿ΍¼?Ç4­7ozWÏæÓ6½Rú_טôÂû#¯à¥z¸Äãã—h.ÛßúiÕ­Ã/þÞä±<5Çêû·Ï¨ü}ÙžÑô ƒüýœÆ}o¹¾òþ&®ýFæè/EO¿s^õp¥-KŸ~Y¼¼ð÷ÖWÍÃz®s)mWí5ª”uڅk¹O~‰¶µîõš§1nxK×Go_·³”™Ê)ïâóÀµ¿ôõK÷–²àK'Mëú0¿ã繝7ÒvßGWý…w¡´såa|ñõР+v_ygyl.}6Äc´’¶[¾°âÅR–c‡›oÀ•#‹‹n#U4%/ä}´]þÔ£¾–UÁIhã7àµpBÓ já²Eh‹[û—å«^€ÇZ‚g~¾è!¼/ý2õ0y(]{Þ7ßµñ™âàë=lÞíò×íµÌ”þ<§Ýûº‘EK`œ-u^ݼH®ù£UÿZÊ:߇w£±xaLëçÖ²\Ú²¸Íëw>på÷KYv¥-W·wÁÐȞ¯†N»pu{?=õ¹Õ?:Ô¿aQ{g®ùÆPi‹KU—RüKØáՏüBÑm¨ªéx³åTÝòðŠ×º¼—å¼KšŸÈ`NÌÚ¼þàIÃÅÛ!›š·ôöl^4òÄ]UcQïow»‡ñ: ++àhÃùny\n,úó½s}²>t±¨ÈÉtþZ á(zçp’`ѽ¶ ¾bCO¡A5S]™Ø2hÕÀô Ñ!˛6Yëi|ZL €Ã åAƒãÖÌR6(EݐpKƒpFP)ò”¦‹|«eÇóџZŽ“4ö–ŠuW> g?YŒ=ÝCÔ ¦«fáHòÇqòˆÌ¦*“͈;F‚gUµ ô·ò0ñÄZ+ÖXzÒ€ÒuJ »÷ÉÝ´µPTÄèG¯•24"Y¾¿šF#Xîg-3™<·Ê ++“Ë"(ά`3(ÄhAÂc©èxú „7sgšl#øþê+…ýý¦‹&„ÝGšÒòšÃ áó4³ [°ˆë¦ ++©¶ˆ,ÐÔC}xÒXÒ )¦ÎA'Ò5 2ˆA4 œr¦ú’emŠG³õÍ9‹äftˆÍ¨‹32:øD¤6£O2Ò ++Ö¾¥ybu?oh+Õiå9Î@²ƒ³Ç#‚Û•DÌÐ.d#èƒáÝԏYˆ@ŒpÍWç ++š,̳³±ƒ.UG0× ~¤ÙG]„™„#u])%Œ&ÕCóᚹj(U`'¯+z.\RÔšöà1™,…÷Ivx3DÌIj4xìUˆƒÖo+COuˆy*R¤¦@Œ‰L×Ã+€Þ3ôÁ  5ú€ž|…‡1ùTºÛr€uÇ õx’2MyªÏa6)j”²ÉwãHŸïšž?“puçƒåþ«Ö†ÔVjxéÂÔåtôB¥IHÝgèê û¡Ëà|‚AÑ,̘f.Þ£ô2ÒxI€r§Ù€ÑòPµÀ¿Ó~Ž-¼ÿàԁ¼•Ô8&z®T‚ÒÇAÿBëäDŽO„ǃš¡je-J°È`d©©~¢ü“ÑB`mÓeL’3q2--N ¶¡"Mdv¯À §àØJBÈðn ‰é}HSͱ¥FŠí}p?F7ß Z‚âf‘‡ãw_Q·¡'Äÿ_ @ ‚££üÿC·žö¡ñ¥Çôînß7ÌvWÞ~J¿Æ-òüÃ-~úP_€ýK;ëÀ£ç×xÞܯð Ï?u’8ÿÂïúùŸÃ8œ߽h1óüüù9“øüïjí9TðùI|þož„ÿâýàçÏ8xòš²?Óþ­­>ñv¹.~ì÷Tó¼Ÿ{þœƒÅ@Sý7òñãýÿ§õfóñà'‡î¯ñý*Vyßaâû÷7ƒ?ܾ¦ð½øejʨÏÿÄ\þ crŒçòG=NüÚʧ*ï^yÆ)Íï}Ó+›fU¼ê ++huÆ÷_ÐøÐ {Ïÿ©ÂY{UøÐKø·©‰¹îy|½9´m|íôójî€Ú–=­ßS=G4eÔÏ~büê‹¿}~átžUxâ›øzÃSÿþ+S ×íª·Á2¾‡‰óÜØúz묍%¯€ÎÕwÿ?š·Æš—/þbǑ—{ØÕúlÝȅח²Tûå„6‡=æ´ØÿÍ;ütå¥UáOmz‹Áœý6Ï~ï܍å<«ÏÂ#í¼ƒ3VT¯T9äg[,þ g}cÓÀ¬9ÿžê'Pûì›|½;i»ä¥Gï+e±ê4n˜9zÞ]VÊr›mY6wé+ÕO ú:ÌhšAπ7›nèãρ¢¦kŽñ¬?âþúT;_‚”pÚcëá–@7|˜¼ãó øDs ‹QK¸ižg½Â2DáC“1Ö§Ÿ &Æè2$KP‚Àߨ’_ª›ã6Ø ++v÷iÔ#b¬–«Óqaе ¤Ðl}S(h¶ð,QÍj?Ì3’Ö£8ÎÁ÷„Þ:xÑ4à|ôî‰Ð\Ð8z9ÐԆúÛ{ê Œ†Æ«N—Ìàäéý”-\²£^óLģϐÄ¥1mO¥Äù” (£#å„Q°°(nô`@‰¢àQ€d*‘.nafa齦rIÁ‘ðpÒ|€$"¦!@éIƒ?ÍZáÿ@ @ xÿCÖÿ@ @  ÕÿoXÿà Ǘö{‹šwၯ/zéœûÕÛ zڅÿ8ë…êc•:ñçi[s×¥%â´-×t¶¿1òò—k™/úÜÅM¯þàý«‹.²).K­ìKg¯©:÷ꕶ¤åßô³{§é‡GæßÓéÕKËã!· é²µìwó=ü9mË÷y]ñC˶”ík¹ÕÜÔ¡WªF¼ú¡ýøÄñ]­‡F+žgH¶Âeë¹lm›oÛX|Ƃ®:ðggvc°úéãªy×l9ovËÓ·ò¥e†ºÞß¾¦“Ÿ“M @ ŒÓŠç¨t§×vV¹ÃyKºkGõxòÐ~DŽ܂zzièŒà`‡$pPÃ¨Ð@¥Žì•& ´yìhÁßL— ò"WÜ>…ÿc2>á! ++oÚx_?D+„¨j|ÂgpŠN. #`—GÓyäÁ4õ¾²7*yÈäM‹S°É°+ù­3‘eí&$Çöq^;º/‘g‘Šz¤儋Msd£SŽ €+ŸW†£D’U–ŽpøôÊsâÍ=NL …}Ê Òwö„Ë]BjUɘ਻q*’@šT 9ܤaWe“ෝ±°³p^t>§ƒ°Q…£E\‚d Ó·ˆýÈÎÁ3›ú]¥Dÿ)2áÕ$ù:Ǖ:¶Ô<'‚óO…—c‹{øzú©ø™ñùS…ÿ@ à¨À(ÿ?w凿5¾´ß›3I>¿=-ÕÂw¾[}Í\¿·€÷Ï«7­çxÿÄ^n§¶sž;\<Ҭ㼠@ @ )Là‡¨u´jLŽÐ÷¢ÇiÒÐ]$«aŠ©uRÐ{ ÿ/@ ÁрQþÿ;~çƒãKû5Nþ/i›ûïg^Pâòµ›Vóí!îþí“~ý…ÿ·Nòb @ àýöX@†G${D&ǜØèŽsaª t‚íAt>er¶F)oÜÒºè#§…<Àål†²>ic­AbM£rôÊU c‘Ñ°YAÎ þÚ"·£Îta­2ÿ×ú4‡–y‹“ðà4—l‘á}€dÛÂÿ @ @ðþ‡¬ÿ@ @ 80ªÿÿø·=;¾´ß[ÌyäàÿwÊÒÓÿ­æÿ ýêÙ7˜ð…1ûç\Îûs¶ýÞVÞ¿‚¶m#g¾…ý.;ªç®Þ3~õ¸'±ß+•h«ç#~÷{ì#ê÷vóþŸ¡íŒƒ'¯Áþá;x-׃x„'ޘû6öS3Õ´Þ½Çvõ\5òϧ—܁ÖÙ)ðj¹¿÷µOý¨ä´¾”­?¶»Îo¾¾å.³J•üyo6¿ÂO½ìû¥Œþá²Ë‘6pÊ"Ú®ùèÐS¥Ì©’pCóR|{æÆ’«ÐFç¹ìŽÖêöÕß.>‹Ö¸)‡æ1¼rdÇý¥,ºRçP;oÍi«K[²Ñ%?à¼Y][nqkŸ+e!–ë];³óÎXñFß¨¹ ++÷sÙRږ¿nïà2£k[vµ{¿lÛÆgJYҥϖµ¶¬:uø¥âã¨u9oqëë]ÛW–܈.Ö¾¾™Ï›MÛqg¬ÿNÉ%iíØ‡8ïàŒ#¥,¹Rçv>oâ܈[[NÅ5#ÿÄãgûƒË¾ÂcôEÚ.záᯢŒ†6”¶¸™ÝýÝ.ÜSÊ\(ã¾¥å¡üÆ/~–ÛBÃÎç @  ++à;–éË>s±Ž¾>mpVYú„óÎjoUÐI렝¡U‚ŽÁè·³è }ªr>::iÏèK’Ê4LÖ舐i‡õJgdpÁ8K§eãè_>YU¤e’Ô)ºrDú7‘_-Äè"4֙>Z‘•ÎÓ?øj¤¯æìØg-h‹£Y´ 6:.o!…rOðvã To5 uv´ùüB‚3[*û©¡Æpn=å#"ï÷*¦.O}zZ4 ­SÔ)ÁЕ#nžßÖ{MC°‚H*è‘ê-Ñ׬ñԝðtS°‘ÓÈ!ˆnòåÚ69K+±9òËÅÌû©ÿm¢ŽÎZsä ³0–£îpHµ§ð™3Oצ¯wj[ÒԉŽqÆ*OýD­@ÎAêt£ª>$‡tæ±ëŸlöÓ*%㿊uí:«Ñv ƒ_æÿ&ڛ‚Òtòöe]ûNCŸ™ã„&Æ.ßâÿA>Eº7Á¢ßiÆ$‹£‘æê´Y “ŽPîk—®‡˜ë÷A ++˜M֖>â>ðŽfžö.h|†Èj¯ËLW´HUÈýç<=54Ÿò/†ÀÙiü} 9ᐏ’.d¤ÙBó«ÄÐ:Ý]#:‡‡…37ÆØCß²þßÿöÆ3×ÿ´<ò§þýç–òÒaݾs’uþm½½à€ãu¬óŠö/âã·Ñ¶ä¹“þ“×óÁÄ~ÍEúüÃOóŽ&º›Ö›ÑÖÊoÝðéWŠï€w%_ÀÎìé§ÎêÖh_:{ÝH)£^-kÉv­OïÚ|vi3—í8Ìzø¶®Ý:kãwk®ƒdƬ±§mÈ_Uγ4Ƭ•ÑΡ‘cËÔSÊNä²\¶ïËuíêËúô™];W?}üC\FÏriçžö»Ä'_~ðžníZÎ;õØÉ×µ»Úyýàgoã2£¬ø5@ ï‰ßUh՘|àpîȼä‘ü-áÿáo0eýìiY•‚³_å|C·Hk䲿õ´¦¦þPŠVâ HÑ_ÆxüƔi]ŽÉðäOíwžÈaúÁ ~HQ[Zª»¤³u¾¬µiù;~´<[ü` .«©ií`Èoiñju¤›qàgñ«~V1.9g2†zQ3Sð†B%‰ë¢;Ç3‰.©# 6~2A¦¯©,Иà' ëM»ÿÒ)!Ü?Q÷_çŒ Ôü ”é*SDÿ/@ ÁсQþÎãk>;¾ô˜ÞÖÆÿß0Û]\xc7¥ßÛÏû£mÓ5 \øykû½>óÚ«h›»ãŽU¼?úØ£}?4ŽàÆc»ãçï¸ã׸~ç}¿÷k´·Ó6ïÇ;Â:ô^âýà◞»òéÂï» ÝÉ´Þ¾¦ Ø4²é¡¢çw¹ðß[›¦ýª½Fí}0E _b ®£íÙ¿Yö/Eã|Õå·ëýõÜuåzÞT=ø3º>xñþϼZtùÉýù«|½¿ íë?wÅîÒ¶rñ;¹lm_;ý¼R–m¹‡¢M‡~a˽k‹~!ÅT®·¾é ֍,x¸hï-…E­ƒÚû“p.m0sù÷U¿po»‡åۖì-ãµè@ c~1û`Çj½í€ØØ{fƒ½+ÇYhªƒ×ìX®RòÞ»è陴uôѬéCß¹ A#}´ZØî|ª‰µä´¾W YµÉ6ãlc‹.–5øô?­Ê)ÀV>¶c€ˆ=Y>´šêhXÚD×òF!}:ª­ úoÒÛC}Mk ++,ðYÓuÀ.;¥sˆƒžn#C < ¼•£›ð‰n‰Ü5jƒ²Þ$—’f>9•Ñ£}„G܋§Ž1 ++ûȎï,²§®ƒv?P»#ÈõD×מ ++u‹RÙ*:«¶!B‹î´É ++í(ñ΁ïÏùäCCAk6pøÎ@hO7=Ú¨J§©ß¡.×Ô55#Qý²Û¤•ó:yêò¤¸¿3hHÐ9U&šFžG–ÚŽó5Ó*Î`04͉Ĕ7Ý54jƒ«\½Ó ®i]GS5Óo„!zêt;0T7Rܳá~Â^îbšKÐâS{mŽ ++Á™Žµü«@ó“£ ëáú­£EÕ¢ M$›sÕNª9R'hãSÈ ÍpŠ:€…Æß@ÑOõR:G¨,ڕÍ)´Ói\Ñ$ «ÿHíŠeè®;#‘èÿ£% ÷µ£ƒ >p-ÝLDdµu˜˜å4+FÂÿ/@ ÁQQþÿõ{õ‹ãKé혆ÿ‚$Þ6ïcŸa¿½dhÿâéÝþëNÛt ög ]À<æ¶u[øøA>ÞzÉ¢Ÿ¼xªÓï­d.<ÿßïñ%¹ž¹O^ÿ|ñp©ßûþ•múý³øºÞXªgˆ¯ ÿ¸yϝùnñÈtüÝÓ»vîX3ï­r_!÷{p{VÓ6ÿ¿îü$ߗñÔþk¹~pïó(öÌAÅi½EÍîÁûW¾^…P4EWp5m+NYóÝ¢UP•“lzWß ‡ÁM|-h.ÕÃEW S.z„›ftçm¹ò¶¢q0ºÄÿß<£»×U·¿\˪Á-ÓGÏûĶR–S©³h&ÖFÌn>zÃ#óï)㦫7ß9Ó»±{ôöu;K™©‡K¸ ÿºb÷•wV?Ã\ÚY¼ÖÒö“í¿õÃÎϰø<ÁçÁ PýéÚKY6Eq;·å>Ú.ÿoö®6X¯ê*çUÆÜ`¥àGlk%&ö÷‡:ÐR†ò"ä³P $@ ™6Ã8C0Bi&ÄÖ:2š*qŠÒ/g˜GF‰€Dˆy 4ì:X:ø<{Ÿ³ors´©´YHÎ>gïµ×Þï½{½k­g=õM_ã&Bè¸ÚþZõü#Ój[êÖamãZøôóî©1¶‹·˜ßöñU»§ß^ۂ©r®?¶ŸßÁ܊ï4}^;<Öv܊¦‹ý(Ÿò0\ôÌ¢c:¾ˆnÝ7·ñV¾|áïu܊ªÊrLÓõåÃóÏì¸$RïØ1¥ßgô­U•ÑùXu}Bã‹Xþì_ëÊ3C]¿;Êxä}¸|Ïû~ºãOìæ¾sJ?ÞÊá¹t©Ê¹{F¿—n9ye/*UûœSö˵ìs—¾¿òS˜Ng©éeÙð‚G:î ++U×hÏÔþ3ºã¤e{J[¶¾ŽwBû\ìÙçO«?TáÃÁáAn/c #U,¹žzŒcÌæ¨æLG“ÉšžCkbýsÀï&ºæËK‡„.~ᦨ™lk´¥70$Ü޾8_W9FúM™DŒG|ԅ_‹^(œ7<³qI¶å˜‰¬br†¾-æg«sïûë¹ÁŠ/ G5þbç§óÙÑÃIŸ–Çœ -~ù8z:Âñ ++¿m¬·£àW®UÜá×¹Žž È^¥R"›´[ETÅ>PV-l!‹)tłò8ÁaÞ©ãs3ӂ傭Ï,ø 2 »Ô`†Ì·ü Y”¬ _Á:¹2ÆOÌmW8…›¦Àøf‘ã#‹Ï/)é>Gɖ|OZ@֓JY&¸ã1L„€åÈtÆãçÙç˜ÞŽ£674o'â_<¦À%#_À¯Èë¨tb.? ÈxÀ üÃa¡ýøQ{ì̈ÛÃAÅØÏ?:q/‘,±~žñ#…|)•ü|ŀÆxZ~Ø2Æá]¬¾#· ~Ä:|>8Yz÷}&‹!ÒXþ„^¬£"\ùƒ†T6=·yíÿ@2¬Iùy€%rš,å§%䶒ÿ/@ Áѱÿ@ @ 80ÿ?ãÚï}i|ëä.f—ñ¼·Í{ù‚?&Xÿ靈jŒº!o_‰Efüö±ðïJoTzd°»ñ̽6:k´Äí[Æó¿UúgݽÃy%ßeæ<Üâ×\6·Æó{G·5Ž¿SF?÷\‰çF¡ÿ;=wtSáéK޼ƒÓÊó¬Ï7ëœÞ-qûJ«)ƒ/o¥]^c»uìxw5®Âg®{µÆÃë®NàÂÒßB\ë¬xª¶9Uc´lµãß>îºo£«1Ó;ZÛÃݰ»ÆÊר¯žGð‹¸Vç YcÞûº}³gôrª{—mïâèM™¾£q0Ì?¸¯Å¼¯yýœŸêxUmûù"˗q]|æõ¯Õ¶¨ëxóÛº×>¿Õ\ºwAO×ÞTn§§õã×>©í‰K¾~{móº¾÷í–ÿ±|ãuÏÖ¶ÔÉr|Ë­8éäÕ5E.K›jœ‹î[]9 Ò3i¬î"_~êw—½YÛ¢¯}~¾íŸÃkO®ûÙv1ý›§÷{îÝi—»XyWu]ëZNó>»Õ‡|nó-/Õº‹Öw1ýÓû9|ëW?;¬qí=äžãúñ~[ô•ÚæJ¬ž@ ÁG¸æxÊç¶Îì\ Éfˆ¸I6G­²qVdýt֚7Žœp ++OáÏ)“ë-y†Ðã_Ç r†\{¦>0i€=¨œY)޼t93!—lN€•ΜÃð$£Ÿ3aBô¹òzS‹9•Bs¦ë7*Œ ªÄ€œ?«žk·ùlµËŠáÔ, ïmÊ*[ J?&°~|(õV„F˜eU;ÃTÆõ²æAÕ/Gf ++”ÊrÉaþä‰Ã=‡wÈàæ™yCJ<Ÿ£Ì=Eƒ¶UÍ_G¾¯õ^*ñqA¡'SâËRžTvû­=t™Oãse¬bá@æT0ó¦ÄìôbJ‚ “+<+‹¹R/žÌt¹ä1Ý _wKH¿±»†YB8üÂørV—Mš0‹XMfÇŽe ÷«Ww(þHæuX.2ËÖ%«°€?ò|tc/§õ"$&h¦ð0 =ÓD„劅Ä’&ȃ'cûµgR…µ.²Ä¢A1|Ðrɰ€@xÁDJ¯ó¹WI虐Å,’&*²/b÷b£9?-4ñÉÃ.r9í—Ë‚Ó×1dƋá¢w:…ø.$n1ûÿΏ]¸füό‘Îþd^îœÇæ]Vùï5ìêÔìíÓF¿yNµy\¬oùöïõv±Ãs€}¾¹åНþä/ýCµÃ­œ0½·Õ¾pëÜ}€}zÿ=Àò]wžÞÙСËí/ã­Ãuӟ^÷f—oÞ}'q~[‡eÃs¶VûZ«jë¯8L¾ùæécïÝÿášSnbý^%µ>/>~_Ý£ª›ßW¦Úf¿·}¯"5@ ümqR§[Ò±kX²äcÏ5=æà°¹p\Ûߎ=²y暉×4JYìÜ£kAê ûfb9qË,zئxŸ²Ã^Å?’ñ èüoÀQêGm£±DºÆùÎçœ|f¡ôD»ÚFÚe<ÒgÖ´wL.Çü4³©¡pŽæ&¹Ô¡:X7‰OÚôÌA'o&‘‹éÙÂÆ·Ífå7†yÙ4Û¡Û»:ëI³Ò:‰4`™ÚxÉ™”"yóa|,‚b¹ødH+Or‹ÈïY"ÞH‰Ìí…wšT¤:HäŠ×^Ñì6äÃðdz·ÌÁW ½U¾¶Ñ¤¡àÂÁÚÓäò°¤¯çW=)A¨èÙSö:g*€iêÊNÀ±±ØÁùž7"{æÁ“gy~Ð:žتJ偁×Iý¡ÊW4gaãbçÁ΄ÝP ++¸œÑ©é9?fºóËòm‘l?aG`Çzò”ÛÌô܇¨ùp¤óõїó…ßÃgU¾|«yìû”žû¡ÿ¦ÙßFsßaKbS“ϼ'yX$þ_ @ ‚Ÿ|ˆý/@ Áр±øÿ?ù÷«ÿp|ëÈàîCÄÿŸÛîX‡ïæ–{ý‰·k>†Ýô±Øç¿o)mǽ¯hã\×í¶Ò6q^ùgO>§Éò;ÏÛÝå.„Ú6{¿˜ñîªmYÙ(@ @ð>¦_;<ß×ëǯ0Q͉jpV>2Àäìîç ˜(ßàˆäWˆÿ_ @ ‚£cþÿų½2¾uÊ`wãág{åW³:Šâ@ @ xρ1ä4ŽÞ](7£“ü@ @ ŽŒùÿŸù¯Õ0¾uò`gË¿ßp¼»°ÖBs¸?V_þö_[wQW·oÒÈ`g©ÕÆüùSG?°ªäë§Ìº€åþR\sŸØrIéÇy?2x¢ÔØÛ†kÎ<ù߅G@Å0Òåý³Ÿù£n{åPvdðV©Í¶ׯ|ÿ‚³yßkG7·qOýÜs¼¢Q§Õ<àñV7î†á?\kZWkØ=1½Ÿó•/\º¹ÖýSºÖ°Û\ä}®ßzíæRoN×2š­¶üB\묨5­S•ã`×´^Ž·»îåڝ/m/4Ù×çník VŽƒÊcÀñÖì=ñµ-ØÊpv‹Í¸åÌUß©Ü !Õ>¿ÝjÒ«{—m¯œ ++\9¶=ÝÆ»~x¶­œ ++AÕùí+m_Æuñ™×¿VÛbW÷oӌ~~÷¸O=_Úrˆu¼+ÃŰ­ÕŠ¼|xÞ»Z‚]Ý¿M–ÃG©µ]W+ñɶÇV ÷üqW/Ð׺Žë×hɋ‹ïªü9×ñoã\ðáãúu8˜ûá¶6Þy»öN.mÚùªëöã…Ø2µ¶%~…&@ ø?Ðå@[o•1ѽcsV¶c;g=Ny>fx7à읽Ç9ŒõÍQ±XbƳ–eüTðÁZæE'§ÓXÿ“¨-Ÿ‚1x¬«npLÖ ÝÃnA'V•Þ¢Çlµbe¿Ì,jÖ Áâϐ-jô-Ž¡¦$b³–bЬB1@ʑÕµ‹>&–Q ¬AƒÃ;Ù°H Œ•0NN¬Hç™ò­´Vµž^ŽèO%Om© ^d·I³Œ£ÂA5æCæ£×:}Î&–Á ÑZ¥£˜—3¬=çO﯃ 0lJ1a4—XFžeYú1²rœ:YUÎ1Í\yÌ @®U`<–»Çl rf1Gt3ËÓ)çtðɳ ¤bi²p\•”´wXçäT¦Ê ++x×\÷„£yÏXk‚Õí”õÉáíYì2iV´3™açx-ZVȃ€D•\zh´ßS\«ìV5¦N/ãsí¡Ù5¦¢=žt!Bà„ùy–àceÈ ¹Óbb­ÀŒ­ ]é˜XSR± ¥CsɰÇÔêz@4œT蛊½LãsûY¡’@¿>Õڕø{ਜ+þqJ¬ÛÇ=Ÿ,+jkXÔÑb·ˆj ¬”ÂÞM¬yhÊøR‡1–Ýúډ6¯¸é [·ÿ18ďJüÿ@ @  óÿ›Ç^¼z|ëäÎïIŸèÆ9g]C¿gLfÒÈ`[óŸŸ:zé9Ŭ¬¬m~ÙSÿ~Æ Å÷êU,)÷é>á/¿¼w®ºøõ®ÍWøýÓú>ÿjÖåµOoúºež›p}uÁÒ®m.Tü1¥íý¸þík×쪾úä«üþ6ß%[¯­>þ¤ ++ÿ”Ámlí⠒u›§õëvÕîé·×¶`jۣ彅“&òã¾Å7,Ý»à̲~˜DÃÝÍWùp~õÕg«_ýcm«f•6krõã¥éåÝ3ÖþKms®‹aØ/6àü:žõ©ö9³Å0¼sìõ/Õ¶ìªÎj|Ãí¸Ý·zgP¹öùõ¶§VÏ} ‹Hõ½sËxŒSøîW¯y¦¶E'~|@ ‚ÿ?ô¾l-ý»Õ¼ã½¨¬->Ýì#n3b@1F Dƒc±¢K'`>¥RÄÓ8š+çhàƒr¤§4v>«h¶x¯a,(G·wŒdm'kzàkÉ_» •—=dØÅ”œv@ @ ~”ø¨ŒSʼc4ÞG7Ù•þuºÊ¢‚#¥@‰ëð^g­ÈÀ`’ †!6iå¼&'9Ó2™Hü`µ'CN3©È­RÂØÂDGÏb B3„Æ¡·ð”É%|Á1ÆZüÿ@ @  óÿßøþ_Þ0¾udðtËë>0Ïÿéýòÿo:«òç?2ØÓêÌylÞe5^€ùü3Ëýñ<ÿ=;ûY7\÷·•kßåC0­qÊkžº ®æ°W÷q-HË^è8ìMÍë0öûZ®ýM¿xem˺ã¾_Óxÿ—l_>¯æ¾“ÆòÍ'΋¿£ÍáSÍéÚBÍEßUæÀö¥³×¾Xsص®ñO&gþwÊxŵøÖå·w²Œñé¯îþóÚf}ísSã xzےWj[ôuî{Z>ý-g\Wsß}T5ïKyŠ[¾ëÎÓk[ ++U–=-ïÙð¾žk?V‚bÉëÿ@åÚW]þþަ³O¾ü7[+×¾*ü@ Á‘FŸ§ÿåþãð÷ô9çh5Îß&g]Û}tÑ(•C?Ljïœc¹361óÝÁÎñÉæBæo1Ïè`1e é¼U ÏQz‹;Ó±I{Ü´çyúΝÁ¤æç4œ¶¤ìwFo ¬+Ü"ï?5¹ýâzÄÓø«Ê1[-†…Z+l€Ì´]Åÿ/@ Áр1ÿÿÞwÇ·NlšÊÿÓ'¾áxwañá7id°¾Õ³ÿ𢓿[ùås<Ù¸Þäùß]î/Å5÷‰-—”ûÎû‘+÷émtÖh‰ °ý|¨ùœOýl©'¼Ñ#ƒÍÅO½‘ý?ÿ¡ÿ)÷ƒ‰§ÈI¿÷œçç}¿ÞÏid°kj/çn»¯ðÿkç¦ Îoòÿ熫_©q ¾ã¤ßÕÆ¾a8ÅÖØ†`ªŸ|Ú´^W¾p鿝 tõ“»âëÖm+‡µÍ«ñ<÷놟ØXÛrª}ÞÛú\µýÆ_¯q͇Þô9söò—jþ)m³Ûnœ¹îÕ®-UYî-ó^ˆký‚®6€uªöyz‹ÝX;œ»õÙ»Ú »ªêü^‹Í IVl©¦SƒIq 8ÔBý(""H Á’hŒo)N‡±e”bÚA‡ŽØ¦•©ÄIù¨Q°µ¤u˜©Ö´F‰R1Õx ˆ&X±¦¥ëÙkŸ}oÞ{ß÷O‘Éz˜à¬{öÙ_çÞsó¬õ<ìa -û ÜÙÖc܋à5m ›§ÚšsQs'N/y·Óë‚{îò5Vs V·6Ýa«9'A»š«q ôå ôÚ¿õ‚}ì) «Æÿêr½É9{Ú­ÜÍ^ιڗEݼÜóþU?:8â”r=䔼àøu_ã<[Çþø‚®ŸWÝ~>÷3tktf9ïdĝÃ~Ñ'ße#ù§ÝÊùZqnȵ »}ùÍ[W~¿Æê|^3rÞ>Á1£¸Ÿ›Ëõ6Òkí^½­ÆªƒjëwÆàæ|¥(@ <³mn‡Êâ€Ò_ÐzNE=5›_÷ÿ×#ÝDT-ç«:žJ非NË>CYœOòO/ï7Êò®YšûdÍúNwŸïFµâ­‡ ÍMŒƒ¶¾vÕ€ÚÔÞÇ ó,¬ˆ¡–i¬…âÆæZ ++=,ê­7`b; ÿÖÿL«¨?O>Eü6h!–ÙˆÓ²ÕŠ‘Ë‹K?^hI©‰R荡-¬KÐðWtžÇZà·CL¡ÃI¥-¯]³œmq±¯åYšlHºÀ·N‹>ä™i¹hÉh‰£cž?»à1•¶T¤Ó\FHÜclt!ºF(N ôȚÐ)»34±uo…dÑ€Òw[V#€·pcpŠF‹ž¾E­=*çôµRQi“hßS?iV#t÷]¦A#I¦ˆ†jhhãÓí£‚ªùÔڔHֈ(ò§›ÐÑ †yJ¼|¢Óh6]Žú áþLíã—nÔª´ñg »‘Û3núåiàA·õA{º}“JXl•‘¤€ÓTDvE v2û3ÆI—¦U¦u {H•´PÿÑі¥ÕÀÍ› ÚÆ´©½„»"ŵ€¶´R…Þ†$„hÛelîè°¿"¶I¢ßd¸&ýt‘ú@ @  ùÿøÞsŸ33:¯§ ++—:Îÿ_ݸç—l<þ 扵í÷žÑ 8ꮯÏt|C«KÿÊËÿ·´cƒï÷Ž.ÇÇùÿ=…‹}3½®,ÿq9ž?ª¾ðÕ/ø÷J¥~oKãù?¹‰ù|ì÷nl\éoîÿƒûJ^@4ªß[ÙjÓOxüÂûù¸5ýÊÓ£?;×,+׍)ä~ï”Å]û¯ºð„ÒÏìLœß[Ñjê—l]Ë<»R–kãokùŸ»cçÀZ´Ä.Xԝ·úŽ•_çX̕ß-c¹ã?vÍ78ÿ@UÍ×®÷ǞÏ~ øË«ÛÒbklÍÐ1s_¶·<Žñ¼…?:¢[›·üÕôw8f2sۏ6þú¾[.üÇlåÒoly ëw?¸ƒcÁW}†¦¥0žÓ°¤­ÕxÞÂm¥ÍS¦&å-Lϑ·pu™ÏÉ>G¶¹V7­ú*ïUìbľ¸ Ûïüáƒ×pK—ï°ºå;lÎùp^-±3›ÎŸVľÒÏséõn½þ‘ª¡8¶bA׿¸VDjùk+8§Á8Ëc¿¹­íÃ7}›µ"r͓8©œ79OâȦw±fÇêÇRÕÂØ\ΛäÑ1¿÷@ëçêÁÇrÌîg¿Í縎Ä%mÝÏ»÷3ºÆÇ´Ï†5ƒã_Ê9ÖrlY[Ûñ\ˆÝ³êHÌï­+mþ ½Îxàï?ÙÅø¼³Gò$Ž«çiËûlg›Ïû¶\ñmŽY_ïÛÃó.ú0Dzæ±OµýrÆ÷Ÿÿ þ§QªKm–’s(…[‡â_Wø…Êm?ê4_¦o”}*5»šÀ‘Üû0‰§7hÔêHý¢oø4RíÀ¦C\#Ñ@‡Â:kT$£ûð±w>˜”CÜ„Q;L_•>Äz¼°ÔÔ4ÐÁ`9ü§‚ߎ¨϶<7ÎÔpGù´N*9ÍχOA.„Fu¿Áš $?RãÁµá´â9ó3@?#uvM?4®Ü´KÍÐb£¤LoáŽ+ýÌÒ©G>]‰‚êùãȾ+Æóe½ן˜úlsÑ¥§‹äC /ôR¥ð ››¾:J3…¯mc¥0@jÈÒ^¢‡z5’}ÑÏGúg•›-'„†^r>&Õþ£úž6‚J I®TÁH=ÐÅ<ݧx3ÝØéH´ §dTûÓ"Ð#tó¤èTÚ¾´=)Xr èöÄ$jÓÆ2AçÀ[\†ï:„d*ÐÍHO¿ ++)8%ƒÅaž2}à(ºõi=‘ƒ­~ƒ<ŽHû9ZÜeŽÚu´ p+=<ê;õª™³DT)ðîL+›!Ž`i=i¹‘Ñåæ”—ðÿ@ @  ++òÿ_8nÕfFçõ®oºð×-û­w0n¦ú½#÷{°ÎÿÛ=XàÑÆmž°ÿÅëêñÜïÝ]ޏzì«O}ñ—¹–Ù©~ï‰Yt˜cCû¿ç叞߀·¿¾qØÎ}÷–ú3Õ¸¼û?²¾OžÞ¿­¼ÿOéµüñWß[øg¨ý͍ó=Xw`[9.ÿ;çýzéOŒÑQ?[û/Û¿¹p¡É!ïঅÃã痼ƒ-wO˛Õ#èò Váý?ÛúúrÜxÛï¥#†í¨5åxPq~ïæ…]Ƶn,mE¯‹6ªú&˜QÿÉú²ÆëÞuÓÚ]3•K]XÆ9™_ßÖ´®xåºp,ÔºùÃZ¾Æ8÷¾ïðníÕŸÿ-ŽeÃì–6ß÷œ¸’Ç]å噷žÌÙ?qxwÞ϶n`¾%v å@Œsö;Ëõ¦§PoÿۇU‚ZÃåÞë|åâw~ƒc¹ê¤Òædmƒ/¶ý}ùûÞòŽu9¶9»}êí÷0×ßy17‡÷Ãt»7ÆuÑK˜Éç_Óæúã©ÎêáJìÃ»ûÜâ¶6†q½„Ýí¾X3øW¾^4Õ»Ã-ÆfæœÞîãq½Ö»˜¬‰°y$`_¶óòœÿ19`{ËKºaÇ©qÌEß¿·}ýûúUß­ŸM‰çåіôkó_¿—c±ŽAµñ‰>ƒ@ <ý˜¡™žs—}H» ^=ÒáÆIvœï3Í3|F|? ¢^»\<Â3ç+å”Ãð¼Ï®ãMiÑ ÉÖyk‘}»ýä»<‚ \å˜FøÓ]“=[C­9ŸM»ÀÐ(ç•`mSLÀ íƒa­þlãÜ1óÙÁ†ÑóŸâÚqzƒëچ쀦 ö$6Uwœ~aÖ2p¢ñ´óh+–Úûºv°’§yó)!#þDš„Q°.`Ú"vñp€pB?›}R™Ó6- -³Ç6Ží4ÚÔÐú7†&½éBP'QË^yÿÙôÊ"OÒG˜E»_äJà‡B‚ÉîØªùài2#-¤óqwY<ˆƒ‹Ç]¾Ñ½H?!1€Faûf°!@€4‹}KÛÐۜ³ö™îÎL·¹†=¢!­„>( 6 E2Œ¥ÉÔp< KGºs} ä’Ç£M›‚ëC€Ž¿¥iÃ6Ä©t@QÐ`„؁£ùÆ”úÓB¨D*´wè7!Í3Ý6è-ÝfȌ@Dõ|p44Lú¬‰ Õ ++,‘¥73*ùsI¢ºõè.‡ÌE(66Ðå=]œº OÚ_5‹ ¿ „ÿ@ àPÀÿá-Ûÿzf´ßÛY8·íôZöØ®Ÿ^‡ÿÇækÿ7;õ åxá«Õ,<üõ³èùßÙjf®·¿­ñk¯ý)óüI:~CiçWèµô´£ž,|¸Òª_ë€Çyu® ¿^ ÏyÞ¿•ã>Ñu¯,ï'ø²ûÞYŽç˜:N“µÿ¿òÒZ_ï˜C½©œžôÏN\;¨¾‘9ÔÇ稡g­É|ü–V==Xñ‰Ê¹×zâÍmLgÝðŽïÖXæ¾ ùÇ;?}Ñ>Ž¥Àç-,±•ôºñƒoîxõÚO®MÇ ßúÃå72wn«^Á°^zã`¹Ð»[¾Á8¯~y›³ñšömm|k¯ûóÜI1ŸûŶç|ç²W0ÏM‹Sb—µ¹þ؎uµnÝGû™­Ÿ«_Z5üu­[ouùãõçW6¾úÇ]ó½Ê-»êm0G=ø¶6g¯ÛûŸó*ìy|»ÚºsÄÛ[®ÇLŽX àPCãàá ++`‚JüV»©‘:qäC‚É„Èþ'è¡þÁ‡9’Ëñlôk§§EtÌ£N åDŸõ:œN1Óã+)èDdhš2ãbfeR2žº`§Ë*PÅ)9ƒ¬PêÆÒ¯,:„œŠ„JqU$´†Dòu‚T KÍ@&‚:ìèÁ-eOCÖ¥^Ý+eçàæ»Úû–«ðsà®s©Æ×:Ρ¹0[Þ ùESc6½4M6Ô d`˜˜h?øl\ )¡ÆhV]ÎÙ£ò¾Ì;T?°Iu¢‘ÑHŠZe}¤=’™ƒ¢áQú‘!<‚¤ dÕ]=Ü ™†:ÌUBJ‘ ¹k > %WÈ@þ?EWô7¦fÓZÀLѫҾðÿ@ @  ++òÿË?~ϗgFçõTãSGõÿçõ64Nô¿qñ™•oŸê÷®m5Ö'|iñUS<õ+g;®ÿjã‡Wìw%/Àyeû½Ý‹»÷/»ŸõüCÈÔΝ­®ø`=ÿ%K>þɗ¬áúüìú½Ç[û£uøó{KæÐßg¾w²þþÎvýñü€©VG=ž°½é%Œëï_?GîÀ#­Öý÷ºìت£_ë҇^ >Tc&0g}RéË)S“tô_Ór7þvéZ»7Û<µôƒ\¿gÓÖZ¯_ç岯»oìäü€·9¬gÿÖïØË±®&OәßððiÏáZ~_s®,ý¼^Üs—çX¨¹[ZýõÊ[7²®@âZ¸ù½kÚþ[¿ïˆp,ÔZð-sè\ÞöçÛv_z"kú»ê=pyiz÷þÝô79ÇÁ{ß\zÿœ{2Y;à°Ò—É^ŸoÚoºsÓW«€æó6´}6ž7ñH[¿'OžfÍëÏÙê9¼vµý2®°«õåǯûZÍ©¨ºjMÿéÝ:¬<ò笠«āòw‹“ëõ‡^«g°×D’§†X÷³—žÅºój#L®ågí‡Ézÿý‘šüS—r.†©ë¾§i–¼wÞéŽùÄó²pQ“@ xö£«³~ëÚ¹]»H_…T(©(¡rs)8oR†ó–}—P„LÀ·µòyè`T ®Tá’'ú±«¬ ;n«¾þÓªþTøLИä UöÁDýz³¾ò§ôJ]KEA+ ÝtD~xG¹Õ™yv?R:i`uuÙóy ++¼žu~ñ³pÊÑ"QÀÚ©¹|èѝ6wTu®éaÏ%|CÓU´LLèÝ\üüÓí½AÛ "ýp|H1ÎêÿÀ{]Y;«¦ÆÓ«Ë@Ve|Ž:•ñYy Ê Fr4„ÿ@ àÀÿì§ï¾hf´ßÛ;K}þqåø¸^=מϬ·Ÿßû|ã,ÇùvÖ@MÿÙ¿x&ûÁÇ\}믞ƒ“ÝÕôÎßtõ9µ&=VN}_Ëøé1粎8ð»{q׿¥ŸþzÕI¯^ãæÐPßÓøïqÝòÝC~øÁ³?Ì|fÎÌåÞÜÚÜñ±ßýƒ=ÊošÃ£|sã]çÞû_ÎÜ£*ܪ@ @ ü<ðsÖ¸Ÿ™àaíPÒM¢×5¿€s]è:0±ïr3è÷\,Z[F‡¬M6És¾¸pXv ϝU+`¦Á³L‹¡å§ v^фâu³§é÷HW1Õ;DÃҋ&Ú ×E²ÂHý¿@ @ ‡†üÿsßtë‹fF;~ðÿí_Z|þÿ͍Ïî[_\ôÿcVª_õ×¹Þ~sá֓ó±Ó¹Çû—l]ËõèJUÝù¡üÚG~éªÇx yüq?pÖÜßJ¯3¼ëvŽÅÊ«ïiכ©ç.@ ‚CàÇsv&#IÀho \L֖‡¢€ Cv\ À@G½…óCÑÎÈ!ÐDl‚«µ½Y%$?Ÿ²2d½ò:™‚+®Ԉñ&Ó¹LW¤7)HPó.°ôÚö]N2-J¾5Pr¼7ôΘ“Ò™šítý‘nEäBh7’7Á¾ è†G¯\K¯…ÿ@ àÐÀÿ¿ê/?{ÅÌh¿wváÑ?E¯¥ÿµü5ÌÛk×ï]ÒêÖGuõûµž}¼þÿ²V˾á¾+rÕÆ¯:è×6Ëß÷–Tô»fÄëýnÖ ‡Àª,œ@ @ <£ÑùÙ;xTd”Â똆Ç!, œW>À]"ÅÔy8<Ëêòé—-ý¶M98jÏ'Œ•.®T锧î[WŒ@¬…ÍCrÁÑÈ-l;Š?…51Á G(®½7{Xm¸hèZ ƺ¸0Àç#Úhaq—ø: ¼o3)ÞÒ9xz””¤"j!$$Ê ÿ/@ Á¡€!ÿÿíÁ{_13:¯—Šÿ5xûkto(uôÆÁ ùÙ÷Oï?«ðù΅~ï¨vü„/-~€kùUêWt4vì»VüOÕ¹×ýÞÑ¥}Ôéÿáë^øÏµýØïm//±^ËÛõ“¢;  ; J;ÈX±ßÏtç•í÷N*y ++—ÐëÃ?|þÝåxrtÝí%àÍôºn°¼ø¸Œ~n[Üõçâ÷¼ü1÷Æj§´½N¿ÿ˜ÿÆñ õç¨#º~¬wp`A;þ½£¿\ò ²òýޑm\oý‹Êñ¬¬žßÛÙüç/ü¦½¥æSt¾õeÌóèõ¹;V 8kìnzg\ý´Ë£ hsýîw”þŠ¬ÄŽjz ^{Çrbς©–“±î«ï:¾Ä¬J쑰¡y¢¿kÉÅìÉ`uõK¿¼Äވó¾~à•sŽÛ¼¦ŒÞ ++?;ù÷s,8î‹[؍aÉ-+YÂéªó°°õsÓ`ç%bõkXRúùz}ú—×ïa[uXo oxø´çpÌ+ž³ e >о¾rÓC‹šÏ;¦éJ¬¼ucÉ9ÑIUùKʐré /äó²V<öÓÛýð¶Ý—žÈ1Wç剅Ýyãy,7´µ½ê¦Ù«Â„Ä×[Öæåɓ§¿Qb4Ÿ¦ÄR›—Õƒ}Ÿäüëٛþ‚E]›Û±ŽÛt>òøöµ}vÞ½ŸÑ|ÆÀktóáݜ·÷ƒ'U½ÀcXÒ®·f0ý© *ó:³¨ßU·Ÿÿ]Žu{éè‘ófzch±Uƒ38‡O%ƾ ðþxÞ1ÓemQ)ÅóräÈyێ­±È}Ù¹°[¿³—žÅ}Én‰íi÷¤hÁ3Ń]¥ä}«ÓøÎW<è #„˜|¬cHÅOÜY妊.¸‹F©Š¹³Éªœ(4z€½3É3ö@Ç¢²ôö³zj.y£`qNoÕÖúKE®7:*zŽÒ03Ï:X‡§4\èQíëé{?Gè|SD³Q»‹ ++_¯‹ÙºFk&Ûô´™´w6à»-£F{zvÔôÍS´º7Îxç;ýrŸwºš¡žØ¬aNxz´¨Bö*æN똃3:+Mßa^Á&ÝP?u€ºÆÿ%ú§Î¡¡CÙ;—ŒÍµ~¸«ÿäÛn"õÿ¦«&zފU+œ¦€æ!GGҕŸõ§¯vWj’ ++òÎ`¦iÄswÎjMxjÒÁDžžW }7ÓhÄÚuÂ`i¡P]mÀñƒÒŒ)xC“O‘TÚú?ö®fϪ¾oҍ·(˘¨k&7¡\„s¿ u8™1¬r-—ÖÖ℁òÑa¦qÎ%Ñ "˜C2¶IF™r ,¢¢2ÃB—uE±ÓŠå£ÕŠ—âÆ~¿ó?Ïù¾~ßW’eº œ_úRúœ÷9ÏÿüÏÿœ÷yžÿåçYáÚÍÖáæÅå“"»½Çí¯‡êIƎ +}²¤;gásp³ yЊƒˆÑpv‡Úï{ó5ã^:ÁÌ ++/=tÎZô‰šÍ.ºªëùxà"{€úMUǚ,ýêÃ"ú ›S¤š‰Þ`Œ0³T{(ùÜhс¥j'I<,ÑÒ6˜žYKŸÔð>” ôY¿8”LنK¦£W˜å}„SLŸ®A't é(©¿[wt†[Ãd=SÂ'fäšÃa–Ó ½Á*t)¬O4 í!<š=o޹š0°€¿t²¸&ŽõçMR°UÌ2nL)1×UNuUæòÂRr̐÷Ž=ð 6-;s¡Ý` BF7ÌÌRÑ-ëãڃéb±2¿žëCqÞg´¢ C£d€ºu–´ãÂÇ^AšM#'Óbf¸d8Nxç}¢}WC¶H9 W‚Ձr$CƒÂ ”*~å ‚ÉŠN9c §BšPì˜%X ++ºÄöÝa xRáÃwÄR@j`© »!f¢¨†Œ•mx}˜±p d$!avS.vÌ-Â% ++0Ä\tÿGGGGGGGGGGGGGÇËÓþÿÓ?𓵳[Ç£+›¿ýØÝ—½IüÎÆGÇÛ5øl~xÙOÅßÜà·§ïmÅ ¯¾6f<:§_…ÏQ[6QŽ;~.oq{úá4ÿóÍ]â|ðqµïôñ™u ,>èÕ<þó[ÞVüùÆÛñèÔßWkËñ âÂÑÍÿ¿æÓÕ_¯b_ðÖ¦ÓõS_>BtjømoXÈ6úºOӓۥ-eñ£®l¾ç¹~þ•m<¦®:Tüî&ˆ?ô#åz§ózß7ªúäô¹|ñôy?Z,mɋ,+šœ“SÇ|BüõÆVÿë¢a~î¹kýi“w« G÷–>¯ÅçÎãW}µ´yÄg}aé“_8ÛÅ·ˆŸßV½ÜÛbþôà5U?¿9ju%ŽO«·J›øŽŽ)sO?øåw¼Câ&RL¹´ÚüÄÏt¶ðG@×r޳͟í¬2(mïÁ“×>vÊÇÄ_,m÷”ó~Ÿ•?\ówâwWZÆðlóóÏõÉonqs}òW.d™ë[?µÍí\ßú‹»?cç¥ciK5þÁµ8†Ÿ}|íã•;ÃU—5´³'Nü°´y%rnj6½zê“×H[ŽÕ·Þâ{ÎùöÊ¡-‹®·-t=×'ïÊØ?†ÏÉ[?w³øäUá¸dáÐç[¾ñèq²g¨j×[[œÎöY1%m>‰-mmz9yjÓbiK|åßÑÑÑñ¢Ã^ø­÷æcÄÿӝ5¶Ã`,óT#½CNã÷Fz½ØÔ3Z•QÆYяµFy•Jª¨¶¬r­2N¤Û^/:jmPø ×,îfËôR:b]Ò8Ùë3nÐÐ]ªZ)toÓ oÆÍ=Š1ҁeuõÎü@2Å.ƒ‰ÒËLÛâî‚@BFx´¸Ï½w¬Mm0 j F6¬º[ µõ†öÁŸ•àŠËRB¯4tTü¯–ZQy†<{ó ïá›Õ¸ˆIÖ >[Vò¶*Zºú­þ¾ŠU¶=n9s,¾YÌÉѓ§9á§)að=&*C­ÌÆÅHr.^>¦cÞrÀðM±„†C@Ð94¦Ú@¢î¤xël•à Rvôú*Cg..a!Åÿ— ¦úZüz'&FÓ'\|´AáÞ"§à™XÌ«hú‡5'€áC‹™ºL ¶ = /Ôá®Êg£¡ba# ×Ô*qÔ ++dŒ(ÓKɬèLW&ôÑü¥óðŒ36ÁґkíÄ<~Ìbë7òr–ìç@‹,¸Å_Ram  f4ãâŽ6™ib¡„^`m8FX@pŋNçšÏDžn2Ã\ÆÚÊã`5kJSX7‰€ºF‚Ùó, ++EŠVt€)§g\qñE‡%C‚¶øˆ¹¾V¨6h«ã¡×7†¨Ð9æÆYœj"§—ÒX‰´ÏðŠbÜ #"#3,ŸŽ°Æ-ŒYY™¸,¬¶ŒYÀ?Œ Ü,—#†ÊRþªPXú •ÀcYf½)nw¨ß9aý}Ø;&Âá0‘šñšO´L“u1ÕøïÄÆ¡æÜ3â_)¹ÿ°좞fŠ.a–ŽÛ0ö1îo kŒq+Œc0Œ}‰Pk´œ9¬ûˆ h†!”XiÖ¯.åýY“íÁo—B\6AJØ ž¹ÓÀ0O|#!(¢Õõ;\;˜ŠÀ0(>ètÿGGGGGGGGGGGGGÇËÓþÿS~þáÙ­ûŒžj~Џ.Ó»KÞ{2ã‘ÚK^½øiçúíkþù#Ÿ?¸øÉù‚y\s×é£Ü²vùϤÿÇ£÷—ã'Lìé·ò¶Å_}±ø¤©¾×qËéþæmïú‘´ÙêË^ÒrÝçúÎ)ç͟³¾ ]ï=SÛ?]}Ë^r¥…›`ŸuÛß¼ ú•øB'Úy릎‘œgãªï\rºç÷ß;#ú­·‰XWç}m|×ñĝâC-¯¦::::::::::::þWØKÜÂìØ˜_Vî½I,) ó)¡1à¿ÆXgËH%ãq«{ç¼ö&ҏÍB6{†o”°‡äUÐA{zÃ#ÓöƒeQËøc²cm†i–ؘ™çÏê †!,™!Wœæ%ˆÎѹϊ)Êñ_DüÅ/"&„‘<,TBJ…”Èæ­§’µ¨5F|©ò,Úýÿ/}ôçÿŽŽŽŽŽŽŽŽŽŽŽŽŽŽþüßÑÑÑÑÑÑÑÑÑÑÑÑÑÑџÿ;::::::::::::::~0]ÿïþ\³ÏìÖ}F'¶ºyWïïN)5猛&Ûñå}¶p¼é8=RøÁXÏïØçŽ}Njâ±Îß¶ÆÕuÜî/üA­]—Ç£sZ?GÿÓÒ¿bý?×jÝ}ùä£ÿ»·ÁG7®0rÙüÜÉ'–ú‚Úàº÷އï_xöQÂ#è-ŽooœdË•z„!ä4mn¼i{ò^Rä?ab6_àõEN^ä×忔ãYAž›Šœ³yŽ^Y®ËÎÞ9õØßÿŸñR05]Ìåÿ»nápÓßPyY¢´½¾œ7?7àMmü«þvò±Z1›ÒvØ¢a¬´óòÊ ¨jÂƒšþÏûÊ¥GÖ¶$u ++Ÿ.ºø0>üÃÊï ++Ç_ðr½»— ãÛð½ KeþC½Þu…?î*|.øÁŸß*×Û׊,óóÿÝÑø/žÚ"µC¬\}ã2_óóÿm+c¿Ÿsú‚¯mAdyªèó|.züˆ7J[¶¢ÏgWåÚÃW§´e£…ïÆ¢—¿ÄçÌ]G ?žÊVú\Qæül|þDŸ¿KlÜ+ÃՍ÷ñýK/z¸Ú’ó&ÛøæÖ„|jFۊ"§±¾ÎÃE–ñYã×?YÛª®·.®wçÄI[ ++RŸrûâaþNÿäÛjÉzÞûówÎö×½F¸••±ÿ¸É²fj¿C¥Í9kn.~Cþ”¶{gçåŸ;ëñÃp&¯¥ÔµüWé3šZcó¾ÆÑø­ÛÏy¢òz‘åkãá¼ÕS§|BÚLå)\и+OžÚüÉÊ)è¤V¦kuH¿øWøÝ=ùǍ»òóqҎº…Ü ::^t(¼K1°º‘ÍäbÒNsÓ,üoŠ4IÁšD’*ërj5›BÒN8ÒLP,•±q1)»L ++QüS‘Ù®lëšdsQE2Q…¹c“Êàç'‡ì ú¸(~©Èتl,õ™²"úHdfËý%[øš¼#³~‚R¶TkÒÑ¥ C€ø™xѱ.TÔ8–ð[Åkúd*ÿ–ɾp| çœI‘|¥ú“Ã=+${…±JS|2çE’¼…Œkf›tLÙaD>JU-´yò¤åÒr_AbŽ#„ J/ç AU•ÁùR ˨"ƒM…ÍK±àpžæl{‘òÎäš+¶àÈp45‚Is*êZà ¿‡C¯_1ž3\7³X›ø¿fs{•Zm9y¶AÇʄd1%ä&äȰnp)Ü?â—/ÂZ­Ã£uåx7J3£Ú ! '2ÄÈÂd¹X¶fE8Üx£ß lÖ'²È9r$Zò¢a¥8V\˰ð6¿ˆšg‰5äHÕÌ15 X­X"±°ó‰c² 8Æ)ÒIÍâ¨äÔ8$.‰ÉrX X†¸mD/d…ó¤.„5 ›ÌZu$CdåoCºKë=‹ÜaÑá ++Äye °F%צ&aSàš+,‰XŠhÖ¬e§ EH ÆiÄ#-R™¢܄Qv®` õ‘äÍi•rä–…à,EšD’Iܨ¹<¶5ØPbM;ìkÑc%‘H_¨8xOJ?XèpïŸu±L¶{-6 óE¸|â")¶ƒS UúrTäŒÅðË3 ÷ ++ÍÊx ++–r6mƒq;²MF[mÔ$ŸU¹0¹/«ÝRuÐ,Ôª¸¸3+ –š{0ÖÂé BN²òqñL04ÂÍ»EÆ/€˜ì£ÜÁb^±Ž¡qìÁÔa_؏¶•RŸ‹€{/gÔrwÏ0_˜¨ƒAaôø}€QÃü2™­¹yB^Çò€–·ë…S2Q»‰tø…À®dë~‚ýÛz!q©“% ++‘IˆÍú(į˜QÆH±O ÃÜÝ2W•‡ºq*ÙDÑŽOü29 g>ÿuë†ãgÿöŽë³Ÿýç¥[ësžŸ·•ûkÖÌ_tÚkþ±ÜCc™ŒG¶ûî#Ÿyí^Í÷ז~.Áçšþæýå8~ŽÆ£eß{&_ÀÂÑýûíýùùÊ¥Ã3ÏÏïX'<ñJ8sñ ¹ßð¬{ᓯø|}f­ÏmR˟ÏQß¾ë´ïïù<{õÒ½?{nlüòϾZøå1wÒ牭íç·Ôç!ÝNLóÒSÎçß0)ςÖÕó\ãøéïþº<+Åúìrn{÷ñ¾#ÖJŸQ)‘óŠ¥ÓÏC³¹ÙÜÆþ¶Ç>sûðÌ£û-dGGGGGGGGGGǯæ»àòޒ/4_n„¹ï*KžÈ+˜u拞UމE…g{>Š«¤C}/2ßfðÝŸÛ£Ïz>î¾`’w¥Iãë9òýZT9”wNÁy>ŽáÉß ×g ~>ð§\Þ~&C‡Xyï£T{å½öÃûޔ}41á¡Þ)¾k#¿BR ++Oø”—oGUŠ8®Ê9« ø"'šœÊ‹¯ ƒU|e‰®ùœï¡bŒZ…(OK¾Çÿwttttttttttttt¼ôџÿ;:::::::::::::^˜Žÿßü•'oœÝ:][rsWásȖM«$Ú3ß¾äóލÏòŸ<øŸ%ž_Å0ÝQòŠ™ÿ¿s÷!»ËqËã»J?sãÿï+9¼sóöw”ãÅgÅ£ý—äí3ÏÿéÒÿ ³óóßZbßgçáGû·xù£v«µåxPø¾Äæ3Vþ¨gw\TŽç˜Ž69Ïÿ™O×X†LL0¾~Y‹çŸ››}yÂ<‰ ¿ù¾,m¡æ„O4ÖO-´µÍH<ÿ²2Îùsú_Ùò›7Lmø¬äô»,9ÌY2Ȳ찷KîºÕV®·y¿éó®ªùþ&ˆœ÷µ¶É©£n—]ó¾/)ºý=|κuÝÎږ%çâ€6ö/Ü´îAi35Ÿú„¥ÃîzÅùÛÄFlmۼóýÜiKUŸ›Z^ûÊ_?õ‰š›_õ)¹äù;ö+ù÷š™t¥mKË19ãŠ3kÎEԒó>Ñì陃Ζ\rmkÇ݋‡>×>vÊÇ$ÿ^+¹Þ§Êü±®Ä™;í¦Úf$ãÚV'`Õa“ß–<Ì|i»¢ÙˁG\ ²XcEg÷7]¯›:ïÚ–EÎ5ûöwæc—?äûËø¶¶Ï.ºø;ҖknÈ#-o䷎<㮝c‡ù[4È277GË)y~ÉYµ- }.úœ›‹²µåùœý¡õÿ.mI‹}n\4¬õŸ}|íã5o߉,ÛÛ¼¯þúŸ•6geì©Íß#®–ú Ùz¹ÞMMg'O­¿FrX²–œ™]­VÅ[¾ñèq¥M+/:;¬åá|ñµï’6±ÁŽŽŽŽ—+š±¥bL!Z«ð£ËlRg˜·ùëlUd2¢ L6M)&oËà«Ú–”öY%ˆéÔQ1{ÕDå³Î!{“‚Søõgª¸ažzÊøÅù†™Ñ×q:øäu)ˆ Ù›a˜-îêðûà˜ˆËb3Éü>0 ÞG;³.Sèƒ >F¬Z]󳍆¨Ì±Å­‡™ Õ:ÖXÚà¬M1˜XWcr²e4pñhÓæ™îÏlz[ÒÝ]Àwœ±™É¸Q€.ð½!G^ó'R{¦Å&W†f^ôõ ,“¹C éj`̎Qf4±f½+©Ç–éÞ¬J€ŸPæ3]žÅ(ð;Œ››˜ keà@bæ:Œ wëÎp6 ¢.9ð¼ó‚–TúòL¥g¤³uÌj‡]1‰<« óàM/. úu˜¦2§Æ¤:ï.K|6fº¿O¬äñ=¨RYL,†ËÀ¾p/Ȭuˆ i)] ++ƒx̊c^8Œ—ßÄ,¨èq/SêKýÇVÛ2,ÿ‘¢£Àµ&C€Å@w_a¾ «maWR¿á`Ķ‹ô¬Â ¾†ˆC^=• SÅòÄâbÓÍR›ÒP¨™ÈD ð%ÐJ€š¶Œ—ÊF£bKg°“™2†q$,P3åªX‡JÓ ++øî`"B µ¿ßî¾{Îw.Ÿ´8@ö7žóî{öÝÝg÷=ûìó<¿çòؖ/ã³üѯߔÊ\ŽYÙ2MŽ˜Î+øXɉùÁÏï“b4Ý+***þ_ý{=vWظ„ÆÑžyÙLÐt†§—¼wÁ٘6‹žð ݦé¼îèuìð ³F¿j+”h˜59Ѥü¡kèïn耯˜¯PxÔnSz‰ß:Tgð(#­o”¢{¶¶x‚G£œaMÁ`!ñæDýB¨i¸°‹Ï`6.úÏòÇT{mÑZ¯Tt*Æ%EWb£éÌè&mÄU&ò¢ï<ö Árwç«|̧‡æzAoZF+0%ŒôLæcô*Á8Щ[kðÄ@çn’ŒëèÊÝÐù–Qu·ùö螫èòË Œôù rƛ)¯Üï¹cîÀ LöfêJÉÛJc¥,½ sû)3ËAö–ˁ™9é˜õ’}€ ÄØ\„’é×\ü<î˜}ÎjæP³}¾Ø%£k±Å m\HæHÌ=ç¬WãrËÅ\m1»š”.ށÒ1B0õ¡`¼€a®CÁL1žñ&žÅTà$‡Lðä—ÇdÀo} ú0 *e€ŒŽy%³EÆùÉ$ŽØ“ZƒÉÄDæÆÇ Î@2dFµ~ã=óQùó8[ øè/uŠ™pž!8Ìû‡u‡"¶U2ë¢ÂÚÄΜÎå’ ‘B5M ×1vLÞONq¦CÅn+¶§ñ)c¨FÓ1A-þrpŽ5qLhgØSL<<B_˜¿è/Ö Dõñch G‹«€ôúN1¿eìmßû¹û+ç&VJŒY‘ RÒè"“B^Ra Ö7ã’<§êU ƒ©L®Š1¤Åf^>¾|02*åP•´Æ2€Ã;Ÿçã{Òú„€¶ræèÇ<ÃÁƒåƒU"¦æxcUú?LîÈà!´ÚÅ(‘¾µúŠ'é×ÿÕ­ó÷ þÆt;ۊ¾²áâÅ/%VA¯ÞZöù‹w¸&ép!t;;Š^}â’w'½/ÇnGŒÑçç—ýûá?;(Æç3ð õ—øï£^úÕÿŽz8*êv–έŸïWöåǞµ8òðåßí<<2þ¿?>ù¬¨Hý’9¾üŒ“ðÂùžÌ±õYÏ\XtŠáØúmÓÄÈo/ãò ÎHܐvÒÃGÁøÜôþS¿Êðþ‰ew}ø‘›ÏMüÖçÜè—ϯG/ýûkê7ß=9ëµ!ë„×—¶\tÝù´qð¾ï,`´žÙÝw¼.¹§äŽg¿ºŒËp<ûce¬¿ó©Ó^Hz&æx,;¬èS§ïüì19f=ç¶ïίgê2†óÐ÷뙃º¤/ÜÃñì)~tŽú‰9ãuÉWŠ–=|ûµSõÅ+J[î\úTÎCïRÿæÌmûðޙ'íLëÈÅvVTTTTTTT¼çJ–.OEzz†aÖtí.Ɠ3±¹ô?ï,ä­tž“bØMCæŸÏð4*ýŠÚ¹çÁEŸÞ>Ž¿BEâáúݔ]Hÿ• Õ¸àxnî<ãìô®»á‰ t‰#¨iCW·@¹¥:ÎÓ2w ¹¤¸àyµB2ð¼ O‡*C Á¡Eœl¶Âw;[ÊõEÿrwŠ#6t;…Ï|ª?ÿ}Åf<çøýïyëYRìÿSó\YláGîþÂÙñº7M7Ûù‡óܯӖýøéï۝üœîv^)ϝ°©øù÷û#´~ü£s\R| †slíù<ü‘«·¿Èö;û'·%?i‰ALþՉOŸã%>¿ú‘äšô¼ç¶m\ûôq¿”e’m÷ÉæÏø…÷ûÓNe6û²¿VüêWÞú¢ä+IJM±-§àó'òìg³Ÿ{îÃÊø½Ñ>Wûü“Gޞü´JÏK9Èû?aÖ?Ÿ}Bæx/þêÃöÛ§ñß/>ï<>o§¼>ûzgŽ/–¶œ6¹ìöÌEŸÇsÝ4¾Þ[Êx®|úøO½ð9n ¯ÎëS[ †TöX‰Ã¶ëßU¾·lré‚ì“}K6îÛ+Û:;•y§ëKª¢¢¢¢¢¢¢Ñ>H×hOæpÁäAéäëüú&7^0ĉiò¼íà½Ü‰×]I)©ü­u.ûݧû˜‚ŠÆ‰®K6ƊF MxåœP´Û’åݒ!5¡qÕXeè’M˶Ñ ±:šßÃ=1Šdוç"ñ·Ó![|hž‡å|îÁ ”8‡à¹á•ŽˆrñJ[ô›0÷C¿-›q.Ürki´ìë?óHazÛuà3I #d¬¼aäæ¾ñ*Ą&h§ÑŸ`è ¡#šè‹©¶Byè/žÊ›l©fÀӓŽæ:T “e’‡é¥™û“HF P”Ú0†ÿœ]­“”2¸ Ç5Œ³ÑVŽˆÁ)²ÕLàÐ ‰AÓɝF@¼˜Ü˜Ùx`LRÀP©(0,kfv‰‘,ã‰Îýø*”#šp½—AÄü PŚéü)bŒEµÿWTTTTTTTTTTTTTì èÙÿo}ôww –v;¯E[-mà ÿùS'§˜vm»«Æðÿmã°$Ú=·ñþ—îûiäçζ¼üsí‹"ÿŸ±¼ÿ¾gÔî?û~âíkD7Çßóùùâ§0•/`E©gjüÿ®i¸ù¶Å3‘ÑÜ|;J¿‡múWûíúə*—5)¶|[± ŸzͺǓM¿É6Ûïm˜Üp[*Ó!ňûWÿ‡OmÊ|"óÓí™ÝöaþÂÓ˜y ++TjËæ}{u¾0;•ùWßãüèÖ<“dg}jç‰ñyŸÃçœg>ó•ä_ÐÆ«Dž=û± ¾œÊTHÏÛ^Æù‚É퉋À:ìá+â÷VãóÓmç<ז%›wòŸíÏpå¾íX¯yèö9i.y›¹b£ùßçý Vüòò'sYöÉèñJœ½kÞ§g‚Í~ÇÄ:é{°éÆÕ“™OÁ§±ž_ü5†¹ïâhA?«—3&×,Ȝ !}oF׉h9Ҙ%ߊÑ>{b[Žeÿž›øRâLÙ_cc7ß o߃óÚþýík’o…6.Éö’"‡‹þiÝw3CæÊ[:«]£Ã ›Êº[¹ó¨÷e•dtÉì^[y_,~?û¾æÛ©Låï͟Ֆýø¦sS[0_R^,\ާ\ºþ‘Tæeš»K§á}ØVü††¹—Ävþ>Ÿ˜ûáÇR™ñ©‡>ÐaއËÊ»qå£+Zߑ̛ùb‘òÉ{®Ë¼¹‰“„kú¤Ço½¡å„Hò»±ï{ sVîŒo&Ÿ÷{ߑA¿’+Æò¶>5³?ßçÄÉTf|ææ˜×–UŠŠŠ·/Æpƒ æwФ~J•X]iôÈSS“›9%yÈHýåiodÐ1£Œ™¡­'=¡õN¹ÅÚË íø-1 ïpÍÇøÙÌ÷‹åo›1M,qü‚5Ø ±IÞcðãh íߤ`#ç[Eî%h@uØÜa`CŽ1¶[‡¦ ++æ§Y0ái¿G“CâÔ£­ÓÑzn[›òˆ飸ü¦Ä#ðL痐â´-é‚6Q ++×q[@þÂA¾¾1œ~ãx$Ëxް©·ü£låãrˏâ(ĆݎMÐÊsŠcÎc†;EK­Æ ‘@âØFitކ\9Ic‚Ñ—ƒI“µs‘µÐ Z†ÉÔd°œ¾˜¢’ùàɈÀDðŽ‚¡÷t“dM0sV¦ÓF¦7Òâa“¢•å¤l&·¥‘«1Ž¿¤ç¬Öô¢àDUÁ쌅Oä}Mbm\$ŠƒlILh9„¼žú-”Vu‘sÉGÞH\ÃPfh›k,jóxÐFn(éÀàx¼XP1Ý î¢Õ=ÐFí#»$þ§±ÿН C~ˆ&îßqk2NrÍÑ5#D/ Á´ö”†$$ÝÒü“~§ց…ñJó‘+ ÎÚÚÉ 4© |LösùÅr!öâùqú Ñ&ý#¾ç}➠ë&­ù*.w¹§5©"ÍßNå""†€,d²ûKúhÛèàtµÿWTTTTTTTTTTTTT¼ýQõÿŠŠŠŠŠŠŠŠŠŠŠŠŠŠ½=ÿÿÿºçk¯ –v;ÿЃO>ôÇ9ϟíöå1j÷‚ÈŸ§•³ý9Ňùð+eÃþêÇLã¯.JÙy“³TÎíÞ$Üg‹/ípöw•ç ç¹{GñŸ˜|ö°Ì¾´KbÙ¨|no~dNA’ºàcbÂ6¿eãpÍ8ÛôådH´&Õy“cfúù#ßj9.ÑgX)ñøìÞ§ÿ/ظpDüŠ›ý{–¿¼è„'/uˇ?Ì pٜö\`ñë‹_Ϝð¸Iáç?z÷׏˜è¡ÛYZâ€/Yzà¿çØTÑíìWbÔ¿µlÑÿÄëʚngs‰IÝð±£ÿÃøÿ#Ë9ÅTM…o}j^€u¥=Gì^ù¼ShώRÿg>yĞœïíÿx¬‡üùs>ü+ÿ¯/»oôÕÓÏ/°sÞøsµ±­_ÀçCrÝÎTæCŠE>sš¼G–1_sÿ…‡g.€/¾+Æ"ŸŒÏú§‘ÊZҧ“·œûD’U“ù®*íŽÛ_ZÎx¹ùÜÔNësìó™%>}8Æþê’×~å ç%~ŸÖÑÌÎÅ%y8þ~ã¼Þ9ÏΛsü½I}¶ð œÿÜ£›SYۖcÊ9ϪCNKçJ äŠe+ ++‡ÀpÜþ’óþÀmë~çª0&õý–"¿×f]ðÃrüö]%}8Vþâ2ß&&Ï;4ǵç¶,Ÿ&>}Kéûi“ÇݐãÌ3‡À1szeƒ9 ++f”þ Ç _UbÞÿXûD^[1ž¨¢¢¢¢¢¢b¯Ð}Œ¶ ÀfÎr( h§¶Ñ©¨²Ï^bG" v¼š‘ÙAA—°1œ\aWÈÌá² ‚±ç%ޞêFÌßè›<È06¶¾/ž™ôÐYÕ#ö¿‹æº†¨MªIÄW9瀠RK§ñl¦”'ÉÚG&k”Ž ++Âö˜Ä¨]0e»•1fG@0:åÂâÞ@§´•àIA Éxà'íÐ~RG0²ÚB!ĕÀÛC5Ë(荚îQ£z†M6ÊVÍÇÛßãHÀØ73ùTL5¥»ÌÆ{T¼ x ÝÑdèãѱ‹):`‘D>+ÐDˆ–l÷ÔZ©Þ5ɘH €qÞ0ƒ=)õ1ƤÆ`Ì:³Í3-i%È×á=å k ++†j'$Kyp‹å xel?Øüód³À܂†<µß£x'¨-ã±¢?B¬Ã`¾6:Z|Éd%LžÌIÐò pH4n7¡èýQ_oHú¡8²‰JÀîàÉBà-yœŽFs? &¶Á ++-4)%ŒIùFðF „+ÉI(ò–s$½ÄÁ‘–Rõì(d)"³…tœ÷§¥T@4¨¢åºFõ*ò½UÿÿŠŠŠŠŠŠŠŠŠŠŠŠŠŠ·?ªþ_QQQQQQQQQQQQQ±7 çÿÿÕ;Ü¢ÁҙÇúrÚ}ëÐä«®tòYÞU|ôOwg>•|ÎMΓ·­ç—|ÿé‹R€Ì9Êî‰eô+¿ø/N}&Å囜CïªRö‰›V?ÑúH'?ö¥-ƒ>ÒoUÄ8 Ñ0§—2˜ S~ú”sTŰë\¾Ö-„6ÂXËD«ÎÄ\0§–^K†Ôx© /ªý¿¢¢¢¢¢¢¢¢¢¢¢¢¢bo@Ïþÿê»¶^3XÚí|±ØÜï¾èw’ý¿1ÝÎcxþ–Žáí»cV{¾€nGÄzè'°àÞÏE6m´ïv®|hä³;èõeK#oŸl\·³µð¤Må󛈼kä‡[¼ç¬‡xtÝÎÚX?yÜÞù~“×]¢Ûy6ÞÏ?¿ÿjâô¢ Ý̧¶ŸÃ¾ùžíñº xîå³ÛçNå \1·Ôÿ£"¡ý]>»½~ÎIï‰×ƒP²Û¹gN¯ž_`·/Á¯í:?^ÎÏì\ëٌϪë>ô½Ä¿ØHžùÌìLÌnûð“Ëÿ(ñú £SÙ åù7gþAáBò±x0¶a#>9xUª“¤Ž±lÝìV~²!Õ)¥OßÛQÚ>ì ²¥ð®ýþGC*³¢?ŸBúÞL•Ë27áÆ"ŸU*焐.óŠÒ–S¯Y÷xâBlBêßò³·arÃm©LgNÃ¥eN½ãÑ;S™5ý¾'üò…ó7<™sPd>À³Ú²W瞟ž§œNíÜR¸û†9,²[ûü¯}-•Y•Ú¹¹|®ß•ÊçÉÌÎÊÂ?(>¿ú‘įšÔ÷ÍsÛ²4ñÄ¯¨DjËæ2/˜\šÆÓٜ×b]YÃ܋»fµc}û ¹NòÏIJ­ñ{ûà³éÆÕ“™{Ñ'Á[¦áW\;MnŽgµké*½ú¡\æ²Üç¶í|õ7Ny2½?TæLœ££szœPä¾zò/;—Ù4Öß(íüø¾ç/¿“|*Û^æÙp.;æ¶ï¦a¤K§.\÷h⁔y­¬,r8cr͂TքTçæø=òcN˜õϧ2“çîeeÌ&&w]›ø#•Iun-ü˜ÃyI..óå”K×?’ʼLãyu©sÕäË\£óº-ýûÉ߬úQö›ÒIF¯Å²Q¹Nð~)9RV>}ü±,´|£'9,›¼çºÄç*2?æe³{e oHeR¥qÙ9«W¶þ¯RYÈï³ëË;ù½3Oڙø*2õGº¢¢bÓðy“»«i¬RjF£ÌJkð_çôÃæ|vVz¼Îeª!š²BXƒ÷4~âðcí…®Ã7$ߊ¶7gv *X¥ÔR‰Ì ¦"Ç+ó…ç,rÎù–û3!ɍ—¥ÑV4~Š.ÞãYåL#¸GòJ7;nt?ñŽ´zo´AŸ7¦¸G’Íې±®qFI’â¡ úE¶pöÆ27Î+tO ËøMAœ"¡³hðV„æøà5ž< 'Ÿ‚ÄFE'ÎêÈ·æHù'¼–i/yÑIˆ†ÍœÒÁG~7üpFÞ?gș†C"Á¨àUäfŠ,h"ŒáŽ›ÂÑ>Èc^dœ¸Û“=¿9Ü 4»TTÞh¿ÖkÊÜ¡>«u äh) IžÑD26à ‰·ZÄaBs”äˆÿ$‡´5V±ÍÁx? C¶ÜGy² ++ë$iÜR¿ YÙɉ}ÜÌǶ+2´a~ 5?-ÉkHú>ÙrâaHŽ<çó¼góÅt՘(Ö8G®?%Û1Åm£m­ŒÞ:ÜõyN`õB¢ä‚a5ÎCKÎê± i21K6(À ++ЬˆL'ŒCÅ(ެ‰>asLÑïÆl¤HЇ­æ˜;üӑ³S}T VˆOFo1¬MhùÇñʆÃ;àçp&>CGMËqҒ¸/e°oN)‰bÊC |÷ â^5®/Ã7š6enàåÃÎbB¾€bèg‡ BUûEEEEEEEEEEEEEÅށžýÿKóç½9_û|ê;µ!}Yo,e¥³ê}Ã|í¦:Ö:óÃÚ½ÄÕûu}æk7Ôû†sn®ën8oßúôÌKp¬Ø&7å2UÖÒC3ð§W×¹}ð«¿ÿ£RVÖāsú÷MåO—Ôü¿÷ôÍü©(ÜqÖgppNÝöê¾% Uí°¡¡¡¡¡a·!åNË¹î’ø` Ÿøt¼Ÿ ÊhEZ]kòÏÊQ· ÊC&¿vç},¼`€¯Æ’t§LC#‰ ++œ1&¤ô`䤵p rŠ*F™Ž5Cƛ¬9ÚfƒŽ¨›<­3›I$cµ`Æ9|%À.‹¹îÁþ.fD‰3<먤1R“ä5J8 ++7¼Ã)oÑqͬd6Ó`¨#~ÑGÒí¨Öb7†“¿*ü¢Œ“3ä¬9܋£Ó褐1b—IE³jåóÏGtD0 s⥴|Ü¯£ú#(j8$ıádû<¾`È1”AYOÍçÊà_Œ¥‚:ƒ²”b8Òáè&¿ä½cý@Óñ¶ØÏ±­‘I©ŸÈuG5…èøâˆ­]÷3öð®ê&ë(ÐZ² :æ>øö£Ó20ß` Aï™QPcN<¥Ì4(f˜é!I_GÆ jÏõ˜5 ˜“ùmÒËX[EŸ`ª.¸Ò0©6„=z‡‘3Q”Dù‹àÝq%"Xj2ð¹)í¤PXh´Ç¯"5Äà"œÆ[°Ü˜ÄÑ1;':XŒne6BŠM´ª\|¤þS¥¤|L‰·E朕&½»XƒŒÈO/Sì´=†™™y2V½ªˆ"µ ˨ËEhÐ Íô‘è˜ Lúh§ƒÙ1‘I15%FLèh} üO¥`@:Œ˜å›eCá’ųETù°—X2 ô×+¼B*Ãϰ\ vü’#MxëÿßÐÐÐÐÐÐÐÐÐÐÐÐа7 ÏÿŸ³ò‹§–öÆW׸îÿóÅ33Ïl\oÀßÿ˜ïÍI|°²äíÅlž'?yìÎ>˜ùI{ã'VÞyɉ¿žõR©Þø#5†}²^àùýºçOöÈqíŒ]¿þ•_y8<Ÿ9ӏáX7±à?ÓùÈv¾Q¹âÉ>Íîê]û§9þß*úlJÿ?ä+8¼~r❝Qxβĭ®cûxÈÿ¤óŽÏ1µ¿Gïüãg²ï€½ñ^}þdGgwã0Ùàõ:'LòG`0Íì¢_ÿÖ z„̏Žÿß^=†ãñ·Õøñgî8ÿµ;¯mæžÚ¯«ïs›—çúèP™Êz•—^;ñ¡u¹¬ËÛðH]++¿|~Ö?tqćÄñ_{X.S.kNIsqï{j×¢\fJ<þ·úšŠ;ÎɱìFê|ßÖªcøÛ¹+rß­r™“¿)éFk#n®}ÿ“E+sì¼u¥;Ҙñæµ/®Sʊ>ààý»qyâçäqñÆæyØZߟ5}[Ž«W1?óÄZö©'¯ø@Ž7ŋ ¤uò—8>º}Á5éý±x ++ÌKõ­£®àw‹nÂÍÁ®:+&ޗµFç±ÞRÇìãë:MEynçÍîúðÞ#/œ(±ì:?óÉÙýg.YT´eþö¯¾_}pe¾ÏXŸŸysõSxâ‹K_Ëe¾¬¥y5&}ùƒËÊ}][¯>Ë&ȱìV©Ü÷]u>¾íËÇç²àò˜Íªž$ùCΚ!~kêßhÆ–Ú÷¥·_ŸË¢Ïëì^׿-ï]šµ-±‹ãß2 ï˜¿ãÝݘ=ø[Ÿ™ÈŸ…:é;v?wE]_P²ðpScck¥—ãðY9)Ɨ†eˆøÓ¢ã\q«dhuN«è„óN¥$Ûª ++NGɨި½g &ý9œö"’èq¸Ó'2¼ŒÌ5ÆçŒQ"à†!ÕK‡|E²Êˆ'à#Nó#~lJìùÿ;‡,lˆ#Œ“"‹,GfÐ9–^1–˜ªHÖE¦¶Ø=`…ÑŠ¨œ×ó7 GçiMꑍï86¿¹Á3¤UÈHæKÓ†Üú†*ް%RX¼÷¬½²ÎRï5ûïÉLØF£ØßI2´ÁÓa[Ė£ñƒð±IŌi‰ÖZ¿£X$hyA©bi#Æ.­Ÿˆ.’åÅØâ~ç8™L…'K‡aÆÝ Ê8+ •GSéIÆá2†j£‰$)+§T±ó¤™±±“3‡¿w6Řkc3w¯Fq±øS›8ðQñúґ$86£Ï8ÉÆºÞCŽž66Z ࿊Æ´)PÞ&òÕ2:ce±KÃÄxƽ;j]#¶ [L†²“LuҒ¾ô …v¤†=ÿ:rþŒßÓ8ÒÒcÃr¬2ﻱ㻉ÅØoם›&þžL3FÌSàDwΐ2Ç&o ––äºI1òX2†-&­ ++.pÃ%é¨t ó6 è8ºÌë=ÙnË-[èû! ¡Þ¡¯äô}©Ïòm7ÅÒw>€o‚$ao¯i1AÞ'¼&ž´åÀ¤qùaú …’ï.:KC|âÅÁÌñu¦®πz”„ô,Kõº‚i¥Ú³°© Å½ä‡ւíIàxáÕI¯€×Yˆ~|¾‘aOòàˆÔ/p⥉ülM_Ø|€qŠõ`º÷²̵Cs­+ø„’' þHàÝâG+fÎcø<ÿohhhhhhhhhhhhhØÐçÿ¿tÂΧ–öŠÿ5 «C/™ÿFŽ—ºW¼¶‡ýÿ7Wnù؝ž—¸­H>_$Îk3ŽyÿñØ'~^Ðÿÿæéüj,ódþKõ„¿èì£2oo5®•÷ü«ë8 {íß4À}¯¹¥øÔËÌR½áÿðåO~[t\må‡yñGkþƒKªD.ë8úè×÷Ú~¹,^5ëFó۟­mYõÊs_Ê\t(<õM}ÿ‚!÷»j}Ãïë+ÿûÖ­eWh“ùÑìIN¿ò§ÿaõ³¹ÌÚAπÑ1üïIõ]ÃòÛ/|>sâpí;ê< sÊÎÀ)›ÏõKŽÌ¼±îúW=ׇ9åfðUß±_¿l~~¦×ºðÍõý曷Uïûgï<ç'¥¬Ìæ:ÖÃ|ój.a¾ùøª]Xÿà○îÆç><\µ4þ[ê}$Oz±ø$ßÿ†††††††=zQq×ÒѓœæNr ºð÷yá=Œ_ÒâtÞæSýʧp¶»%¶}:ž¿ä/à -0Bx¦^3ªÕi¥=»´ oï1Žxn>X%LàT0 -˜,£Aa‡`»òh zÊTŽÂÚï“H–[?4†íO (]ømÀ{'¨t©×$à1C†"#n”™vëhº`}Ê­àœc®‹ÈEâ“Sÿ´œq>oÑ|ø@I¹$$*„ˆ›Ñe܊ÕAՀ†ù(Àè´˜?©é£0‘ZFÛãå©>Ì»à™»›l|«ó.påJ™SLŠ€¥iÇ[“?}tù¼ÏÏè”.Î|´×üK5æ}˜Ã~²ÆÊ¿yD‰•ºð÷KÒ3é°hþÇ^-¹È‹·ýóõ™Ã~ò9/úIlË+Ëþ¦ðԅ÷ß5ßlfàj7ø»oÜ/ó±Á›¶PFyµàGQµ.%·E§) "åӝ‚Þ Bw> Ó咰.¦,ócc?÷ׂf”à‹`ÒcĤ–QÂ2逶ÌaAۃÀ”^â¹tû^e½N^L߀¯|‚‘dБt’1Þ´A¦äÆf`b |d‚cúm$W\‚ë4p •%Ö¦ó-þ¿¡¡¡¡¡¡¡¡¡¡¡¡¡aïAŸÿæ²Ï_>µ´7þzÃŸìÿHåÅ?êû²Ÿ¿2¾7~VŠQŽÏ?°z²ïóãƒR¼}ˆÂο©ÆÀŸÿ¬¾#ÇÕËâ½½ºÆ¤¿u׊'Ї}áìO¬Ï{`ÊÇr»Tɑޏ?sýÅ/–²˜ËNIe£ãã·Õ>‰ KÏ^ºÄ¤:µ…Ô<¿æÖRVüô®mÑG—û¼P9Æÿ Ê篙Xœcç½+y쳏û{p¬úñ‘‹Š–¡xØo¬¾÷ݹ,÷=H7èß?Z˰0•Ö2|!•ãJyAŽçÿØJew¥úè pî«Ç-*e¥}oÿOL¬ûíRær}OÖv~vΪ->!—^cà¯ú‹sÿ=ÇøwõíªžùÃ~óûxدœ[Êb³×ëšxç„Õ¹>mJß·Öù»{ìÂ'rYǟ}øGk5f¥²Ñ~[j†=æU­Ë°OýuÕãý¯CñE°Öçþå8þµ8®¸eUö0pRdmÈÃé>z&üìÊeÞ Æøgo€ÞY|Š—Äñõ½;kî™/o™×ÒÕÕOÿ´‰K¯Ïz“˜rH44444444Lò¦†9lŒÿ:çDŠÏ7ä.ñ.S ++Ugð ùȜ^‡h¥Ö—I wÚbáéÁÒ_Þ±§õŒ7§•V$j@OgzC+Ö¨¶~.…§[ÚXÆ5›ˆÑjÞ{)­ÏøþÀ4– ++²o‚×b §Çžä›?2¿¼Ãcsnz&Jptœ—Fßý 1ÁêèyMJÎñ âˆ%#È;Þ{7ñÛtAʋ€¶1߁•)„ÃÒCžR‰Ð _¨”H;pº.HtÕFŽ¶Õ˜' §µB0ˆ*ñö)W† Êû]À¨< U/€ùìr¨(gÒ}J!ŒÖåîÓ¿Gb™»=ÐSc: 4&0Fö¡ñÿ {øÿüÕ§¦–î[|èI ^sÄÚӓ¾4c½’£›|㿜¶à§¨í xÓOöÿ¿?ñšô{?ôíÓ']€T8]õBŸ¬Ø\ý¾¹fAò°ÎúÎG`XG°±¶ó¼‰¾–µÊfnô®ÊÏ/»çœ§ŠŽ p÷jýW±6k¤ ¹ì[•o½tbvæîeçÁ¿¹òןۼ {÷oKícþþšaX°½Îñ°`cõÒ_þÂGn,¾þ"·å‘š+`˜ólÎÿ¡Ú÷]ïZóo¹,N|뜮¾aïþ-uM,›ØþµÂ³ßûM\úGn)9ßEæõ3—¾ Ç?YœÇ%ØR6–î»ÇéÏ=pw.óEw’ó܈㴭÷}3ó좔­¯Þýßþò©/ÏWúžÊFûóï¨ïÁŸï»¤äŠ·¡ùA4444444ì.Ž3òùØV)Š5¬2—¨"Ó´fwÖæk‚çÖyEŒ!f‘·ÞØ bÄîËbO¤´ÑɅžžô†§<9Q#¥ŽäŽ“Ï¹4ÖË»¼õ¨Õh<5ä˜îÄïŽâÂGåBPB1¿ªWš~ùUK¦`Øž©è„ËT9íEâÏ] g»Ç-ê•ÚEÒøÆç0]Ž-#MUˆ‘ÁâhªavjôtzŠétÛA*”¦HÂ8¡BÇå/©cµÑ`;é)JpÑÚ(ƒ£R"²}Ê)OÒ"Ñ t ÆBؔXûäÁSÒ§ŽÓ¶¬] §NîómÇ mi¡Ïtè‡Æ÷…G´bšzô¤HÛsè4Uh‹ú1`¬P#æERñŠaäÐG–WG´‰îܨc1ßEÿ`lÊ_¯Dš‡ïA›n~ g¯˜-C’®ÁÀx‹‚ô3.­†H¹×Å?böÈÓó Ža¢´Vk&a ¥>®W\zEXÆrP,'OŒÁrwdíÙè´¦Ñwƒ‹E ÀÁY¦¡À*ÜÑN´QYú€·‚‰+„ÁûƒqÖ£dEA …/¼‘‹Á[ׯPè$–\в êseDê'<'Épˆ±Fmãÿöôùÿ+OzxÇÔÒÞø²Ä-߆cî-8¥Äç›Þx¨œå¼ZpvæªÉóoOç/}ÌÛǼ]âÁqýuõúc¾7gkæiEè•Øëa]À–zýÂÜ'ÅH» ðœÌŸÈz¿ûþGÿ/#®ŸUãÂ/üðû“. ++-{9ïÚõÒªt>úÐqûä¢ï½§ÄÐ ç2/þɪm8÷«_Èü½*ñàYgÀú¯:®Äåk#r|ýþ•ã}óÝ«ò}ڛÌß/©|úE¯þÚ·3ïï ++×~szæhoõ•ûö¸¡öaØàëUŸðÖ­%þœiIÇúyFóþëü™YËr¹4Å? Wùíӟ:sV™Û’ áœ4™¿?õÚÌû‡Ó~H}æŸÝý‰üL×é!¾^ó9üò!«sì}TE»pU³¿p^<bÚÏͼ¸ ++E/Pç¯å´ohhhhhhhF◣Lé"8²¯ZõùFK˜¤:‰_“ý·×j£H‘ÚÁ˒;>ñÙ9i»±¡x¢Kïô¬£Ãþ“bWQ¼¼Hü©@­2_œ±*Do¤5]Î÷.º"=ON>FÑ;Ùù¶O“çÛké£Õôhï|á§Ë•¾Ûxt'œ`¾4\†Iô¶VBXeÐ4åØ:’ÔZ ôÃN›!âÌ/Ñ'•²Ø‹è­C¹p¸6¦H{Šb €—­öô ÷ړ³Oì¶³¨•ð2eI'[í2Œ­Ot5ihlÂ¥ ¨fÏÇÆ±:]—vD†Ù VíèJ "G{ü†Öbl\ Ù‰rŠ-ÐhoŠžF¸Äҁ€|8ú‹™´)8º 0-ё&÷Qc’ËÜúD`$0ÍX~J›ˆ¦9ÆÂ[ú)h’ô_‹øti{åHð³µVQî,öP *ÇØ¤åÃÞLÊ]Ðù=àk±,<¾ßÐ9AŸòà“çÍàxڊnS5ã¼´¢pÔ@DŒ|²À{‚—#­p4–?†ªñÿ {úüïöåÿ<µtßñí5¾zݼ߹˜\ªj¬7¾8ñ½üÏ¡—Ì#sÖR÷Šû¹8Žztã$îÕXÛ+qÚô5׿ùtÞ Ù_Yyã…;MŠk7Và9Ô¼s¿í³ù¼ ½ñ³ªßüþ'ÿê÷“^@PG°:ÿ ++ޝŸütÒ åzã¢úÚÏçÐå©ýžz„eõ9ûœ÷ßM磽ñY©^rǏ¼:÷Íì/àÄìñÓSûé¿åïÏúQáïmæ°ß¨ýpހPýã¯xßù/gŽ^ÿÿ‹8ó%9Æ^ې¹öy3øÇÕøûå«oË|ºˆù¾ƒSÙèøô-1ï›+\{НjhhhhhhhhhhècÀ›_ycO'°À„ì霰JEmKL9æ˜4 JËÁXma] žò†Ñã;‚¦©ýꙩqˆÆ’'’¦Þ3Gýÿ±wí1~×Ù¿†Ê?㥅 šlñ0`æýJ ´ˆÁ㦵)¬1PªºµQ@ŠC(ЖV–‚$PI‰¡@ãüad¤Pń—!Hq6Lµ+h1¥ß™3wv½¿Ýý«®ŸO\¼{çÞ¹3gfîc¿s¾“,ÎóV;Ÿ­NÆFŠB'¢Þç(„>hbÑS$ï “s"·€h‰7¶Ú8³.U‰(“¨`ÄOÁؤPHcÀÿõÇ.6>*e`³ÑÎ\u,ZHy s¤« qG²ûÖMßSäLM^ ¤aàayë76GºNFUž÷¬H›ßz’*h~)Ÿ »ÑÊHÉLçBI0°‘\Ž1Îä׀¬ß qÍd(³ZŠ`MÂþD铁¶hƒ¦VP/9¹¸¨5YaÂaèœt²ägRÿÉ«€Òå¡k*F2 ¦CԦעÖ@Îä•S4H×ÁøØåDþ_ @ ‚}#üÿÒ]›ÿ{li¿w…¥Ãó¿Wb¬‰ç?âÉ».`ÍyÒ翵ñö{Æùhðßóä§ ßîŒG=œÓ|ç¿¢ü]bPàöæw0:/@>¾þÿÍëÔÿßXÚ{¶…s–=ÇÿªÆ´ßÛÎû֜ Âe6òyG7}‚/-¼5”f^ÿ ¦EpØÜ%¯°€¶|ûPÅW¶æµ¬Æ­_ßøù5ÃߘÃe&p,üK-OÁ’xûX_ÛyZ£A݁[š¯ÀÐð¼ ]¾ŽËWå¼ñ5 .jãõOG,g›ySõꯞޕ ú;°ÿąØÞ}à’·¸,:îß®–Û^ýՅÿÆeÙpÿ†šȗ?[u¢U܇kËõþÛ9'­æ¾ÓFù¼R6¾‰MáܯœW5b£Me~-ÄvÒ1 ÉZ¶ê¬,獯s°jTž‚ãbgù¼k'ÉoÀyNƶ୥ÿPÊ(Þlʞy&–oâ:«6c½ ²ËUÿ<ô,—Åš‹`QómY¾ãÀOÕÜU;a]Ë%ñጅÕ$՜ ·ÎìÖÊ`΄kKÙøZ «¦wí\6ü¯ì?B1Ql³Y][Î}ýÊ>—uúǵ󟺁}R´b»ÝÖÿâgþ—9ËmY0sä¼ïÞÌe9rÿ6•²ñu#noklëÁ‹wp™õU§¢­•G¿ù?Û3GÃ)­gÏ­zº¶e¨Ýwó7œÑô&Ö?zÊëµ,òygŽÔy×tÖ¢H‘Û²vVgëón:ãRf¢@ðIÄ^еÞ[yÉÇòºŸO'vžb§)Ê܍Š¥o±½5¹ñBÒ}!dñ†A¡Èª$«÷”æ›x[C9½Ñ×@9íC°Í­uÔ¸–‰Þ’’:±ÌÙK*êšrŽœƒÎ¦—'ÕÂ:SÐwôÄ&zŠŽ×Éx ++H”c]¥šO>»†Èy’ ¨ëÓÔÚ¦i†^(jÑÍ~LtòŠD!½@V C‚XuÎ`ÞyÝî'؏oZ´ÈlÑ&À¤…è6Õb#ÁqX´VCÆmÃHûEÿ_ @ ‚}#üÿq›v.[:µ÷-‡úžñÿ[¯5çU¿ËܸñýʅñþϬd½úœû=×øòcß|sdû™×~ÛÑïly·ðÿ*†~ováâùÿç»æË'¼Sökú½³ç>´ù7/ñÿÚ¢þ;G:׊ËþHÇ׎ÿõŸò#ŽóWhÿ¦Ö¯y;UÑ ÈAÅi½Eã{á{+Þf¾ßzæ ¯h}[ùԕÇ0ÿ®jÿ͇`Ðà®QÜüqw0ÿn*—|kéÿøz+§wm¹æ¤•o27*G»ßôn¼Ö¼¶æ€ZVs\_Úù l—¼ùõ{˜ï¸Ï¡òw ñ9ö[O9¨a0â[±ìÈÅÜ¿l4ó¾[Ëyãsì³ËyCؖoûBåØ]儙ï?Áim~ òï'6­…µ_½àM.óŠm}mk璛.{¾æ'¨ýÛÒÊ>üÜÐsÌÛ»êCp[Óaøæ£+™Gw>òyªic,ÚvüïT_—ê[±¾Í£¥Ã³˜+§?^ò8Œ*»ô(.³Õf›šÿ̒çÔ\íƶyû¥-ãë>Œæ ÇòÚë¯ýSÏf~Ú''7F@ üá#Ìw'Kñ·®ðÜ{Ã?aÜÜۓiÚDbˆ)ÊÛ£W~~˳ž‰vD‚G;*79ó•0Wù7P<;ùÀ*ÑæÄ±òÚ: ^i`ôPyÔD´1•ëF…ï5Nµh Ëó›Q‰Ñ8Î8‡¡V8 ++?“,<1³¤ÿœO¦Ð֞âҍŽ”‘^©œuIU@ß"–}âž1Òè3FÊ9\>atØö<‚¨)Á¸ÿ'Éy²©³ÉÎFÃxía¼)ÓdÄ´L*3õš<š0VÄEÃP˜Ë¸‘êä3‘]ñÿp(™ /=ç0Љó3P:*ÄuÊ tãñÊÜ|ØgƒX}ՕgôŒèü@)P)¦f-Búû"%3AŒ@B›r)o.„a¢A1˜(°f?yÄ`e¢Õ‰¹|”AÓ0>–\&· EŠ>Á>W˜&” {Š OI„ÆS# feÀ0Õ$qõSÆÄ¯ö‘ iHY"5¯‹ýßK>A´ŽQ£2Å?àv†ö—SSÍ'ñ±ÑMþ_ @ ‚}#üÿ 'õÿfli¿wï:ü7¾qŸßÖb™çí¼ð…«GâáÕbrO^1gá՝‰ßIÜëû÷.ºÆæWîu[»ö`ŒýÒQ±òoOg^=U>~û$±ëgO¢ÕÿÞ$|õõí¼AŽxÑ$ñÛW·~_ýПwñÔÕo 7Oýê(­þ3ªqъ¯·¥ÙeÑË º¸èÌý{rÖÈy{jüw1ýԖߞöÅmÌõFëe@ ‚ &й÷^ûê#cöF%¯È™(N©¾ƒÚ{Í? j{4 ~ò_Ñ1¦Ñ: ä‹btêrt>{Ã÷h”öHÑ!Ё”Li®ðÿ@ @ ìáÿ×_uËoŒ-íW-m⚏Þ|ìùÌ¥ëØïmi|øu§º™µ«öolºã?>óØÿ)ûmðýÞK³ºý«ÎŸÇqûÞâø]e?9»ë÷K\vp&ô{»GùÜR8üä(¿sûÏ?o÷öˊAŽ©ËmOÜöÞøÇ¯±¯üüº>¨iþÀ„¼@ @ >(\7©Bƒwʤàrª9H<>#¥ðP:{|¹ZíÉO:XRé }§Xû¤µ¶†¤ÐŒIçy«ÏV“/EîSR Ÿc0ß­šô ++R¤L&çd9XSn«ñQIú&¸ttV%M.2(ÚäIsA˜ä³*)ꪗQüõ-…D œ%±ª¯¼+õå´M©úXqlqÀõ9ƒðÿ@ @ ìáÿÿö‡»ÍØÒ©½-ÖüÆÙî¬ÊóOé×8sâÔç0ÿƒš#Ýõ{SÆÕ˜Ö[[ö¯Ã¶ì»ç<Çü¼ÑÌÏ?Ürœæ~¿·iž_¼}Ö×8Ÿ@0#¿½Åº/ÞþmŽ»ïò|/˜$¯ø¶IbäW5?‚±y¾@ @ðÿâµKô;sÜ:XomôŠr\P ÅåkÙהbÊ1ðNë`¼¢D 9W~}oÄÜkÊHQTùCT•³Çq>êœcÕ(98È5€K ÍÎÄrƒŠ$ `’q‹IgÊR<¹”D(9àº9’Â.|Fuв ©V¯`ˆ€]ÞErd ÿg¨"ô8åD)-„ÿ@ à“ùþ@ `_Àˆÿÿº×¿nléÔÞ3ä ++?Žÿÿ®æÿ¿fíüw؟ßÚ~ï‰æ??çKGýûëçÐï͝Þö_yÜìW¯u¿çÊ~òÅ?aç#§VûÜïÍh:Ç|øÙe´?FŠ/`?Š8þß/º€V›~oiiÏblóÞ¿û‹EÐx;­—èÐ â)eS±ýË÷sY¡”m/ý¾ÛÂ9Ëø<­4Çlk±ƒy žÙÕù—,ã:IÙ¡”8½;ïâg^~”Ë‚çX†ûwýý£×¯žÃù •âœ~•vRLÅåoÅeÁp|ÄA3;û æA<¥• ÏÛPÊÎ,eq0¶—ï?ç . žëJþËdg¼¶âÕãƒ+Á|!e0b–Ì[ªÇhfOæÕè?NÇ,C¿ùk'‹i…Vaµf,%£GƜ’»a^æêCnt6嗣-‘W¸Eç5:•r¤©…å„ÞÓ½ÂFŒAÄðéD÷ ++Z¯ ++Gi§ƒEÞÚIÑ-`þ'úœÀmæ‚Ñ1S ++ÃZdàð=•­µä—nÈ˜× ¦v¸<Ý(&òs7JizÝqÔ@ë¨s8 ÿǨÂӑVyXëÁãÎËÁgéÔQÖ8‹uãT\ßeÎÒ=%£„òã¡ZX;µÜw˜hMo¼˜åè`4ÑI$ëØ;G{hNb¨„â°J±.°Ll ‰06¸s‹éËkIQÿ3Ž¡{¦åØîrÁ’hyöb¹ï¢Þœ•ç{‘ÅDrËMã÷ʲžuؖM‹êpeFÂÆ0¼rœºË §pŸÆ]¹,rº…bw†‰póÅ·-&:ºG÷c ,–ªÂ4ó0% ++ ëúÁRͦ;!ê>ëÑyú&Ò¤IƒÕ…o ©âî>³â6äù;†ò$jzjØà'ÊHSPø@ @ öŒðÿ7ìX²}léÔÞí…×äÿ×5ŽxO>ÿ±vü±oæãUÈýÞ-…C#~{þ®/–<њ~Ÿxè#N=èÃÂÛ+­¦õ65NñòáÅü»uÌ ÞU®Müßas—¼Âœ·¶Ìã±^á9ØV>»û$.sŽy¼;Ûµ9ïÛJD^üê껙Ÿ¶¹ò¾¥lºérÐÏèú°zø[9èÊ?SÊÆç§Okš‹+_|h—¥ê—°´]ïß:ö6æ§­eîóáÆ%/;r1ۅHR6T8Ó¿Ævö³_Ú¯ê5V†EÍ×bùŽ?U9áZçúæC°xø¬;˜‡5ªòÓ³º9°õàÅÌk玟~`FזAŽvmãß×?zÊëÕç#²]>ßòGþ‰>ù5æa‹¬†@ `À\vá.;ž>{¯•ÓŽœ ªïÂÇÑÏd<“hÉ¡ÇÚêPúü‘õ3RäyÑ#SåÓ]*¹ôŠ?¹H£¦óÁ‡‚&OŒ›N Öwë!? O(´Í’q&åʝêæ>u<±î¦ÜôKÐcýŸŒ¢9€ÚØs@ëBÞkô…ÒûYŒ³!ÿt+“5éKÔz¯ÈåɐŸA ' ++².’:¿ ++Ø3Jrùd ;m¿™¤#yI`J•­2oM gL Gž.ä}bMäŸÉՊ̪°#ô"+Ì܄)C¿iK#`ÈA“cqÌaš¦ ­Ç¼$? íðoö¤Hˆ`1—Fó5{PÄbÈe܄ÿ@ à“ùþ@ `_Àˆÿÿ{Ÿ¾ùÏǖNëmiþØW¹æ5öÃ׉ýâw5®o͹ð'ÕG?rÙöVöȝ˷°¯½©>ó¿*e¬Ñ5wC°ìÿ½{Tٞú]@ @ %~By¥u6Ö*å]P&ÕýÁ†.VÂxEñ{|ÿÏ{7Ü7¶¾©½¹èÿÏ.1Ü`;âÉ».¨qï±_ãïõÿŸ(õÌÆö•S>ó£×­ú½+Z,ÿu§º¹Özn›ÞÕ?ïÉ»Î-û÷ýªÏN8~矽À:FMë=6¢ p÷ò§YË_ÕöÝ­+~j¿Çeºjº¯kõ­^}kòÍe×·óV>uå1U“?±¦ûÖ֟÷?w΋U“ßñyk÷ïlð_3/ûw.‹Uƒ`{Ó5˜H“ÿkض>¸àg{êœÑêÔäO­ïƒšü/5½€5¯­9€ËBfµ“hléû€Á­lõ–ó¿Ãcl2·óö֖A ‚Ý¥- ±tÌÂ_²­ùw½€!lË·}¡ê¸ª!QéûÚúežŒ¯­?»Ô9¾æku®ýêo²î~wÞªº±=wãê§j™æ¶¬oý»`îÐË¥ÌêZççgv¶^²í†«ŽBà¿k-mólÙðÐwX[_eîÃP± ­Æ«î¸ìm.ÓUCâ½éÝßßu÷ו2Òm8÷õ+û\–êy³Û-~öà°nƒ«c[ÐòW jë߸g³3_zèÛü÷·.‡ÃږÃã‡7œ¾½ê6ÔyvQÓÔÏg½ÑÏ‚õû%k‰;¥œW>ÒuŠ©ÓH£™>©~¼¢0Ü`­9–âšñŠU룦€íÿeïêcþ¬Ês‹Îß -²Íu ++µ ++´XÏ÷‡ ++«¤LFQ¾JiGç˜m)c!¸%dšI&A¶C\L &J·°@¶l a£sdÀdPBçà…j\ÁÉĹëºÏù=ïËû¾m²?H˜½¯äiésžç|Üçœç÷<Ü÷}]™Äդ䎤q¯|¯¡L3Õá  Æ‚_“™Ój­39¸\«Ï>;¼E¦œC¦A-ònf#3}Ѽ‘0}Úá}Æz^]mÂï{SéÛ+Sn{.ù«Æÿm™~Ž|ú¦T’©›¢÷=GšDõÙ'æIKf{GR}˜NIÙ_x–IÚ5Æ@½È£RÇätÇwv›Üì>rÈÁ–EÔ}xÍå(Kþ7SÛ-†S ++åð§£¥`™H&z´ џŒI'/‰©À ,“Âa82ÖgÒÂ'¦”gz™§²¬ÁP¢('¤l&yì pLxÚ#,á Z.Ì=¾ƒD`’ç>O'¤igÌÎí·X ¸/a9Ç4ᢷ՗Y9îûã»§69ÞödÀh`Éuπç$gXk?ùùè8ÙåCàLN¸°ªr„µøîZ —`0œ#̈‹äÀN@½T È܅žk²’˜ŸkVÅjÚòno2Öd–o ++á¨\K³ —´ ++ʸa-óòїb8 0 v¥Ö ++VVÄlcfñ‚OÎ3ìҀ"k°Àø€ñ0–qªXèX ¢É€ÿ´üTž/¯äÈGW<|Zà[û O‚ŒÅb"7¯‡°—°Å ++»1¸Øxvä¶Ä„ñ‘‡î›&´íO#Æ@;xz%ìñÆiPD…€ôf–Ò Û<¥öíŽ5Z±[03x4aÉ[ ++A aŽk{Ýr·S½#ñ¡ ++›Yj*`<è#žQEô9"¶ v!LMõ:îX‹Â ‰ì Nãÿ ++…B¡P( ++…B¡8 ßÿ ++…B¡P( ++…B¡P ˜‰ÿÿÓ³~æØ¹¥ã®ÇƸåÕû._Ëñwq^ùq-*`f…íð‡C‡)ËVƍädô9àuÑáߎÑ8W,³4½VóM`àÌ´ãœØ'—œ]Dó©Z0`qsd+bif\0ÝSä¬Ûø„®šl|6 ®š£ƒ—kŠm`zEÎù”ì}ÈX2³4LPðYQÑa¦š&,x|Lø€Ù†½² ¹¢m܈ÉöÌ€q’$¬xƒÞWñù0f_œ3N¯®¶æÜר«Tæ‹!àJ¬"tŸaÿÌ €ñ«‡ ·) öÀ*c.¸Ž¶ö8ƒ5{°JÁ´l†Œ~aQ$Ç,ð©†zqŽy ++Ž !d¬Ÿê­1 îçBdNþi˜‰b²G³øe>@À?±mЧd'y ëSò æ:Ut (1MJpMŒÍÇj¡#÷CàÊMÂ6³È݅}ˆÕàÐzÈtì>¦U”W/WAýÿ ++…B¡P( ++…B¡P ˜ñÿßúÅOÍ-öNñï?DZü«NîÜyaŸßÚáúå_ÿô¿ñ|ˆ¡ŒG×Kýô3_;½êE9_CÎ’zæÇ¬9}ù;¿·ü%ž/5™  O¼xõ>‰ .OŽ['àgåúÍ7ܱ®ñé™Üyñ.â~ó¡Çïj1)¶²÷Jß—à¯_ÛÊjih÷,ôãw–m{ºÇ”æSß+}YƒãŠ÷t?½¦ùÔK{ô©_úg:Ï ku–Yí=wh++=~a×ôÂЗù\‚[½‡+OØôÝÎØÇðüÀa·uú¾;&± í¾k›ùw®°Å!×â ®’~’OïãGõñeß9ì’™:×ú¿`:gž”}ÇOغ§•å3pëÀ}·ùÙǯnñ ¥ÇK¬›á·{ðüU-FÁÚÙºßKGžût_ècرtRçyß{Ï K°áj‰_X˜Kp÷`ëß[ºùá^VZ\Gb76~ûÜc"L‹mh1À±ï–‹žée¡Õi»\8}ʧ[لÛoía“1é¶Æ%h;oã†Ã&ó0Ÿƒð™¿ œÛ§×~ª•EÓÆ°FöÃ-´õã÷­,÷µ»ij¦½/M¸ sßÝà'¼l°Ùõw­ÝÓËrë˚©I?í‘o¾«qš¾§·1B¿kOüÎ[Úãd®_:y*¯¡Bqð û} ÿWď¬L9ډkŽßõ@|k6ùˆGC§W›ó-™dÈÇ\XÄ I’®H÷*¢÷¿$x¸›’q_ ++ΏË,ý~O7Òt™šñJI¸¶Š÷)düâÕBÒ;KooÆï_È>Ó·Êתœ0>œ©¼ÌÅXðÃêsr|zÂ/'„k•î«ä;Y Y#¿ø‘‚IÑFóÔ¼!_ˆ5ål2jAïSE¹A{1åBsñzrgÁ¤tʺa.¼æ­jq½¬µó¡¡±è{›ŒT˜¤Žó…Ž74e+ÌÙ{üPü’›ÊéJôw“)/r o}ÍÙîKÍøU/³ÐÞ÷Äߊ4Ø3aú`UoLíþ¬Ÿ¼ÌWä ÄU×îÃ{š'#œu¡”E òºŠ^„@ï>n/Ý$¬rBÇj)ô-ºÈ%àj¥›ÚÓOŒe‰ÑV¬§x*Ó赯ô)†ýðÅÁxÁU:ù²h(ü®z/NPŠ®ÏH:@ôÄ&®Nœ…‘-¹«˜Û$ €Îpi¯ç˜Y²!’'0Ò½LB@þ"R—a¡ˆû# CÚ`*Z¬ô c”À}@ÂÀ”¸Yꎽ¯¨f§Ö¬²K`÷"·Å’™.hFÑâ-•L‡˜ºYgíùÆçF'lNEæ¥`ÝánCϰ ûÜcŸpÈØƒôålJ4H’ºè1.zœ‰QéÅ'—Öw‡µ™Ä†hÙÓ«-ô “ΓHKÕLO³lÖ*– yô¸‰b$##é ++#¶”¡·:$òTš¾f0ÉÞHî<2A$”5Õ9çàRô‘1"x¶a²Jás"½vy'÷§2‡ç”aè;¦¯†C¬ è is•<¡|`a)`šiºpÆj„YCêvÚ/ß#[y² ÷~FzùCœÍ¥Úùþ=yÍe.¸¸1äAŒ¿úÿ ++…B¡P( ++…B¡880ãÿ_|öÿynéxt†ø¸vôrñŸÇbÕn ++…B¡P( ++…B¡8˜!<äXË @~„­‹•A8 PrÍ):o*Y¥ƒ„_1V wát­Åd¼aÙ ¨ZHw¿ó)»H•?ŸTÈ0a$ÊZÆ49ÁEË OÉF†O•‚NåȚjd(ð\Dc¼úÿ ++…B¡P( ++…B¡øé‡~ÿ+ ++…B¡P( ++…Bq0`&þù%ŸÿðÜÒñhç ÛöJž¿Æ]F>¿å÷Ý|^פËãγÕôß²©ñ²Õ:î¼k<¿rßu©WBÌS£½ÃùmÓ[olœy®sµ}aàj›¯ÏwìûærßÝ)e ëå=0Թ6~»blã;CúNM¼—Þ±¾iâUÛóàûäÀÿvù—6?2áxkÜbÛ ‰·[Êȋwæ[leÑ6n±çgñ¿Ú¸è|,«íža|¦÷þYãq³¯ìù¥“:ÏýÄ¥ßjeÅ6®¶-RçGYç“öÖÆæ:çáÞ¡½ù¼jëî´ùh× \‚¿2uړ­,wn¸]R'¹èNúM76~4ã•M¡P( ++…Bq0€:z…úw¤ƒô^UÙQÈ®@Îdc]¡2¡§Äb¦Z`¨ÂÂg)…'tŒBó–²7É4>=Òt&Ɓg‚¯à,u1×LžAKª…”£ÁOâÎÑr( LOèdÍT>ôä ­£#'i°du…W’>4G—?:ãß³1â¸\ô*é îÓå æ$bö¯QžA # ÷«‰Ô¿Ìe6ßþ´:gé9rŽñõDça™‘²ÄtÅúJ¾Z‡ö“èGzÿW( ++…B¡P( ++…â ÀŒÿÙ®£Ÿœ[:îþdú¶O]óK÷6ÿ®sãÑ©‹'ç?qʛÛyòxtÅàÓ>äƒoýªœÏƎG7-™\¿øýG|]tûŒ)ãÑîAß¾VÎ[‡z~8øœ/9w¥ÄÄèqþp©çZöç›Gþ7ϧÄë/‘zè»ÿöùo¿œsnzÖãXù£[NþBýx´Sê™Ëk85Ú%ã¢üÒéûEëÌZZ\Á–A3ð’G¯¬­,™æ?¿~ˆ+8?_Ô´ê|ìñŸêÜ2½ò¶¦·g}‹Ghšs¿Šãœ/_¸§—Õæ[ÿ9)ûŽ]uÖ¿·²›oýÖÁž¹ü¦Q]×:ûá0g榮ŗ|9عx2?óµøÎ’²_ÀqÖϞÑ4 ++s­-`ÇPvûÊõ-£ÚÔbÂ`—T ++9Š?‘b`!¸D™=òƒ¡:‘Cuԍ³&SÇ­OŸhÁ{ ïËâ'4 ”R¬¯ ++ÙÆ\R‘îN¶P=Õñ]ŠC±¸›¬c웡ÙzmÂJV$èS|ËøwN‰Ki¶Æ%½½¢Gf9\î,U«+¢W)ú†&èÔÍ=3ÆÑ&с˳m"õþJ¢÷—ÚvyÐ@ÌTõÙK2¢ÑÖ éh6.¶àê´ÔœGš€¾:“(›™c;oè#Æ48̅§E™ó eS@—Ñ *£?Þ”êtSSíb”¤ô¸Ö„’"uEZ‡j ^á*%³­†BŸC³œjÌb³©µùÖ½ŸèÎñÿ¿â@ƒáÂ8ï&q s´,)ÉX±š)%MÂL™L Ě(*IGlö!ž¡þc¬XœVvÆ|[ê&R*î{¬|†0”A ÕR_•sPa±ÚµK*IÀ ²tŸó3‰¶#Zˆ”Σ&Ö1µEwO¡F$ç9FöÆqbsEFP½Ô9Z.bJjÁ¶¥¥…=±,eçÑ ì`Š[b¦²u-ŽK“ÄÐØ•™®ê‚͏‡‚(žƒÍatŠEbèS!‘Øìø@`L¦Bî¯>Ñ£u9«ÿ_¡P( ++…B¡P(ŠŸ~è÷¿B¡P( ++…B¡P(fâÿcÏö·Í-ðóý|/oqíBå P( ++…B¡P( ++…â5É"ߢ·Õxr}å÷¿»óø?™{Ïxtߐ7¼zß9'uþ;í<äÏàØùð²ÿ”åœÂxt½ä 3þþÓWýäûÇ£÷z+ï»ùL9"ο0äïÙ·\òöƒÏi'ÀÏÀ•Çoþׯ ;WÂeRv<û¹ä얿Ÿciu¾nÐÌxñsŸêœ¡õs÷¬<ü·µü}ë›=w í=ú…+Ÿhe>¶±ß9Øå®·lºåïûÔú¹aƒæï+ ++…B¡x ~ƒxò¤h_wM)1ƐcŠäe¯6lÂGŠ ¶äÂúl]p¶ÔYœè ñ Üö¾tž÷êpÎW‡wÌÔ9ê]‘Iø¹ƒWÝê:·@NÅw>v¦gÛÉy\ƒwW—\q>þ5I»7Îe¼œ /¾ÐÓ;fď¶bÌÕžMLÈÆ8…´ 9_3n‹µâZ’M?yq%Ø>t-Á>‰ 9Ûë;é È'a0òa|À…,<òL”7!š˜Þ.aÇÐÇ!]ŠL…/Š#Q@!çڌ¥,CZïÐ_˄þH´B ++ÔZ1řkE¨ÊÖaÂ'OHäùwè4•`¨bHwGŠ-_a (ã3ðý×òôƒ¡J Ã?ZÉø6à°† ?áýÝdÉÚï|ûå¼H9²b!œËЉ ¾ ñ¿¨akÄ|8‹Õð‰ƒ†*-žÈÝA¥ƒ@êëªáäkü¿B¡P( ++…B¡P(füÿŸÿò)wÌ-}C÷eÒ1yí1ïûmñŸ·hgŸzEŸs9öÿõ¨³á\)7…51—?·ýºØÆã¼Øöà¬ö{]ž„—ÆÛ¹}åÄ<·Aå<„[oÛönِó,”NÏ[7ÞÚö©'­|>çY4ý|ìËùÏ¿-ñ$HÓ$[Ú]¸5Î}F}6åDÈ<ëúr)ݗڴJ÷Ü»]+š¿&éʼnœ+2űfò¤ù©Me^†Ãʚ^qÜ9;׃’YŸ3Ûç=ñ† žÍmy ›f¶÷oÎTÛ`ŽÉÒñöy$ß¹3å‘DXç’'3œ?ÂÏií쌽ö¶”c"TÍ1©ò³¯ó Ö3<Ø0"䬾 ÿtRÇ͹q䕆©G4såI¬SìkDLO1úÇêFq]·øã¸€Ë Ñ4Z>à7cmÞXbFâ9x¼'4<+M ++Ü5º1ì²Á£kĆǦژ Ž³ÞÆíӍpÄn·9ÆÔÏÑÝÆ;y ñöÔÖÆMŽ}ÎgÖ4œõ½Øæ¬Ú¾¢mËzY¿7œÏ~ÃÜ©{òÙ/+7sé3™Ï>ÖtU©R¥J•*UªT©r°JÌ/ÒR2·¯çÞËà øÄÜÉx¬W i)½hkñ­2J9#ÈÏ8w°ægÁï®=S;+ѽ šQ{æ0Oˆ%ã=ƒÄ|…1큀,T׺± “]LãØWÏ¿h˜ …s’¸ Šù¾±A±Ö^µ±nã´Co‚íÏGÉ81¬Ýà^1ÖÍ*gR®„vŒþGÿá#„éϟ . ›Œ³Kó‘cއ¶ñ"´s6¢nß 'ÐaèÍ2· åEäU¤7æ6H¦hL‚dE¾j\ú ÃaxO×D!P1]Æ3ƒÿ’ÊÇL'\·š)9²an•`¾ñ'Ú¡Ò-,ªi“¨<'V3óLP³PžÂŒ"ÌeÿW©R¥J•*UªT©R¥J•*‡†Tÿ¿J•*UªT©R¥J•*UªT9d*ÿó)[Žl}ÍØ­…ßîú#ô™ ÷Iãú£#pßXpþ<°ð¼˜ËnˆÛ÷þ>Á~\ÀÝåþûã¾Pòù—/9ꁄEÕ4½±k"¦Y/pGÁôšyö›¿¯;!{·ª‹ ˜rü‰vì«g,<‚²!þ_áÂÛ¿Ž`לv¼'¿xäÞXG€õ2ÿ_—/ðˆxŸ ØÏ½[N×£ÆÇ>Sò믜W™/0sûmŽccÀŸ|)aˆI(#a¤mŠÏ!þÖ<³)ãôE˜!´}¤ô¹‹ï7£Ô+\uôÆå6Ÿê¶•¼ü“?™•Ú|Ƽµäóo¿ûì§:kR?'JíÇÆç¦9¶!õss¹ç“ݓ0ü\æìÅñ Ç÷{!êw8¾ßuÅÖÖï>üã oÏ6i|/ܼM[/J:ó.ã™í+ܒݺŠ›Ë÷ºX|ÿ0 ¦Þ¶8†áõ_/zYóô™ŸÎx{"Õ@\[樋w]±¡ÕæÊç3þ]Öç½et9oŽgwÃë8ÖÎjÇþÑ».ÚÙbÕ¥ï=TôÒå'L|ˆÃñèúqå1çœ;Õ6ˆ9·«ópéqy-g\TÖÕi»žMÆ£3i췗¾t±ê*vÝŪÛ]ù«T©Rå—T~yÌ ++wopøi2^.hb3Zìµæ@sÈtùÆ-6Ú yÄäÔx"›‰ =߯bž¸Žïǂ v!dݍâãÅc7 ++ÃoT>w¼¬ND CrÄ¥ë0 «h(“pŠŽXváT[' +œá”ÑÒ{ÐҍTqè#¬˜ˆˆ\#Â8‚Éñ튳_–X[ ‰§¬9XqèbÝGdÀ(åq7®&M:(¢Ÿçqf`Þ½‚¥NA\1OMÂf$#^CàÖ¼fH%[Ãþ¯ZR)ö°<‚²ÔS«5¯Àˆ¡èJÄì8°h±fØ.#̞U± ™6È9G'[.ÅA~ő8¬#ðe1Dì9X®m}ÁNcÆP.Â~ÿù†9¸÷Æ>ýˆÏÑ¿ýï…˽Խ\'Î÷ïc/;éåäËIÕÖÿ'?ÿMë’?Boì–9íßÕ¢W³ÿüèâ}ì´ßz Ÿ/À_Rþ~üÿ—Šÿ¼hŽ¸&Ù{°`sÿÝ ãý ¶^Æ9¿ã{ê˜ÿ8–~þDéçÉ{>ød¼îøíûFà¬-ÏÝçÿ„Øÿëèó}þìïe,ÙôùgÃqþ—•çìÝÚò¸ìVüž«Oܸ3àG ù‘3Ûó’K¶­¼5™|©^©¥?ÿo&žNmMö#Í}~°äðÑç/ÌmÏUöžröS© {F_ÑaCá¬Â£ÐåH\öÇç‰/¯ø÷ýÏÌ}¶°n^‰YE×Ï-¼%ÙÊø:Þó/è>»ðã [»hêg¹çGæ^þ½ìÏûÔ¶ª`6¼aþ¥ ӝul{bŸ}ë4˜õwD}¾“þõs«ÿ6aÏc!ôe$<‡ÃNATÓ<|ùŸÎ^9™ñ²ï½¹p8¬™œø\òõ±ãŶ÷Ï}0…uÁ䙷¥s€&ãàßíl Ï9¶ßWjsyþVÍjm°‹q]Y·ßøÄi»3žƒMmwô\ù©ÔòZ9¡èú›¿óÉäϧóŸ*UªT©ò+ëë+bžÃۉî\ážÂéǏ‹¦3BŽn¼­“ìZ³B:¾¤“욯æ†n*~ ´N7 ~=^Ä™´üP:¾DL'c6îŸ ;½i áïé¨JAþmKÏ%Ñ,Hü³ Xk ×ÝãËëXFÜÐÉ¡ƒŽ·W°î3öû°zb¼ÝÜ·ïëÒ ++‹—·€*8¬žœöx/"‚ߢÃëíKŸñTôKh¸6xÓ¦ÿŒ§ò(n¹±h‡ç(2JÀ!Çp<ÝU¼ÈÁa=ºSð2à<ÐEµFD ++xþYc8£XŽ ßOFUQxQ€«fUÇwiøŠ‹~ËÚÝA¥ðúèÐCx1†O"0c’¾%øpŠ(ì ùñTŽ#\( ç7îßzâdzܛS†Ÿ}ζ†¾1tS=þˆ¯Èp[À}á£iRHð¼'ŸßX˜‡ç©Á´ç äJÇS¬ rýÔùº`Y¹£‚¿ÆYQ|(#àÀ:·ÀyWrôA_Î;2/ÀŒiσèN‡àúÏ à%³öݹþk‰—€”cw ‰H-xւiƒ=Ñ#ƔCµðQ=Cl‚§IM,½§~¥2†lÃ32ž‹Ø¨,."²(Àq’<äR¤x殒·Ýq§¼ôá1ç‡Jþþ¸‹K1ç&Ç,ß> _ý†Îÿh¹ç}_Ì\ä@m«Kl|͉¤x;Ï»fLÅþù¼Ç¿6ñý«6&År·–ÚŠUÿrá«–9v<£Ô á/µ]øñygâ³gËÚݹ-Ǖו¸òœ§}2µùœ_~{ÉÛ^µëä7纍û_ZrÏ»ùåó¦á˜QbÇ]¾ó—K À`žx•*UªT©R¥ÊÏ[¦É;'+z(qۃ“~Xþô¬I8ØbÁŒj7Ò72ÇÝF>yŽzMÌS‚EÂZçÚzr¤œysâ¡@Óæ.HãôV+åÙËò(.xü‡!fÁÀ² ++“àž{*ÜÆÉÇà`šP"ëf ‘&åF`ž¥8NéÀ盀1ú˜K€å `‰#¿¦.E,×0ø¾—­0EÜI9é˜Ó.Œð1eE*fù˜’fi+$h$Ê ++¤7žÚVL~anaj=$¨³BF¦ÐCE¸½òm.Ȑ¼þZ¦óHÃ"ãýC¹`–6ЯĬ §u )+¯èOy ](‰7ÌïPX{>XÖ^™ýÅ8”™q°äoÔø•*UªT©R¥J•*UªT©r(ÈTüÿ–7ݹe°µ76£Ô›Ÿð­?='Å͉Ÿwt‰‹_³ôMßÍñXÑ{¶Ä¯pøâõ/á³àŇÿ'Öí ‡û,*øÇ}ç“ßOõüÚãz|îûñùÔs¯ýv¼îy=a¥uñü–Å댩Ï~÷ë¾ëÿqu‰™/ú§_iÖ Ý0ÉÞ²çÆó÷šxûbìšuÖ>Ü+ñz°׆8kKÌú—,Žy ,.Ï8ˆ±¦~K[ß/r=ú¦øŒá˜׎·ßëâLÕkoœ¼â¶\ߟãÿ׏·ý~òÎK~’ÚTÆò»c|ê{ƒ8g½uëôWL…sn~ßÎÜRÛT=ú‡N]÷¹N?ו/ˆýä ×ï¸bK®Ó©Ÿ‹¢Ý Ǽ#Îù]ø¬}ä~“ò)¬Í˜pÅoœ•p ]IŸ"ÚÖp À„ƒÇ¼ˆËŸÛ~]jó&å"\3»ý^p[ÑÙe“3Nc°MúÞËãí÷önِjñ…Ò©/·Ìlí¿›¿‘jñ‡cn(óÞÅ!¸½<ï£ß˜HÏk¬OÏÛWp÷.ž\~jÆ!ðùyãm_®þÊDÂÔ.×÷/-ö¿zò²ù)Cå”­Å–ºX×½t±vÌnŸwÞÇ®üAjó2ÙIJipæMƒGxmœ÷á8;Æ[›øÍc&v¤|‘&¯±¦Ã*omâô§¿š± ++EÎÍéMƒ_0of«—A<Â*UªT%}uÁŠÁAº0Sbév–ÍMëޅqNnò¬Ù´¾pmª_&,l¬uÇk‰—¶¯öv8ÿ¶Áæg ÝG¼0ÛbqÀ›úystÆåþ5~‡¡%¢5.è øg¼Œ°>’Ág'œbÁ¼eå{éj¬Ó•å ^è`Çðº³x'Ó¶at˜]G£)à~^1p p¤†±3tYGÌi‚™Yíⳬ]g}-£®è}Ãgß]âYß.d£}޹$õÄ Œ+ÂÀ1VÉZ}¾¤M“Ï@XCtê×)ç¶¿–Z‰úðئîô˜}çíáéñÑcâ6ÆØ8³œÔ!âÛq Cêïcp¾o|N´N©„-€I\€°…6¯aD]?L‡“™qÐb2b•W“ ++µC«XOqÀÒš!~ƒ@ŒÌ_&|7(¢XjÁ[ÂsÀZïÓxf,ЃR#&Á2ËÅc7á&Œ ƟBUL%p.ö‚›Ÿ€1J"'`úa«Øu˜|ÂásÁcCÇ.€à ++4A-`‹”q“¼3:˜‚€÷mMÀ •Y&NìHX+q ±Æÿ«T©R¥J•*UªT©R¥J•C@ªÿ_¥J•*UªT©R¥J•*Uª ++2•ÿÿ¯¿w°µ?~Á ÏKyÞäá{tŠÏïœùÿ™yþloì‰xžøÿæ­MyÓAõÆvǜ[æø.~uñ«9¿Y÷2.ï¿øŸçnË8rÌÿ/\hoÝsÿ»rnèS°ó–/9êÌ%Þôr.p—Gð¥R¿°}Á¼u[GÔ<\ƵhÏMëãuoð܉ò÷¼îc}Tèç£åïOÞóÈUgM#{c·–âO%žBkî¿`aª¿`®òâ—.y*]Wxîg ++×üÉ/¹7Ö)@½±^_]C?nâìÒÏÕ÷¬z,×äœüÄSȶ¿>þ¢M˜ŠÊ¥¶Må~'7~-Õè\pc¹g—7P~È«ŽÞø£Ü–9ߗ”¶Wæ\žx ++•Ó)ü¥R7Ñ­GXç~8†c⣼Ÿ»Þv~ƒÑ6å{o-|ŠÝZ…3[»üÁ=ïKx’¶­ØQ¸)ÕəoЉŒ©øpÉ­ÿð±ßÑ)‘î¹£`TÞýúõ;r[ÃoíqÝS÷ÍNmÞæ\÷ؗyø\þÃù§æ‡œÏ¾¨è¥‹y}©èÖ1ì*ëô÷¯97×*¸Ì¹uV»N=ieâ0”څó¿w>,×?›ñ$EšÛ)ŽÏ‹&oxGnËuSXšçŸ0±=Õ#È\ã°¯´ýô”‰Tã tîç½qìÃù—•ïí›yÅ¿¥¶ÐÖ#”u¶zòÛ÷¥­Óøn-µHÝú‡ú¾7Xÿ0QöŒ ÿ²LmΦ¹½7ÚüFÞó¶Ë’êdÆÄ\Wt½é¾•?lkÒóRíÀ)ø|tι©VÁ™\ßñàÜÖ»õÛJ_ºx™½Y­Îºõ»‹Í¯8KS¦¶³¦ÁÙ<¬Øçï=þÔ[Óþ*LÞ'JÍÏ`ýÃøØæRÃqî Ëœö_1•ªT©òó‘˜o¬ˆ‚…½Z;ÙÇaE`5æšæÍHéE›—Mî2lí–i©× ð2ddd#›·1Úތ|RXòJüŒ4ØÞyf;¼.óN“Ü6NkÖ54¶1%ÜE6:‚™¾üq¯™lB`.¾µVÄZ#tÄ-k\ÌgÆoo ++š“Óò»õ†áxÊcU'Ñò…,|kJM“ `®oÖê/B¢Aå*FÏ3%œDv†Õäǯ˜Šõ‚å0”m¦jEH¹{ ¹í¼ë´s3Œ¼ŸOnD J[g@ˆ?Â{Ãj¼ Lé÷Ä=dûÿ±÷íÑvež÷,q87¹!Hƒà4£P°ÞyttˆÆ!äI¢‰’t1=YˆKÖèj1ÄۅKz†Õf AÇ2= B;™‘Qlƒ # á’`xš8Î÷ûªvsï9÷þъMýGswí]»ê«ª}vï÷ý>$E¤QAÿ fµ‰ˆAa^Í:€ôzkðºÖh×iH“îØÎñÏiÿ?ﴴτžÿŒ‰Í;çÑŸöJÚgIÝÎqòÈ/0å¾ ÒžqøLlÞÝGê |yBÿ}þæÉý¹¹?íóêç÷Ò^ ¥=«?õÎx?¯°¯>´Äÿ¯8çøtÜjªÿ•1öù›J.ô‘ú§—}þH3øü…ØŸ¿vãØn´ñh·†&7í©#0TÞÇÏ{TߒìIϗN®ôù¢áŸ—÷í&í7®/v:ó”¼ß§ ã»öí\ç¶y×§=½È{.÷­MeMœö–ÉÍo½ùž/vX~ÿ'¦å²‡¾žï‡ü=­D*s*Õ¹»èH¼vÊÜGr™É±Øãèl8öž>í]ûᅬâûÝFŸ“ÂÂmYc ïyäþõ׸|œ½yg¯5ÿ֏§¶‘÷Z”ßOzu6L{o~e™oŸ¼é‡r^‘Ê64ö>zïAcï•_)sâÒS.|0ïkóoí2—zãúO.k±7®Y™ç—·$õb¶kOßÏ{À¤±÷µ[KÞø|3aìýéš Íï w¿ý/‡SY÷ŠŠŠŠŠßËo ýö cŒ# za†Ú7½ô§|òMNõ¾{ÿü›Ez¯µiO:jó»þFAí嘨~qδíF .íªètڔ™˜âöGç6[NÛjÚÉ9[¶‚ºE¯ÛØßӛµÂï@ ­3õ²ôòð´/¡^юÐÓ^XBÛÁþ÷Fx¯6>ߛ^O-t š}2²ÎÓþSŒ>Ö>²ït¶³´Ms]ûºžxý?°Öƒ¤!—lCê|4‚eò^‰¶U´‡"½‡t€bQzd<×gÚ§F‹PqÚè¿G´ÈqH´vdz¨Ð«(?Ýû[D?½wë£Gþüd±§¥ÑD,=½öQOiïH»w¤^§Qô4·!° LĀ!g … Fœ©™æJò·íÃ{R¯°zñ+M„ü[…ŠXtÌ Ëuò ++¿«Ð ŠÈN“ÃÐê5> M(Í :Ù*È4ªÔpKé±"æ¤ÁiKGÚ ++#¡Ô ²MG‡óŽŒ?\!mæèlh›@¹€Vݖ– ++~뢩ç‘ÕBQ?»~Ó觇B?ÑTÁwýfSÖÀ(­†?F½‘±òàgWÌ+ì>ðS =r+ÿ¿¢¢¢¢¢¢¢¢¢¢¢¢¢bÿ@Çÿç†EG—ØÚVxæ#ýüžèȼ[ØWØëÏcðù70ÎÀi¯¾ýW쟗ˆ/8¹œ?’?DñûŽäÏo*¾éi¿=šyïHÙnÝÌ~ƙ8ÿû~ûáe¤ú‡JÁŸ<âGÉ?/l;癇xèì7ý#÷×9Ø ++ÅïØë‡Oþôþzþ; ‡¼WÏ?qÀM˜w̒tUš|µsûàËü껖&N7XX\vmñöúÚ÷Ÿr/ï~}W€/dÿ½rÉO½ƒËæ¢Î÷&ÿ¶6™“sño/òËv¥2›Ûy߯¿oÃäÎýFç˜_bz}û'}öϾù»™ç¯SßWðuýc¶ÁÌçÒç×/x&qL|悯çvöÏ;peÉðÀ»æ'[{“c6¶›ùÿág¦_—|û:ûý×Mj®ëÍð|ásôúöE‰=éåݧØð¨Í‹o› “Êæ 6¶>{—ސ9*Câ5ôÏpDá,ZÛp ‚Ì1¥ìö H|àR;M©ókw/Ouë3Ÿ½ð‚zùó[ÛMY/—àú ²ÓoÉüùú ¸Îþ|­e.->íÖ̑Ïܓ{ÚÍü|ôÖùOå²<~k¸ÎŘÛOͺ"•ÙpÇ8ù®œÔ¹ßÍÇä2Ÿú°yœü»'5m¹öîY»òsÎ'{^ݕ“`֔»”׿óÅ֕»PQ16˜ûËy¸C`~£sÈ?áö¬þÜáª:v¿‚ÆìèÁ%bà• ++°ß2P#´…SÍ"3ºqA¸¦<”Ó­ô ++!%¼ŸŠþV hÓ±À<Ôä‚ßK˜¾µmH>¦×#ÏvòWâ6ôŒ-yÔÇà«÷ñ{Q;á6QŒkËȵR¥dÚÖ«ä½õHd6ÒÖ ++娱àg;…óñ 40¦¯ðõðÓ¼Žºã£¹Ìð€‡†0FÜÁïÊ;@t@ψtöÙè& ¯}pZ瀦78484·à´B‡¿æYŽ9/²@BuOƒGÀ‰ø:û®_¯ø¿÷©Ü4åA-4 ú#è^ozÐÌ¢A¦ I]s4|Ø7ôÀˆˆ0€p<Ɖîi–#õƒá%ê$&O|PBhäxî0­ˆÐg çåèÇÓ “E† ++˜‚ ++ì ++ï¼ É!اLs Í¢eJKšA2BÓõìEfýw² Y <šÔ×ü|è—Äxæc4¹GȎ¡É‡ ÁX/ñ‘C&è%΁ÞÄ=Œæ“ì+ñ3 ïHâVôÀC‚<›©ê"!?½é†l`<¡– UMOnxÞéŠÀÏ^OŽFK¬D]à…]ѳŒ¾44^â5,¢8lF‚¶ƒàƒHš)ËßQ4$ôÍfQS´HW@S ++_=B—ø ÓÓ2`ѓ!D~nL<Í+ÆûÎs³‹#Ôä˜Á£ªþÿŠŠŠŠŠŠŠŠŠŠŠŠŠŠ?}ÔýEEEEEEEEEEEEEÅþ€ÿÿ Ÿ¼`ti»µ›¹Êߠϔ_M?=óÞM»õ|áøŽÔùû\ÑS_½æÄòqÝní(çäÿï`~.¦¾°ù×ÌÿÞuëŽÔóÛ8†nß@9~ê`â^*÷Gð ++/0ØÚÐnêyùê&^º°™¯¿“Ëúkè//ñ½ú÷-·^-¾E+~®\™ôçeÒ¤l}§‹¯¿êëI‹OÉTçõ%þâü-ÛïNe.ë ÝVtº{ùús;ûóõWöêòïèhýß2?Å1™¹Ò7—±Z9<ãë™Ë¯»ùÞ¸xõ«'g¾¬ë~G»™+½ÚûgŒ£Å—b:ÀÛ>ë_Íy*kñe{^Û¥··ãï_ßÛı¾n¨ó ŸÙ~e*kî·~}ýËxfÒç:sî#YÃÏ'»\Ì}€6ÞCw®|4ñü­M}¿ºèØ-xö¤S³N~ÎpIÑâ»lò…?Ëù0Bw|»äñ~©ÑþKý»¯û }öܸlg.Ëú~—NþÒáI _™<—m¼Ã» qù!ÌËe›ŠŽ|¯öþ=ÜwÄ[œyÓ‰#oD£Ë_bMø«…Ïe}ýß±©pÝ{ã¶•µÒ«Cxy»™×½Úû_.kvéîCސÊBžƒ×•¸ ßÍÎeÙ.C܇þšýóËóêÓ·ŸûD£ÙŸÛÒјìÑ6¼¸+ŽáÇ)>À«¬[yíÄNÙ´Ôw¯uºnsÑÞ\øàáw¦x„¤}LÏ ¶Ùô™³ý{·§2Ÿu+7—¾÷Æ\RbFªö~ž p÷=°,Ȳ†5ÞúiÂ#<Ƀ1¥B¸a柂B£¡=†Æ|?þ{·¶yù»gò­)NÕË  v Þ»“àË:3Õ§-p ö2C)r9â ®’xà ¥ ++å}‹#€A¯h /‡h\ô ªú¢sž¾y…—™ÌúÀÂÚà*;2`€Kð`AbWÔVj8ÎTf-軖.Pýƒh˜€ú˜Á¹ÄFØúÝ膁W-!Y0“bs›©œTj*sq©%`“Iâ’l“ZòkÆÍHhŽ‘ý5ìjéuÑPÃÁ§>)‰H‚¿¦ç¸„P-D³<²SASßB ÕR×tŠ— ;ô8Ͻ×Gk.å2­•>ž>bÛ´ö -¯ÑZ€cåBh41ûÂ_} ê?ÔäÂðÈ®¤AÃì 6‚, @ÄT‡¹i~€¬ñ>õz,VZôwgÈ$Ð<µœº1©ßÂU0¬dñ3‰ÚÃÆ’?ðBA@!ˆÂ٢˨@ ×àOKeB—u"©Nz§s†ììEžGôõklÖu˜ ž!J#˜ØM f¦7Ï҆s£i©zÏ"ü!p uWƒkï¡,Ií¥'Ÿãð ÙA§!¼²hâ Á‰¥o ž› ++r‚ó+q-4?ك¶!!…FijAd¢¹è»ÛD‹ +Ó‡B¡:ü±êVÿEEEEEEEEEEEEEş>êþ¿¢¢¢¢¢¢¢¢¢¢¢¢¢b@‡ÿÿ㏞øõÑ¥¶Ö3·¤ÕµSßý1æÉ5ÐnQø¯#ùÿIŸÿúÜû³#_LÜWgÚ9·zâÿüaæ¨FèüY8Ä#õÿ×]ò¡÷öCæó Ú­£¸ð׏þÍìY|\*:/sg×ÒçŒGŽúç”Çï(Þ{ŸòjÒùw¢á‚÷×ì?´hö÷òüG³ÿ꒳à¢áŸ—cLæïNì” ê¬çŸy÷¯”¾.ы÷\úÌg¿dœ€½:eï[›Êî2Ùzþ·ñýþ}øæÒ]™ËŸs¯¯lÚò½õK7g.æ _=ԌU¯fÿå|ÝèsÁ/?ÿÍÄåùºÅÜNÄ8|ëÍç?–øú:—}®hï_r۹Ù¯R[¾\r7ôòî·LjÚÒ«¯?«ä¤õ¨sžÊúú&ñà/.1½œükË\ïåݟÅׁçÿ¡;VݟʬL×=_ÆoÁ±+·'þ¼Ìsb`nýžgý¹õ{»ôõwސʴMu.ê”mJ<cržƒ %†£—“¿¢Äpôòî¸-ýy÷C%†cю«NÎÜúœ#`÷ÄÆ./Þþ±T§ó™w?cný–b—^íýECÿ¬)g¦ë¢–y=”çÈìác3^fþüK%Æ¡jèWTTì‹h¸ÝÒipøCÔAjï 3n Ó§AÙTAG×V{ú~BŒr@0¬Ó€(¡å,ÒÎӐ‰çÔ<_Å1q §G(ý#Œ F Åwpoñ²ãDTÝIÙW "3]áÆÊ90§_Z0|Aöe’sà©}8Ïy£>wž¾ø¢P ãNC"¡ãOöu’¾Á —¨¿APäÀµÒ°½Q!õÒÝ4*ёmÀÇä{Pˆ7¤6»•òPg0\ —gd¤0ŠéÂãôý+A]&ëõ¯ h˜ñ °kìʗ0Vnə hÆPšs_‡Üd §´SƉ..‹ÐËñ¦5ý4ã÷×\¿k\Ѝw¶/ÈêQ4zŽ9¦Šú A§~*Ýc!ÒSˆÎ2dä@¤qzïIJÈAÆ¡ûJNb†Hš–ôxÉ:ý´¤=­"ÙÅ®Ë"ZÑ-áT"¯Ü(,²ЂÅÀÒ Tgîj‘rtÅ?`N ÷žsºhOÏ6ZÔ¨ñ $÷ ÛÒ¬6˜Ä ++á)Ȼ™+é$ âŠÈi Ð7冱q¬ø³®X1̏¸Φ`EEŒ4’n±úOJåíè¾OtÚà s­‰œ œ-€&KìŠíÙⶪÿ¿¢¢¢¢¢¢¢¢¢¢¢¢¢b@Çÿè[¿þF—¶s®ò^=¿WŠü³ïÿ×?HšSÆ·[ǖ¼î#ýù§½ºÿûì—tA˜vëäâs=á…C^cÿ¼–ªsÃÏwüžsæã^ÇÁÖ¡¥þ^}¾eEÃíµÛ–>ýö¹,ù ûûíwß犇/Ù7/’ýô¢cÖë·_Áeð%d×%Ç$»È9É—ëV?71•…ì‡]Æ6íïŸ_ü›½Zz§—œò½þ÷Ó¹NøS·kîÓ©ÌÙìïç²þþ÷˸_¡ÏÜSW¥¶xŸsÃ/žÜÔÙ«³·¸ŒO¯ÎÞ2.ë¯Q·³K£nù”¬C»}É¿½Vý"•Å|ÝK…DZeãü'Fúµç½¼ù;Nx[òO ôÝ®/~û^ÿô¬®œò³ïÊZl"͗3ºò¿ßtM*‹>õ}¨h¸Íß~VS–Çï¨Â‘ØzøÂÝÙwýö¡Ølöð½7e ·Ü–ÄÉøʶÝuC£ïV}×ÿR®½/²ÏÓjE¯ÓеtŠaI[/BO€wù@Ö.„€]PM^÷±´áû´ÒhpJ¢0҃ð{ñ׎ä,쫜’bcï…2B¨ÆŸó®Sï¡!(£èÒq´>vË$jR @$ÔêEÄ0¸Hí·ÊAKÔ±(sQ`9P¨ ++Ã`”éoÇ ++~Ñ;P~ f •é c ++‘A¥¨%Þ;ºO$»( :Ð8D诵:ŠÔ|È\ÐÔtÜ?2MM;é»Îû}ëubì%t!«(YI– !åj!ÍY Ö@ê/*š$ÑÒm<8/… !mb´§YI3Éyo<ƅî­Á±°(”/cbEXg³X$ˆ+4wAՊʻÆ>ý¸+ãè5þ¡ù$ƒâÀԐel¨»ÖTÿEEEEEEEEEEEEEÅþ€ŽÿñëÿçèÒvëÊâŸúƒéç¤ümðç¹Ä<Ÿ1ó-Éÿ/•j·6Á ØTÎÿæ}où>ó”ÕíÖü’»jמ){ø¸Fþ?ÁõÌ£ÏÚáé/óñhp ]€½|±¿/z۞”Ïϛ†wì{Î;‘#±Å`kké×yê[r^C•|þSKzóõí,<†^®À%]ñÿ£¹÷•ë–ßÿ‰i™+’_f‰eÿđ«“Ÿ]§\ƒ­ç¹-ð_¿vÊÜGr¾¾œgljɃ×ëó_Îeýãñ7–þ‰õ ïOe4Jé~|Ý|ú\wÕ¼Ÿ§²è“Oürîáô¹ðÉãNÍ|€&ÿÚäf×ü§¿ÌññÙ.kÊØ|ú»+S¬¾r!]÷XÏÛ.x ùü›Øò‹‹={càח:¿v÷òT§±>õ/iM ñu»ÿkÎ÷–s#ž5©±ç9Ÿ½èç©,Èd³›Ë\|ù+KžL~}²(—}‡ëìŸm÷81é-‰‡¯¿ô©LÛÔ÷ ++Ÿã»W½gΉé`ΤN]“Ê"ëSTTTTTTTTT¼þß€lÊەÓÑ*çèµÙê´ÞÇ4>”¤¦S›Ó.î=tŒ to&W˜¹í’£Öá•ð‰ÚËÐ *èND 5/àzŠs+Â+l€M>F Ú¯éÍñÂpó†cœBÆUä¹sÎ ¾–ö8]ZHø˜ê Ƃµ@[; ÁF'zìÓ6dxïlÐÖ5¼ƒÃN;Ù¤­!A¡&4 çd…S]ù%¡…1ã¤DK鐨Ù®|Ì èx/<Ëp8Ǭè|8Oû $ÑD¶Ad D ++îó"´Brۅ4ÔÂ:G—Š.†ò~Œ\·ìׇ}”A¬1 –tñh[Ì´jKðÕÿ_QQQQQQQQQQQQQñ§ºÿ¯¨¨¨¨¨¨¨¨¨¨¨¨¨ØÐáÿÿôžInti»µa þºÂ]þügމyõҘÁÖîÂçî͝—òAÃíá[Î{.å«ÓYÃmkáǟ¿eûÝ©ÌeÎö½…ÃÇ·.ڙxîÁ%îüw¸ âpç?¶êÆÌeÏ÷{‰Ëúçl»¾ð²­½ð¡T²î]âe/¦Ïܧf]‘xàVdí¾Âs?{íO§øÏÚ(¯Àe×bÔ:qå!£D£¿§¼WJŒL±Ô]yýF秄–£ç߫ଠÈkH59äèó.ŠC@rSe=0b„L ´ø´ÑZ•“Ѱþm"=ÝQGM€‡‘š™5Ys’.hô÷ ì¨pGÈ1zÍ펊ʌmb Õ÷zÅTÿEEEEEEEEEEEEEÅþ€Žÿÿ­ÿãó¯Œ.=°5‡€_þêƒÍ³ž?«h¬­úÞ^Pí쏇nى{>ù§l£ÿw }îýّ/²OÝ;Ón­á|ié3õ…Í¿f~€þßK|_pVœs<ç´VûvëžRÿŒ=}>Vµ[w”¼r'ìùKöõ;«d»5ÄÇ᯿oÉԗS;]l·V–\o|òˆq~Á(¨ÛÊ}ï}vʫ鸃­å%ç[¯^àr¾¦nÁ›'5×õòŽ-¶íÕ\WÚw䱋~‘5uºnoWŽÀãoÍùs¾»ï”zß[¿tsΘuÿ.æëúk.+:ƒâ‹ç6º*çú+šyŸ:zñ9 HšyC<·Ñ礰p[*s*õ!pÿ ™wá3Û¯L9ƒMí< ðD–¼caê’d$»pþ }ÎÞ==ñ/DÔIƒð²bÏù÷/šÎe’Àe[&5cmXœrRçS[6=½s‡×þE*³.ç†,¶þäM „S¡ Î ÍuK‡g¤Êä|Œ÷r;¯ Ï™7]ðXÒ 1Õ¹©ÌÇÅÛÒuƘœçpR3Çzs^;N.CSÆá°iËšÊt.›ÁeÐCü›°"é!Zë×åžb³EýLeÞ¥ñ[_ì²døÇǤu©²¾ä¬bÏ^=Ä9e=,|ðð;sîĬyxF±YožÃ­]eU×°¢¢¢b_ÆXºZH@¥¥7ôdB(úR†5’‹Eþ.üÿïªäßҁŽ%,ÈSC²ûã ¦Ñã‘MÌÄÔþ <¥Gï¤Vð(6퇲Y@j18ڔ3.Ò ’¹Qô~è¼F!'[«*Ç¢†ºš±øNuڋ¨‹.Ànžj´šÞ^´‹HFgèŔŒ  ØM„R#cX¤zèî‘j “j¼~”œcT§kþMCC- ¸»tS‡— ÇHíõ4XÚÐ ˜#Sk1Ùö”Ö†FËÂΎZ…‰t.½¤ª@(z¯×t>5ÍCÓ-ИYº PŜ‡Ê›s:åg3ôŽçŒR΋Аº"¡¢!­b%Äi™Ñ¬¢ñA¦C…;êŠ6d/¡i}ÄwÐHÔôä )C3›þPÆÉóÑÃëMæàüˆp«c„,½ jRdM¬ ê ­+º—Qƒà3G ++A„è蕙:àñH¡…ŠÞSwiqEÖÅt¥Š=ShCªÙþyQ($T¤ÐBF{nc¡Ñè"ž2û˜dõÿWTTTTTTTTTTTTTìèøÿÿlÞ³F—¶+1û þvåãÉ­²ó.ƒÏñ3— §2+ª/¯¢¢¢¢¢¢¢¢¢¢¢¢¢â æ˜xe::m<ˆâ¢á™¨êÿ¯¨¨¨¨¨¨¨¨¨¨¨¨¨Ø/Ðñÿñ¿dti»5Ä>þô9þ¾ âx]cm»5µ+ßp¼½±B·[†ÿgúLé½KíŒríÖ>Ž á^8ä5Ž«×R5Zûˆ½þoǜûÓ;¯}Š?žÁ׀_ðÕw-Mü¨rÙó\†Øòìºä˜;/R¼ó½å^«ŸX=™Ë¬Ëœ…|¿¯Ðgî©«v¥xuŸuÿ-}êÙ~¬äxñöq^å<Ç4WTTTTTTTTTTTü© +Î>z!S¼=í§‚‡Â½`MHI¨¨¼ÓŸ‡®½ŒÆ*-]´ŸSØb)4]g5Bîµ J{g¬ŽPӏީHûDiœÁo¨ŠF4Âúi¯h á!èÖÞh FÁÚ RŤÝ!È}AoB ++úO;Ë~î •BÔ|ô–Û®«-ŒY‹ß ++è8h«…R^;ÄÙC„êSPt0Ú: =-ª ڐ‹°–zHÿB°¿‰t®–2D=j%d“{À’-¨ÃÜè( ¤C„öÔG«é ++ô ¢¢JÐÊ9Mÿf-§¨QT³¥Ž(º˜ÌáœÔÐõ' 2Âý·>˜(µ£fÒ1C×ÐHHxȱØèÂ"큐,pVýÿû:þÿù«óÅÑ¥í¬žôü睖tïµl·æOì?tYÒoºÝj³ŸM{õí¿b^€”¾Ý ++Ecý›÷½åû|\Y:ÿt>ã»öLÙÃÇ5ôÿ—Á/8˜ï Ýñ)?üÂ£é¸ íÖó…G0ôÞÃ~Èy„ ã3'vêéΰ¢Ô?2_ÀÖÂ9x|ÑÛ¸=Þ{ÓnÌõƒo0í·G/IÇ#Ÿ:©éïû^}'ç)BÅvÖF@ýÇïYÇ|`,ÙaKiçȼ+‹ÝÞsމ|ßh”lQŽ¿|õGŸHö·&q6 ýÅ?ÿÁTæcâN,+yzyJß/ԙW¡’üm¥Ý«‡W}=ë=d}ýå“:e«ïLe&&îÄ]×½om*‹!Õ¹‚Û2“>kNÊù´ICùAëž›˜ÊBÖ¿™Ë§ÏöoÍ}:å2p6ՙòF¬£Ïí'-Hý³Æ%ùï͊KO]þËÌÿÈmÙTl&Ö/¼?å9@F ”Måë¥Ï…Owjâ†Dr Uæï]·æ>é’].;¨™“«6ŸóT¦bºß¬‰Í¼é́°mrsÝG·|ò]i ±”2•1ÔØì:sî#©ÌùTg˜ØÌÑ×nÌZÿÊå²³Ê|üÐågç2/Søº•ôYºãߐó#dÎÌÌIM;<{Ò©9?‚Je‹Ëê͝0³Ø³7wÂcel{s':Ô)[>…Ë´Šéºûº®;#µEۜc—½‡>g=³ø¿çœ y~®á>ôÏǰ~nÏ@Yó_»{y²­ÕÌ *ã·t÷!oH¹Bž+J®†E;®:9—¹T眲– ¯üF⠉˜ú°‚û.Ñ9Ÿ½èç©,È4¶Ü ‡O»5ç\Èc”r®,¦Ïܧf¥¼Š\¶®ð¡>ðø·oÍ9òüL\-¬‡k+•ŸÚ¹±Üoöð,(÷¦²ùCÍ\ú7ƒؑʼNíl—Üg¯=ãé”ƳÎpEEEÅ#à;…\T&Ä¢§uq¿Šwçó¢ëäèŸ ¡Û·ñn–¶§“é›\;ú&¤o5z{Ւ½ÝTH°#ƒ=h•P‚æŽ}š*Зµ¤úmÈR@ÿ‹ª”€{0yú”EF) àn%²x©á(ÔÑ"¹‚7‘¾1ÝÈBjݪÝé”×Ð\WPòÏíö’ùÐ!7pIJäi¬jn zƒÈ¸¤f2JHtÎòú9 4´Ì¥÷A'"!9YÕê´æ¼æA[M›úÞdEõ9ªËÂ¥*¬w18² B—a}ëéR’¢ÑÖHç#|¬h:B„i ==jÖC·6¦÷k  <íȯÝuäB·äqö8^žvj5ûª§:rNI¯í’ÿ_Ápnn‰sž8„® ”¹`‘ñAÐ(ìkùà¡æyJ#Hvìø«c¤¹C÷OÃêH¦@#@âÜÙ>)—î¥à…ŽT û±F¬ƒ|. /›2ZLÞÑ8iŒp“kÃz‰(¡ÿ¤Q‡ ++4hP¡c|÷ =xlh¢6çДÇü¢¹§Ê}áÇûž§ƒ4ÌNsZ³"- ++j’ö ++ɨØ`ì²GXËÇ¿À€›@FñôÿÎ9^“Þ I‰Æî)x?ÐYót¤û=µ˜†€®UX€sšØ9h¡Gÿfö,öÏKåÛÙ÷Ë~ò¿•ëñQˆvë®>á)§ú[ö“ )[[Ëñ^_qâÀaõÀ_-|nd¾õ½ìǺ‘>s¶ïöäSó.•Qê|ÓQ+“?1ªìûëøÐß|L.óÕÿUQQQQQQQQQQ±/‚sÓGCÛp¤U´!s´1 ++ZG§”Vð?£ÐhIEÁëZÒQKEʳ>:¢ÐÙom”7t²±ÿ6DO6he€Óaýٗʪè´0ÆDºc§ ++XtݶVå)Þ{)ÈJÔ Ç†ï$á¤>|o4m¦åhþ µœú ++A…€?œ+¡¢ðÔÚÅÔøÿŠŠŠŠŠŠŠŠŠŠŠŠŠŠýÿÿ)3ï:ti»5«øÎùČߤØQ)Û­½EÿòYoýQŠ 5¢ÉÐ˘Qüù+pØÿâx{©c»ÆðóÏ,1«÷>;åÕ'ïÄ`ë€k½âáKcŽ]9>½+–ü 9'€rÉ_?¿ÜGŸã¾½ÈñÍÇ.çŽÎ±Ý^‹ÄHqÑ·ÓgÙß³©ÌåØç#JÌmol·)u>tçÊGS¶µ)þw%—}‰>s<3ÇasXâö»â”wސ¸ ++Ú¦²#Küý’áiÇq™×9÷¨¿ý¡]Ÿh§² r[Jœòü§ßûÖÄU9žú¬q8/•Xò­‡/ܝʚ¶$ýôaö¶»nhâo”>ÌÞ01͍àk®„ŠŠŠŠŠŠŠŠŠ}M,7¼ÙZxm¤³Zg½x¨DŽåWðÞBF!*xZ•&jiý)ËœÑp{ªD㜗ÂõQ£á5WÁá‚%ß½1æt–€>ÜËZ Ÿê P…€0Gü Úú-%|ÖÞ'3tÄê½A,»‡zA ý ++îiƒÊ1öÔ(Iµ*™ÿŽêwQhhB4ñÿ}4- .àFùâ•B‹@6€>?dð“ZQS|wì¿Õ‘ºÈÞ/a ²ÝSiö¼ÓeV9ÚëP#ÙTPsµBh{Œtºސi£öüÆyê tücÚ‰z2§déÃ6"ƒâlt ÁñN“}¬Ä¹FÓÀ #¨oÔhÍx¾v§iè=µ“¬Jƒ¦À=PÆÖ, ++¾H ŒÃЬ!‘ò€ªˆ4®LŸHÿv4‘*t€šH]#C@… VR2 w!2 ++"‚0@ó ++S'Ð́²úÿhÁnúP.cÁÒ4…=i ¢ÁØWÿEEEEEEEEEEEEEÅþ€ŽÿÿÛK>íG—¶³øô™ò«é§'yièøþü“‹žô {þãÃ|Ü+Ñèü÷êÞodóBúÿڍàx~Ö ˜Zx#õðgþìº$ûøEÖÇåÞ+‡g$íz£²Þx»h­/䮡äÇ.ùǏä2èÿMÈzêÈõÈeýýKîš÷dÒêŽ!ù¹¯Çç>§K`vÒGt —-æ²þšGÍû^üuÅÿ?{øØ¬ñ-uÒ꥝߽êý;³Æ·K}¸rRÓ÷÷Ð#ïLþxagâØ.ýïꫯ¨¨¨¨¨¨¨¨¨øC€óØ@[+¨ô[Ù¥ß€t‘ö!Ó·Â)a¨\Z:€€}ä˜@˜¹4ÖÕÀF%‚²ˆŽ÷::‰òHYײ´´ûà„@ì§§ª• MÜýX¾lpØ9ßèögÍùnžÀ“¾"ïÉöÑëCÎñà‚4cå.(DžAF¤J1ó„2Dg$þ™‚ •dº¢q¤^xëY*”CÖtšäº¨Uù<"5ŽÊ…£s#YÄEÝ¥sã†< ^{ð*@éðà„БˆÓh`d¤­ A”lJ˜ˆ6°`…èêÿ¯¨¨¨¨¨¨¨¨¨¨¨¨¨Ø?Ðñÿßÿ?0º´ÝüûüÃ'î™wZòÿkÙń+Ÿó?¯^sâ ù¸n·V´;çòÝ)>_ÙvkÜë è3å¾ ’ÿÝúvk&ŸÏúg÷bŠ¡®Ýº‡ï Ÿõ‰ÿgò¶ä“¡Ýº¸ø¹GêôÞÃ~Èy ++·§´õ§ÞÉv°J«vËLhŽß°j:·Ó:ôw9ç_KŸ39ꟙáï`C‰µß«©ž Tlò ̤ÏÔïÿù}|\F:c—ã÷¬{ԟr‹ß†vžý¦dބ dŸÅE«àø½;/äãчÁ֕…qÞ£ú–ÌïP‰°¾ôáå«?úD*³&q¦–û_4ü“ãÒ8k“8 3ºÊuÖhPI§às%×úWßµt8—ùTç=lƒ¿¦Ï\¹rG*K9x[×݇ó¶Í»žË”ÈyíCÉO¿zxUâ}(•s¯àq†ŽÄ‚¿]ùx.Ë9á·­Š‡o9ï¹T¦s^ˆ;&4íüÌÆ%©4Óu—£3qe»¯5'e- mDâ \Îm&Äk§Ì}$•9“ÚyIᵬxöÍßÍù+tºßõƒ(C^û­wÖ?ÌmqÛl}n?iÁO¹Ì—4®ævbB¬~bõäTærßÛõo_÷Aúì¹qóZd6õïË{~èŽU÷§2+çeey-~ÿRYÃ͹—ËÀ±Yl/z–Ë´mæÄ„fï°ê©,æûí>¨‡3oº qsŒÈ×=_ô>›¶ü§éy•4V['OlÆvéîCސÊBæôl+Ï¡%Ã?NyD¼Êsbþ8¢Ûʺ]øàáwæ²ÌzibS6ûYפ²“]Ö،_¯Ȧ2?ðø·om4=R[Ö 6ς»¿öïÿi¤ÞÇu¥-£ùEÅW€¬ÞȜ¬#|-ÒHӐg› ¡øëCð£bK×ÜE7Ùúè­Å7q{Íjab}D] ++WJ¤CÖô݂èK ucn¨5I·éN*àL¸1<µÅǜۚ)ÁH+dŽ}Ôt­AØ%R)ÓÚùì] ̞eyî—Iø ++­¸„)¸FMé ¶Œ=çÂHI é*-X ++´FËA’Æà Ó d²M—‘ŒlD «PF7·à`ÚÄ:94Òpø-ri™ØÜuÝÏû>ÿáûû/¢n}nýª}Ÿï}÷søÞ·×}_W¯—=Îál© ®ú<ÓžÇøê£35“à”ÆÚË.ñä)8nÈTDwèNÂЕ¶ñeTn³ Ï3ÁEšÌBEƒV%|ù¤p¸ÄÔiì#ê-;“O=›yifõâ}D—¢G'Ð…Ÿ(ꓣ/ÔW§¦5³/†‡‚SUžñゖÑ(»N7M‰G1ILe§‰Aòm Á1Ý]Ò!G\£ð9!:C$ÑzOТ^Áù N"èÆT_<èœ°¨Èƒ-ŠèÙÁ…Š?¬AÅH@-˜µ™ªã ŸÀ‰‰î1BúÑair°f¢Ã$âÿÚ¯xK˜Wx0x•˜+ì#Ÿô"3T™Í?f¼äÉ*8jëðÔ4Zä¥YúÅqaZ"Ö ëµË‹®9֊Üë«âG‘#W†Oºd!+<°(rc“›2ÚulSìA`d¦6:ŒsDåB2äVdžóÊS©œ[žŒèxL„`Qá&*ûœKƒcR3öƒ¡^½ÏFOØÎ9ᄐÐ.†IqvH¸´(³ë$lír^a•(:ž»”'FbZ=Wµeî;Ɔe¦dj1÷¬ŽG¦×Ì«¶<ö8Nz[…5eOYrÒñ\/kÎñœ$ŒŠþàB‡±ˆe³fÃœ“ly¤³3c¥¯u&]YƱ<º¹ÿq‚aí8 ”ç5}‚5¹É•Å´¡»Þˆî;ÎL™“݈ÞfæXéÀÛñî<íuÜáClEÙר“–~ˆd“wäÇWB ï-eäqNÂoŠ)öm3чšÀÉü¹tråp:Z®v.RìGô>`ôšG9iâòžÇ+Ṵ̀Ð2–êsd:Ài‡s%ù‰¿yX¡Fèö9ÒÒï)¹òe=*á¦OÜk˜M%1¤ÀL’Ö¾‹1€ QêÔ4Wv ßÀ&_‚ÃY™/Ï)Ã㉨àò@bœ ++ÇŽüúEÆ% Ûø~€Q#V ÖN‘DE€ÕcùãCÒüªqòèLt fa`Ð<îÀŸcü„8”yÏ#Û3‰Ÿ;Uã'[(c-ãWފpŠ3!á·ÕóPão½á‰Î“ÇIwÎM‚…Œ9?ª~-xLã%0ø¶ãjÀêÁ鍀ÕqnÅî:¹7€çý†ÿ7kÖ¬Y³f͚5kÖ¬Y³fû‚ãÿÿ¹ñ‰_›Z:¬¯¸÷Òã}¨`;Æ oËõQžÿ=õû“ñöƒ+~{ä¿î'XkHÊ V<ø™3?,yþ1F\¿^ê9~ÖTÜ{‡\'v7ÿă&8¶ÒjöàÆªpùá—¬ZëT°+5v|Yå%˜·à̧ &«íDü ®Øx᳟@.˜×暧ÿƒ»–ÿh2&»CÊ®Ã炯ýjÁV{¬ìútÖ ŽFüû®÷Ÿ¿³Ó!èî[=·÷Ó÷Ž^U°Õè:­…Õ‡£¸ë¼WpÊ՟(Ü*vc?RÊÃáÞ³úÙ¢Cà:œwI8ý•ß=®”ù®ŸKêb¤kk?ÿúþµ¥=çcöª1Š‘®¯X皱Ý^xt*un›Ûß÷ڝ>ZÊ¢›¨C0½&Âu­Œr)l¨ãÅ:—VŸýñþKÇʚ÷©q"4kÖ¬Y³f͚ýÿ6ÁØm6ùw7Œ¿È¦DxCϟßǚ0š„%¶û>ƒJ9ž¸%É7#?ü;÷ ++fP‡·9ú´áû˜«½òÝ;Fj0K=W=€>–e:\ž‘HY¸í)u`º|z2؜ݬÉñ_[Þ fÝk0–¡Ä7a”ÞeÒ¬™4í½Žfۖ˜2›´A1žÊ¡fÔã» þaü•·ï4 ÒÐ qp »Qø#º²‰DÚy†ÿ:Š'0Ɠ¯SLU¥rÖ— SΖÑsÖ0¢Àà}}DO5Ãp¤o–³n”Pœ.±$*0þn–EþSôÁ²ý³^ԀF5cu¿šùJ⼑ä̸™.ÒGÁ1hӓÚo܎5[ôVeÊB˜˜$¤ˆq.ŒèÒ14þÿf͚5kÖ¬Y³f͚5kÖlŸ±qüÿÐí¶ljép°D0éQüÿՊôÍßúÁùµŽ³Ì€‹—üÒéó‘—JÙôùÈ/UŒ÷ì±µó Þlr)›%÷€Ï©/¯þr—“Ûå~o–2â۟¹ó¬g{îþҗ]5÷û©;Vý°äÈêOßTc N¿âÙN÷^Üx{½oãýK^èxöcéË5ΠåÁ6kÖ¬Y³f͚5kÖ¬Ùÿ΄K€$NE’VX¼6F·×ù½Å ”¦Ý{«k\*œsQ3®Â2|$’á¨`<ÞiMa 0‘„6Žñ È»÷r}Ö¤¸Žw™Cƒ d'ùS|vQb¼§ò&x¼ˆ3vA“šBb!ºØŠÈ!”é¬(j ++ ÿoÖ¬Y³f͚5kÖ¬Y³fÍö Çÿ¯üË 1µt8¸QxÂGyû\åáVÞþÅß|èãåzÈÃÁÇæöõ,Ú¶é¹î¼æÕïÏÿÖuO~—úøâìëN[Txõ½E»·ÔÜìɼúæôß_ød¹BF=7ÈõQžüÂ#P®Ÿõ„\ýÜ"ÜٌwØïùC¾-׳B?¬|¿2ÿÍr=¨aÇO>•oö`^mw”“þaic>—üȨ޾ãÇßZÇ÷æÜO¾z])»©òz¯}òî9e.R(1 kçôeo?í¶ÂËn:îü÷Õ¸‹s_^|S)³]ü³û²Q>÷aýXsø…I$R6g®÷-U³`”Ïý˜Ê«ÿÖ­ë:>ëJ_¾.u2ÏÿûßXÿT)ó¾ð¼*ã; Ÿ?Òç¿Ôñ¨ÒÏ…>=Gü8ßÂώ]ÿX‰q]?—ÌéËFy –¾LÏõþžÊe¿zl×WJ™õå¾]³û1\þOë W‹j"gDás?ñŽ.æDN…Â_ÁX•׿´æù®Ì_ï9 _{£±*;e½ÜŠÏÉ?¸ïÎR;Έ¥uOŒÆ±ÌŸqÃ/Ûq÷W&󹤮¥©q,³;=~á¤ç^Ù¿”9_üòÜì~|ËÆ6XÊRl¼ ͚5kö˱ž‹› »ÞP<„)<õÃ"(åÈ`mÇ?•Â3 iÈ]ÑáaÎ0ŧq5Jyÿ'¹Ý§ÃÂ&ä8ÿªð„O§IÞë¬SÊ\{ŒÊ8™Cïšéù¹j­4ü¿Y³f͚5kÖ¬Y³f͚5Ûlÿ¿Á¡gN-Ý¿Ó'¦÷¹ÅÏ,+œí×w ++FÈ?þ|áï](¼ýÉÌn®¸÷Q»WžX4ã­æT¾€ÃVñZÁ™sv<ìďú·ƒv”úUÖÖë“ãígOú`á#0.ʛOä#®ß þÿp_¸öªE{·×ÎÍ,­ýÕ¼¿²¶ý7‡õïæ},¸è8gÀ¨Îüçê}£kgÐo?D0Úéu–ΠðjÅ}WÝqыÅתÃ}7Ö¾Ü}G§OÏ»—2Wçú¢±ç¾VÊ¢/܏ÏéÛÅûÓÜ~®þð‘ˏ.e.•ûN­Üý£˜~áKX‰Ïq]YtØùïµRvCmï3÷®/q&¤2W9&FõÛWW¼ÓßSûyæ÷ÿQ—µC‰Kx©®“5cëo+\*wºèʦj´ßXuNyáSÃRÖëÌÏ«ú ++£˜þ¼ ±ÿ»Rfº8[dÞWã³ü‡K®)e¾+ûHÝ£Úî›æô}Õ4¸¥ŽaÙØ‚®Lwzñã1OÜüé§K™õÅ×Ã÷Žß×0ýf͚5kÖ¬Ù;3ÉÅöÊMà„|7¤ûtðyã§Ó8·âWb6Úç»8‰>–ƒ;ÑáØçû(\ë9àËÖ;廨)yá³þڐá=‚­!t¸|Ï÷?56Ã8Æ0èœIÜïd|ˆ…ÿ=(<ƒfâX&l3BÂǤ8¯0›;°Ú` yG‚Ýu 3áˆñN>z¦»+›²RÉ{‚ëhK%EÞ{O(žA<}ÕYøúYFe¢ò~|LڇĨǯå˜=ÆêÒaj¼¡çDz…'}¾ ø2G93Dƒ„ÄÊÉÙá nKÁ)'Ü(HB˜¡/‘QÂØ¢{á0>$R&ÈÍY»¬XŒäàŠ‘2Á¸ 8eÉɑ) £dbñ– 0‹.YfÿkƅÜßqcA˜êOþ ++\s¸‡tž¢‘‘)9QIÀÈ[¡ ++—×ÑL}1Ê)…®úPÂßÉþ߬Y³f͚5kÖ¬Y³f͚í 6Žÿ¿~Í5çL-¶ :1ôK7õ“.Ÿß»äú¨.Àž ùÿZÛåùçá`³äBŸ‡›÷Zɓn8˜%ý¨ŽÀM•ƒ|rþÿ15Ïþ;Ëÿ—\·Á×õýÆ7…ÿ_“Ïÿ²9}ÿ·­Yøz‰_`=ë¥ÝãñYø/¿¹Mxt޳Ÿ¯íž÷”½½ŒWw|øëjîü[[Î.¹ó*Nâ’g¿.?üÒ u*÷½Ts¶×=ñé\ÊB‡ð\C¸j뚒WO•G)ÛYó¹ÿà…++¼ªã‹ß,ý_ŽÏÚGß>®”¹N'`g_X?¶Hâ˜.Sâ%VW~ƒ¯ßuÉ®R–BÉs_-íqbÏßyñ­…oÀæ.^¢æãò ¼!ewâsÎ÷îó¥,„2†­•gᔫ?ÑñýG]òΖ1LŸÿjÏ+údáí×9u<óöã;{ìÈ»K\‡³]®~ÕoÍÿ_/u^ÄûžÓ›»œûnn·Õy?ãÑ|£”¹.?~K]ÓgŒm.ùÿÙÄÒ^ÑV(ùñ—|¡¬Ó¬M;Xš5kÖ¬Y³fï¢Mäß·B§’¹-¼@¿N}­<¹çÅó©wA™‚CFKñkKû^3Ÿ?©¨4å"ЍQ¶Óˆ†5xç¥ö\çÓ䍾{BÂLŸŸ5)ï^3ëZèCT=€²ä\G÷1à˜ÇëpÏà9„l¨obvÙ2iß$•(ú®2gÒ¥«hñ0B䨐؇Ïd´“˜„­֍¾tÁà[ÊPñÀèdSâQ_²Âïߐ3PÊb*2¾†ÇoøÃEÒ´S߂:ó‘ì ÏÐl“éãýX¨5qjL&qd²FôËS ¡ÿIG͊ïZæcI  zÌlu¼F) ++M—I‰ÚÁTnð\kÑmT?PK^Ãð2AsŽ-¢ ]¸3ÜoƒG„[¾ËãÇ;Œ`΄à“Êo¾è$Ë=1áääò·!PÿÁÁ³d9á‹IԔ Å Å ´ˆU0†€[‰@?w‰ï2ý—á<ôUQêÅ`öáP~ŸÃìò¥áÿ͚5kÖ¬Y³f͚5kÖ¬Ù¾`ãøÿâß¿aÁÔÒý«kþÿ5‡_zrǓ?k8¸ºæÖOŽ ØQqÔÉ|þW ++öºŸ…?ÙþSáçW1 ;^râæ Ÿ\,ø9õ˜òô8ü’ƒú{F±öqýKƾsDÇÑï ++ÀÆzß·Ÿ÷サ[_ʜ”‘§þ­c—Ízj4Jٜʋ?ЧŸ\ñíQ<}Kõݹ//¾©ÄBX[xÕï©ýåÚ?GʎÇç&wVéK±`û ¤/ÓkÝ«ŠEââ¯Vü~”ïà¹ï|N}yõ—;­ûŽ—áƒ0Êo_¸è§ç©¿b]úGjÅ(ßüº:Gï_òB)s±øå}•¿ª.}³f͚5kÖ¬Y³_ŽMƒù¾S½vÁ‘|l§£ÊĊ㸾ý´\ñütó}®øtñ’;§p¼jhKNýŽÿ窹N:gg2HVæ’ ϸý ŠË|s: o8Çs ++Ð{"ø9ª0S\øÝá‡/Æñ N ++:g>'$"B`h)ÈOÔè>ZÌÔfËZRàO” žêó¨Û÷þï÷¼äö;ä„ÑXEöÍÀ§m\‹Ê: S™ ïÆäb¸¾ª-óåUŒ22o°24懂oKLñx‰Ét)®z!ð‡3P}”Å¥èYŸÐYnhÖf¸¸ã`ó‡W2;ׇÀåm¯Q³:aЩâ_ %ðÞÃX*9°# A@ 9¹§°·˜MæC¯3Ý?ÚLñ3jK¤ÈëÂ? %X“5cÐÙL‰¸bKb ÂPÆÌzÄ{¹Þðÿf͚5kÖ¬Y³f͚5kÖlß°qüѯŸ{ïÔÒáàÁŠ)µ{å‰ί‡ƒ%ϚXì‚þÓ÷va8Ø Øî(/À³ûz~g÷}'v¸nFýôõLÎó/˜41â¥ÇúPÁz–v‰Ó_½äCß.םêóüùýϞôÁò}ãÐî–ÚÏùߺNôçwi8xà€¾?Gîþâù¼î“Gý›cžªk0ìp÷QM5ß|¿ç‘þ¤¬<ڕïók¯Z´§‹›@=¯V¾ƒÎ;Jêç?ÞMÔ­ŸwkÏ- ºXrÏçñYó÷ˋ¦‚2ºä¯ªã^ýµUvœ]Îþžb!ÆóäWÛÝÇü){{v:ú챎¯ –ö6×ù:oÇʛK …êòù¯Øýé»þ™Nß!—ûÖNÐ~øñ%¾"u±B9 1ë^yÿ½e-[î;¦úq4¾béÜ~ ÿ0ÿì2oB‰iØ.e×ásÁ‹×~µp¨.þÀÉÎÂç§[/x¹”EWÆðRõ§ýí3¾[Ö¯êô$Öɦç9x¤Æ±¬ºã¢Kºoi?ϯú§Í”´PmK>¸¨—õ—wN>UÓêXÚ=1,ﲓŠý‘©±Bh6>/_¹éK5­Úñ¼:·a Ë»õòl¤¼uÁkƒïýçÝï*uÁx)mx¾µoý`e)/SúöÁÆS13ŽÈÄØKõãz×Mo~²¬{ýø<²å9“S¢· â{ï_¸zPÖ?K]–´5j͎ÕO—50tJ~ä‚ýŽtíÛ[uE_¬fœk3|§ÄÜæ&Daô!ÿþ÷þ´>©Ú"C[%êlƒÉA®é1LÓBCÏmºoke=ÝM£¡sÊQHu—År‡Ÿ§£‰x'Ä˼r~;旲’-ëcõmðûnžQM«Ï\~â³q^÷2¡F¸øÔ¦T‚¿[‹NÎã=zFkç’Í:·DG_>q§ !’Û°~‰!¬ý|-•’-#«¸6Tüjkµ§šW;(áÈ'4¹À©»¤&Ü4›”áÉЇ»÷•‡ UÐÔbÖvêà5u~A)î¼Øíþ%®óN»b_I ]yï̜FûâGïÙüÕbî\±q_’å¶×ïv?Sm¹«Mö ÍÞwÔ^{Ek߅;.´Úk×òîl¶ø›Ž¯\€©ÆºËi³ÛrãîM –•8x4<Êi–ÓfÚ]?Ôìû7>óó?[Òbõm(q$_‡ë}Kהò‚«qþXÚ÷éùÇ¿µØy'Smê‹Ïy֞gV?'q÷@ ü_ Íw§½ÑØ[fŸ€l‘«bìbR6›9k¥}êŒrÿT™Îâ!MJ2;2–åtH´”wÆz¼J ~äD/ÆYbŒ½˜¶ïÜæTРa¤êžæË‘¬wÍÿ;´Ð9‡Ü<šÑڝ&þ>[ÓOB»Dn1K#ïê¢m°]¶3¦«öv}ü´jçO ++9šsm³}³WwÈÖ[§4‰ö a‰e‡g dlè(`h.M¿Ÿ»sl;†9£ù4¤§Iæ*®£çIf¾KÁÓ ­‘Ô|”îY¼Ãnc¨º<ÊI‘^(N[ÏþS±Éd.^ÁCÑVdMPô¹ê\¿â¿òýèòÏù\€ëäÞq6ï'íÌÄØ‡òóä¯;掍—rUåŒo¼pW¸å©ÂIØÅÂ{·¹qۍƼß=O|úSò{§ãºÙnx<§%jï\ÞZ\§­\ûláàËa9‘¶3¿·ׯ=¿ù’’fkŒïsyoÁµÿŽ‹öÖXë5nøå}ûî^pÉŃ/úÂÁw]ÎsöØçwµöÆ¿%§±²¿4qöžÂ‰r,r@ @0¹Û:åT×%mŒRÎz¥c—®¼ê"C¸ëbê|J$]tؓ'GC›)ñZ ¤´ZYÃPì&vÈL‡H6œGºòx6‘t1Ø »”"É#;ÓuŽ ‚6˜`”&¥dȈ;‰içÞ¯-y)}@Æ(J{äà# ÈɈ#’ÑÖküQ™ó õÉk•K4Îu&¾ :£Þâ?m5ZcÛ+RvQ‘†.‰ŸÆå")çʶ¤kì"êÝ%†º·–äyÊ;F¶x-&‹¥B¹™žÎùÊßUP÷ÕNjZ™ž¿0jH'´ç³8¹t.·Éi”bå¡Ì¼…‘4„FD憿š™Š”‘…ýc U‡ª¹Ž¥…ΐ<Ò$DB†Éè”GG¡éø‡%ᣉhDbG²!—O–IOÞ=ƒÇI™Èšá†JìEVXc Þ!$* ¢vÞ&4"!ȧPíQmÒóÊØÒÑ%•YF!Ø´ rOv$$¡e€tг™ ƒhÈýmDUb4>žØ‘2p„¢¹†¬ë½ÂÉ/óBŸ:<žéC!6 ++<ór¦è¦ŸÿŸ^ø£]3çűSçû5«¾qNán÷¸ÿ|æ—çŸ+Þð®rž× ÆÇî_Þ?ÿÚý¯Ú”ÏÑ1᜿­ñùÌÿ¿gyÖÝ~Æ«þµò¸«ñ±;'x4.Àésðÿ/ÈÏ_‰ëßù…ûóýÈûÛÚw„%ozù¿ð¾SŒGpC‹p麓¿—ïcv]“Ÿÿs\«žSæÍÇ,C¹ççrwàZýø±ÿ]â h<¿»µ÷Ôý¿÷ïù>fùøØù>9ïWþø¸õå;H²}ü>òþóÙ>ZÆMØÚøú/9û•YIÈçþ,ÿ»Xÿ5/û·|ßEÜÿÌâa>*çúx³79:×é:\ë?zÞWJš®ß>µ¼ïÏw ¾ñ75͕ï['ú<xWŸ'~N›\<üÞ2aÊ÷¯Ëw“©Å}_]üå¯ï*ß[¼+ßiŽ\ÜËÿÂpQ‰‡`\W¾¬nynœü‰œ†a[b œÛÚ÷¹Û6>TÒt¿0ÙúúïßXb:`•*mØÞÊ{ïi›¾]Ò|,õ´¹OøÀÅ»¯¸#§yScAܹ¸ŸêO7|­¤%]äy[«‹9õ‚/–˜X7sڇZ|‚KŸ~ãÏÔøª´aÅÒ&ëךּ¹ÌSûHµ¶_6Xdêw(]Þ[ÐÆþä/\U¾5¥.KæþÖtËòþÛÛhœÛÊÛ88ëú'¢Öó¾ii3ãD\´¨Ïsý®©AùFÕǗ¸¨}üëxiIs.¹\º¬Ÿ£± >8Ñ÷я—¬­ïÅچçÛøœ<“Ç'~êXº²ÅÙzïÚo–´K]öŽ÷õ|ßÝžêÓJ¿ïmsqý`e‰YŸñ’Vby°žoÛ÷;ã%­—ËmÎ_0xË­9-êú}î™üÞeù{`wgMÓµžÃ÷ι·¤YUæÑ¶ÖöÑX±ÅÏ8ûŸþDY;ñ«”Ó®ÎýðgüøÄ½îÓê÷Îñ¾v½æ=ƒ²¶–X%Áa²¯w ++›­¼ßÁ¾k0÷K[»üûÅ}fL.s»8î|½'9·RÜ’³]å=v‹ý¸µØc·ÛqS¸³åæ[IëwÒøÉÆ›ìá–Î;2Ý\ôž¯E×ï_ñ›‡³[=k4N<\`Kn¹xŠüÒä…G[#2G4ùÙCå'¿xdz:]fŽÇbVì"þvk‹·ð¶=8ò`KŸÈ ®¹ 8‰A<íø€óÏ[ØÕðÓà°Ù@˓&9*Ààé|€ÃÎ[}þ€Ýç§Z§zæÀ0ÁŽ#Zl¶q¤CçzÕÎí â k´H¡×#õüäØ;ôgMqc0E˜ž#<被e&Æl˜M™K=¹zîŒÆú˜È¥¯qjäYÇEþ˜ š6ÅiuÁ0Â1&$H ++m¹ÉÂÞ g2Œò®‡„Ã$N• ÒD_ 26_É&7"rÅ ‰±еŠ"æN‡Øb^L ‡yÀT°*R²JñÌ93;ÿp&Å Î0„õl.ǶcN -Æ „ý‹½·É2¿g‰‹À³6ºÌ£–‰£Ã¦ø¢œ‰<#àF(qP)ʼnŠÞê׌~L&ÆDp¦œ­Ñž #ë eÌ\Üú\I:RøÛ&3BåÝf9ϋŒ‡@ã,—¤Äؘí87wyc“‹Õ‰GyÌœÀCˆÉ‰”˜óœ}6GOeÖO*¯E˜šÜ„£}иEa]áèCG¡@† ë½gìÔkòâBdÈô)MÁðÀމ€Ù ™jÖ7àh›¥Ššy‹*ñ;:˒òÊ×¹„ä2±«Ÿ#.‡dâ³ ++çi,WX’8õ1Ÿ15Ëa}²Ü±ôa3DOÒ ¦Y;°àâkØT ‹JâœÃó ³8°ÇÀÕҋüÔÂ)Μ0¦{E,ꑤÿ9DE§ëZ ¿¸¸üQk–ô(¿/àœÅéËÐ腀îLŒU‘+æXDZÁFH`0xç 1r›ÎFPsüšDöSÎ2EäïS:À¤‰üœ1OŒ4:pk©ÚZc-Ï\[N¨éýŽ<,—çÊzò'+¯Åþ_ @ ‚ÃCýÿv¿ë•3SŽ’õŠ£úÿëšýÿ GØ·dݒ¶¸CÓ{^{â–s³^º³ Æ«N—ʱã.[y èQ;3>vDÎTÿÿ@¾?ªÿ?¦•{°þ¼éšOùç—~7ëᣲãcÛs>£þ{æÐÏ¿Ðt{'ïߐõù1˜4>6™ïÅrßx䏋~¾C=Co_ô€£~ ±Õó_5¯þU?øÜâ¾®õ«U—Š~pkÓ5¯7þGI ©è·5½ð;ŸX{Kѳ«®èioiv£>SM¯øÛû¶žPtðª÷]XڗwÌ«kyü™Ó>”ÓÎõé‘N+iÖ½ilãeTwÍÐ6áã“÷i¥ –ß;åÖª×7ÅÇâÆ¬3¾ž2þö¬Œ^Çy`ý¼j¶%¿ÜT)/U깩ÕóŠÁEϼ*2+¶!Gâºü›'•ö…Tëyz³{¹xï²k‹îÞ×þ[Ñò¼l°ç“%-¸’ç•müì<ù‚ï½~Wý=®ncô'^Pú=™j_qfóyôžÍy¼kå\‘K±1˜Ý/åÁæëòƒc×}«¦Ù’¦Zyïûìæ¢g×>–ö]×Ú0jpe³¯¸pÇåÖ´ªóoyuÒ%ƒj+`ÊXºr;‚_ŸVÞêÓJš‹¥žÇ.îe6åÞýlM«c÷SmÝõ‘¹zYßö/ïœ|ª¦¹’¶³ÙBŒÚ-XÔçùò•›¾TÖ:SÇîê6Fm&›oÓ¨ÁÍ­¾ú‰ÉÒ±s%ÏmM.£ö§·÷Fí.m¶TŸý“³ö¿­v.Ç´žÓ–¦ ++Ou4AçØèØLüg]ä1ˆ¦XŽÃ2Ðrç›ÔešpÑ "e‹Åa‹ao1Š:šRÌeÛA³ ƒ:(. óÙp%ÚØjš º€ÐÕ Ø<Ú Ñ}‚všòÊòËvÓ8ã¢R/+ïóƒ £”† y“7¯M•CÞôɎ#1wÏg ú@ @  õÿo?êìߚ™:>vfÖCòÿ ùë^úÍ£³Þ;&åzëìzã盎wjpÙIU¿Ö]XlºÚ™º7@ @ þ¿1Í>cÄ~èâ‰,6ž —Ãóÿ¢gϽqf{'Æ6·óüÔ''©Üo•íêœv-®Çþñü'‹Í¶wÅîuk;ëÚü®n6üdétÞu8퓿ÐiòÐêdé>B§pO/è:-öÿ@ @ êÿŸÚvɓ3SŽÝœ¿Ìäù{0Ç«õ ØÞø¼^»íË}òá“9ãȑµåê×~¯Þ7¸¿¤ÏÅçW­+qÙº0^cò^׸½¾pΪÿÉ÷wãcÏ4{ƒ_ÙÄ;òýÄ|kœW§ì·_,| ++åÞßÊ=˜Gð3ÍÞáàx%vÞ[q÷£sÎÈ÷;Æÿ»¯µ÷ÔýïÉù{§ÑÞÛ_؊ÇWý¨Ä LÈç¾eÃç§Ç ü`–ó(OáÎ9âü•¸_³Çù»kžX~…‡Žå|ú“•kŽ!ŠrÚ5­nï|á¤Â1hláF»¿ÅüÛ6|©¦…bò©y¸ n1Ö¶ ®¸µò֘uw.¦m¹§¤ÙTÊ;bi_Ï?ع¾Ô“Œ"9í±Öw£q'ã¨ÿ‰mœq?|Ýy—4oKÚEK†uùîâ’+gÜ]Y֯ǵöc÷UÞÂTäyô4¾Ã™¼…·5¾¼ÑX…O4îÅKŸ}Åg«íŒ)í{>·Æ8wÿÚۋ¬õÓcù±Ð-OmY^ãVN<Ûd}ÅàÁÂ?èCåü;·ñ9ŽÆ*oråIÜÞæÿ¦Çï]RÒb/74;ž+Z÷‘Âw˜Ãq¼4ž½«~ñû*ßaåW|"ׅÞ¶}MáÒcH•C¾JÖsÛòË¿Rx S,í»Y?×ì3·×‡ºÊ¥¥QÞB5cp¦-Òö<®×ùߙú»Â¨êø¼¹½75Øûá’f\)ï@ã;¼iצÊ#èBéÛ[ûþ£Âõ8ä|¦ñGNî9õ—‹Ÿ“ªƒÏÍéÕÇbœps[ûÖ6¤ðªTúý®Æ¹îßýµ’»ÒG;ۚ<Ê[øÜ¢¾¼÷žTæŸªŽ‰mK†å͌›xuãU›xç´¸‰3ù's]¦p÷­3®-i®ò9n×;pûõÏÝ]ÒBG…Ç“‘/;vóë:ø\“Ù,1[|ÇјŠ%¾#ØuӛŸ<8¦âù­í39û؏³Å[œ;£q6¾áêšæbwºt˜çí‹KZ %íš%}­Ù±úéòû:%—Ÿ ++d´ŽPֆŽ‘ìðû¢-z£Jj]¢´¡×I—4m9¿Úåû•ËΩC͵ÅÚÃöƒAÐ\t(}ÁAñÆgçÄ2 B é¶ÁNE´!zò~Y’¥iR·aùÜc¬-›EC‰ëå!žÿeïêcö¬îrŸò´@™ ++Š€ŠP¥´ œïù°KŠc„o ++h¡:}¡@j‚ŒEÂêdP¶ÔØ?ˆ,¡ $6À6F@êÖ(8*’Ò½-ÂØ\A׀âïúsŸçá}ž÷5Ñ4nöweO—÷>÷}îóuqý~×ç4˜ FëҞœ³£[‡ñÚ 6j=ÎÂbièè5ï ÷µ7ça\èithúØ0î(ŒY©ËѰÑÎ*Î nmFx ++Ú]ìVdùhò Ì#i d:cÆûrÖ|g4HT½èå vžÃ‚3jîAK·'1´âË6­^Ù]³éüÉYÙ¶S*é™WÕCí«qÒÕ¿Fjð93P$‘9¬!˜a•»ñöTbkËA—Æ~i´´!­ç ÑÖÚ3΃oœ÷bŒ8RÖuÔcõ©ÝMÐZfh³Æú1°–êß4þW£6V~.m®xúÁx^[bÈ ++ú‹j£z T×:,2˜ÀY^?X-›`AIKIÓð`"gÒÖË4*0÷ëô(-|ìiI×yi^¨.YXÔÑú£)N0Œ¤FñŽôæà©yt´]ĹéÒð„Ä¢w¬BéáÌý>HZ8öÑE ++‡;šEÖÚóÚYeiÑ«DSÏýÁ• ++M?0Ò“•!@Ù­‘œ Ú)@ZَÝÇzjÒm,ÐÁžn“¶ãÒ ;]ÜǰéV`¡ LZ-7@ÈAÒ­OC5/Áh7¼¬S»1pÔôDUµ;±èñ.H#¬\ˆt×Kt^O£5Dè²!`Ä Ñ„R£,œ33V(ŒiÊ ;k&—×$ ‹›Îc’–S 4vh_§“™ HIÍì|þ†}ÿþ‰*%šº‹D¾ Öc-4¡£hëöCy Âÿ @ @°7`Àÿï¸ä–N-ݯòÒ£~~'òöÂó¼²ð{Ùö{§6Ÿ¿£¯[ô…;Ñz˜‡?~×7N©žU™¶3?qá3ϖøhûræDFýÿ ++o?ÊÃÚ8·5Ÿ:žã ¼±¦_¹?p@«.\P¶{KûßÐ8ë‰gy†yx Ÿ¿§[û?¾»Ôû”~ï…!~à 8»·¸Ã(g~—}™~çè‰í¥,U~ôþvžëŽX³£òԕGš?ęOå¢×ÍéŽ;wý'_¯œråÌWԝï‘_¼âµÊãVþ©p§ã=í–5Ÿµ¥?{öŽZVùû­Í¯p”ã=²q™¿ûý…J™í|òš—áڇ.¬^x©ðͅ÷¶úû¯ÞZÊRõD[Âý[L¿ îÒÂÑçËùžhu¾wïªÊÎ÷×9Þ oSã᯿¯ó­ë¸èâ‰~í†[.z³”yUxÀS/~Þ¦«Ÿ¯eºôa}ãïÏß¶ö„η®—ÚÚzx֕ß-e©zý-šS^ÖøßQO»%W½ì­Ÿÿ™ÊÿÖ±^2[â!®ÂqÛõý…;5Õ¯ð6·£:‹ìÖÄ(¯:ˆa¹xòþ£kY,cýÃ!¹Í÷Uî´òÔáãî@ÙÖÇïù0¯Úo1¿óÒËÇT՘Ž#fà\¯mkb*ç*‚=ƒaO¸;4‚ÎÀ¯*„#—wÎØ@7yn0éˆèíRáËÖi>®-ð«®Ô;ìƒç³ƒ}ò[=ícC¤Gó°)SZ±½½Ð™D¯ Æ*£˜Õ‡FO¯‡-à4ôÄÏt h2zŽÁ[žt^’OÅRͲ±žñ°ùƒË®†%´+Ê\+EÕÛÔñ˞±Ì§{Wþ¦g’öZü7ÕË®DYÓ2ùa–ÞZS`ŽÞÑÒSçŠ}_ªc@ ˜)w Rëôaç+ŸU…KýêÂ0?=Ÿ8]ž²¬]½öƒ}©ësÕy"Ƅö °[³4Ç.§Ê5ÒdX´B±·]HàRAÁÃd Ä2ֈ  ¼³4]6F@°ð¯£‰¤î+ #MB° PéÔ1¸Ìl0µ,8¶[䐀éCA…=ÆÕ²Ç•{ANÇ0ÿÓèI¨=fUqd ++]tpôƒI!ìã轘º§‘wîpyeZŒ*Ók(µŠ­iUDèËÂ"š‰¦"ºˆØ"º ++k‹ šêa6™Ž¦^ÀÅ."Ȃ–oFü €§¾Ò̧Ç@£BL6.¥¯âžÁ7’>RhP¢b±§<5aƒi" ŸÇcý)-VE§S ÿ9]â-V?-Ãċ A²˜qº­QãpñÐEé¼F,$âY“a¤I·Ì}Ftì ++i4‚.„[j¶t›Ä⃠d‚Ob ¯OÄ¥hº-p\°ðÿ@ @ ì ðÿÇ^}ÛM-ݯ·³ål®[¸íÌÂ;†Yýޑmûq»~õòÂáæÜ¯Úþ£yû›xûhÞþrÞ~ýlÙxowž¶ÏkõÌ9ç×¾ÅÛ£Ò³{ýü\+Í·~«å*/{þ’……Ö5Ï÷¹–«ìöY^øS$\pÙGZ¾õŠmgÝÑqDžÕÎ7Ê+Ÿ8—{D»©©@ @ ö †â:m~-ÙCŠ£áÈO@McH`*Ç?UKÂz«WLô13ôYi¤¬ÚCÖ#a+‡fxED©Ø¡ý‘³Ê}W+è-Xp §k<Êtz Æd_Ñ~.$X ÅýPeJ!Ì&„éáÿ@ @ Ø+0àÿ/~oßw§–î×ÛØòó‡õÿ÷«üö¨.À­gŸ÷­Ïž[8xú5yT/`ç4ùÿ©é•æ´Ãž­çýÞú¦g=Ðï­l\ü[~ù)Ö 0žêßÎùÁÈ ÿÒäÂwy{F{V5~Ñ®/_ÁºÉ›~ïNn矢=ï|Œ9ýà í¿xÝþ÷yûbúÍêð-¬  3µóÔï°ùí£vóöhÿUM¯ú¨Sþ€ÇMiÚ¾¤å¨_yÆáß)Ûá›0¿é|î¼SÇÙuZÚãõÿWµ1ýÄ+ök՛¡æ|ßÕ4ªGõÿŸœ!¶b#w-Æòè/-¥K^÷ʦÙ>Æ ÕyîIµNíª¶ÀÒÖÎUÿxc.e¡æÞonósÍäl[ËLÉi_Ü´×ÿü·.›¬e±èˆ¯mëïòç¯;¶h'¨Tb9–5mN¨:÷Ö©Röãv¾‰ÉVÿª½~jÓîÕ\XÜægÓ#×ì,e)”:—7ýñO¾üͪÕ_óòomëXýÉ¥ÿT´ú³)ã2ÑÆlT«ÿÑÖΫ'—”q‰¡Æœläþ=L¿•ßý†¯e¡ŒËº–ë?ªã¿¡ïñë¸$]µÐošÛ]çWìœûÇ¥,Ôµ4Ðô¸jrŽ­Z ¦Ô¹yÿ®/=6ñJÑjð¾ŒËkíÚØ}ä…;ªVCõ)x¨é1ŒÆâƒ³è·ëޕ;k¼MÕPmyÕ1Õ7@—yx¢imŒêF,oý»xò¾ÛŠþCŽ¥lË ^êÕ¥]Yõ¼¸y­† m\Fµîj'£úøEü+³ÏØ^Êbõ8tn·&D_ øÉrréiÆiÎÆº¢ Ð÷ÉABßÓ;=b æn2,9Äã2ð·F:î÷6Ð,7ôn=%lbvô'Ì À YzЍ/*ª+¹àR`XL?DjC¦¶$°«`³á´hä Ó^H¹…ÑB²ðIÊT_²œ›ì!#oƒ Œþ/"A;G‡Ä‹¾ ‘ºèqŠ$÷ìS§¿M tМôÊÃ9½ÙÏ だá¼mf¡}ևO3ò{° àlmCCÜ4ê‹Fñ©ýÈ ++Ö 1ñ¶¤K†·²êý°§Y¢¦rŠ{ì¬`½°Äº’]( @­²lÈÓé¶ÓÖYc4zã՛"CWɰ`l&<ÜV¦Ñ€ÔC¦IPÈéÇ8`Í@cˆ5X€FÀÃWV‘¦qŠPp éóuÅBk Â¥!CY?CžFžxŠÈЧM°³€ j2Ž&”¢|¤I.$Ë£ êÀÜÂPÝüØÀãleÿN»Âi$W`Œ9 )->4“•±C¢k"%ØPšÖG¸vÐ3y\hPXZ~X/Þ(¥ñ˜u0dÀ¤cœ£i@oƒ†À:“7 4óЉw0èà~@…iôŽå ²Õ郇ý,ÖSnj¾Ð*L3x2LÕy(úü´:¡G’å5á 1ŸaF¯;ýúZ‚: 8ä.¯ŸÊ8ÂÎ`Šc8÷±^ còîé…ÐdÎõ÷Ðoˆ©jeŒÕ0Ԛ˜i 2B¯}tSˆŠ.6Å÷úNÁ°â>†µ¥X]‚fÑó`ŠN Òð-Rû1ŸÈíϺ^Çôj4ÕÂÒÝ ¦)TW¨ëÉÐÛ1½èFhP„zMã®â‹'…MCž)µ?¯ÐÅ-”k‘¦_A+Wc­ƒÃ `$Â-ôÿƒkWø@ @ ö ++ øÿ[9ò+SKû½Y÷>n×§N¼ô­CÛ¯ÿhá`ï÷–N£ pDóTþ°/ÀüVχ}Žl<Ù¾ß;ô;…?W~vÕ ˜†žÁO~ŸÆƒýÞk®¼°*|Ö¹l¼ßúÊç0Ê.šAǾÄG€çtAñÇ«Úêm,FýÏ ÷ûgô;ÿ­…Åÿa{Ö@~<çXâÆû˜ÚøÏ©^å@ `ïAÇß+ ~}|Å\yt]ânb0].ü8~ޗIrç\ÔàÊM@„Hbß ++ú6Ӛ£M"í‚XïøTäyû¿B²žš‘A¸ûäLð>Ä¢“”!#XÀf }LÉô°YðŽ•ü="D7ƒÐ ĪÀÞ#&[g bL‡Dߒ*!"ÂÁB%E›b\<¢p3ò8OkÑvϱ±üw„o§í#L±7ñ/ScŒ¢SÐ÷°öA7&ÐéµJø`M*Ä |àp‹IÄúÀP!Âø#"¼ÄFÅãæqKþN™&!…à`3è/Øk jћ0¹Ð™j Ñ§YrVø@ @ ö ++ øÿGÎ:ùå©¥ýޖæEÿaž¿äçC·ÿ¨-/*ùÄ>vqÈ =îoÚZòMUê÷În~÷Çîþã<|­iÿ-œK:šŸ¿³ååð±C¾Íùù ++õÐr±?¾ûøå¸er¿z™£ v]Êùù)ZÚ~6ïŽ~Áû;Wsþ|ŽivïѦ/0šë¾a†|ö›ZÎìšÉ«ï.1¦òìgs›Ï—_~zËoÝ}àêm¥,º·°¡y­¿úÈ9ÿRrȃ/eóù|ãsÈÜò…Gsȟ8°+ûԯ׶D«ÊqOrãcֵЫ&·ÿu)‹¾Ä&ÜÞ|®?ìoԘ†š{~yÓ5wØØÆeƒ»ôåš'K[NmþíïÝ»ªÆBXWú°¸ÍõhœÄsvëæäc/x»æ×<ñþPÞö¢ÇK¾·³¥lã]n¸å¢7kžxÕ¸³­‰K¾Ôù9$]âGnnkb4Oüˆ¦GðKÇ\9YóÄm‰-™w`·þÎß¶ö„.f£œïÄ¡¼í÷”¸ ëKËçvó>šïýè 9Ý?l¾?zø“%‡<Ě_¾¡åQ¿û•ß+9Ý´Ò¸ì5.[N¿sv,)q'È#â²[[¾÷h.øW‡rÈïç¸ä镱^És{ýÎÜúø=Õç¢æ{/n10_ÿüi;kÜO(unn}_ÿÍ%oÔ²Xæ}^;ßh~ùâ¦UpÚö·÷«Þ#¾êB̐_>_òˁ@ð?ò›U%ß=!+Øv:Ý?‰~ê³Æä[s[èRz לä@ï?mÿi´ ¦r¢–Þ풉ð4Óúßò¤]nóØÜåªPòßéUÚyåC±dO]¾ý0¿º‡thŠ ÿè pÚ5_;æè‘ ++îSÈà­©I+yHÈS7SÒØ$bf-´ßs —[äð;p¾žÞ±¿·ªH)ß̃ǢIO5ƒ°NP¼ ¶G$•å|ë@§µ‘Ö‘‹]Žùžò¸ŸNê`Ÿ9¯]ÑwýikÎýtSsóY/$Ы]Ԟ¦qo2.Lð´ê=$"º9“÷ }h$MG†º†¨NãÔè£*%ç Ö@W M9]‡¸OwžÛè!Š ÐEËñ žs½½qØË'Ÿ.ü¯s®p„ï4ÎõâÉ3KD2g ¸ÓÂ-Î{°jØrÜk3ð•k/.ü¡@ @ ø¿çñÃË)f•é›Ä"¥^ŸA‚'˜"¤˜càttk ’ÊurÞ¸˜Kƾ9î Ç4e(ð”œqô‘†HcCDª:Œ|  ¢8ÌBCÁYõÉX‹Ð„f¤DŠ5e¯€˜¯TópA ŠvLˆ{ ŒQ& ÆGúS±a„£h3UJ­B"¨­ÈÚuN‡BUÆÖ̚ÆC '· eÙ¡Æ(:kȁúèU@ø Ô÷i¤¿A?Ã،ølV ÖG›²üÜ)â |DèGš1–"8kyVôTV0 ++°:aÞh¬gh ©[Ö ++˜1­¢ƒyU£èüYEHÐ~ =&>¡ûql@ @ @ @ ‚Ÿ~Hþ¿@ @ òý/@ àÿú¿ò¾SKû½}ØÃë6úm~ñˆ±^^ ®ß{ˆ·Ãí3§ölÕŒýÞföç‚/à‚-ÏãíÎû~oûll‡¶Þ¢]îyöùóÊö{;y;ôúö^)Û]ê÷Nl^lÏò ¶ ?¿Ó›ᢿٗ}æBRԞ'›ÇÜü§ßÂþ:S{f ùÞÎ~hÉÁ§p^óÜ;ꔃ?`=B¥ÕìÞÓ¼ýVú­¸ïœ‹/ ÑEð}nëµô»àè¥L«ê·±y–]ÿ›k^/eºú¼-k~ýåĶê˜KÛçtí[3¹æ±RærñH[?wPöƒý‹g`ªpOr¿~myà²âÅçtõd›˜ÓõmÔOp ÷ÿlz䚝¥,…â×v眮£^ƒOr[¾@¿+ßüÜÅk°ór›à:—ÑoÃç/è|céߺæ·7êø(Ÿ^u/=6ñJñ÷ó¾¶eÿ®-»¼pGõ÷sÕW®ùµ¹}–o<íª÷Û¿M£'¹©­Ù›Zýb)c‹—捇ƒWl;뎪5©Š§ÞÒ»óz®k}8oÓÕÏ×2]æá†¹Ýù>8i¢œÏ:WÎwzӚ¼lòô“;_À҇­¼Î mùß¼¼h[Қ-cýt;ß!Ç^þÅûÏÚâáwÿœî|7ž´ºxÿùX=74ß¼“U|U.ç+¾•k0Gw¯þA)ÓªÖ¹ÿà¸S¿VËRYó/ÌéÖÒÚÇ/(~‚pÂᲇڼúáK_ïÊJ[vÖÙ1+Jÿ¢ªí¼«y>Žêl^Û¼<ÏÜñ w—{Žª¾Ž7‹‡Ÿ@ T°Ž–nþmt‡5ôJ²q ÖmÅSMi«üȼ†AZ0Æ9ú7$©éÅÁ¹ !/µÏ .ZNøc%z`y<”SpÊE«¹m‚W©ÞbTmö)ÍàgF·ñ`,œçèÀ½æ—S ;éÑsѱÇ̆Ùó+òß,¦“ò»Ó)†¥ ³½˜L²ƒ2ÅП=u\ÓI!FÝ¡7’D'KÊÐáD³†Ú«!‚æsf?9ȗÑ3ÓKVDÑu:ßè@m‚¸XT6Ág޶+Kïx¬Ùœ1¸VÑsZ:Av¦øÍù˜±+ÔØ"<¼Ì ­¶xÝY¼ƒ°ÿFÇdi"-»ÙÑû°¥9a 4c`:W´ÄØeÎӞ4òp‡KqOj­ÁÝ Nl–-ïèøÎ7OýW{gbW†anwd›4b#bLùÿi‚…‚…A;Q‘°),ìba ÑBÁJ›B,"–¦S ¨Hü©DÄ÷ýfîÉÆì¦ ++yŸeYöœ;sf¾ù¾ážfž^ σõǺîå<Ûíü2Ì: ïÜ<剩¦yŽ|ôە`~=;-ð:<¤Œ€6^- FÎÉd„È:tŒH"ÍR¦âV¾c¦JqñÐ!$™3fÎׯŠn¹Ṷ́ƧUnã§ÛËUˆÌBB¡ï`îºÚjų‘÷ˆ>­}>#á{¦ÝÑÎÝc%òÁôsS0È¥Å×¶ìM,hV’åvDŽ {7_ ++TGbñk¡0;sàEª•/EøŒç±tè>ҘGccB4kDÉù‚2á˜xÀŸeò¥ 9ÌÈ ++½q R`GŽÓ¡œ·\âIƒXA”cÝ8üÐ ÷dr¡ÍÏÏu¤yÒ]ç,¼±/P`ˆò±Ï;¬V"bóÉØ)B›¾½ˆØa¢”\"K±+à!ئ°²žžÁˆwzóxŽE€éFsU}™u‹§þ«……ãcQS4p:‡·¢@nôH›#Ç˗Â⸏aÀhSýfÌØ])VtH©†ü¤å©G': p³Ó«ˆŠˆ•Ç£‘ žAÀ«V«–©ÏÌXT|"$ǽ;1ƒy¶_CqFîKqÄ(¡–:ö¯ž¸°¨–‚j(ÈÂÃИNB„µŒ1q'¢¸Ò^…B!„B!„B!„B!„B!„B!„B!„B!„B!„Bqƒ‘ÿO!„B!„¸¸âÿ»üÛ¾ÿ}w½ztñjm¿|߯Çãzõ±9Ãèá»çÓOWœ¯ëÕó‹óìáûo^@ÂzõêÖæúÕ¾ÀËv.°Ï9ð·]%¯Wg?ÚÁßßz–×sËìÇú?Ëþ¿ºóOóÿ•€~Üm›ñ\ítËxž;|ÇgÃóýzÕì:>uïvݧtËêÜuü¯ìðñxozüüðÀ]47m§. §™§©Äî½±u¥Ýkw _(Ã-÷®Ýcãíï··¦soºnmbÿ͇/ü0¼zÃi³qËñy/}ðÌx^«mxÒZæ|üî§. ç^ð£Ý—6Î#ø=´ÿÈ/Ó«7Ýy—µ¸Ö¹7¼á÷‰Ÿâ¹éÇ Ã÷¶ÝÛ݁waY÷§Ï¾øÅ¸×üpĽ¿ÜûëÖ—†¯§Ñç¾eîÇ?96x›v'—ù]ë¹{s‰ç±~gúêòô0.óûúüÑ1¿æg<Xòù跏¿>îõéSüƒÎѨWh:tÔȅîKí%¸LqaÌÙÇ^›§`/Ò4éóõ…„o“Ñ /dev/null ++if [ $? == 0 ] ; then ++ echo "skipped for tmpfs (no O_DIRECT support)" ++ return 0 ++fi ++ ++$MKE2FS -q -F -o Linux -b 1024 -O mmp $TMPFILE 100 > $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "mke2fs -O mmp failed" > $test_name.failed ++fi ++ ++$FSCK $FSCK_OPT $TMPFILE > $test_name.log 2>&1 ++status=$? ++if [ "$status" = 0 ] ; then ++ echo "ok" ++ touch $test_name.ok ++else ++ echo "e2fsck with MMP enabled failed" > $test_name.failed ++fi ++ +Index: e2fsprogs/tests/f_mmp_off/name +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_off/name +@@ -0,0 +1 @@ ++disable MMP +Index: e2fsprogs/tests/f_mmp_off/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_off/script +@@ -0,0 +1,30 @@ ++FSCK_OPT=-yf ++touch $TMPFILE ++ ++stat -f $TMPFILE | grep "Type: tmpfs" > /dev/null ++if [ $? == 0 ] ; then ++ echo "skipped for tmpfs (no O_DIRECT support)" ++ return 0 ++fi ++ ++$MKE2FS -q -F -o Linux -b 1024 -O mmp $TMPFILE 100 > $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "mke2fs -O mmp failed" > $test_name.failed ++fi ++ ++$TUNE2FS -O ^mmp $TMPFILE > $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "tune2fs -O ^mmp failed" > $test_name.failed ++fi ++ ++$FSCK $FSCK_OPT $TMPFILE > $test_name.log 2>&1 ++status=$? ++if [ "$status" = 0 ] ; then ++ echo "ok" ++ touch $test_name.ok ++else ++ echo "e2fsck after MMP disable failed" > $test_name.failed ++fi ++ +Index: e2fsprogs/tests/f_mmp_on/name +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_on/name +@@ -0,0 +1 @@ ++enable MMP using tune2fs +Index: e2fsprogs/tests/f_mmp_on/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_on/script +@@ -0,0 +1,30 @@ ++FSCK_OPT=-yf ++touch $TMPFILE ++ ++stat -f $TMPFILE | grep "Type: tmpfs" > /dev/null ++if [ $? == 0 ] ; then ++ echo "skipped for tmpfs (no O_DIRECT support)" ++ return 0 ++fi ++ ++$MKE2FS -q -F -o Linux -b 1024 $TMPFILE 100 > $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "mke2fs failed" > $test_name.failed ++fi ++ ++$TUNE2FS -O mmp $TMPFILE > $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "tune2fs -O mmp failed" > $test_name.failed ++fi ++ ++$FSCK $FSCK_OPT $TMPFILE > $test_name.log 2>&1 ++status=$? ++if [ "$status" = 0 ] ; then ++ echo "ok" ++ touch $test_name.ok ++else ++ echo "e2fsck with MMP enabled failed" > $test_name.failed ++fi ++ +Index: e2fsprogs/tests/f_mmp_corrupt/name +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_corrupt/name +@@ -0,0 +1 @@ ++repair MMP when it is corrupted +Index: e2fsprogs/tests/f_mmp_corrupt/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_mmp_corrupt/script +@@ -0,0 +1,41 @@ ++FSCK_OPT=-yf ++touch $TMPFILE ++ ++stat -f $TMPFILE | grep "Type: tmpfs" > /dev/null ++if [ $? == 0 ] ; then ++ echo "skipped for tmpfs (no O_DIRECT support)" ++ return 0 ++fi ++ ++echo "make the test image ..." > $test_name.log ++$MKE2FS -q -F -o Linux -b 1024 -O mmp $TMPFILE 100 >> $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "mke2fs -O mmp failed" > $test_name.failed ++ exit 1 ++fi ++ ++# create a corrupted image ++mmp_block=`$DEBUGFS -R "dump_mmp" $TMPFILE 2>/dev/null | grep "MMP Block" | awk '{print $NF}'` ++echo "mmp_block is: $mmp_block" >> $test_name.log ++echo "corrupt the mmp ..." >> $test_name.log ++dd conv=notrunc if=/dev/zero of=$TMPFILE bs=1k count=1 seek=$mmp_block >> $test_name.log 2>&1 ++ ++echo "the first fsck ..." >> $test_name.log ++$FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1 ++status=$? ++if [ "$status" != 0 ] ; then ++ echo "the second fsck ..." >> $test_name.log ++ $FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1 ++ status=$? ++ if [ "$status" = 0 ] ; then ++ echo "ok" ++ touch $test_name.ok ++ else ++ echo "the second fsck with corrupted mmp failed" > $test_name.failed ++ fi ++else ++ echo "the first fsck with corrupted mmp failed" > $test_name.failed ++fi ++ ++rm -f $TMPFILE diff --git a/patches/e2fsprogs-tests-f_random_corruption.patch b/patches/e2fsprogs-tests-f_random_corruption.patch new file mode 100644 index 0000000..0d64b48 --- /dev/null +++ b/patches/e2fsprogs-tests-f_random_corruption.patch @@ -0,0 +1,330 @@ +The f_random_corruption test enables a random subset of filesystem features, +picks one of the valid filesystem block and inode sizes, and a random device +size and creates a new filesystem with those parameters. + +It is possible to disable the running of the test by setting the environment +variable F_RANDOM_CORRUPTION=skip. By default the test script is run only +one time, but setting the LOOP_COUNT variable allows the test to run multiple +times. + +If the script is running as root the filesystem is mounted and populated with +file data to allow a more useful test filesystem to be generated. In some +cases the kernel may not support the requested filesystem features and the +filesystem cannot be mounted. This is not considered a test failure. + +The resulting filesystem is corrupted with both random data and by shifting +data from one part of the device to another and then repaired by e2fsck. +In some rare cases the random corruption is severe enough that the filesystem +is not recoverable (e.g. small filesystem with no backup superblock has bad +superblock corruption) but in most cases "e2fsck -fy" should be able to fix +all errors in some way. + +After e2fsck has repaired the filesystem, it is optionally mounted (if the +environment variable MOUNT_AFTER_CORRUPTION=yes is set) and the test files +created in the filesystem are deleted. This verifies that the fixes in the +filesystem are sufficient for the kernel to use the filesystem without error. +Since there is some possibility of the kernel oopsing if there is a filesystem +bug, this part of the test is not enabled by default. + +Signed-off-by: Kalpak Shah +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/tests/f_random_corruption/script +=================================================================== +--- /dev/null ++++ e2fsprogs/tests/f_random_corruption/script +@@ -0,0 +1,272 @@ ++# This is to make sure that if this test fails other tests can still be run ++# instead of doing an exit. We break before the end of the loop. ++export LOOP_COUNT=${LOOP_COUNT:-1} ++export COUNT=0 ++ ++while [ $COUNT -lt $LOOP_COUNT ]; do ++[ "$F_RANDOM_CORRUPTION" = "skip" ] && echo "skipped" && break ++ ++# choose block and inode sizes randomly ++BLK_SIZES=(1024 2048 4096) ++INODE_SIZES=(128 256 512 1024) ++ ++SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }') ++RANDOM=$SEED ++ ++IMAGE=${IMAGE:-$TMPFILE} ++DATE=`date '+%Y%m%d%H%M%S'` ++ARCHIVE=$IMAGE.$DATE ++SIZE=${SIZE:-$(( 192000 + RANDOM + RANDOM )) } ++FS_TYPE=${FS_TYPE:-ext3} ++BLK_SIZE=${BLK_SIZES[(( $RANDOM % ${#BLK_SIZES[*]} ))]} ++INODE_SIZE=${INODE_SIZES[(( $RANDOM % ${#INODE_SIZES[*]} ))]} ++DEF_FEATURES="sparse_super,filetype,dir_index" ++FEATURES=${FEATURES:-$DEF_FEATURES} ++MOUNT_OPTS="-o loop" ++MNTPT=$test_dir/temp ++OUT=$test_name.log ++FAILED=$test_name.failed ++OKFILE=$test_name.ok ++ ++# Do you want to try and mount the filesystem? ++MOUNT_AFTER_CORRUPTION=${MOUNT_AFTER_CORRUPTION:-"no"} ++# Do you want to remove the files from the mounted filesystem? ++# Ideally use it only in test environment. ++REMOVE_FILES=${REMOVE_FILES:-"no"} ++ ++# In KB ++CORRUPTION_SIZE=${CORRUPTION_SIZE:-64} ++CORRUPTION_ITERATIONS=${CORRUPTION_ITERATIONS:-5} ++ ++MKFS=../misc/mke2fs ++E2FSCK=../e2fsck/e2fsck ++FIRST_FSCK_OPTS="-fyv" ++SECOND_FSCK_OPTS="-fyv" ++ ++# Lets check if the image can fit in the current filesystem. ++BASE_DIR=`dirname $IMAGE` ++BASE_AVAIL_BLOCKS=`df -P -k $BASE_DIR | awk '/%/ { print $4 }'` ++ ++if (( BASE_AVAIL_BLOCKS < NUM_BLKS * (BLK_SIZE / 1024) )); then ++ echo "$BASE_DIR does not have enough space to accomodate test image." ++ echo "Skipping test...." ++ break; ++fi ++ ++# Lets have a journal more times than not. ++HAVE_JOURNAL=$((RANDOM % 12 )) ++if (( HAVE_JOURNAL == 0 )); then ++ FS_TYPE="ext2" ++ HAVE_JOURNAL="" ++else ++ HAVE_JOURNAL="-j" ++fi ++ ++# meta_bg and resize_inode features should not be enabled simultaneously ++META_BG=$(( $RANDOM % 12 )) ++if (( META_BG == 0 )); then ++ FEATURES=$FEATURES,meta_bg,^resize_inode ++else ++ FEATURES=$FEATURES,resize_inode ++fi ++ ++modprobe ext4 2> /dev/null ++ ++# If ext4 is present in the kernel then we can play with ext4 options ++EXT4=`grep ext4 /proc/filesystems 2> /dev/null` ++if [ -n "$EXT4" ]; then ++ USE_EXT4=$((RANDOM % 2 )) ++ if (( USE_EXT4 == 1 )); then ++ FS_TYPE="ext4" ++ fi ++fi ++ ++if [ "$FS_TYPE" = "ext4" ]; then ++ UNINIT_GROUPS=$((RANDOM % 12 )) ++ if (( UNINIT_GROUPS == 0 )); then ++ FEATURES=$FEATURES,uninit_bg ++ fi ++ EXPAND_ESIZE=$((RANDOM % 12 )) ++ if (( EXPAND_EISIZE == 0 )); then ++ FIRST_FSCK_OPTS="$FIRST_FSCK_OPTS -Eexpand_extra_isize" ++ fi ++fi ++ ++MKFS_OPTS="$HAVE_JOURNAL -b $BLK_SIZE -I $INODE_SIZE -O $FEATURES" ++ ++NUM_BLKS=$(((SIZE * 1024) / BLK_SIZE)) ++ ++log() ++{ ++ [ "$VERBOSE" ] && echo "$*" ++ echo "$*" >> $OUT ++} ++ ++error() ++{ ++ log "$*" ++ echo "$*" >> $FAILED ++} ++ ++unset_vars() ++{ ++ unset IMAGE DATE ARCHIVE FS_TYPE SIZE BLK_SIZE MKFS_OPTS MOUNT_OPTS ++ unset E2FSCK FIRST_FSCK_OPTS SECOND_FSCK_OPTS OUT FAILED OKFILE ++} ++ ++cleanup() ++{ ++ [ "$1" ] && error "$*" || error "Error occured..." ++ umount -f $MNTPT > /dev/null 2>&1 | tee -a $OUT ++ [ -d $MNTPT ] && rmdir $MNTPT ++ cp $OUT $OUT.$DATE ++ echo " failed" ++ echo "error: *** This appears to be a bug in e2fsprogs ***" ++ echo "Please contact linux-ext4@vger.kernel.org for further assistance." ++ echo "Include $OUT.$DATE, and save $ARCHIVE locally for reference." ++ unset_vars ++ break; ++} ++ ++echo -n "Random corruption test for e2fsck:" ++# Truncate the output log file ++rm -f $FAILED $OKFILE ++> $OUT ++ ++get_random_location() ++{ ++ total=$1 ++ ++ tmp=$(((RANDOM * 32768) % total)) ++ ++ # Try and have more corruption in metadata at the start of the ++ # filesystem. ++ if ((tmp % 3 == 0 || tmp % 5 == 0 || tmp % 7 == 0)); then ++ tmp=$((tmp % 32768)) ++ fi ++ ++ echo $tmp ++} ++ ++make_fs_dirty() ++{ ++ from=`get_random_location $NUM_BLKS` ++ ++ # Number of blocks to write garbage into should be within fs and should ++ # not be too many. ++ num_blks_to_dirty=$((RANDOM % $1)) ++ ++ # write garbage into the selected blocks ++ [ ! -c /dev/urandom ] && return ++ log "writing ${num_blks_to_dirty}kB random garbage at offset ${from}kB" ++ dd if=/dev/urandom of=$IMAGE bs=1kB seek=$from conv=notrunc \ ++ count=$num_blks_to_dirty >> $OUT 2>&1 ++} ++ ++ ++touch $IMAGE ++log "Format the filesystem image..." ++log ++# Write some garbage blocks into the filesystem to make sure e2fsck has to do ++# a more difficult job than checking blocks of zeroes. ++log "Copy some random data into filesystem image...." ++make_fs_dirty 32768 ++log "$MKFS $MKFS_OPTS -F $IMAGE $NUM_BLKS >> $OUT" ++$MKFS $MKFS_OPTS -F $IMAGE $NUM_BLKS >> $OUT 2>&1 ++if [ $? -ne 0 ]; then ++ zero_size=`grep "Device size reported to be zero" $OUT` ++ short_write=`grep "Attempt to write block from filesystem resulted in short write" $OUT` ++ ++ if (( zero_size != 0 || short_write != 0 )); then ++ echo "mkfs failed due to device size of 0 or a short write. This is harmless and need not be reported." ++ else ++ cleanup "mkfs failed - internal error during operation. Aborting random regression test..." ++ fi ++fi ++ ++if [ `id -u` = 0 ]; then ++ mkdir -p $MNTPT ++ if [ $? -ne 0 ]; then ++ log "Failed to create or find mountpoint...." ++ else ++ mount -t $FS_TYPE $MOUNT_OPTS $IMAGE $MNTPT 2>&1 | tee -a $OUT ++ if [ ${PIPESTATUS[0]} -ne 0 ]; then ++ log "Error mounting file system - skipped" ++ else ++ df -h $MNTPT >> $OUT ++ df -i $MNTPT >> $OUT ++ log "Copying data into the test filesystem..." ++ ++ cp -r ../{.git,lib,misc,e2fsck,po} $MNTPT/ >> $OUT 2>&1 ++ sync ++ umount -f $MNTPT > /dev/null 2>&1 | tee -a $OUT ++ fi ++ fi ++else ++ log "skipping mount test for non-root user" ++fi ++ ++log "Corrupt the image by moving around blocks of data..." ++log ++for (( i = 0; i < $CORRUPTION_ITERATIONS; i++ )); do ++ from=`get_random_location $NUM_BLKS` ++ to=`get_random_location $NUM_BLKS` ++ ++ log "Moving ${CORRUPTION_SIZE}kB from block ${from}kB to ${to}kB" ++ dd if=$IMAGE of=$IMAGE bs=1k count=$CORRUPTION_SIZE conv=notrunc skip=$from seek=$to >> $OUT 2>&1 ++ ++ # more corruption by overwriting blocks from within the filesystem. ++ make_fs_dirty $CORRUPTION_SIZE ++done ++ ++# Copy the image for reproducing the bug. ++cp --sparse=always $IMAGE $ARCHIVE >> $OUT 2>&1 ++ ++log "First pass of fsck..." ++$E2FSCK $FIRST_FSCK_OPTS $IMAGE >> $OUT 2>&1 ++RET=$? ++ ++# Run e2fsck for the second time and check if the problem gets solved. ++# After we can report error with pass1. ++[ $((RET & 1)) == 0 ] || log "The first fsck corrected errors" ++[ $((RET & 2)) == 0 ] || error "The first fsck wants a reboot" ++[ $((RET & 4)) == 0 ] || error "The first fsck left uncorrected errors" ++[ $((RET & 8)) == 0 ] || error "The first fsck reports an operational error" ++[ $((RET & 16)) == 0 ] || error "The first fsck reports there was a usage error" ++[ $((RET & 32)) == 0 ] || error "The first fsck reports it was cancelled" ++[ $((RET & 128)) == 0 ] || error "The first fsck reports a library error" ++ ++log "---------------------------------------------------------" ++ ++log "Second pass of fsck..." ++$E2FSCK $SECOND_FSCK_OPTS $IMAGE >> $OUT 2>&1 ++RET=$? ++[ $((RET & 1)) == 0 ] || cleanup "The second fsck corrected errors!" ++[ $((RET & 2)) == 0 ] || cleanup "The second fsck wants a reboot" ++[ $((RET & 4)) == 0 ] || cleanup "The second fsck left uncorrected errors" ++[ $((RET & 8)) == 0 ] || cleanup "The second fsck reports an operational error" ++[ $((RET & 16)) == 0 ] || cleanup "The second fsck reports a usage error" ++[ $((RET & 32)) == 0 ] || cleanup "The second fsck reports it was cancelled" ++[ $((RET & 128)) == 0 ] || cleanup "The second fsck reports a library error" ++ ++[ -f $FAILED ] && cleanup ++ ++if [ "$MOUNT_AFTER_CORRUPTION" = "yes" ]; then ++ mount -t $FS_TYPE $MOUNT_OPTS $IMAGE $MNTPT 2>&1 | tee -a $OUT ++ [ ${PIPESTATUS[0]} -ne 0 ] && log "error mounting file system - skipped" ++ ++ [ "$REMOVE_FILES" = "yes" ] && rm -rf $MNTPT/* >> $OUT ++ umount -f $MNTPT > /dev/null 2>&1 | tee -a $OUT ++fi ++ ++rm -f $ARCHIVE ++[ -d $MNTPT ] && rmdir $MNTPT ++ ++# Report success ++echo " ok" ++echo "Succeeded..." > $OKFILE ++ ++unset_vars ++ ++COUNT=$((COUNT + 1)) ++done +Index: e2fsprogs/tests/Makefile.in +=================================================================== +--- e2fsprogs.orig/tests/Makefile.in ++++ e2fsprogs/tests/Makefile.in +@@ -27,6 +27,8 @@ mke2fs.conf: $(srcdir)/mke2fs.conf.in + $(CP) $(srcdir)/mke2fs.conf.in mke2fs.conf + + check:: test_script ++ @echo "Removing remnants of earlier tests..." ++ $(RM) -f *~ *.log *.new *.failed *.ok test.img2* + @echo "Running e2fsprogs test suite..." + @echo " " + @./test_script +@@ -66,7 +68,7 @@ testend: test_script ${TDIR}/image + @echo "If all is well, edit ${TDIR}/name and rename ${TDIR}." + + clean:: +- $(RM) -f *~ *.log *.new *.failed *.ok test.img test_script mke2fs.conf ++ $(RM) -f *~ *.log *.new *.failed *.ok test.img* test_script mke2fs.conf + + distclean:: clean + $(RM) -f Makefile diff --git a/patches/e2fsprogs-tests-f_uninit_blk-uninit-set_inode-uninit-not-set.patch b/patches/e2fsprogs-tests-f_uninit_blk-uninit-set_inode-uninit-not-set.patch new file mode 100644 index 0000000..f1b63ee Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_blk-uninit-set_inode-uninit-not-set.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_blks-used_blk-uninit-not-set.patch b/patches/e2fsprogs-tests-f_uninit_blks-used_blk-uninit-not-set.patch new file mode 100644 index 0000000..554d4f9 Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_blks-used_blk-uninit-not-set.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_checksum_invalid.patch b/patches/e2fsprogs-tests-f_uninit_checksum_invalid.patch new file mode 100644 index 0000000..74307ac Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_checksum_invalid.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_disable.patch b/patches/e2fsprogs-tests-f_uninit_disable.patch new file mode 100644 index 0000000..2d092ca Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_disable.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_enable.patch b/patches/e2fsprogs-tests-f_uninit_enable.patch new file mode 100644 index 0000000..2feb4b8 Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_enable.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_incorrect_free_inodes_count.patch b/patches/e2fsprogs-tests-f_uninit_incorrect_free_inodes_count.patch new file mode 100644 index 0000000..e7c88b9 Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_incorrect_free_inodes_count.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_ino-ref_beyond_bg-itable-unused.patch b/patches/e2fsprogs-tests-f_uninit_ino-ref_beyond_bg-itable-unused.patch new file mode 100644 index 0000000..a84d384 Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_ino-ref_beyond_bg-itable-unused.patch differ diff --git a/patches/e2fsprogs-tests-f_uninit_restart_fsck.patch b/patches/e2fsprogs-tests-f_uninit_restart_fsck.patch new file mode 100644 index 0000000..c1bba53 Binary files /dev/null and b/patches/e2fsprogs-tests-f_uninit_restart_fsck.patch differ diff --git a/patches/e2fsprogs-tests-s_basic_scan.patch b/patches/e2fsprogs-tests-s_basic_scan.patch new file mode 100644 index 0000000..a273217 Binary files /dev/null and b/patches/e2fsprogs-tests-s_basic_scan.patch differ diff --git a/patches/e2fsprogs-tunefs-dirty.patch b/patches/e2fsprogs-tunefs-dirty.patch new file mode 100644 index 0000000..14acbeb --- /dev/null +++ b/patches/e2fsprogs-tunefs-dirty.patch @@ -0,0 +1,30 @@ +Running tune2fs on a filesystem with an unrecovered journal can cause +the tune2fs settings to be reverted when the journal is replayed. Print +a warning if this is detected so that the user isn't surprised if it +happens. + +Signed-off-by: Jim Garlick +Signed-off-by: Andreas Dilger + +Index: e2fsprogs/misc/tune2fs.c +=================================================================== +--- e2fsprogs.orig/misc/tune2fs.c ++++ e2fsprogs/misc/tune2fs.c +@@ -1855,6 +1855,17 @@ retry_open: + ext2fs_mark_super_dirty(fs); + printf(_("Setting stripe width to %d\n"), stripe_width); + } ++ ++ /* Warn if file system needs recovery and it is opened for writing. */ ++ if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & EXT2_MF_MOUNTED) && ++ (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && ++ (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) { ++ fprintf(stderr, ++ _("Warning: needs_recovery flag is set. You may wish\n" ++ "replay the journal then rerun this command, or any\n" ++ "changes may be overwritten by journal recovery.\n")); ++ } ++ + free(device_name); + remove_error_table(&et_ext2_error_table); + return (ext2fs_close(fs) ? 1 : 0); diff --git a/patches/e2fsprogs-uninit-fixes.patch b/patches/e2fsprogs-uninit-fixes.patch new file mode 100644 index 0000000..ed5c9e0 --- /dev/null +++ b/patches/e2fsprogs-uninit-fixes.patch @@ -0,0 +1,36 @@ +Index: e2fsprogs/debugfs/set_fields.c +=================================================================== +--- e2fsprogs.orig/debugfs/set_fields.c ++++ e2fsprogs/debugfs/set_fields.c +@@ -583,6 +583,8 @@ void do_set_block_group_descriptor(int a + current_fs->group_desc, set_bg), + sizeof(set_gd)); + ++ set_sb = *current_fs->super; ++ + if (ss->func(ss, argv[3]) == 0) { + memcpy(ext2fs_group_desc(current_fs, + current_fs->group_desc, set_bg), +Index: e2fsprogs/misc/mke2fs.c +=================================================================== +--- e2fsprogs.orig/misc/mke2fs.c ++++ e2fsprogs/misc/mke2fs.c +@@ -284,6 +284,9 @@ _("Warning: the backup superblock/group + ext2fs_group_desc_csum_set(fs, group); + ext2fs_free_blocks_count_add(fs->super, 1); + } ++ /* The kernel doesn't need to zero the itable blocks */ ++ ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED | ++ ext2fs_bg_flags(fs, i)); + } + group_block += fs->super->s_blocks_per_group; + } +@@ -2378,6 +2381,8 @@ int main (int argc, char *argv[]) + } + no_journal: + ++ if (!super_only) ++ ext2fs_set_gdt_csum(fs); + if (!quiet) + printf(_("Writing superblocks and " + "filesystem accounting information: ")); diff --git a/patches/e2fsprogs-version.patch b/patches/e2fsprogs-version.patch new file mode 100644 index 0000000..fb85598 --- /dev/null +++ b/patches/e2fsprogs-version.patch @@ -0,0 +1,14 @@ +Change to Lustre patch version number + +Index: e2fsprogs/version.h +=================================================================== +--- e2fsprogs.orig/version.h ++++ e2fsprogs/version.h +@@ -7,5 +7,5 @@ + * file may be redistributed under the GNU Public License v2. + */ + +-#define E2FSPROGS_VERSION "1.41.14" +-#define E2FSPROGS_DATE "22-Dec-2010" ++#define E2FSPROGS_VERSION "1.41.90.wc1" ++#define E2FSPROGS_DATE "18-Mar-2011" diff --git a/patches/libcom_err-unidiff.patch b/patches/libcom_err-unidiff.patch new file mode 100644 index 0000000..ccb30e1 --- /dev/null +++ b/patches/libcom_err-unidiff.patch @@ -0,0 +1,15 @@ +diff -ru e2fsprogs-1.40.4/lib/et/Makefile.in e2fsprogs-cfs/lib/et/Makefile.in +--- e2fsprogs-1.40.4/lib/et/Makefile.in ++++ e2fsprogs-cfs/lib/et/Makefile.in +@@ -113,9 +113,9 @@ + for i in $(srcdir)/test_cases/*.et ; do \ + t=`basename $$i | sed -e 's/.et//'`; \ + ./compile_et --build-tree $$i ; \ +- diff -c $(srcdir)/test_cases/$$t.c $$t.c > $$t.failed; \ ++ diff @UNI_DIFF_OPTS@ $(srcdir)/test_cases/$$t.c $$t.c > $$t.failed; \ + if [ $$? -ne 0 ]; then echo Test case $$t failed; exit 1 ; fi ; \ +- diff -c $(srcdir)/test_cases/$$t.h $$t.h >> $$t.failed; \ ++ diff @UNI_DIFF_OPTS@ $(srcdir)/test_cases/$$t.h $$t.h >> $$t.failed; \ + if [ $$? -ne 0 ]; then echo Test case $$t failed; exit 1 ; fi ; \ + $(RM) -f $$t.c $$t.h $$t.failed; \ + echo "Test case $$t succeeded" ; \ diff --git a/patches/series b/patches/series new file mode 100644 index 0000000..ffe5002 --- /dev/null +++ b/patches/series @@ -0,0 +1,77 @@ +e2fsprogs-discard.patch +e2fsprogs-version.patch +e2fsprogs-misc.patch +e2fsprogs-osx.patch +e2fsprogs-dblist.patch +e2fsprogs-bigjournal.patch +e2fsprogs-e2fsck_exclusive.patch +e2fsprogs-bad-ininode-ea.patch +e2fsprogs-blkid-zfs.patch +e2fsprogs-fiemap-lustre.patch +e2fsprogs-count_wrong_valid.patch +e2fsprogs-specdotin.patch +e2fsprogs-extended_ops.patch +e2fsprogs-lazy_journal_init.patch +e2fsprogs-size_high.patch +e2fsprogs-tests-f_many_subdirs.patch +e2fsprogs-extents.patch +e2fsprogs-tests-f_bad_ea_value.patch +e2fsprogs-tests-f_extents_bad_blk.patch +e2fsprogs-tests-f_extents_ee_block.patch +e2fsprogs-tests-f_extents_ee_len.patch +e2fsprogs-tests-f_extents_ee_start.patch +e2fsprogs-tests-f_extents_eh_depth.patch +e2fsprogs-tests-f_extents_eh_entries.patch +e2fsprogs-tests-f_extents_eh_magic.patch +e2fsprogs-tests-f_extents_eh_max.patch +e2fsprogs-skip-extent-tests.patch +e2fsprogs-tests-f_extents_ei_block.patch +e2fsprogs-tests-f_extents_ei_leaf.patch +e2fsprogs-tests-f_extents_imbalanced_tree.patch +e2fsprogs-tests-f_extents_inrlevel-incons.patch +e2fsprogs-tests-f_extents_orphan_blks.patch +e2fsprogs-tests-f_extents_overlap.patch +e2fsprogs-tests-f_extents_res_blk.patch +e2fsprogs-tests-f_extents_shrd_blk.patch +e2fsprogs-tests-f_extents_unsorted.patch +e2fsprogs-tests-f_extents_split.patch +e2fsprogs-config-before-cmdline.patch +e2fsprogs-new-opt-shrdblks.patch +e2fsprogs-tunefs-dirty.patch +sles/e2fsprogs-SLES10--m-support.patch +sles/libcom_err-no-static-buffer.patch +sles/libcom_err-no-init_error_table.patch +e2fsprogs-uninit-fixes.patch +e2fsprogs-tests-f_uninit_enable.patch +e2fsprogs-tests-f_uninit_disable.patch +e2fsprogs-tests-f_uninit_blks-used_blk-uninit-not-set.patch +e2fsprogs-tests-f_uninit_blk-uninit-set_inode-uninit-not-set.patch +e2fsprogs-tests-f_uninit_checksum_invalid.patch +e2fsprogs-tests-f_uninit_incorrect_free_inodes_count.patch +e2fsprogs-tests-f_uninit_ino-ref_beyond_bg-itable-unused.patch +e2fsprogs-tests-f_uninit_restart_fsck.patch +e2fsprogs-expand-extra-isize.patch +e2fsprogs-tests-f_expisize.patch +e2fsprogs-tests-f_expisize_ea_del.patch +e2fsprogs-ibadness-counter.patch +e2fsprogs-tests-f_ibadness.patch +e2fsprogs-tests-f_ibadness_bad_extents.patch +e2fsprogs-tests-f_random_corruption.patch +e2fsprogs-mmp.patch +e2fsprogs-tests-f_mmp.patch +e2fsprogs-tests-f_jchksum_bblk.patch +e2fsprogs-tests-f_jchksum_blast_trans.patch +e2fsprogs-tests-f_jchksum_remount.patch +e2fsprogs-i_size-corruption.patch +e2fsprogs-attr_cleanup.patch +e2fsprogs-large-ea.patch +e2fsprogs-tests-f_large_ea.patch +e2fsprogs-lustre_ismounted.patch +e2fsprogs-lfsck.patch +e2fsprogs-add-trusted-fid.patch +e2fsprogs-add-io_channel_readahead.patch +e2fsprogs-e2scan.patch +e2fsprogs-tests-s_basic_scan.patch +e2fsprogs-data_in_dirent.patch +e2fsprogs-tests-f_data_in_dirent.patch +e2fsprogs-rpm_support.patch diff --git a/patches/sles/11/rpm/README.SUSE b/patches/sles/11/rpm/README.SUSE new file mode 100644 index 0000000..ef2be40 --- /dev/null +++ b/patches/sles/11/rpm/README.SUSE @@ -0,0 +1,11 @@ +e2fsprogs-devel +--------------- +Since the e2fsprogs libraries has been split out into own packages, +each having its own devel package +libext2fs-devel +libblkid-devel +libuuid-devel +libcom_err-devel +the e2fsprogs-devel package is deprecated and is provided for temporary +backwards compatibility only. + diff --git a/patches/sles/11/rpm/e2fsprogs-1.41.1-splash_support.patch b/patches/sles/11/rpm/e2fsprogs-1.41.1-splash_support.patch new file mode 100644 index 0000000..e7ccde1 --- /dev/null +++ b/patches/sles/11/rpm/e2fsprogs-1.41.1-splash_support.patch @@ -0,0 +1,186 @@ +Index: e2fsprogs-1.41.7/e2fsck/splash.c +=================================================================== +--- /dev/null ++++ e2fsprogs-1.41.7/e2fsck/splash.c +@@ -0,0 +1,100 @@ ++/* ++ * add support for switching the splash screen on boot ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "splash.h" ++ ++static int verbose = 0; ++ ++/* nop implementation ++ */ ++static void nop(void) ++{ ++} ++ ++static struct splash_ops nop_ops = { ++ .splash_on = nop, ++ .splash_off = nop ++}; ++ ++/* ++ * bootsplash implementation ++ */ ++#define BOOTSPLASH_CTL "/proc/splash" ++ ++static int bootsplash_exists(void) ++{ ++ struct stat sb; ++ ++ if (stat(BOOTSPLASH_CTL, &sb) == -1) ++ return 0; ++ ++ if (S_ISREG(sb.st_mode)) ++ return 1; ++ ++ return 0; ++} ++ ++/* write msg to splash control */ ++static void bootsplash_msg(const char *msg, size_t size) ++{ ++ int fd; ++ size_t written; ++ ++ fd = open(BOOTSPLASH_CTL, O_WRONLY); ++ if (fd == -1) { ++ if (verbose) ++ printf("cannot open %s\n", BOOTSPLASH_CTL); ++ return; ++ } ++ ++ written = write(fd, msg, size); ++ if (written != size) { ++ if (verbose) ++ printf("size = %i, written = %i\n", size, written); ++ } ++ ++ close(fd); ++} ++ ++static void bootsplash_on(void) ++{ ++ if (verbose) ++ printf("setting bootsplash silent\n"); ++ bootsplash_msg("silent\n", 7); ++} ++ ++static void bootsplash_off(void) ++{ ++ if (verbose) ++ printf("setting bootsplash verbose\n"); ++ bootsplash_msg("verbose\n", 8); ++} ++ ++static struct splash_ops bootsplash_ops = { ++ .splash_on = bootsplash_on, ++ .splash_off = bootsplash_off ++}; ++ ++/* ++ * Initialisation ++ */ ++void splash_init(struct splash_ops **ops) ++{ ++ if (bootsplash_exists()) ++ *ops = &bootsplash_ops; ++ else ++ *ops = &nop_ops; ++} ++ ++void splash_set_verbose(void) ++{ ++ verbose = 1; ++} ++ +Index: e2fsprogs-1.41.7/e2fsck/splash.h +=================================================================== +--- /dev/null ++++ e2fsprogs-1.41.7/e2fsck/splash.h +@@ -0,0 +1,13 @@ ++#ifndef _SPLASH_H ++#define _SPLASH_H ++ ++struct splash_ops { ++ void (*splash_on)(void); ++ void (*splash_off)(void); ++}; ++ ++void splash_init(struct splash_ops **ops); ++void splash_set_verbose(void); ++ ++#endif /* _SPLASH_H */ ++ +Index: e2fsprogs-1.41.7/e2fsck/Makefile.in +=================================================================== +--- e2fsprogs-1.41.7.orig/e2fsck/Makefile.in ++++ e2fsprogs-1.41.7/e2fsck/Makefile.in +@@ -63,7 +63,7 @@ COMPILE_ET=$(top_builddir)/lib/et/compil + OBJS= crc32.o dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \ + pass3.o pass4.o pass5.o journal.o badblocks.o util.o dirinfo.o \ + dx_dirinfo.o ehandler.o problem.o message.o recovery.o region.o \ +- revoke.o ea_refcount.o rehash.o profile.o prof_err.o pass6.o $(MTRACE_OBJ) ++ revoke.o ea_refcount.o rehash.o profile.o prof_err.o pass6.o splash.o $(MTRACE_OBJ) + @LFSCK_CMT@OBJS += lfsck_common.o + + @LFSCK_CMT@LFSCK_OBJS = lfsck_common.o lfsck.o +@@ -101,6 +101,7 @@ SRCS= $(srcdir)/e2fsck.c \ + $(srcdir)/rehash.c \ + $(srcdir)/region.c \ + $(srcdir)/profile.c \ ++ $(srcdir)/splash.c \ + prof_err.c \ + $(MTRACE_SRC) + +@@ -475,3 +476,5 @@ region.o: $(srcdir)/region.c $(srcdir)/e + profile.o: $(srcdir)/profile.c $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/profile.h prof_err.h + prof_err.o: prof_err.c ++splash.o: splash.c splash.h ++ +Index: e2fsprogs-1.41.7/e2fsck/unix.c +=================================================================== +--- e2fsprogs-1.41.7.orig/e2fsck/unix.c ++++ e2fsprogs-1.41.7/e2fsck/unix.c +@@ -53,6 +53,7 @@ extern int optind; + #include "e2p/e2p.h" + #include "e2fsck.h" + #include "problem.h" ++#include "splash.h" + #include "../version.h" + + /* Command line options */ +@@ -941,6 +942,7 @@ int main (int argc, char *argv[]) + int sysval, sys_page_size = 4096; + __u32 features[3]; + char *cp; ++ struct splash_ops *sops; + + clear_problem_context(&pctx); + #ifdef MTRACE +@@ -970,6 +972,7 @@ int main (int argc, char *argv[]) + exit(FSCK_ERROR); + } + reserve_stdio_fds(); ++ splash_init(&sops); + + init_resource_track(&ctx->global_rtrack, NULL); + if (!(ctx->options & E2F_OPT_PREEN) || show_version_only) +@@ -1284,6 +1287,7 @@ print_unsupp_features: + fatal_error(ctx, 0); + check_if_skip(ctx); + check_resize_inode(ctx); ++ sops->splash_off(); + if (bad_blocks_file) + read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks); + else if (cflag) diff --git a/patches/sles/11/rpm/e2fsprogs-1.41.4.de.po b/patches/sles/11/rpm/e2fsprogs-1.41.4.de.po new file mode 100644 index 0000000..0347505 --- /dev/null +++ b/patches/sles/11/rpm/e2fsprogs-1.41.4.de.po @@ -0,0 +1,5069 @@ +# Deutsche Übersetzungen für e2fsprogs +# Copyright (C) 1996 Theodore Tso (msgids) +# This file is distributed under the same license as the e2fsprogs package. +# Olaf Klemke ,2002 +# Marc Langer ,2003 +# Philipp Thomas , 2007, 2008, 2009 +# +msgid "" +msgstr "" +"Project-Id-Version: e2fsprogs-1.41.4\n" +"Report-Msgid-Bugs-To: tytso@alum.mit.edu\n" +"POT-Creation-Date: 2009-01-26 20:41-0500\n" +"PO-Revision-Date: 2009-03-09 19:33+0100\n" +"Last-Translator: Philipp Thomas \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: e2fsck/badblocks.c:22 +#: misc/mke2fs.c:165 +#, c-format +msgid "Bad block %u out of range; ignored.\n" +msgstr "Bad block %u außerhalb des gültigen Bereichs; ignoriert.\n" + +#: e2fsck/badblocks.c:45 +msgid "while sanity checking the bad blocks inode" +msgstr "während der logischen Prüfung des »Bad Block«-Inodes" + +#: e2fsck/badblocks.c:57 +msgid "while reading the bad blocks inode" +msgstr "während des Lesens des »Bad Block«-Inodes" + +#: e2fsck/badblocks.c:71 +#: e2fsck/iscan.c:112 +#: e2fsck/scantest.c:109 +#: e2fsck/unix.c:1037 +#: e2fsck/unix.c:1120 +#: misc/badblocks.c:1148 +#: misc/badblocks.c:1156 +#: misc/badblocks.c:1170 +#: misc/badblocks.c:1182 +#: misc/dumpe2fs.c:505 +#: misc/e2image.c:576 +#: misc/e2image.c:672 +#: misc/e2image.c:688 +#: misc/mke2fs.c:181 +#: misc/tune2fs.c:1515 +#: resize/main.c:309 +#, c-format +msgid "while trying to open %s" +msgstr "beim Versuch, %s zu öffnen" + +#: e2fsck/badblocks.c:82 +#, c-format +msgid "while trying popen '%s'" +msgstr "beim Versuch, »%s« mittels »popen« zu öffnen" + +#: e2fsck/badblocks.c:93 +#: misc/mke2fs.c:188 +msgid "while reading in list of bad blocks from file" +msgstr "beim Lesen der »Bad Block«-Liste aus der Datei" + +#: e2fsck/badblocks.c:104 +msgid "while updating bad block inode" +msgstr "beim Updaten des »Bad Block«-Inodes" + +#: e2fsck/badblocks.c:130 +#, c-format +msgid "Warning: illegal block %u found in bad block inode. Cleared.\n" +msgstr "Warnung: Nicht zulässiger Block %u im »Bad Blocks«-Inode gefunden! Bereinigt.\n" + +#: e2fsck/ehandler.c:54 +#, c-format +msgid "Error reading block %lu (%s) while %s. " +msgstr "Lesefehler - Block %lu (%s) während %s. " + +#: e2fsck/ehandler.c:57 +#, c-format +msgid "Error reading block %lu (%s). " +msgstr "Lesefehler - Block %lu (%s). " + +#: e2fsck/ehandler.c:60 +#: e2fsck/ehandler.c:109 +msgid "Ignore error" +msgstr "Ignoriere Fehler" + +#: e2fsck/ehandler.c:61 +msgid "Force rewrite" +msgstr "Rückschreiben erzwingen" + +#: e2fsck/ehandler.c:103 +#, c-format +msgid "Error writing block %lu (%s) while %s. " +msgstr "Schreibfehler - Block %lu (%s) während %s. " + +#: e2fsck/ehandler.c:106 +#, c-format +msgid "Error writing block %lu (%s). " +msgstr "Schreibfehler - Block %lu (%s). " + +#: e2fsck/emptydir.c:56 +msgid "empty dirblocks" +msgstr "leere Verzeichnisblöcke" + +#: e2fsck/emptydir.c:61 +msgid "empty dir map" +msgstr "leere Verzeichnisliste" + +#: e2fsck/emptydir.c:97 +#, c-format +msgid "Empty directory block %u (#%d) in inode %u\n" +msgstr "leerer Verzeichnisblock %u (#%d) im Inode %u\n" + +#: e2fsck/extend.c:21 +#, c-format +msgid "%s: %s filename nblocks blocksize\n" +msgstr "%s: %s Dateiname nblocks Blockgröße\n" + +#: e2fsck/extend.c:43 +#, c-format +msgid "Illegal number of blocks!\n" +msgstr "Blockanzahl nicht zulässig!\n" + +#: e2fsck/extend.c:49 +#, c-format +msgid "Couldn't allocate block buffer (size=%d)\n" +msgstr "Konnte keinen Blockpuffer (Größe=%d) reservieren.\n" + +#: e2fsck/flushb.c:34 +#, c-format +msgid "Usage: %s disk\n" +msgstr "Aufruf: %s Laufwerk\n" + +#: e2fsck/flushb.c:63 +#, c-format +msgid "BLKFLSBUF ioctl not supported! Can't flush buffers.\n" +msgstr "BLKFLSBUF ioctl nicht unterstützt! Kann Puffer nicht leeren.\n" + +#: e2fsck/iscan.c:46 +#, c-format +msgid "Usage: %s [-F] [-I inode_buffer_blocks] device\n" +msgstr "Aufruf: %s [-F] [-I inode_buffer_blocks] Gerät\n" + +#: e2fsck/iscan.c:83 +#: e2fsck/unix.c:818 +#, c-format +msgid "while opening %s for flushing" +msgstr "beim Öffnen von %s für die Puffer-Leerung." + +#: e2fsck/iscan.c:88 +#: e2fsck/unix.c:824 +#: resize/main.c:285 +#, c-format +msgid "while trying to flush %s" +msgstr "während des Rückschreibeversuches auf %s" + +#: e2fsck/iscan.c:121 +#: e2fsck/scantest.c:116 +#: misc/e2image.c:482 +msgid "while opening inode scan" +msgstr "beim Start des Inode-Scans" + +#: e2fsck/iscan.c:129 +#: misc/e2image.c:500 +msgid "while getting next inode" +msgstr "beim Laden des nächsten Inodes" + +#: e2fsck/iscan.c:138 +#, c-format +msgid "%u inodes scanned.\n" +msgstr "%u Inodes untersucht.\n" + +#: e2fsck/journal.c:507 +msgid "reading journal superblock\n" +msgstr "Lese Journal-Superblock\n" + +#: e2fsck/journal.c:564 +#, c-format +msgid "%s: no valid journal superblock found\n" +msgstr "%s: keinen gültigen Journal-Superblock gefunden\n" + +#: e2fsck/journal.c:573 +#, c-format +msgid "%s: journal too short\n" +msgstr "%s: Das Journal ist zu kurz\n" + +#: e2fsck/journal.c:858 +#, c-format +msgid "%s: recovering journal\n" +msgstr "%s: stelle das Journal wieder her\n" + +#: e2fsck/journal.c:860 +#, c-format +msgid "%s: won't do journal recovery while read-only\n" +msgstr "%s: Das Journal ist nur lesbar - Keine Wiederherstellung\n" + +#: e2fsck/journal.c:881 +#, c-format +msgid "while trying to re-open %s" +msgstr "beim Versuch, %s erneut zu öffnen" + +#: e2fsck/message.c:110 +msgid "aextended attribute" +msgstr "aerweiterte Eigenschaft" + +#: e2fsck/message.c:111 +msgid "Aerror allocating" +msgstr "AFehler beim Zuweisen" + +#: e2fsck/message.c:112 +msgid "bblock" +msgstr "bBlock" + +#: e2fsck/message.c:113 +msgid "Bbitmap" +msgstr "BBitmap" + +#: e2fsck/message.c:114 +msgid "ccompress" +msgstr "ckomprimieren" + +#: e2fsck/message.c:115 +msgid "Cconflicts with some other fs @b" +msgstr "CKonflikte mit anderen Dateisystemen @b" + +#: e2fsck/message.c:116 +msgid "iinode" +msgstr "iInode" + +#: e2fsck/message.c:117 +msgid "Iillegal" +msgstr "Iillegal(er)" + +#: e2fsck/message.c:118 +msgid "jjournal" +msgstr "jJournal" + +#: e2fsck/message.c:119 +msgid "Ddeleted" +msgstr "Dgelöscht" + +#: e2fsck/message.c:120 +msgid "ddirectory" +msgstr "dVerzeichnis" + +#: e2fsck/message.c:121 +msgid "eentry" +msgstr "eEintrag" + +#: e2fsck/message.c:122 +msgid "E@e '%Dn' in %p (%i)" +msgstr "E@e »%Dn« in %p (%i)" + +#: e2fsck/message.c:123 +msgid "ffilesystem" +msgstr "fDateisystem" + +#: e2fsck/message.c:124 +msgid "Ffor @i %i (%Q) is" +msgstr "Ffür @i %i (%Q) ist" + +#: e2fsck/message.c:125 +msgid "ggroup" +msgstr "gGruppe" + +#: e2fsck/message.c:126 +msgid "hHTREE @d @i" +msgstr "hHTREE @d @i" + +#: e2fsck/message.c:127 +msgid "llost+found" +msgstr "llost+found" + +#: e2fsck/message.c:128 +msgid "Lis a link" +msgstr "List ein Link" + +#: e2fsck/message.c:129 +msgid "mmultiply-claimed" +msgstr "mmehrfach beansprucht" + +#: e2fsck/message.c:130 +msgid "ninvalid" +msgstr "nungültig" + +#: e2fsck/message.c:131 +msgid "oorphaned" +msgstr "overwaist" + +#: e2fsck/message.c:132 +msgid "pproblem in" +msgstr "pProblem in" + +#: e2fsck/message.c:133 +msgid "rroot @i" +msgstr "rRoot @i" + +#: e2fsck/message.c:134 +msgid "sshould be" +msgstr "ssollte sein" + +#: e2fsck/message.c:135 +msgid "Ssuper@b" +msgstr "SSuper@b" + +#: e2fsck/message.c:136 +msgid "uunattached" +msgstr "unicht verbunden" + +#: e2fsck/message.c:137 +msgid "vdevice" +msgstr "vGerät" + +#: e2fsck/message.c:138 +msgid "xextent" +msgstr "xErweiterung" + +#: e2fsck/message.c:139 +msgid "zzero-length" +msgstr "zNull-Länge" + +#: e2fsck/message.c:150 +msgid "" +msgstr "" + +#: e2fsck/message.c:151 +msgid "" +msgstr "" + +#: e2fsck/message.c:153 +msgid "" +msgstr "" + +#: e2fsck/message.c:154 +msgid "" +msgstr "" + +#: e2fsck/message.c:155 +msgid "" +msgstr "" + +#: e2fsck/message.c:156 +msgid "" +msgstr "" + +#: e2fsck/message.c:157 +msgid "" +msgstr "" + +#: e2fsck/message.c:158 +msgid "" +msgstr "" + +#: e2fsck/message.c:159 +msgid "" +msgstr "" + +#: e2fsck/message.c:160 +msgid "" +msgstr "" + +#: e2fsck/message.c:323 +#, c-format +msgid "regular file" +msgstr "'reguläre Datei" + +#: e2fsck/message.c:325 +#, c-format +msgid "directory" +msgstr "Verzeichnis" + +#: e2fsck/message.c:327 +#, c-format +msgid "character device" +msgstr "zeichenorientiertes Gerät" + +#: e2fsck/message.c:329 +#, c-format +msgid "block device" +msgstr "Blockgerät" + +#: e2fsck/message.c:331 +#, c-format +msgid "named pipe" +msgstr "named pipe" + +#: e2fsck/message.c:333 +#, c-format +msgid "symbolic link" +msgstr "symbolische Verknüpfung" + +#: e2fsck/message.c:335 +#, c-format +msgid "socket" +msgstr " Socket" + +#: e2fsck/message.c:337 +#, c-format +msgid "unknown file type with mode 0%o" +msgstr "unbekannter Dateityp mit Modus 0%o" + +#: e2fsck/pass1b.c:215 +msgid "multiply claimed inode map" +msgstr "mehrfach beanspruchte Inode-Liste" + +#: e2fsck/pass1b.c:567 +#: e2fsck/pass1b.c:700 +#, c-format +msgid "internal error: can't find dup_blk for %u\n" +msgstr "interner Fehler; dup_blk für %u nicht gefunden\n" + +#: e2fsck/pass1b.c:743 +msgid "returned from clone_file_block" +msgstr "zurückgegeben von clone_file_block" + +#: e2fsck/pass1b.c:762 +#, c-format +msgid "internal error: couldn't lookup EA block record for %u" +msgstr "interner Fehler: EA Blockliste für %u wurde nicht gefunden" + +#: e2fsck/pass1b.c:774 +#, c-format +msgid "internal error: couldn't lookup EA inode record for %u" +msgstr "Interner Fehler: EA Inodeliste für %u wurde nicht gefunden" + +#: e2fsck/pass1.c:430 +#: e2fsck/pass2.c:780 +msgid "reading directory block" +msgstr "lese Verzeichnisblock" + +#: e2fsck/pass1.c:552 +msgid "in-use inode map" +msgstr "»in-use inode«-Liste" + +#: e2fsck/pass1.c:561 +msgid "directory inode map" +msgstr "»directory inode«-Liste" + +#: e2fsck/pass1.c:569 +msgid "regular file inode map" +msgstr "»regular file inode«-Liste" + +#: e2fsck/pass1.c:576 +msgid "in-use block map" +msgstr "»in-use block«-Liste" + +#: e2fsck/pass1.c:630 +msgid "opening inode scan" +msgstr "Starte Inode-Scan" + +#: e2fsck/pass1.c:654 +msgid "getting next inode from scan" +msgstr "beim Lesen des nächsten Inodes" + +#: e2fsck/pass1.c:1122 +msgid "Pass 1" +msgstr "Durchgang 1" + +#: e2fsck/pass1.c:1181 +#, c-format +msgid "reading indirect blocks of inode %u" +msgstr "lese indirekte Blöcke von Inode %u" + +#: e2fsck/pass1.c:1225 +msgid "bad inode map" +msgstr "fehlerhafte Inode-Liste" + +#: e2fsck/pass1.c:1247 +msgid "inode in bad block map" +msgstr "Inode in »Bad Blocks«-Liste" + +#: e2fsck/pass1.c:1267 +msgid "imagic inode map" +msgstr "i»magic inode«-Liste" + +#: e2fsck/pass1.c:1294 +msgid "multiply claimed block map" +msgstr "Den Eintrag in der Liste belegter Blöcke verdoppeln" + +#: e2fsck/pass1.c:1393 +msgid "ext attr block map" +msgstr "ext attr block map" + +#: e2fsck/pass1.c:2134 +#, c-format +msgid "%6lu(%c): expecting %6lu got phys %6lu (blkcnt %lld)\n" +msgstr "%6lu(%c): erwartete %6lu erhielt phys %6lu (Blockanzahl %lld)\n" + +#: e2fsck/pass1.c:2449 +msgid "block bitmap" +msgstr "Block Bitmap" + +#: e2fsck/pass1.c:2453 +msgid "inode bitmap" +msgstr "Inode Bitmap" + +#: e2fsck/pass1.c:2457 +msgid "inode table" +msgstr "Inode-Tabelle" + +#: e2fsck/pass2.c:284 +msgid "Pass 2" +msgstr "Durchgang 2" + +#: e2fsck/pass2.c:803 +msgid "Can not continue." +msgstr "Fortsetzung nicht möglich." + +#: e2fsck/pass3.c:79 +msgid "inode done bitmap" +msgstr "»inode done«-Bitmap" + +#: e2fsck/pass3.c:90 +msgid "Peak memory" +msgstr "Peak-Memory" + +#: e2fsck/pass3.c:146 +msgid "Pass 3" +msgstr "Durchgang 3" + +#: e2fsck/pass3.c:334 +msgid "inode loop detection bitmap" +msgstr "»inode loop detection«-Bitmap" + +#: e2fsck/pass4.c:196 +msgid "Pass 4" +msgstr "Durchgang 4" + +#: e2fsck/pass5.c:70 +msgid "Pass 5" +msgstr "Durchgang 5" + +#: e2fsck/problem.c:50 +msgid "(no prompt)" +msgstr "(nicht interaktiv)" + +#: e2fsck/problem.c:51 +msgid "Fix" +msgstr "Repariere" + +#: e2fsck/problem.c:52 +msgid "Clear" +msgstr "Bereinige" + +#: e2fsck/problem.c:53 +msgid "Relocate" +msgstr "Zurücksetzen" + +#: e2fsck/problem.c:54 +msgid "Allocate" +msgstr "Gebe frei" + +#: e2fsck/problem.c:55 +msgid "Expand" +msgstr "Erweitere" + +#: e2fsck/problem.c:56 +msgid "Connect to /lost+found" +msgstr "Verbinde nach /lost+found" + +#: e2fsck/problem.c:57 +msgid "Create" +msgstr "Erstelle" + +#: e2fsck/problem.c:58 +msgid "Salvage" +msgstr "Rette" + +#: e2fsck/problem.c:59 +msgid "Truncate" +msgstr "Verkürze" + +#: e2fsck/problem.c:60 +msgid "Clear inode" +msgstr "Bereinige Inode" + +#: e2fsck/problem.c:61 +msgid "Abort" +msgstr "Abbrechen" + +#: e2fsck/problem.c:62 +msgid "Split" +msgstr "Aufsplitten" + +#: e2fsck/problem.c:63 +msgid "Continue" +msgstr "Fortsetzen" + +#: e2fsck/problem.c:64 +msgid "Clone multiply-claimed blocks" +msgstr "multiply claimed block map" + +#: e2fsck/problem.c:65 +msgid "Delete file" +msgstr "Lösche Datei" + +#: e2fsck/problem.c:66 +msgid "Suppress messages" +msgstr "Ausgaben unterdrücken" + +#: e2fsck/problem.c:67 +msgid "Unlink" +msgstr "Unlink" + +#: e2fsck/problem.c:68 +msgid "Clear HTree index" +msgstr "Bereinige HTree-Index" + +#: e2fsck/problem.c:69 +msgid "Recreate" +msgstr "Zurücksetzen" + +#: e2fsck/problem.c:78 +msgid "(NONE)" +msgstr "(NICHTS)" + +#: e2fsck/problem.c:79 +msgid "FIXED" +msgstr "REPARIERT" + +#: e2fsck/problem.c:80 +msgid "CLEARED" +msgstr "BEREINIGT" + +#: e2fsck/problem.c:81 +msgid "RELOCATED" +msgstr "ZURÜCKGESETZT" + +#: e2fsck/problem.c:82 +msgid "ALLOCATED" +msgstr "FREIGEGEBEN" + +#: e2fsck/problem.c:83 +msgid "EXPANDED" +msgstr "ERWEITERT" + +#: e2fsck/problem.c:84 +msgid "RECONNECTED" +msgstr "WIEDER VERBUNDEN" + +#: e2fsck/problem.c:85 +msgid "CREATED" +msgstr "ANGELEGT" + +#: e2fsck/problem.c:86 +msgid "SALVAGED" +msgstr "GERETTET" + +#: e2fsck/problem.c:87 +msgid "TRUNCATED" +msgstr "BEENDET" + +#: e2fsck/problem.c:88 +msgid "INODE CLEARED" +msgstr "INODE BEREINIGT" + +#: e2fsck/problem.c:89 +msgid "ABORTED" +msgstr "ABGEBROCHEN" + +#: e2fsck/problem.c:90 +msgid "SPLIT" +msgstr "ABGESPALTET" + +#: e2fsck/problem.c:91 +msgid "CONTINUING" +msgstr "SETZE FORT" + +#: e2fsck/problem.c:92 +msgid "MULTIPLY-CLAIMED BLOCKS CLONED" +msgstr "DOPPELTE/DEFEKTE BLÖCKE DUPLIZIERT" + +#: e2fsck/problem.c:93 +msgid "FILE DELETED" +msgstr "DATEI GELÖSCHT" + +#: e2fsck/problem.c:94 +msgid "SUPPRESSED" +msgstr "UNTERDRÜCKT" + +#: e2fsck/problem.c:95 +msgid "UNLINKED" +msgstr "GETRENNT" + +#: e2fsck/problem.c:96 +msgid "HTREE INDEX CLEARED" +msgstr "HTREE INDEX BEREINIGT" + +#: e2fsck/problem.c:97 +msgid "WILL RECREATE" +msgstr "ANGELEGT" + +#. @-expanded: block bitmap for group %g is not in group. (block %b)\n +#: e2fsck/problem.c:106 +msgid "@b @B for @g %g is not in @g. (@b %b)\n" +msgstr "@b @B für @g %g ist nicht in @g. (@b %b)\n" + +#. @-expanded: inode bitmap for group %g is not in group. (block %b)\n +#: e2fsck/problem.c:110 +msgid "@i @B for @g %g is not in @g. (@b %b)\n" +msgstr "@i @B für @g %g ist nicht in @g. (@b %b)\n" + +#. @-expanded: inode table for group %g is not in group. (block %b)\n +#. @-expanded: WARNING: SEVERE DATA LOSS POSSIBLE.\n +#: e2fsck/problem.c:115 +msgid "" +"@i table for @g %g is not in @g. (@b %b)\n" +"WARNING: SEVERE DATA LOSS POSSIBLE.\n" +msgstr "" +"@i Tabelle für @g %g ist nicht in @g. (@b %b)\n" +"WARNUNG: GROSSER DATENVERLUST IST MÖGLICH.\n" + +#. @-expanded: \n +#. @-expanded: The superblock could not be read or does not describe a correct ext2\n +#. @-expanded: filesystem. If the device is valid and it really contains an ext2\n +#. @-expanded: filesystem (and not swap or ufs or something else), then the superblock\n +#. @-expanded: is corrupt, and you might try running e2fsck with an alternate superblock:\n +#. @-expanded: e2fsck -b %S \n +#. @-expanded: \n +#: e2fsck/problem.c:121 +#, c-format +msgid "" +"\n" +"The @S could not be read or does not describe a correct ext2\n" +"@f. If the @v is valid and it really contains an ext2\n" +"@f (and not swap or ufs or something else), then the @S\n" +"is corrupt, and you might try running e2fsck with an alternate @S:\n" +" e2fsck -b %S <@v>\n" +"\n" +msgstr "" +"\n" +"@S ist unlesbar bzw. beschreibt kein gültiges ext2\n" +"@f. Wenn @v gültig ist und ein ext2\n" +"@f (kein swap oder ufs usw.) enthält, dann ist der @S\n" +"beschädigt, und sie könnten e2fsck mit einem anderen @S:\n" +" e2fsck -b %S <@v>\n" +"\n" + +#. @-expanded: The filesystem size (according to the superblock) is %b blocks\n +#. @-expanded: The physical size of the device is %c blocks\n +#. @-expanded: Either the superblock or the partition table is likely to be corrupt!\n +#: e2fsck/problem.c:130 +msgid "" +"The @f size (according to the @S) is %b @bs\n" +"The physical size of the @v is %c @bs\n" +"Either the @S or the partition table is likely to be corrupt!\n" +msgstr "" +"Die @f Größe ( laut @S) ist %b @bs\n" +"Die physikalische Größe von @v ist %c @bs\n" +"Entweder der @S oder die Partionstabelle ist beschädigt!\n" + +#. @-expanded: superblock block_size = %b, fragsize = %c.\n +#. @-expanded: This version of e2fsck does not support fragment sizes different\n +#. @-expanded: from the block size.\n +#: e2fsck/problem.c:137 +msgid "" +"@S @b_size = %b, fragsize = %c.\n" +"This version of e2fsck does not support fragment sizes different\n" +"from the @b size.\n" +msgstr "" +"@S @b_size = %b, fragsize = %c.\n" +"Diese Version von e2fsck unterstützt keine von @b-Größen verschiedene Fragmentgrößen.\n" + +#. @-expanded: superblock blocks_per_group = %b, should have been %c\n +#: e2fsck/problem.c:144 +msgid "@S @bs_per_group = %b, should have been %c\n" +msgstr "@S @bs_per_group = %b, sollte %c sein.\n" + +#. @-expanded: superblock first_data_block = %b, should have been %c\n +#: e2fsck/problem.c:149 +msgid "@S first_data_@b = %b, should have been %c\n" +msgstr "@S first_data_@b = %b, sollte %c haben.\n" + +#. @-expanded: filesystem did not have a UUID; generating one.\n +#. @-expanded: \n +#: e2fsck/problem.c:154 +msgid "" +"@f did not have a UUID; generating one.\n" +"\n" +msgstr "" +"@f hat keinen UUID ; generiere einen.\n" +"\n" + +#: e2fsck/problem.c:159 +#, c-format +msgid "" +"Note: if several inode or block bitmap blocks or part\n" +"of the inode table require relocation, you may wish to try\n" +"running e2fsck with the '-b %S' option first. The problem\n" +"may lie only with the primary block group descriptors, and\n" +"the backup block group descriptors may be OK.\n" +"\n" +msgstr "" +"Hinweis: Wenn mehrere Inodes oder Bitmap-Blöcke\n" +"neu geordnet werden müssen, oder ein Teil der Inode-Tabelle\n" +"verschoben werden muss, könnte es helfen, e2fsck erst einmal\n" +"mit der Option »-b %S« zu starten. Das Problem könnte\n" +"im primären Blockgruppenbezeichner liegen, und seine\n" +"Sicherungskopie in Ordnung sein.\n" +"\n" + +#. @-expanded: Corruption found in superblock. (%s = %N).\n +#: e2fsck/problem.c:168 +msgid "Corruption found in @S. (%s = %N).\n" +msgstr "Beschädigung gefunden in @S. (%s = %N).\n" + +#. @-expanded: Error determining size of the physical device: %m\n +#: e2fsck/problem.c:173 +#, c-format +msgid "Error determining size of the physical @v: %m\n" +msgstr "Fehler bei der Feststellung der Größe des physikalischen @v: %m\n" + +#. @-expanded: inode count in superblock is %i, should be %j.\n +#: e2fsck/problem.c:178 +msgid "@i count in @S is %i, @s %j.\n" +msgstr "@i-Anzahl in @S ist %i, sollte %j sein.\n" + +#: e2fsck/problem.c:182 +msgid "The Hurd does not support the filetype feature.\n" +msgstr "Hurd unterstützt das Dateityp-Feature nicht.\n" + +#. @-expanded: superblock has an invalid journal (inode %i).\n +#: e2fsck/problem.c:187 +#, fuzzy, c-format +msgid "@S has an @n @j (@i %i).\n" +msgstr "@S hat einen defekten ext3 @j (@i %i).\n" + +#. @-expanded: External journal has multiple filesystem users (unsupported).\n +#: e2fsck/problem.c:192 +msgid "External @j has multiple @f users (unsupported).\n" +msgstr "Externes @j hat mehrere @f Nutzer (nicht unterstützt).\n" + +#. @-expanded: Can't find external journal\n +#: e2fsck/problem.c:197 +msgid "Can't find external @j\n" +msgstr "Kann kein externes @j finden.\n" + +#. @-expanded: External journal has bad superblock\n +#: e2fsck/problem.c:202 +msgid "External @j has bad @S\n" +msgstr "Externes @j hat ungültigen @S\n" + +#. @-expanded: External journal does not support this filesystem\n +#: e2fsck/problem.c:207 +msgid "External @j does not support this @f\n" +msgstr "Externes @j unterstützt nicht @f\n" + +#. @-expanded: filesystem journal superblock is unknown type %N (unsupported).\n +#. @-expanded: It is likely that your copy of e2fsck is old and/or doesn't support this journal +#. @-expanded: format.\n +#. @-expanded: It is also possible the journal superblock is corrupt.\n +#: e2fsck/problem.c:212 +#, fuzzy +msgid "" +"@f @j @S is unknown type %N (unsupported).\n" +"It is likely that your copy of e2fsck is old and/or doesn't support this @j format.\n" +"It is also possible the @j @S is corrupt.\n" +msgstr "" +"Ext3 @j @S ist eine unbekannter Type %N (nicht unterstützt).\n" +"Es ist möglich, dass ihr e2fsck älter ist und/oder dieses @j Format nicht unterstützt.\n" +"Es ist ebenso möglich, dass @j @S defekt ist.\n" + +#. @-expanded: journal superblock is corrupt.\n +#: e2fsck/problem.c:220 +#, fuzzy +msgid "@j @S is corrupt.\n" +msgstr "Ext3 @j @S ist defekt.\n" + +#. @-expanded: superblock has_journal flag is clear, but a journal %s is present.\n +#: e2fsck/problem.c:225 +#, c-format +msgid "@S has_@j flag is clear, but a @j %s is present.\n" +msgstr "ext3 Recovery-Flag sauber, aber ein @j %s ist vorhanden.\n" + +#. @-expanded: superblock needs_recovery flag is set, but no journal is present.\n +#: e2fsck/problem.c:230 +#, fuzzy +msgid "@S needs_recovery flag is set, but no @j is present.\n" +msgstr "@S hat das ext3 »needs_recovery«-Flag gesetzt, aber kein @j.\n" + +#. @-expanded: superblock needs_recovery flag is clear, but journal has data.\n +#: e2fsck/problem.c:235 +#, fuzzy +msgid "@S needs_recovery flag is clear, but @j has data.\n" +msgstr "ext3 Recovery-Flag sauber, aber das @j enthält Daten.\n" + +#. @-expanded: Clear journal +#: e2fsck/problem.c:240 +msgid "Clear @j" +msgstr "Bereinige @j" + +#. @-expanded: Run journal anyway +#: e2fsck/problem.c:245 +msgid "Run @j anyway" +msgstr "Starte @j trotzdem" + +#. @-expanded: Recovery flag not set in backup superblock, so running journal anyway.\n +#: e2fsck/problem.c:250 +msgid "Recovery flag not set in backup @S, so running @j anyway.\n" +msgstr "Recovery-Kennzeichen in Backup @S nicht gesetzt, @j wird trotzdem gestartet.\n" + +#. @-expanded: %s orphaned inode %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n +#: e2fsck/problem.c:255 +msgid "%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n" +msgstr "%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n" + +#. @-expanded: illegal block #%B (%b) found in orphaned inode %i.\n +#: e2fsck/problem.c:260 +msgid "@I @b #%B (%b) found in @o @i %i.\n" +msgstr "@I @b #%B (%b) gefunden in @o @i %i.\n" + +#. @-expanded: Already cleared block #%B (%b) found in orphaned inode %i.\n +#: e2fsck/problem.c:265 +msgid "Already cleared @b #%B (%b) found in @o @i %i.\n" +msgstr "bereits bereinigt @b #%B (%b) gefunden in @o @i %i.\n" + +#. @-expanded: illegal orphaned inode %i in superblock.\n +#: e2fsck/problem.c:270 +#, c-format +msgid "@I @o @i %i in @S.\n" +msgstr "@I @o @i %i in @S.\n" + +#. @-expanded: illegal inode %i in orphaned inode list.\n +#: e2fsck/problem.c:275 +#, c-format +msgid "@I @i %i in @o @i list.\n" +msgstr "@I @i %i in @o @i Liste.\n" + +#. @-expanded: filesystem has feature flag(s) set, but is a revision 0 filesystem. +#: e2fsck/problem.c:280 +#: e2fsck/problem.c:647 +msgid "@f has feature flag(s) set, but is a revision 0 @f. " +msgstr "@f hat Eigenschfts-Kennzeichen gesetzt, ist aber ein Revision 0 @f. " + +#. @-expanded: journal superblock has an unknown read-only feature flag set.\n +#: e2fsck/problem.c:285 +#, fuzzy +msgid "@j @S has an unknown read-only feature flag set.\n" +msgstr "Ext3 @j @S hat ein unbekanntes Nur-Lesen-Flag gesetzt.\n" + +#. @-expanded: journal superblock has an unknown incompatible feature flag set.\n +#: e2fsck/problem.c:290 +#, fuzzy +msgid "@j @S has an unknown incompatible feature flag set.\n" +msgstr "Ext3 @j @S hat ein unbekanntes Inkompatibel-Flag gesetzt.\n" + +#. @-expanded: journal version not supported by this e2fsck.\n +#: e2fsck/problem.c:295 +msgid "@j version not supported by this e2fsck.\n" +msgstr "@j Version wird von diesem e2fsck nicht unterstützt.\n" + +#. @-expanded: Moving journal from /%s to hidden inode.\n +#. @-expanded: \n +#: e2fsck/problem.c:300 +#, c-format +msgid "" +"Moving @j from /%s to hidden @i.\n" +"\n" +msgstr "" +"Verschiebe @j von /%s zum versteckten Inode.\n" +"\n" + +#. @-expanded: Error moving journal: %m\n +#. @-expanded: \n +#: e2fsck/problem.c:305 +#, c-format +msgid "" +"Error moving @j: %m\n" +"\n" +msgstr "" +"Fehler beim Verschieben von @j: %m\n" +"\n" + +#. @-expanded: Found invalid V2 journal superblock fields (from V1 journal).\n +#. @-expanded: Clearing fields beyond the V1 journal superblock...\n +#. @-expanded: \n +#: e2fsck/problem.c:310 +msgid "" +"Found @n V2 @j @S fields (from V1 @j).\n" +"Clearing fields beyond the V1 @j @S...\n" +"\n" +msgstr "" +"Fand unvollständige V2 @j @S Felder (vom V1 Journal).\n" +"Bereinige die Felder hinter V1 @j @S...\n" +"\n" + +#. @-expanded: Backing up journal inode block information.\n +#. @-expanded: \n +#: e2fsck/problem.c:316 +msgid "" +"Backing up @j @i @b information.\n" +"\n" +msgstr "" +"Sichere @j @i @b Information.\n" +"\n" + +#. @-expanded: filesystem does not have resize_inode enabled, but s_reserved_gdt_blocks\n +#. @-expanded: is %N; should be zero. +#: e2fsck/problem.c:321 +msgid "" +"@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n" +"is %N; @s zero. " +msgstr "" +"Für @f ist resize_@i nicht eingeschaltet, aber s_reserved_gdt_@bs\n" +"ist %N; @s Null. " + +#. @-expanded: Resize_inode not enabled, but the resize inode is non-zero. +#: e2fsck/problem.c:327 +msgid "Resize_@i not enabled, but the resize @i is non-zero. " +msgstr "Resize_@i nicht aktiviert, aber die zu modifgizierende Inod ist nicht-Null." + +#. @-expanded: Resize inode not valid. +#: e2fsck/problem.c:332 +msgid "Resize @i not valid. " +msgstr "@r ist kein @d. " + +#. @-expanded: superblock last mount time is in the future. +#: e2fsck/problem.c:337 +msgid "@S last mount time is in the future. " +msgstr "Der Zeitpunkt des letzten Einhängens von @S liegt in der Zukunft" + +#. @-expanded: superblock last write time is in the future. +#: e2fsck/problem.c:342 +msgid "@S last write time is in the future. " +msgstr "Der Zeitpunkt des letzten Schreibens von @S liegt in der Zukunft. " + +#. @-expanded: superblock hint for external superblock should be %X. +#: e2fsck/problem.c:346 +#, c-format +msgid "@S hint for external superblock @s %X. " +msgstr "@S Hinweis für externen Superblock @s %X" + +#. @-expanded: Adding dirhash hint to filesystem.\n +#. @-expanded: \n +#: e2fsck/problem.c:351 +msgid "" +"Adding dirhash hint to @f.\n" +"\n" +msgstr "" +"Füge Verzeinishash-Hilfe zu @f hinzu.\n" +"\n" + +#. @-expanded: group descriptor %g checksum is invalid. +#: e2fsck/problem.c:356 +#, c-format +msgid "@g descriptor %g checksum is invalid. " +msgstr "Prüfsumme von @g -Deskriptor %g ist ungültig. " + +#. @-expanded: group descriptor %g marked uninitialized without feature set.\n +#: e2fsck/problem.c:361 +#, c-format +msgid "@g descriptor %g marked uninitialized without feature set.\n" +msgstr "@g -Deskriptor %g ist als nicht initialisiert gekennzeichnet ohne eine gesetzte Eigenschaft.\n" + +#. @-expanded: group %g block bitmap uninitialized but inode bitmap in use.\n +#: e2fsck/problem.c:366 +#, c-format +msgid "@g %g @b @B uninitialized but @i @B in use.\n" +msgstr "Die @b @B von @g %g ist nicht initialisiert aber @i @B wird verwendet.\n" + +#. @-expanded: group descriptor %g has invalid unused inodes count %b. +#: e2fsck/problem.c:371 +msgid "@g descriptor %g has invalid unused inodes count %b. " +msgstr "@g Deskriptor %g hat eine ungültige Anzahl ungenutzter Inodes von %b. " + +#. @-expanded: Last group block bitmap uninitialized. +#: e2fsck/problem.c:376 +msgid "Last @g @b @B uninitialized. " +msgstr "Die letzte @g @b @B ist nicht initialisiert. " + +#: e2fsck/problem.c:381 +#, c-format +msgid "Journal transaction %i was corrupt, replay was aborted.\n" +msgstr "Journaltransaktion %i war beschädigt, die Wiederholung wurde abgegrochen.\n" + +#: e2fsck/problem.c:385 +msgid "The test_fs flag is set (and ext4 is available). " +msgstr "" + +#. @-expanded: Pass 1: Checking inodes, blocks, and sizes\n +#: e2fsck/problem.c:392 +msgid "Pass 1: Checking @is, @bs, and sizes\n" +msgstr "Durchgang 1: Prüfe @is, @bs, und Größen\n" + +#. @-expanded: root inode is not a directory. +#: e2fsck/problem.c:396 +msgid "@r is not a @d. " +msgstr "@r ist kein @d. " + +#. @-expanded: root inode has dtime set (probably due to old mke2fs). +#: e2fsck/problem.c:401 +msgid "@r has dtime set (probably due to old mke2fs). " +msgstr "@r hat dtime gesetzt (vielleicht durch ein zu altes mke2fs). " + +#. @-expanded: Reserved inode %i (%Q) has invalid mode. +#: e2fsck/problem.c:406 +msgid "Reserved @i %i (%Q) has @n mode. " +msgstr "Reservierte @i %i %Q hat einen falschen Modus. " + +#. @-expanded: deleted inode %i has zero dtime. +#: e2fsck/problem.c:411 +#, c-format +msgid "@D @i %i has zero dtime. " +msgstr "@D @i %i hat \"zero dtime\". " + +#. @-expanded: inode %i is in use, but has dtime set. +#: e2fsck/problem.c:416 +#, c-format +msgid "@i %i is in use, but has dtime set. " +msgstr "@i %i ist in Benutzung, aber hat dtime gesetzt. " + +#. @-expanded: inode %i is a zero-length directory. +#: e2fsck/problem.c:421 +#, c-format +msgid "@i %i is a @z @d. " +msgstr "@i %i ist ein @z @d. " + +#. @-expanded: group %g's block bitmap at %b conflicts with some other fs block.\n +#: e2fsck/problem.c:426 +msgid "@g %g's @b @B at %b @C.\n" +msgstr "@g %g's @b @B auf %b @C.\n" + +#. @-expanded: group %g's inode bitmap at %b conflicts with some other fs block.\n +#: e2fsck/problem.c:431 +msgid "@g %g's @i @B at %b @C.\n" +msgstr "@g %g's @i @B auf %b @C.\n" + +#. @-expanded: group %g's inode table at %b conflicts with some other fs block.\n +#: e2fsck/problem.c:436 +msgid "@g %g's @i table at %b @C.\n" +msgstr "@g %g's @i Tabelle auf %b @C.\n" + +#. @-expanded: group %g's block bitmap (%b) is bad. +#: e2fsck/problem.c:441 +msgid "@g %g's @b @B (%b) is bad. " +msgstr "@g %g's @b @B (%b) ist ungültig. " + +#. @-expanded: group %g's inode bitmap (%b) is bad. +#: e2fsck/problem.c:446 +msgid "@g %g's @i @B (%b) is bad. " +msgstr "@g %g's @i @B (%b) ist ungültig. " + +#. @-expanded: inode %i, i_size is %Is, should be %N. +#: e2fsck/problem.c:451 +msgid "@i %i, i_size is %Is, @s %N. " +msgstr "@i %i, i_size ist %Is, @s %N. " + +#. @-expanded: inode %i, i_blocks is %Ib, should be %N. +#: e2fsck/problem.c:456 +msgid "@i %i, i_@bs is %Ib, @s %N. " +msgstr "@i %i, i_@bs ist %Ib, @s %N. " + +#. @-expanded: illegal block #%B (%b) in inode %i. +#: e2fsck/problem.c:461 +msgid "@I @b #%B (%b) in @i %i. " +msgstr "@I @b #%B (%b) in @i %i. " + +#. @-expanded: block #%B (%b) overlaps filesystem metadata in inode %i. +#: e2fsck/problem.c:466 +msgid "@b #%B (%b) overlaps @f metadata in @i %i. " +msgstr "@b #%B (%b) überlappt @f metadata in @i %i. " + +#. @-expanded: inode %i has illegal block(s). +#: e2fsck/problem.c:471 +#, c-format +msgid "@i %i has illegal @b(s). " +msgstr "@i %i hat unzulässigen @b(s). " + +#. @-expanded: Too many illegal blocks in inode %i.\n +#: e2fsck/problem.c:476 +#, c-format +msgid "Too many illegal @bs in @i %i.\n" +msgstr "Zu viele unzulässige @bs in @i %i.\n" + +#. @-expanded: illegal block #%B (%b) in bad block inode. +#: e2fsck/problem.c:481 +msgid "@I @b #%B (%b) in bad @b @i. " +msgstr "@I @b #%B (%b) in bad @b @i. " + +#. @-expanded: Bad block inode has illegal block(s). +#: e2fsck/problem.c:486 +msgid "Bad @b @i has illegal @b(s). " +msgstr "Bad @b @i hat unzulässigen @b(s). " + +#. @-expanded: Duplicate or bad block in use!\n +#: e2fsck/problem.c:491 +msgid "Duplicate or bad @b in use!\n" +msgstr "Doppelter oder unzulässiger @b in Gebrauch!\n" + +#. @-expanded: Bad block %b used as bad block inode indirect block. +#: e2fsck/problem.c:496 +msgid "Bad @b %b used as bad @b @i indirect @b. " +msgstr "Bad @b %b benutzt als bad @b @i indirekt @b. " + +#. @-expanded: \n +#. @-expanded: The bad block inode has probably been corrupted. You probably\n +#. @-expanded: should stop now and run e2fsck -c to scan for bad blocks\n +#. @-expanded: in the filesystem.\n +#: e2fsck/problem.c:501 +msgid "" +"\n" +"The bad @b @i has probably been corrupted. You probably\n" +"should stop now and run e2fsck -c to scan for bad blocks\n" +"in the @f.\n" +msgstr "" +"\n" +"Defekter @b @i ist wahrscheinlich beschädigt worden. Sie sollten\n" +"nun eher innehalten und »e2fsck -c« ausführen, um nach defekten\n" +"Blöcken in @f zu suchen.\n" + +#. @-expanded: \n +#. @-expanded: If the block is really bad, the filesystem can not be fixed.\n +#: e2fsck/problem.c:508 +msgid "" +"\n" +"If the @b is really bad, the @f can not be fixed.\n" +msgstr "" +"\n" +"Wenn der @b wirklich defekt ist, kann der @f nicht repariert werden.\n" + +#. @-expanded: You can remove this block from the bad block list and hope\n +#. @-expanded: that the block is really OK. But there are no guarantees.\n +#. @-expanded: \n +#: e2fsck/problem.c:513 +msgid "" +"You can remove this @b from the bad @b list and hope\n" +"that the @b is really OK. But there are no guarantees.\n" +"\n" +msgstr "" +"Sie können @b von der @b - Liste löschen \n" +"und hoffen das @b wirklich in Ordnung ist, es \n" +"gibt aber KEINE GARANTIEN.\n" +"\n" + +#. @-expanded: The primary superblock (%b) is on the bad block list.\n +#: e2fsck/problem.c:519 +msgid "The primary @S (%b) is on the bad @b list.\n" +msgstr "Der primäre @S (%b) ist auf der bad @b Liste.\n" + +#. @-expanded: Block %b in the primary group descriptors is on the bad block list\n +#: e2fsck/problem.c:524 +msgid "Block %b in the primary @g descriptors is on the bad @b list\n" +msgstr "Block %b im primären Deskriptor @g ist auf der bad @b Liste\n" + +#. @-expanded: Warning: Group %g's superblock (%b) is bad.\n +#: e2fsck/problem.c:530 +msgid "Warning: Group %g's @S (%b) is bad.\n" +msgstr "Warnung: Gruppe %g's @S (%b) ist ungültig.\n" + +#. @-expanded: Warning: Group %g's copy of the group descriptors has a bad block (%b).\n +#: e2fsck/problem.c:535 +msgid "Warning: Group %g's copy of the @g descriptors has a bad @b (%b).\n" +msgstr "Warnung: Gruppe %g's Kopie vom Deskriptor @g hat einen bad @b (%b).\n" + +#. @-expanded: Programming error? block #%b claimed for no reason in process_bad_block.\n +#: e2fsck/problem.c:541 +msgid "Programming error? @b #%b claimed for no reason in process_bad_@b.\n" +msgstr "Programmfehler? @b #%b verlangt ohne Grund in process_bad_@b.\n" + +#. @-expanded: error allocating %N contiguous block(s) in block group %g for %s: %m\n +#: e2fsck/problem.c:547 +msgid "@A %N contiguous @b(s) in @b @g %g for %s: %m\n" +msgstr "@A %N grenzt an @b(s) in @b @g %g for %s: %m\n" + +#. @-expanded: error allocating block buffer for relocating %s\n +#: e2fsck/problem.c:552 +#, c-format +msgid "@A @b buffer for relocating %s\n" +msgstr "@A @b Puffer zum Verschieben %s\n" + +#. @-expanded: Relocating group %g's %s from %b to %c...\n +#: e2fsck/problem.c:557 +msgid "Relocating @g %g's %s from %b to %c...\n" +msgstr "Verschiebe @g %g's %s von %b nach %c...\n" + +#. @-expanded: Relocating group %g's %s to %c...\n +#: e2fsck/problem.c:562 +#, c-format +msgid "Relocating @g %g's %s to %c...\n" +msgstr "Verschiebe @g %g's %s nach %c...\n" + +#. @-expanded: Warning: could not read block %b of %s: %m\n +#: e2fsck/problem.c:567 +msgid "Warning: could not read @b %b of %s: %m\n" +msgstr "Warnung: kann @b %b von %s: %m nicht lesen\n" + +#. @-expanded: Warning: could not write block %b for %s: %m\n +#: e2fsck/problem.c:572 +msgid "Warning: could not write @b %b for %s: %m\n" +msgstr "Warnung: kann @b %b von %s: %m nicht schreiben\n" + +#. @-expanded: error allocating inode bitmap (%N): %m\n +#: e2fsck/problem.c:577 +#: e2fsck/problem.c:1378 +msgid "@A @i @B (%N): %m\n" +msgstr "@A @i @B (%N): %m\n" + +#. @-expanded: error allocating block bitmap (%N): %m\n +#: e2fsck/problem.c:582 +msgid "@A @b @B (%N): %m\n" +msgstr "@A @i @B (%N): %m\n" + +#. @-expanded: error allocating icount link information: %m\n +#: e2fsck/problem.c:587 +#, c-format +msgid "@A icount link information: %m\n" +msgstr "@A icount link information: %m\n" + +#. @-expanded: error allocating directory block array: %m\n +#: e2fsck/problem.c:592 +#, c-format +msgid "@A @d @b array: %m\n" +msgstr "@A @d @b array: %m\n" + +#. @-expanded: Error while scanning inodes (%i): %m\n +#: e2fsck/problem.c:597 +#, c-format +msgid "Error while scanning @is (%i): %m\n" +msgstr "Fehler während der Suche @is (%i): %m\n" + +#. @-expanded: Error while iterating over blocks in inode %i: %m\n +#: e2fsck/problem.c:602 +#, c-format +msgid "Error while iterating over @bs in @i %i: %m\n" +msgstr "Fehler beim Iterieren über @bs in @i %i: %m\n" + +#. @-expanded: Error storing inode count information (inode=%i, count=%N): %m\n +#: e2fsck/problem.c:607 +msgid "Error storing @i count information (@i=%i, count=%N): %m\n" +msgstr "Fehler beim Speichern von @i count Informationen (@i=%i, count=%N): %m\n" + +#. @-expanded: Error storing directory block information (inode=%i, block=%b, num=%N): %m\n +#: e2fsck/problem.c:612 +msgid "Error storing @d @b information (@i=%i, @b=%b, num=%N): %m\n" +msgstr "Fehler beim Speichern @d @b Informationen (@i=%i, @b=%b, num=%N): %m\n" + +#. @-expanded: Error reading inode %i: %m\n +#: e2fsck/problem.c:618 +#, c-format +msgid "Error reading @i %i: %m\n" +msgstr "Fehler beim Lesen von @i %i: %m\n" + +#. @-expanded: inode %i has imagic flag set. +#: e2fsck/problem.c:626 +#, c-format +msgid "@i %i has imagic flag set. " +msgstr "@i %i hat Imagic-Flag gesetzt. " + +#. @-expanded: Special (device/socket/fifo/symlink) file (inode %i) has immutable\n +#. @-expanded: or append-only flag set. +#: e2fsck/problem.c:631 +#, c-format +msgid "" +"Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n" +"or append-only flag set. " +msgstr "" +"Spezielle (@v/socket/fifo/symlink) Datei (@i %i) hat immutable\n" +"oder append-only Flag gesetzt. " + +#. @-expanded: inode %i has compression flag set on filesystem without compression support. +#: e2fsck/problem.c:637 +#, c-format +msgid "@i %i has @cion flag set on @f without @cion support. " +msgstr "@i %i hat @cion Flag gesetzt auf @f ohne @cion Unterstützung. " + +#. @-expanded: Special (device/socket/fifo) inode %i has non-zero size. +#: e2fsck/problem.c:642 +#, c-format +msgid "Special (@v/socket/fifo) @i %i has non-zero size. " +msgstr "" +"Spezielle (@v/socket/fifo/symlink) Datei (@i %i) hat immutable\n" +"oder append-only Flag gesetzt. " + +#. @-expanded: journal inode is not in use, but contains data. +#: e2fsck/problem.c:652 +msgid "@j @i is not in use, but contains data. " +msgstr "@i %i ist in Benutzung, aber hat dtime gesetzt. " + +#. @-expanded: journal is not regular file. +#: e2fsck/problem.c:657 +msgid "@j is not regular file. " +msgstr "@j ist keine reguläre Datei. " + +#. @-expanded: inode %i was part of the orphaned inode list. +#: e2fsck/problem.c:662 +#, c-format +msgid "@i %i was part of the @o @i list. " +msgstr "@i %i war Teil der orphaned @i Liste. " + +#. @-expanded: inodes that were part of a corrupted orphan linked list found. +#: e2fsck/problem.c:668 +msgid "@is that were part of a corrupted orphan linked list found. " +msgstr "@is, die Teile einer defekten Liste mit verwaisten Links waren. " + +#. @-expanded: error allocating refcount structure (%N): %m\n +#: e2fsck/problem.c:673 +msgid "@A refcount structure (%N): %m\n" +msgstr "@A icount structure: %m\n" + +#. @-expanded: Error reading extended attribute block %b for inode %i. +#: e2fsck/problem.c:678 +msgid "Error reading @a @b %b for @i %i. " +msgstr "Fehler beim Lesen @a @b %b for @i %i. " + +#. @-expanded: inode %i has a bad extended attribute block %b. +#: e2fsck/problem.c:683 +msgid "@i %i has a bad @a @b %b. " +msgstr "@i %i hat defekten @a @b %b. " + +#. @-expanded: Error reading extended attribute block %b (%m). +#: e2fsck/problem.c:688 +msgid "Error reading @a @b %b (%m). " +msgstr "Fehler beim Lesen @a @b %b (%m). " + +#. @-expanded: extended attribute block %b has reference count %B, should be %N. +#: e2fsck/problem.c:693 +msgid "@a @b %b has reference count %B, @s %N. " +msgstr "@a @b %b hat den Referenzzähler %B, richtig wäre %N. " + +#. @-expanded: Error writing extended attribute block %b (%m). +#: e2fsck/problem.c:698 +msgid "Error writing @a @b %b (%m). " +msgstr "Fehler beim Schreiben @a @b %b (%m). " + +#. @-expanded: extended attribute block %b has h_blocks > 1. +#: e2fsck/problem.c:703 +msgid "@a @b %b has h_@bs > 1. " +msgstr "@a @b %b hat h_blocks > 1. " + +#. @-expanded: error allocating extended attribute block %b. +#: e2fsck/problem.c:708 +msgid "@A @a @b %b. " +msgstr "@A @a @b %b. " + +#. @-expanded: extended attribute block %b is corrupt (allocation collision). +#: e2fsck/problem.c:713 +msgid "@a @b %b is corrupt (allocation collision). " +msgstr "@a @b %b ist defekt (allocation collision). " + +#. @-expanded: extended attribute block %b is corrupt (invalid name). +#: e2fsck/problem.c:718 +msgid "@a @b %b is corrupt (@n name). " +msgstr "@a @b %b ist defekt (ungültiger Name). " + +#. @-expanded: extended attribute block %b is corrupt (invalid value). +#: e2fsck/problem.c:723 +msgid "@a @b %b is corrupt (@n value). " +msgstr "@a @b %b ist defekt (ungültiger Wert). " + +#. @-expanded: inode %i is too big. +#: e2fsck/problem.c:728 +#, c-format +msgid "@i %i is too big. " +msgstr "@i %i ist zu groß. " + +#. @-expanded: block #%B (%b) causes directory to be too big. +#: e2fsck/problem.c:732 +msgid "@b #%B (%b) causes @d to be too big. " +msgstr "@b #%B (%b) macht @d zu groß. " + +#. @-expanded: block #%B (%b) causes file to be too big. +#: e2fsck/problem.c:737 +msgid "@b #%B (%b) causes file to be too big. " +msgstr "@b #%B (%b) macht die Datei zu groß. " + +#. @-expanded: block #%B (%b) causes symlink to be too big. +#: e2fsck/problem.c:742 +msgid "@b #%B (%b) causes symlink to be too big. " +msgstr "@b #%B (%b) macht den Symlink zu groß. " + +#. @-expanded: inode %i has INDEX_FL flag set on filesystem without htree support.\n +#: e2fsck/problem.c:747 +#, c-format +msgid "@i %i has INDEX_FL flag set on @f without htree support.\n" +msgstr "@i %i hat INDEX_FL Flag auf @f gesetzt ohne HTREE-Unterstützung.\n" + +#. @-expanded: inode %i has INDEX_FL flag set but is not a directory.\n +#: e2fsck/problem.c:752 +#, c-format +msgid "@i %i has INDEX_FL flag set but is not a @d.\n" +msgstr "@i %i hat INDEX_FL flag gesetzt, ist aber kein @d.\n" + +#. @-expanded: HTREE directory inode %i has an invalid root node.\n +#: e2fsck/problem.c:757 +#, c-format +msgid "@h %i has an @n root node.\n" +msgstr "@h %i hat einen unvollständigen root node.\n" + +#. @-expanded: HTREE directory inode %i has an unsupported hash version (%N)\n +#: e2fsck/problem.c:762 +msgid "@h %i has an unsupported hash version (%N)\n" +msgstr "@h %i hat eine nicht unterstützte hash-Version (%N)\n" + +#. @-expanded: HTREE directory inode %i uses an incompatible htree root node flag.\n +#: e2fsck/problem.c:767 +#, c-format +msgid "@h %i uses an incompatible htree root node flag.\n" +msgstr "@h %i benutzt einen nicht unterstützten htree root node flag.\n" + +#. @-expanded: HTREE directory inode %i has a tree depth (%N) which is too big\n +#: e2fsck/problem.c:772 +msgid "@h %i has a tree depth (%N) which is too big\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: Bad block inode has an indirect block (%b) that conflicts with\n +#. @-expanded: filesystem metadata. +#: e2fsck/problem.c:777 +msgid "" +"Bad @b @i has an indirect @b (%b) that conflicts with\n" +"@f metadata. " +msgstr "" +"Defekter @b @i hat einen indirekten @b (%b), der mit\n" +"den @f Metadaten in Konflikt steht. " + +#. @-expanded: Resize inode (re)creation failed: %m. +#: e2fsck/problem.c:783 +#, c-format +msgid "Resize @i (re)creation failed: %m." +msgstr "Erzeugung von Vergrösserungs-@i scheiterte: %m." + +#. @-expanded: inode %i has a extra size (%IS) which is invalid\n +#: e2fsck/problem.c:788 +msgid "@i %i has a extra size (%IS) which is @n\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: extended attribute in inode %i has a namelen (%N) which is invalid\n +#: e2fsck/problem.c:793 +msgid "@a in @i %i has a namelen (%N) which is @n\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: extended attribute in inode %i has a value size (%N) which is invalid\n +#: e2fsck/problem.c:798 +msgid "@a in @i %i has a value size (%N) which is @n\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: extended attribute in inode %i has a value offset (%N) which is invalid\n +#: e2fsck/problem.c:803 +msgid "@a in @i %i has a value offset (%N) which is @n\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: extended attribute in inode %i has a value block (%N) which is invalid (must be 0)\n +#: e2fsck/problem.c:808 +msgid "@a in @i %i has a value @b (%N) which is @n (must be 0)\n" +msgstr "@h %i hat eine zu große Verzeichnistiefe von (%N)\n" + +#. @-expanded: extended attribute in inode %i has a hash (%N) which is invalid\n +#: e2fsck/problem.c:813 +msgid "@a in @i %i has a hash (%N) which is @n\n" +msgstr "@a in %i hat einen @n Hashwert von (%N)\n" + +#. @-expanded: inode %i is a %It but it looks like it is really a directory.\n +#: e2fsck/problem.c:818 +msgid "@i %i is a %It but it looks like it is really a directory.\n" +msgstr "@i ist ein %It aber es sieht so aus, als ob es tatsächlich ein Verzeichnis ist.\n" + +#. @-expanded: Error while reading over extent tree in inode %i: %m\n +#: e2fsck/problem.c:823 +#, c-format +msgid "Error while reading over @x tree in @i %i: %m\n" +msgstr "Fehler beim Iterieren über Baum @x in @i %i: %m\n" + +#. @-expanded: Failed to iterate extents in inode %i\n +#. @-expanded: \t(op %s, blk %b, lblk %c): %m\n +#: e2fsck/problem.c:828 +msgid "" +"Failed to iterate extents in @i %i\n" +"\t(op %s, blk %b, lblk %c): %m\n" +msgstr "" + +#. @-expanded: inode %i has an invalid extent\n +#. @-expanded: \t(logical block %c, invalid physical block %b, len %N)\n +#: e2fsck/problem.c:834 +msgid "" +"@i %i has an @n extent\n" +"\t(logical @b %c, @n physical @b %b, len %N)\n" +msgstr "" +"@i %i hat eine @n Erweiterung\n" +"\t(logischer @b %c, @n physischer @b %b, Länge %N)\n" + +#. @-expanded: inode %i has an invalid extent\n +#. @-expanded: \t(logical block %c, physical block %b, invalid len %N)\n +#: e2fsck/problem.c:839 +msgid "" +"@i %i has an @n extent\n" +"\t(logical @b %c, physical @b %b, @n len %N)\n" +msgstr "" +"@i %i hat eine @n Erweiterung\n" +"\t(logischer @b %c, physischer @b %b, @n Länge %N)\n" + +#. @-expanded: inode %i has EXTENTS_FL flag set on filesystem without extents support.\n +#: e2fsck/problem.c:844 +#, c-format +msgid "@i %i has EXTENTS_FL flag set on @f without extents support.\n" +msgstr "@i %i hat EXTENTS_FL Kennung auf einem @f ohne Unterstützung für Erweiterungen.\n" + +#. @-expanded: inode %i is in extent format, but superblock is missing EXTENTS feature\n +#: e2fsck/problem.c:849 +#, c-format +msgid "@i %i is in extent format, but @S is missing EXTENTS feature\n" +msgstr "@i %i besitzt das Erweiterungsformat, aber dem @S fehlt die Eigenschaft EXTENTS\n" + +#. @-expanded: inode %i missing EXTENT_FL, but is in extents format\n +#: e2fsck/problem.c:854 +#, c-format +msgid "@i %i missing EXTENT_FL, but is in extents format\n" +msgstr "@i %i fehlt EXTENT_FL, aber hat das Format einer Erweiterungs-@i\n" + +#: e2fsck/problem.c:859 +#, c-format +msgid "Fast symlink %i has EXTENT_FL set. " +msgstr "Schneller Symlink %i hat EXTENT_FL gesetzt. " + +#. @-expanded: inode %i has out of order extents\n +#. @-expanded: \t(invalid logical block %c, physical block %b, len %N)\n +#: e2fsck/problem.c:864 +msgid "" +"@i %i has out of order extents\n" +"\t(@n logical @b %c, physical @b %b, len %N)\n" +msgstr "" +"@i %i hat unregelmässige Erweitertungen\n" +"\t(@n logischer @b %c, physischer @b %b, Länge %N)\n" + +#. @-expanded: inode %i has an invalid extent node (blk %b, lblk %c)\n +#: e2fsck/problem.c:868 +msgid "@i %i has an invalid extent node (blk %b, lblk %c)\n" +msgstr "" + +#. @-expanded: \n +#. @-expanded: Running additional passes to resolve blocks claimed by more than one inode...\n +#. @-expanded: Pass 1B: Rescanning for multiply-claimed blocks\n +#: e2fsck/problem.c:875 +msgid "" +"\n" +"Running additional passes to resolve @bs claimed by more than one @i...\n" +"Pass 1B: Rescanning for @m @bs\n" +msgstr "" +"\n" +"Doppelter @bs gefunden... starte Scan nach doppelten @b.\n" +"Durchgang 1B: Suche nach doppelten/defekten @bs\n" + +#. @-expanded: multiply-claimed block(s) in inode %i: +#: e2fsck/problem.c:881 +#, c-format +msgid "@m @b(s) in @i %i:" +msgstr "@m @b(s) in @i %i:" + +#: e2fsck/problem.c:896 +#, c-format +msgid "Error while scanning inodes (%i): %m\n" +msgstr "Fehlen beim Prüfen von Inodes (%i): %m\n" + +#. @-expanded: error allocating inode bitmap (inode_dup_map): %m\n +#: e2fsck/problem.c:901 +#, c-format +msgid "@A @i @B (@i_dup_map): %m\n" +msgstr "@A @i @B (inode_dup_map): %m\n" + +#. @-expanded: Error while iterating over blocks in inode %i (%s): %m\n +#: e2fsck/problem.c:906 +#, c-format +msgid "Error while iterating over @bs in @i %i (%s): %m\n" +msgstr "Fehler beim Durchlaufen der @bs in @i %i (%s): %m\n" + +#. @-expanded: Error adjusting refcount for extended attribute block %b (inode %i): %m\n +#: e2fsck/problem.c:911 +#: e2fsck/problem.c:1227 +msgid "Error adjusting refcount for @a @b %b (@i %i): %m\n" +msgstr "Fehler bei der Anpassung des refcount für @a @b %b (@i %i): %m\n" + +#. @-expanded: Pass 1C: Scanning directories for inodes with multiply-claimed blocks\n +#: e2fsck/problem.c:917 +msgid "Pass 1C: Scanning directories for @is with @m @bs\n" +msgstr "Durchgang 1C: Prüfe Verzeichnisse nach @is mit doppelten @bs.\n" + +#. @-expanded: Pass 1D: Reconciling multiply-claimed blocks\n +#: e2fsck/problem.c:923 +msgid "Pass 1D: Reconciling @m @bs\n" +msgstr "Durchgang 1D: Gleiche doppelte @bs ab\n" + +#. @-expanded: File %Q (inode #%i, mod time %IM) \n +#. @-expanded: has %B multiply-claimed block(s), shared with %N file(s):\n +#: e2fsck/problem.c:928 +msgid "" +"File %Q (@i #%i, mod time %IM) \n" +" has %B @m @b(s), shared with %N file(s):\n" +msgstr "" +"Datei %Q (@i #%i, mod time %IM) \n" +" hat %B doppelte @b(s), geteilt mit %N Datei(en):\n" + +#. @-expanded: \t%Q (inode #%i, mod time %IM)\n +#: e2fsck/problem.c:934 +msgid "\t%Q (@i #%i, mod time %IM)\n" +msgstr "\t%Q (@i #%i, mod time %IM)\n" + +#. @-expanded: \t\n +#: e2fsck/problem.c:939 +msgid "\t<@f metadata>\n" +msgstr "\t<@f metadata>\n" + +#. @-expanded: (There are %N inodes containing multiply-claimed blocks.)\n +#. @-expanded: \n +#: e2fsck/problem.c:944 +msgid "" +"(There are %N @is containing @m @bs.)\n" +"\n" +msgstr "" +"(es gibt %N @is, die doppelte/defekte @bs enthalten.)\n" +"\n" + +#. @-expanded: multiply-claimed blocks already reassigned or cloned.\n +#. @-expanded: \n +#: e2fsck/problem.c:949 +msgid "" +"@m @bs already reassigned or cloned.\n" +"\n" +msgstr "" +"Duplizierte @bs bereits neu zugeordnet bzw. geklont.\n" +"\n" + +#: e2fsck/problem.c:962 +#, c-format +msgid "Couldn't clone file: %m\n" +msgstr "Kann die Datei %m nicht klonen.\n" + +#. @-expanded: Pass 2: Checking directory structure\n +#: e2fsck/problem.c:968 +msgid "Pass 2: Checking @d structure\n" +msgstr "Durchgang 2: Prüfe @d Struktur\n" + +#. @-expanded: invalid inode number for '.' in directory inode %i.\n +#: e2fsck/problem.c:973 +#, c-format +msgid "@n @i number for '.' in @d @i %i.\n" +msgstr "Falsche @i Nummer für ».« in @d @i %i.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has invalid inode #: %Di.\n +#: e2fsck/problem.c:978 +msgid "@E has @n @i #: %Di.\n" +msgstr "@E hat falsche @i #: %Di.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has deleted/unused inode %Di. +#: e2fsck/problem.c:983 +msgid "@E has @D/unused @i %Di. " +msgstr "@E hat @D/unbenutzt @i %Di. " + +#. @-expanded: entry '%Dn' in %p (%i) is a link to '.' +#: e2fsck/problem.c:988 +msgid "@E @L to '.' " +msgstr "@E @L nach ».« " + +#. @-expanded: entry '%Dn' in %p (%i) points to inode (%Di) located in a bad block.\n +#: e2fsck/problem.c:993 +msgid "@E points to @i (%Di) located in a bad @b.\n" +msgstr "@E zeigt auf @i (%Di) in einem defekten @b.\n" + +#. @-expanded: entry '%Dn' in %p (%i) is a link to directory %P (%Di).\n +#: e2fsck/problem.c:998 +msgid "@E @L to @d %P (%Di).\n" +msgstr "@E @L nach @d %P (%Di).\n" + +#. @-expanded: entry '%Dn' in %p (%i) is a link to the root inode.\n +#: e2fsck/problem.c:1003 +msgid "@E @L to the @r.\n" +msgstr "@E @L zur @r.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has illegal characters in its name.\n +#: e2fsck/problem.c:1008 +msgid "@E has illegal characters in its name.\n" +msgstr "@E hat ein unzulässiges Zeichen im Namen.\n" + +#. @-expanded: Missing '.' in directory inode %i.\n +#: e2fsck/problem.c:1013 +#, c-format +msgid "Missing '.' in @d @i %i.\n" +msgstr "Fehlende ».« in @d @i %i.\n" + +#. @-expanded: Missing '..' in directory inode %i.\n +#: e2fsck/problem.c:1018 +#, c-format +msgid "Missing '..' in @d @i %i.\n" +msgstr "Fehlende »..« in @d @i %i.\n" + +#. @-expanded: First entry '%Dn' (inode=%Di) in directory inode %i (%p) should be '.'\n +#: e2fsck/problem.c:1023 +msgid "First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n" +msgstr "Erster @e »%Dn« (inode=%Di) in @d @i %i (%p) @s ».«\n" + +#. @-expanded: Second entry '%Dn' (inode=%Di) in directory inode %i should be '..'\n +#: e2fsck/problem.c:1028 +msgid "Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n" +msgstr "Zweiter @e »%Dn« (inode=%Di) in @d @i %i @s »..«\n" + +#. @-expanded: i_faddr for inode %i (%Q) is %IF, should be zero.\n +#: e2fsck/problem.c:1033 +msgid "i_faddr @F %IF, @s zero.\n" +msgstr "i_faddr @F %IF, @s null.\n" + +#. @-expanded: i_file_acl for inode %i (%Q) is %If, should be zero.\n +#: e2fsck/problem.c:1038 +msgid "i_file_acl @F %If, @s zero.\n" +msgstr "i_file_acl @F %If, @s null.\n" + +#. @-expanded: i_dir_acl for inode %i (%Q) is %Id, should be zero.\n +#: e2fsck/problem.c:1043 +msgid "i_dir_acl @F %Id, @s zero.\n" +msgstr "i_dir_acl @F %Id, @s null.\n" + +#. @-expanded: i_frag for inode %i (%Q) is %N, should be zero.\n +#: e2fsck/problem.c:1048 +msgid "i_frag @F %N, @s zero.\n" +msgstr "i_frag @F %N, @s null.\n" + +#. @-expanded: i_fsize for inode %i (%Q) is %N, should be zero.\n +#: e2fsck/problem.c:1053 +msgid "i_fsize @F %N, @s zero.\n" +msgstr "i_fsize @F %N, @s null.\n" + +#. @-expanded: inode %i (%Q) has invalid mode (%Im).\n +#: e2fsck/problem.c:1058 +msgid "@i %i (%Q) has @n mode (%Im).\n" +msgstr "@i %i (%Q) hat einen falschen Modus (%Im).\n" + +#. @-expanded: directory inode %i, block %B, offset %N: directory corrupted\n +#: e2fsck/problem.c:1063 +msgid "@d @i %i, @b %B, offset %N: @d corrupted\n" +msgstr "@d @i %i, @b %B, offset %N: @d defekt\n" + +#. @-expanded: directory inode %i, block %B, offset %N: filename too long\n +#: e2fsck/problem.c:1068 +msgid "@d @i %i, @b %B, offset %N: filename too long\n" +msgstr "@d @i %i, @b %B, offset %N: Dateiname zu lang\n" + +#. @-expanded: directory inode %i has an unallocated block #%B. +#: e2fsck/problem.c:1073 +msgid "@d @i %i has an unallocated @b #%B. " +msgstr "@d @i %i hat einen nicht zugewiesenen @b #%B. " + +#. @-expanded: '.' directory entry in directory inode %i is not NULL terminated\n +#: e2fsck/problem.c:1078 +#, c-format +msgid "'.' @d @e in @d @i %i is not NULL terminated\n" +msgstr "».« @d @e in @d @i %i ist nicht NULL-terminiert\n" + +#. @-expanded: '..' directory entry in directory inode %i is not NULL terminated\n +#: e2fsck/problem.c:1083 +#, c-format +msgid "'..' @d @e in @d @i %i is not NULL terminated\n" +msgstr "»..« @d @e in @d @i %i ist nicht NULL-terminiert\n" + +#. @-expanded: inode %i (%Q) is an illegal character device.\n +#: e2fsck/problem.c:1088 +msgid "@i %i (%Q) is an @I character @v.\n" +msgstr "@i %i (%Q) ist ein @I Zeichen @v.\n" + +#. @-expanded: inode %i (%Q) is an illegal block device.\n +#: e2fsck/problem.c:1093 +msgid "@i %i (%Q) is an @I @b @v.\n" +msgstr "@i %i (%Q) ist ein @I @b @v.\n" + +#. @-expanded: entry '%Dn' in %p (%i) is duplicate '.' entry.\n +#: e2fsck/problem.c:1098 +msgid "@E is duplicate '.' @e.\n" +msgstr "@E ist ein doppelter ».« @e.\n" + +#. @-expanded: entry '%Dn' in %p (%i) is duplicate '..' entry.\n +#: e2fsck/problem.c:1103 +msgid "@E is duplicate '..' @e.\n" +msgstr "@E ist ein doppelter »..« @e.\n" + +#: e2fsck/problem.c:1108 +#: e2fsck/problem.c:1403 +#, c-format +msgid "Internal error: couldn't find dir_info for %i.\n" +msgstr "Interner Fehler: kann dir_info für %i nicht finden.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has rec_len of %Dr, should be %N.\n +#: e2fsck/problem.c:1113 +msgid "@E has rec_len of %Dr, @s %N.\n" +msgstr "@E hat rec_len von %Dr, sollte %N sein.\n" + +#. @-expanded: error allocating icount structure: %m\n +#: e2fsck/problem.c:1118 +#, c-format +msgid "@A icount structure: %m\n" +msgstr "@A icount structure: %m\n" + +#. @-expanded: Error iterating over directory blocks: %m\n +#: e2fsck/problem.c:1123 +#, c-format +msgid "Error iterating over @d @bs: %m\n" +msgstr "Fehler beim Durchlaufen der @d @bs: %m\n" + +#. @-expanded: Error reading directory block %b (inode %i): %m\n +#: e2fsck/problem.c:1128 +msgid "Error reading @d @b %b (@i %i): %m\n" +msgstr "Lesefehler @d @b %b (@i %i): %m\n" + +#. @-expanded: Error writing directory block %b (inode %i): %m\n +#: e2fsck/problem.c:1133 +msgid "Error writing @d @b %b (@i %i): %m\n" +msgstr "Schreibfehler @d @b %b (@i %i): %m\n" + +#. @-expanded: error allocating new directory block for inode %i (%s): %m\n +#: e2fsck/problem.c:1138 +#, c-format +msgid "@A new @d @b for @i %i (%s): %m\n" +msgstr "@A neu @d @b for @i %i (%s): %m\n" + +#. @-expanded: Error deallocating inode %i: %m\n +#: e2fsck/problem.c:1143 +#, c-format +msgid "Error deallocating @i %i: %m\n" +msgstr "Fehler bei der Freigabe von @i %i: %m\n" + +#. @-expanded: directory entry for '.' in %p (%i) is big.\n +#: e2fsck/problem.c:1148 +#, c-format +msgid "@d @e for '.' in %p (%i) is big.\n" +msgstr "Verzeichniseintrag für ».« in %p (%i) ist gross.\n" + +#. @-expanded: inode %i (%Q) is an illegal FIFO.\n +#: e2fsck/problem.c:1153 +msgid "@i %i (%Q) is an @I FIFO.\n" +msgstr "@i %i (%Q) ist ein @I FIFO.\n" + +#. @-expanded: inode %i (%Q) is an illegal socket.\n +#: e2fsck/problem.c:1158 +msgid "@i %i (%Q) is an @I socket.\n" +msgstr "@i %i (%Q) ist ein @I Socket.\n" + +#. @-expanded: Setting filetype for entry '%Dn' in %p (%i) to %N.\n +#: e2fsck/problem.c:1163 +msgid "Setting filetype for @E to %N.\n" +msgstr "Setze Dateitype für @E auf %N.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has an incorrect filetype (was %Dt, should be %N).\n +#: e2fsck/problem.c:1168 +msgid "@E has an incorrect filetype (was %Dt, @s %N).\n" +msgstr "@E hat einen falschen Dateityp (war %Dt, sollte %N sein).\n" + +#. @-expanded: entry '%Dn' in %p (%i) has filetype set.\n +#: e2fsck/problem.c:1173 +msgid "@E has filetype set.\n" +msgstr "@E hat Dateityp gesetzt.\n" + +#. @-expanded: entry '%Dn' in %p (%i) has a zero-length name.\n +#: e2fsck/problem.c:1178 +msgid "@E has a @z name.\n" +msgstr "@E hat einen Namen der Länge Null..\n" + +#. @-expanded: Symlink %Q (inode #%i) is invalid.\n +#: e2fsck/problem.c:1183 +msgid "Symlink %Q (@i #%i) is @n.\n" +msgstr "Symlink %Q (@i #%i) is invalid.\n" + +#. @-expanded: extended attribute block for inode %i (%Q) is invalid (%If).\n +#: e2fsck/problem.c:1188 +msgid "@a @b @F @n (%If).\n" +msgstr "@a @b @F ist falsch (%If).\n" + +#. @-expanded: filesystem contains large files, but lacks LARGE_FILE flag in superblock.\n +#: e2fsck/problem.c:1193 +msgid "@f contains large files, but lacks LARGE_FILE flag in @S.\n" +msgstr "@f enthält große Dateien, aber das LARGE_FILE Flag in @S ist nicht gesetzt.\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) not referenced\n +#: e2fsck/problem.c:1198 +msgid "@p @h %d: node (%B) not referenced\n" +msgstr "@p @h %d: Node (%B) nicht referenziert\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) referenced twice\n +#: e2fsck/problem.c:1203 +msgid "@p @h %d: node (%B) referenced twice\n" +msgstr "@p @h %d: Node (%B) doppelt referenziert\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has bad min hash\n +#: e2fsck/problem.c:1208 +msgid "@p @h %d: node (%B) has bad min hash\n" +msgstr "@p @h %d: node (%B) has bad min hash\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has bad max hash\n +#: e2fsck/problem.c:1213 +msgid "@p @h %d: node (%B) has bad max hash\n" +msgstr "@p @h %d: node (%B) has bad max hash\n" + +#. @-expanded: invalid HTREE directory inode %d (%q). +#: e2fsck/problem.c:1218 +msgid "@n @h %d (%q). " +msgstr "Invalid @h %d (%q). " + +#. @-expanded: problem in HTREE directory inode %d (%q): bad block number %b.\n +#: e2fsck/problem.c:1222 +msgid "@p @h %d (%q): bad @b number %b.\n" +msgstr "@p @h %d (%q): bad @b number %b.\n" + +#. @-expanded: problem in HTREE directory inode %d: root node is invalid\n +#: e2fsck/problem.c:1232 +#, c-format +msgid "@p @h %d: root node is @n\n" +msgstr "@p @h %d: root node is invalid\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has invalid limit (%N)\n +#: e2fsck/problem.c:1237 +msgid "@p @h %d: node (%B) has @n limit (%N)\n" +msgstr "@p @h %d: node (%B) has bad limit (%N)\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has invalid count (%N)\n +#: e2fsck/problem.c:1242 +msgid "@p @h %d: node (%B) has @n count (%N)\n" +msgstr "@p @h %d: node (%B) has bad count (%N)\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has an unordered hash table\n +#: e2fsck/problem.c:1247 +msgid "@p @h %d: node (%B) has an unordered hash table\n" +msgstr "@p @h %d: node (%B) has an unordered hash table\n" + +#. @-expanded: problem in HTREE directory inode %d: node (%B) has invalid depth (%N)\n +#: e2fsck/problem.c:1252 +msgid "@p @h %d: node (%B) has @n depth (%N)\n" +msgstr "@p @h %d: Knoten (%B) has @n Tiefe (%N)\n" + +#. @-expanded: Duplicate entry '%Dn' in %p (%i) found. +#: e2fsck/problem.c:1257 +msgid "Duplicate @E found. " +msgstr "Doppelte @E gefunden. " + +#. @-expanded: entry '%Dn' in %p (%i) has a non-unique filename.\n +#. @-expanded: Rename to %s +#: e2fsck/problem.c:1262 +#, no-c-format +msgid "" +"@E has a non-unique filename.\n" +"Rename to %s" +msgstr "" +"@E hat keinen eindeutigen Dateinnamen.\n" +"Benenne in %s um" + +#. @-expanded: Duplicate entry '%Dn' found.\n +#. @-expanded: \tMarking %p (%i) to be rebuilt.\n +#. @-expanded: \n +#: e2fsck/problem.c:1267 +msgid "" +"Duplicate @e '%Dn' found.\n" +"\tMarking %p (%i) to be rebuilt.\n" +"\n" +msgstr "" +"Doppelte @e '%Dn' gefunden.\n" +"\tMarkiere %p (%i) für die Neuerstellung.\n" +"\n" + +#. @-expanded: i_blocks_hi for inode %i (%Q) is %N, should be zero.\n +#: e2fsck/problem.c:1272 +msgid "i_blocks_hi @F %N, @s zero.\n" +msgstr "i_blocks_hi @F %N, @s zero.\n" + +#. @-expanded: Unexpected block in HTREE directory inode %d (%q).\n +#: e2fsck/problem.c:1277 +msgid "Unexpected @b in @h %d (%q).\n" +msgstr "Unerwarteter @b in @h %d (%q).\n" + +#. @-expanded: entry '%Dn' in %p (%i) references inode %Di in group %g where _INODE_UNINIT is set.\n +#: e2fsck/problem.c:1281 +msgid "@E references @i %Di in @g %g where _INODE_UNINIT is set.\n" +msgstr "@i %i wurde in @g %g gefunden, für die _INODE_UNINIT gesetzt ist.\n" + +#. @-expanded: entry '%Dn' in %p (%i) references inode %Di found in group %g's unused inodes area.\n +#: e2fsck/problem.c:1286 +msgid "@E references @i %Di found in @g %g's unused inodes area.\n" +msgstr "@i %i wurde im Bereich ungenutzter Inodes von @g %g gefunden.\n" + +#. @-expanded: Pass 3: Checking directory connectivity\n +#: e2fsck/problem.c:1293 +msgid "Pass 3: Checking @d connectivity\n" +msgstr "Durchgang 3: Prüfe @d Verknüpfungen\n" + +#. @-expanded: root inode not allocated. +#: e2fsck/problem.c:1298 +msgid "@r not allocated. " +msgstr "@r nicht zugeordnet. " + +#. @-expanded: No room in lost+found directory. +#: e2fsck/problem.c:1303 +msgid "No room in @l @d. " +msgstr "Kein Platz in @l @d. " + +#. @-expanded: Unconnected directory inode %i (%p)\n +#: e2fsck/problem.c:1308 +#, c-format +msgid "Unconnected @d @i %i (%p)\n" +msgstr "Nicht verbundene @d @i %i (%p)\n" + +#. @-expanded: /lost+found not found. +#: e2fsck/problem.c:1313 +msgid "/@l not found. " +msgstr "/@l nicht gefunden. " + +#. @-expanded: '..' in %Q (%i) is %P (%j), should be %q (%d).\n +#: e2fsck/problem.c:1318 +msgid "'..' in %Q (%i) is %P (%j), @s %q (%d).\n" +msgstr "»..« in %Q (%i) ist %P (%j), @s %q (%d).\n" + +#. @-expanded: Bad or non-existent /lost+found. Cannot reconnect.\n +#: e2fsck/problem.c:1323 +msgid "Bad or non-existent /@l. Cannot reconnect.\n" +msgstr "Falscher oder fehlender /@l. Wiederverbinden nicht möglich.\n" + +#. @-expanded: Could not expand /lost+found: %m\n +#: e2fsck/problem.c:1328 +#, c-format +msgid "Could not expand /@l: %m\n" +msgstr "Erweitern nicht möglich /@l: %m\n" + +#: e2fsck/problem.c:1333 +#, c-format +msgid "Could not reconnect %i: %m\n" +msgstr "Wiederverbinden nicht möglich %i: %m\n" + +#. @-expanded: Error while trying to find /lost+found: %m\n +#: e2fsck/problem.c:1338 +#, c-format +msgid "Error while trying to find /@l: %m\n" +msgstr "Fehler während der Suche nach /@l: %m\n" + +#. @-expanded: ext2fs_new_block: %m while trying to create /lost+found directory\n +#: e2fsck/problem.c:1343 +#, c-format +msgid "ext2fs_new_@b: %m while trying to create /@l @d\n" +msgstr "ext2fs_new_@b: %m während des Versuches /@l @d zu erzeugen.\n" + +#. @-expanded: ext2fs_new_inode: %m while trying to create /lost+found directory\n +#: e2fsck/problem.c:1348 +#, c-format +msgid "ext2fs_new_@i: %m while trying to create /@l @d\n" +msgstr "ext2fs_new_@i: %m während des Versuches /@l @d zu erzeugen.\n" + +#. @-expanded: ext2fs_new_dir_block: %m while creating new directory block\n +#: e2fsck/problem.c:1353 +#, c-format +msgid "ext2fs_new_dir_@b: %m while creating new @d @b\n" +msgstr "ext2fs_new_dir_@b: %m während des Versuches /@l @d zu erzeugen.\n" + +#. @-expanded: ext2fs_write_dir_block: %m while writing the directory block for /lost+found\n +#: e2fsck/problem.c:1358 +#, c-format +msgid "ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n" +msgstr "ext2fs_write_dir_@b: %m während des Schreibens von @d @b für /@l\n" + +#. @-expanded: Error while adjusting inode count on inode %i\n +#: e2fsck/problem.c:1363 +#, c-format +msgid "Error while adjusting @i count on @i %i\n" +msgstr "Fehler während der Einstellung von @i count auf @i %i\n" + +#. @-expanded: Couldn't fix parent of inode %i: %m\n +#. @-expanded: \n +#: e2fsck/problem.c:1368 +#, c-format +msgid "" +"Couldn't fix parent of @i %i: %m\n" +"\n" +msgstr "" +"Konnte Parent von @i %i: %m nicht reparieren\n" +"\n" + +#. @-expanded: Couldn't fix parent of inode %i: Couldn't find parent directory entry\n +#. @-expanded: \n +#: e2fsck/problem.c:1373 +#, c-format +msgid "" +"Couldn't fix parent of @i %i: Couldn't find parent @d @e\n" +"\n" +msgstr "" +"Parent von @i %i konnte nicht repariert werden: \n" +"parent @d nicht gefunden.\n" + +#. @-expanded: Error creating root directory (%s): %m\n +#: e2fsck/problem.c:1383 +#, c-format +msgid "Error creating root @d (%s): %m\n" +msgstr "Fehler beim Erzeugen des root @d (%s): %m\n" + +#. @-expanded: Error creating /lost+found directory (%s): %m\n +#: e2fsck/problem.c:1388 +#, c-format +msgid "Error creating /@l @d (%s): %m\n" +msgstr "Fehler beim Erzeugen des /@l @d (%s): %m\n" + +#. @-expanded: root inode is not a directory; aborting.\n +#: e2fsck/problem.c:1393 +msgid "@r is not a @d; aborting.\n" +msgstr "@r ist kein @d; breche ab.\n" + +#. @-expanded: Cannot proceed without a root inode.\n +#: e2fsck/problem.c:1398 +msgid "Cannot proceed without a @r.\n" +msgstr "Kann ohne @r nicht fortsetzen.\n" + +#. @-expanded: /lost+found is not a directory (ino=%i)\n +#: e2fsck/problem.c:1408 +#, c-format +msgid "/@l is not a @d (ino=%i)\n" +msgstr "/@l ist kein @d (ino=%i)\n" + +#: e2fsck/problem.c:1415 +msgid "Pass 3A: Optimizing directories\n" +msgstr "Durchgang 3A: Optimiere Verzeichnisse\n" + +#: e2fsck/problem.c:1420 +#, c-format +msgid "Failed to create dirs_to_hash iterator: %m\n" +msgstr "dirs_to_hash Iterator konnte nicht erzeugt werden: %m\n" + +#: e2fsck/problem.c:1425 +msgid "Failed to optimize directory %q (%d): %m\n" +msgstr "Verzeichnis %q (%d) konnte nicht optimiert werden: %m\n" + +#: e2fsck/problem.c:1430 +msgid "Optimizing directories: " +msgstr "Optimiere Verzeichnisse: " + +#: e2fsck/problem.c:1447 +msgid "Pass 4: Checking reference counts\n" +msgstr "Durchgang 4: Überprüfe die Referenzzähler\n" + +#. @-expanded: unattached zero-length inode %i. +#: e2fsck/problem.c:1452 +#, c-format +msgid "@u @z @i %i. " +msgstr "@I @o @i %i in @S. " + +#. @-expanded: unattached inode %i\n +#: e2fsck/problem.c:1457 +#, c-format +msgid "@u @i %i\n" +msgstr "@u @i %i\n" + +#. @-expanded: inode %i ref count is %Il, should be %N. +#: e2fsck/problem.c:1462 +msgid "@i %i ref count is %Il, @s %N. " +msgstr "@i %i Referenzzähler ist %Il, @s %N. " + +#. @-expanded: WARNING: PROGRAMMING BUG IN E2FSCK!\n +#. @-expanded: \tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n +#. @-expanded: inode_link_info[%i] is %N, inode.i_links_count is %Il. They should be the same!\n +#: e2fsck/problem.c:1466 +msgid "" +"WARNING: PROGRAMMING BUG IN E2FSCK!\n" +"\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n" +"@i_link_info[%i] is %N, @i.i_links_count is %Il. They @s the same!\n" +msgstr "" +"WARNUNG: PROGRAMMIERFEHLER IN E2FSCK!\n" +"\tODER EIN TROTTEL (SIE) PRÜFT EIN EINGEHÄNGTES (AKTIVES) DATEISYSTEM.\n" +"@i_link_info[%i] ist %N, @i.i_links_count ist %Il. Sie sollten identisch sein!\n" + +#. @-expanded: Pass 5: Checking group summary information\n +#: e2fsck/problem.c:1476 +msgid "Pass 5: Checking @g summary information\n" +msgstr "Durchgang 5: Überprüfe @g Zusammenfassung\n" + +#. @-expanded: Padding at end of inode bitmap is not set. +#: e2fsck/problem.c:1481 +msgid "Padding at end of @i @B is not set. " +msgstr "Auffüllbyte am Ende von @i @B ist nicht gesetzt. " + +#. @-expanded: Padding at end of block bitmap is not set. +#: e2fsck/problem.c:1486 +msgid "Padding at end of @b @B is not set. " +msgstr "Auffüllbyte am Ende von @b @B ist nicht gesetzt. " + +#. @-expanded: block bitmap differences: +#: e2fsck/problem.c:1491 +msgid "@b @B differences: " +msgstr "@b @B differieren: " + +#. @-expanded: inode bitmap differences: +#: e2fsck/problem.c:1511 +msgid "@i @B differences: " +msgstr "@i @B differieren: " + +#. @-expanded: Free inodes count wrong for group #%g (%i, counted=%j).\n +#: e2fsck/problem.c:1531 +msgid "Free @is count wrong for @g #%g (%i, counted=%j).\n" +msgstr "Die Anzahl freier @is ist falsch für @g #%g (%i, gezählt=%j).\n" + +#. @-expanded: Directories count wrong for group #%g (%i, counted=%j).\n +#: e2fsck/problem.c:1536 +msgid "Directories count wrong for @g #%g (%i, counted=%j).\n" +msgstr "Die Anzahl Verzeichnisse ist falsch für @g #%g (%i, gezählt=%j).\n" + +#. @-expanded: Free inodes count wrong (%i, counted=%j).\n +#: e2fsck/problem.c:1541 +msgid "Free @is count wrong (%i, counted=%j).\n" +msgstr "Die Anzahl freier @is ist falsch (%i, gezählt=%j).\n" + +#. @-expanded: Free blocks count wrong for group #%g (%b, counted=%c).\n +#: e2fsck/problem.c:1546 +msgid "Free @bs count wrong for @g #%g (%b, counted=%c).\n" +msgstr "Die Anzahl freier Blöcke in @g #%g ist falsch (%b, gezählt=%c).\n" + +#. @-expanded: Free blocks count wrong (%b, counted=%c).\n +#: e2fsck/problem.c:1551 +msgid "Free @bs count wrong (%b, counted=%c).\n" +msgstr "Die Anzahl freier Blöcke ist falsch (%b, gezählt=%c).\n" + +#. @-expanded: PROGRAMMING ERROR: filesystem (#%N) bitmap endpoints (%b, %c) don't match calculated bitmap +#. @-expanded: endpoints (%i, %j)\n +#: e2fsck/problem.c:1556 +msgid "PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't match calculated @B endpoints (%i, %j)\n" +msgstr "PROGRAMMIERFEHLER: @f (#%N) @B Endpunkte (%b, %c) passen nicht zu den berechneten @B Endpunkten (%i, %j)\n" + +#: e2fsck/problem.c:1562 +msgid "Internal error: fudging end of bitmap (%N)\n" +msgstr "Interner Fehler: fudging end of bitmap (%N)\n" + +#. @-expanded: Error copying in replacement inode bitmap: %m\n +#: e2fsck/problem.c:1567 +#, c-format +msgid "Error copying in replacement @i @B: %m\n" +msgstr "Fehler beim hineinkopieren von @i @B: %m\n" + +#. @-expanded: Error copying in replacement block bitmap: %m\n +#: e2fsck/problem.c:1572 +#, c-format +msgid "Error copying in replacement @b @B: %m\n" +msgstr "Fehler beim hineinkopieren von @b @B: %m\n" + +#. @-expanded: Recreate journal +#: e2fsck/problem.c:1597 +msgid "Recreate @j" +msgstr "@j zurücksetzen" + +#. @-expanded: group %g block(s) in use but group is marked BLOCK_UNINIT\n +#: e2fsck/problem.c:1602 +#, c-format +msgid "@g %g @b(s) in use but @g is marked BLOCK_UNINIT\n" +msgstr "Blöcke von @g %g sind in Beutzung obwohl @g als BLOCK_UNINIT markiert ist\n" + +#. @-expanded: group %g inode(s) in use but group is marked INODE_UNINIT\n +#: e2fsck/problem.c:1607 +#, c-format +msgid "@g %g @i(s) in use but @g is marked INODE_UNINIT\n" +msgstr "@g %g @i(s) sind in Benutzung obwohl @g als INODE_UNINIT markiert ist\n" + +#: e2fsck/problem.c:1725 +#, c-format +msgid "Unhandled error code (0x%x)!\n" +msgstr "Unbenutzter Fehlercode (0x%x)!\n" + +#: e2fsck/problem.c:1820 +msgid "IGNORED" +msgstr "IGNORIERT" + +#: e2fsck/scantest.c:81 +#, c-format +msgid "Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n" +msgstr "benutzter Speicher: %d, vergangende Zeit: %6.3f/%6.3f/%6.3f\n" + +#: e2fsck/scantest.c:100 +#, c-format +msgid "size of inode=%d\n" +msgstr "Größe des Inode=%d\n" + +#: e2fsck/scantest.c:121 +msgid "while starting inode scan" +msgstr "beim Starten der Inodeprüfung" + +#: e2fsck/scantest.c:132 +msgid "while doing inode scan" +msgstr "während der Inodeprüfung" + +#: e2fsck/super.c:187 +#, c-format +msgid "while calling ext2fs_block_iterate for inode %d" +msgstr "während des Aufrufs von ext2fs_block_iterate für Inode %d" + +#: e2fsck/super.c:209 +#, c-format +msgid "while calling ext2fs_adjust_ea_refcount for inode %d" +msgstr "während des Aufrufs von ext2fs_adjust_ea_refcount für Inode %d" + +#: e2fsck/super.c:267 +msgid "Truncating" +msgstr "Kürze" + +#: e2fsck/super.c:268 +msgid "Clearing" +msgstr "Bereinige" + +#: e2fsck/unix.c:76 +#, c-format +msgid "" +"Usage: %s [-panyrcdfvtDFV] [-b superblock] [-B blocksize]\n" +"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n" +"\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n" +"\t\t[-E extended-options] device\n" +msgstr "" +"Aufruf: %s [-panyrcdfvtDFV] [-b Superblock] [-B Blockgröße]\n" +"\t\t[-I Inode_Puffer_Blöcke] [-P Prozess_Inodegröße]\n" +"\t\t[-l|-L Bad_Blocks_Datei] [-C Dateideskriptor] [-j externes_Journal]\n" +"\t\t[-E erweiterte_Optionen] Gerät\n" + +#: e2fsck/unix.c:82 +#, c-format +msgid "" +"\n" +"Emergency help:\n" +" -p Automatic repair (no questions)\n" +" -n Make no changes to the filesystem\n" +" -y Assume \"yes\" to all questions\n" +" -c Check for bad blocks and add them to the badblock list\n" +" -f Force checking even if filesystem is marked clean\n" +msgstr "" +"\n" +"Notfallhile:\n" +" -p automatische Reparatur (keine Fragen)\n" +" -n keine Veränderungen am Dateisystem vornehmen\n" +" -y \" Ja \" auf alle Fragen annehmen\n" +" -c suche nach defekten Blöcken\n" +" -f erzwinge die Überprüfung auch wenn alles i.O. erscheint\n" + +#: e2fsck/unix.c:88 +#, c-format +msgid "" +" -v Be verbose\n" +" -b superblock Use alternative superblock\n" +" -B blocksize Force blocksize when looking for superblock\n" +" -j external_journal Set location of the external journal\n" +" -l bad_blocks_file Add to badblocks list\n" +" -L bad_blocks_file Set badblocks list\n" +msgstr "" +" -v sei gesprächig\n" +" -b Superbloc Nutze Superblockkopie\n" +" -B Blockgröße erzwinge Blockgröße beim Suchen vom Superblock\n" +" -j externes-Journal Angabe des Speicherortes des externen Jounals\n" +" -l bad_blocks_file zur Liste der defekten Blöcke hinzufügen\n" +" -L bad_blocks_file Liste der defekten Blöcke definieren\n" + +#: e2fsck/unix.c:132 +#, c-format +msgid "%s: %u/%u files (%0d.%d%% non-contiguous), %u/%u blocks\n" +msgstr "%s: %u/%u Dateien (%0d.%d%% nicht zusammenhängend), %u/%u Blöcke\n" + +#: e2fsck/unix.c:150 +#, c-format +msgid " # of inodes with ind/dind/tind blocks: %u/%u/%u\n" +msgstr " # von Inodes mit ind/dind/tind Blöcken: %u/%u/%u\n" + +#: e2fsck/unix.c:157 +#, c-format +msgid " Extent depth histogram: " +msgstr " Erweiterungstiefe Histogramm: " + +#: e2fsck/unix.c:207 +#: misc/badblocks.c:916 +#: misc/tune2fs.c:1567 +#: misc/util.c:151 +#: resize/main.c:248 +#, c-format +msgid "while determining whether %s is mounted." +msgstr "bei der Prüfung, ob %s eingehängt ist." + +#: e2fsck/unix.c:225 +#, c-format +msgid "Warning! %s is mounted.\n" +msgstr "Warnung! %s ist eingehängt.\n" + +#: e2fsck/unix.c:229 +#, c-format +msgid "%s is mounted. " +msgstr "%s ist eingehängt. " + +#: e2fsck/unix.c:231 +msgid "" +"Cannot continue, aborting.\n" +"\n" +msgstr "" +"Fortsetzung nicht möglich, breche ab.\n" +"\n" + +#: e2fsck/unix.c:232 +#, c-format +msgid "" +"\n" +"\n" +"\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem may cause\n" +"SEVERE filesystem damage.\a\a\a\n" +"\n" +msgstr "" +"\n" +"\n" +"\a\a\a\aWARNUNG!!! Die Benutzung von e2fsck auf einem eingehängten\n" +"Dateisystem kann das Dateisystem STARK BESCHÄDIGEN.\n" +"\n" + +#: e2fsck/unix.c:235 +msgid "Do you really want to continue" +msgstr "Wirklich fortfahren" + +#: e2fsck/unix.c:237 +#, c-format +msgid "check aborted.\n" +msgstr "Prüfung abgebrochen.\n" + +#: e2fsck/unix.c:310 +msgid " contains a file system with errors" +msgstr " enthält ein fehlerhaftes Dateisystem" + +#: e2fsck/unix.c:312 +msgid " was not cleanly unmounted" +msgstr " wurde nicht ordnungsgemäß ausgehängt" + +#: e2fsck/unix.c:314 +msgid " primary superblock features different from backup" +msgstr "Eigenschaften des primären Superblocks unterscheiden sich vom Backup" + +#: e2fsck/unix.c:318 +#, c-format +msgid " has been mounted %u times without being checked" +msgstr " wurde %u mal ohne Überprüfung eingehängt" + +#: e2fsck/unix.c:324 +msgid " has filesystem last checked time in the future" +msgstr " hat einen in der Zukunft liegenden Zeitpunkt der letzten Püfung des Dateisystems" + +#: e2fsck/unix.c:330 +#, c-format +msgid " has gone %u days without being checked" +msgstr " wurde %u Tage ohne Überprüfung genutzt" + +#: e2fsck/unix.c:339 +msgid ", check forced.\n" +msgstr ", Prüfung erzwungen.\n" + +#: e2fsck/unix.c:342 +#, c-format +msgid "%s: clean, %u/%u files, %u/%u blocks" +msgstr "%s: sauber, %u/%u Dateien, %u/%u Blöcke" + +#: e2fsck/unix.c:359 +msgid " (check deferred; on battery)" +msgstr " (Prüfung nach nächstem Einhängen)" + +#: e2fsck/unix.c:362 +msgid " (check after next mount)" +msgstr " (Prüfung nach nächstem Einhängen)" + +#: e2fsck/unix.c:364 +#, c-format +msgid " (check in %ld mounts)" +msgstr " (Prüfung nach %ld Einhängevorgängen)" + +#: e2fsck/unix.c:511 +#, c-format +msgid "ERROR: Couldn't open /dev/null (%s)\n" +msgstr "Fehler: Kann /dev/null (%s) nicht öffnen\n" + +#: e2fsck/unix.c:581 +#, c-format +msgid "Invalid EA version.\n" +msgstr "Invalid EA version.\n" + +#: e2fsck/unix.c:590 +#, c-format +msgid "Unknown extended option: %s\n" +msgstr "Unbekannte erweiterte Option: %s\n" + +#: e2fsck/unix.c:612 +#, c-format +msgid "" +"Syntax error in e2fsck config file (%s, line #%d)\n" +"\t%s\n" +msgstr "" +"Syntaxfehler in der Konfigurationsdatei von e2fsck (%s, Zeile %d)\n" +"\t%s\n" + +#: e2fsck/unix.c:680 +#, c-format +msgid "Error validating file descriptor %d: %s\n" +msgstr "Fehler bei Überprüfung des Datei-Deskriptors %d: %s\n" + +#: e2fsck/unix.c:684 +msgid "Invalid completion information file descriptor" +msgstr "Ungültiger »completion information«-Datei-Deskriptor" + +#: e2fsck/unix.c:699 +msgid "Only one of the options -p/-a, -n or -y may be specified." +msgstr "Nur eine der Optionen -p/-a, -n oder -y darf angegeben werden." + +#: e2fsck/unix.c:720 +#, c-format +msgid "The -t option is not supported on this version of e2fsck.\n" +msgstr "Die -t Option wird von dieser e2fsck-Version nicht unterstützt.\n" + +#: e2fsck/unix.c:801 +#: misc/tune2fs.c:549 +#: misc/tune2fs.c:833 +#: misc/tune2fs.c:850 +#, c-format +msgid "Unable to resolve '%s'" +msgstr "Nicht möglich »%s« aufzulösen" + +#: e2fsck/unix.c:831 +#, c-format +msgid "The -c and the -l/-L options may not be both used at the same time.\n" +msgstr "Die -c und -l/-L Optionen dürfen nicht gleichzeitig verwendet werden.\n" + +#: e2fsck/unix.c:879 +#, c-format +msgid "" +"E2FSCK_JBD_DEBUG \"%s\" not an integer\n" +"\n" +msgstr "2FSCK_JBD_DEBUG \"%s\" ist keine Ganzzahl\n" + +#: e2fsck/unix.c:888 +#, c-format +msgid "" +"\n" +"Invalid non-numeric argument to -%c (\"%s\")\n" +"\n" +msgstr "" +"\n" +"Ungültiges nicht-numerisches Argument für -%c (\"%s\")\n" +"\n" + +#: e2fsck/unix.c:929 +#, c-format +msgid "Error: ext2fs library version out of date!\n" +msgstr "Fehler: ext2fs-Bibliotheks-Version ist zu alt!\n" + +#: e2fsck/unix.c:937 +msgid "while trying to initialize program" +msgstr "bei der Programminitialisierung" + +#: e2fsck/unix.c:951 +#, c-format +msgid "\tUsing %s, %s\n" +msgstr "\tBenutze %s, %s\n" + +#: e2fsck/unix.c:963 +msgid "need terminal for interactive repairs" +msgstr "Benötige ein Terminal für interaktive Reparaturen" + +#: e2fsck/unix.c:1010 +#, c-format +msgid "%s: %s trying backup blocks...\n" +msgstr "%s: %s versuche es mit Backup-Blöcken...\n" + +#: e2fsck/unix.c:1012 +msgid "Superblock invalid," +msgstr "Superblock ungültig" + +#: e2fsck/unix.c:1013 +msgid "Group descriptors look bad..." +msgstr "Gruppen-Deskriptoren scheinen defekt zu sein..." + +#: e2fsck/unix.c:1040 +#, c-format +msgid "" +"The filesystem revision is apparently too high for this version of e2fsck.\n" +"(Or the filesystem superblock is corrupt)\n" +"\n" +msgstr "" +"Diese Dateisystem-Revision ist offensichtlich zu neu für diese Version \n" +"von e2fsck (oder der Dateisystem-Superblock ist defekt).\n" +"\n" + +#: e2fsck/unix.c:1046 +#, c-format +msgid "Could this be a zero-length partition?\n" +msgstr "Könnte es eine Partion der Länge Null sein?\n" + +#: e2fsck/unix.c:1048 +#, c-format +msgid "You must have %s access to the filesystem or be root\n" +msgstr "Sie benötigen %s- oder root-Rechte für das Dateisystem.\n" + +#: e2fsck/unix.c:1053 +#, c-format +msgid "Possibly non-existent or swap device?\n" +msgstr "Möglicherweise ist die Partition nicht vorhanden oder eine Swap-Partition?\n" + +#: e2fsck/unix.c:1055 +#, c-format +msgid "Filesystem mounted or opened exclusively by another program?\n" +msgstr "" +"Ist das Dateisystem eingehängt or exklusiv von einem anderen Programm\n" +"\n" +"geöffnet worden?\n" + +#: e2fsck/unix.c:1059 +#, c-format +msgid "" +"Disk write-protected; use the -n option to do a read-only\n" +"check of the device.\n" +msgstr "" +"Laufwerk ist schreibgeschützt, nutzen Sie die -n Option\n" +"um es im Nur-Lesen-Modus zu prüfen.\n" + +#: e2fsck/unix.c:1123 +msgid "Get a newer version of e2fsck!" +msgstr "Neuere Version von e2fsck benötigt!" + +#: e2fsck/unix.c:1147 +#, c-format +msgid "while checking ext3 journal for %s" +msgstr "während der Prüfung des ext3-Journals für %s" + +#: e2fsck/unix.c:1158 +#, c-format +msgid "Warning: skipping journal recovery because doing a read-only filesystem check.\n" +msgstr "Warnung: Überspringe Journal-Wiederherstellung, da das Dateisystem im Nur-Lesen-Modus ist.\n" + +#: e2fsck/unix.c:1171 +#, c-format +msgid "unable to set superblock flags on %s\n" +msgstr "Superblock-Flags konntan auf %s nicht gesetzt werden\n" + +#: e2fsck/unix.c:1177 +#, c-format +msgid "while recovering ext3 journal of %s" +msgstr "bei der Wiederherstellung des ext3-Journals von %s" + +#: e2fsck/unix.c:1201 +#, c-format +msgid "%s has unsupported feature(s):" +msgstr "%s besitzt nicht unterstützte Eigenschaft(en):" + +#: e2fsck/unix.c:1217 +msgid "Warning: compression support is experimental.\n" +msgstr "Warnung: Die Kompressionsunterstützung ist experimentell.\n" + +#: e2fsck/unix.c:1222 +#, c-format +msgid "" +"E2fsck not compiled with HTREE support,\n" +"\tbut filesystem %s has HTREE directories.\n" +msgstr "" +"Die Unterstützung für HTREE wurde in e2fsck nicht aktiviert,\n" +"\taber das Dateisystem %s besitzt HTREE Verzeichnisse.\n" + +#: e2fsck/unix.c:1276 +msgid "while reading bad blocks inode" +msgstr "beim Lesen des Bad-Block-Inodes" + +#: e2fsck/unix.c:1278 +#, c-format +msgid "This doesn't bode well, but we'll try to go on...\n" +msgstr "Das verheißt nichts gutes, aber wir versuchen es trotzdem ..\n" + +#: e2fsck/unix.c:1304 +msgid "Couldn't determine journal size" +msgstr "Konnte die Größe des Dateisystems nicht ermitteln" + +#: e2fsck/unix.c:1307 +#, c-format +msgid "Creating journal (%d blocks): " +msgstr "Erstelle Journal (%d Blöcke): " + +#: e2fsck/unix.c:1314 +#: misc/mke2fs.c:2091 +msgid "" +"\n" +"\twhile trying to create journal" +msgstr "" +"\n" +"\tbeim Erstellen des Journals" + +#: e2fsck/unix.c:1317 +#, c-format +msgid " Done.\n" +msgstr " Erledigt.\n" + +#: e2fsck/unix.c:1318 +#, c-format +msgid "" +"\n" +"*** journal has been re-created - filesystem is now ext3 again ***\n" +msgstr "" +"\n" +"*** Journal wurde wiederhergestellt - Dateisystem ist nun wieder ext3 ***\n" + +#: e2fsck/unix.c:1325 +#, c-format +msgid "Restarting e2fsck from the beginning...\n" +msgstr "Beginne e2fsck neu ...\n" + +#: e2fsck/unix.c:1329 +msgid "while resetting context" +msgstr "beim Rücksetzen des Kontexts" + +#: e2fsck/unix.c:1336 +#, c-format +msgid "%s: e2fsck canceled.\n" +msgstr "%s: e2fsck abgebrochhen.\n" + +#: e2fsck/unix.c:1341 +msgid "aborted" +msgstr "abgebrochen" + +#: e2fsck/unix.c:1353 +#, c-format +msgid "" +"\n" +"%s: ***** FILE SYSTEM WAS MODIFIED *****\n" +msgstr "" +"\n" +"%s: ***** DATEISYSTEM WURDE VERÄNDERT *****\n" + +#: e2fsck/unix.c:1356 +#, c-format +msgid "%s: ***** REBOOT LINUX *****\n" +msgstr "%s: ***** LINUX MUSS NEU GESTARTET WERDEN *****\n" + +#: e2fsck/unix.c:1364 +#, c-format +msgid "" +"\n" +"%s: ********** WARNING: Filesystem still has errors **********\n" +"\n" +msgstr "" +"\n" +"%s: ********** WARNUNG: Noch Fehler im Dateisystem **********\n" +"\n" + +#: e2fsck/unix.c:1400 +msgid "while setting block group checksum info" +msgstr "beim Setzen der Blockgruppen-Prüfsummeninfo" + +#: e2fsck/util.c:138 +#: misc/util.c:68 +msgid "yY" +msgstr "jJ" + +#: e2fsck/util.c:139 +msgid "nN" +msgstr "nN" + +#: e2fsck/util.c:153 +msgid "" +msgstr "" + +#: e2fsck/util.c:155 +msgid "" +msgstr "" + +#: e2fsck/util.c:157 +msgid " (y/n)" +msgstr " (j/n)" + +#: e2fsck/util.c:172 +msgid "cancelled!\n" +msgstr "abgebrochen!\n" + +#: e2fsck/util.c:187 +msgid "yes\n" +msgstr "ja\n" + +#: e2fsck/util.c:189 +msgid "no\n" +msgstr "nein\n" + +#: e2fsck/util.c:199 +#, c-format +msgid "" +"%s? no\n" +"\n" +msgstr "" +"%s? nein\n" +"\n" + +#: e2fsck/util.c:203 +#, c-format +msgid "" +"%s? yes\n" +"\n" +msgstr "" +"%s? ja\n" +"\n" + +#: e2fsck/util.c:207 +msgid "yes" +msgstr "ja" + +#: e2fsck/util.c:207 +msgid "no" +msgstr "nein" + +#: e2fsck/util.c:221 +#, c-format +msgid "e2fsck_read_bitmaps: illegal bitmap block(s) for %s" +msgstr "e2fsck_read_bitmaps: illegal bitmap block(s) für %s" + +#: e2fsck/util.c:226 +msgid "reading inode and block bitmaps" +msgstr "lese Inode und Block bitmaps" + +#: e2fsck/util.c:231 +#, c-format +msgid "while retrying to read bitmaps for %s" +msgstr "während des wiederholten Versuches, Bitmaps für %s einzulesen" + +#: e2fsck/util.c:243 +msgid "writing block and inode bitmaps" +msgstr "Schreibe Block- und Inode-Bitmaps" + +#: e2fsck/util.c:248 +#, c-format +msgid "while rewriting block and inode bitmaps for %s" +msgstr "während des wiederholten Versuches, Block- und Inode-Bitmaps für %s zu schreiben." + +#: e2fsck/util.c:260 +#, c-format +msgid "" +"\n" +"\n" +"%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n" +"\t(i.e., without -a or -p options)\n" +msgstr "" +"\n" +"\n" +"%s: UNERWARTETE INKONSISTENZ; fsck MANUELL AUSFÜHREN\n" +"\t(d.h. ohne -a oder -p Option)\n" + +#: e2fsck/util.c:336 +#, c-format +msgid "Memory used: %dk/%dk (%dk/%dk), " +msgstr "benutzter Speicher: %dk/%dk (%dk/%dk), " + +#: e2fsck/util.c:340 +#, c-format +msgid "Memory used: %d, " +msgstr "benutzter Speicher: %d, " + +#: e2fsck/util.c:346 +#, c-format +msgid "time: %5.2f/%5.2f/%5.2f\n" +msgstr "Zeit: %5.2f/%5.2f/%5.2f\n" + +#: e2fsck/util.c:351 +#, c-format +msgid "elapsed time: %6.3f\n" +msgstr "abgelaufende Zeit: %6.3f\n" + +#: e2fsck/util.c:385 +#: e2fsck/util.c:399 +#, c-format +msgid "while reading inode %ld in %s" +msgstr "beim Lesen von Inode %ld in %s" + +#: e2fsck/util.c:413 +#: e2fsck/util.c:426 +#, c-format +msgid "while writing inode %ld in %s" +msgstr "beim Schreiben von Inode %ld in %s" + +#: e2fsck/util.c:575 +msgid "while allocating zeroizing buffer" +msgstr "beim reservieren eines Puffers zum Nullen" + +#: misc/badblocks.c:66 +msgid "done \n" +msgstr "erledigt \n" + +#: misc/badblocks.c:89 +#, c-format +msgid "" +"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n" +" [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n" +" [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n" +" device [last_block [first_block]]\n" +msgstr "" +"Aufruf: %s [-b Blockgröße] [-i Eingabedatei] [-o Ausgabedatei] [-svwnf]\n" +" [-c Blöcke_auf_einmal] [-d Verzögerungsfaktor_zwischen_Lesedurchgängen]\n" +" [-e maximale_Bad_Blocks] [-p Anzahl_Durchgänge]\n" +" [-t Testmuster [-t Testmuster [...]]]\n" +" Gerät [letzter_Block [Startblock]]\n" + +#: misc/badblocks.c:100 +#, c-format +msgid "" +"%s: The -n and -w options are mutually exclusive.\n" +"\n" +msgstr "" +"%s: Die Optionen -n und -w schliessen sich gegenseitig aus.\n" +"\n" + +#: misc/badblocks.c:202 +#, c-format +msgid "%6.2f%% done, %s elapsed" +msgstr "" + +#: misc/badblocks.c:289 +msgid "Testing with random pattern: " +msgstr "Teste mit zufälligen Mustern: " + +#: misc/badblocks.c:307 +msgid "Testing with pattern 0x" +msgstr "Teste mit Muster 0x" + +#: misc/badblocks.c:335 +#: misc/badblocks.c:404 +msgid "during seek" +msgstr "beim Suchen" + +#: misc/badblocks.c:346 +#, c-format +msgid "Weird value (%ld) in do_read\n" +msgstr "Merkwürdiger Wert (%ld) in do_read\n" + +#: misc/badblocks.c:424 +msgid "during ext2fs_sync_device" +msgstr "während ext2fs_sync_device" + +#: misc/badblocks.c:440 +#: misc/badblocks.c:699 +msgid "while beginning bad block list iteration" +msgstr "beim Beginn des »Bad Block«-Listendurchlaufs" + +#: misc/badblocks.c:454 +#: misc/badblocks.c:551 +#: misc/badblocks.c:709 +msgid "while allocating buffers" +msgstr "beim Zuweisen von Puffern" + +#: misc/badblocks.c:458 +#, c-format +msgid "Checking blocks %lu to %lu\n" +msgstr "Prüfe von Block %lu bis %lu\n" + +#: misc/badblocks.c:463 +msgid "Checking for bad blocks in read-only mode\n" +msgstr "Suche nach defekten Blöcken im Nur-Lesen-Modus\n" + +#: misc/badblocks.c:472 +msgid "Checking for bad blocks (read-only test): " +msgstr "Suche nach defekten Blöcken (Nur-Lesen-Modus):" + +#: misc/badblocks.c:480 +#: misc/badblocks.c:583 +#: misc/badblocks.c:628 +#: misc/badblocks.c:772 +msgid "Too many bad blocks, aborting test\n" +msgstr "Zu viele defekte Blöcke - Test wird abgebrochen\n" + +#: misc/badblocks.c:558 +msgid "Checking for bad blocks in read-write mode\n" +msgstr "Suche nach defekten Blöcken (Lesen+Schreiben-Modus)\n" + +#: misc/badblocks.c:560 +#: misc/badblocks.c:722 +#, c-format +msgid "From block %lu to %lu\n" +msgstr "Von Block %lu bis %lu\n" + +#: misc/badblocks.c:618 +msgid "Reading and comparing: " +msgstr "Lesen und Vergleichen:" + +#: misc/badblocks.c:721 +msgid "Checking for bad blocks in non-destructive read-write mode\n" +msgstr "Suche nach defekten Blöcken im zerstörungsfreien Lesen+Schreiben-Modus\n" + +#: misc/badblocks.c:727 +msgid "Checking for bad blocks (non-destructive read-write test)\n" +msgstr "Suche nach defekten Blöcken (zerstörungsfreier Lesen+Schreiben-Modus)\n" + +#: misc/badblocks.c:734 +msgid "" +"\n" +"Interrupt caught, cleaning up\n" +msgstr "" +"\n" +"Unterbrochen, räume auf\n" + +#: misc/badblocks.c:810 +#, c-format +msgid "during test data write, block %lu" +msgstr "beim Schreiben der Test-Daten; Block %lu" + +#: misc/badblocks.c:921 +#: misc/util.c:156 +#, c-format +msgid "%s is mounted; " +msgstr "%s ist eingehängt; " + +#: misc/badblocks.c:923 +msgid "badblocks forced anyway. Hope /etc/mtab is incorrect.\n" +msgstr "Badblocks wird trotzdem erzwungen. Hoffentlich ist /etc/mtab nicht korrekt.\n" + +#: misc/badblocks.c:928 +msgid "it's not safe to run badblocks!\n" +msgstr "es ist zu unsicher, Badblocks zu starten!\n" + +#: misc/badblocks.c:933 +#: misc/util.c:167 +#, c-format +msgid "%s is apparently in use by the system; " +msgstr "%s wird offensichtlich vom System genutzt; " + +#: misc/badblocks.c:936 +msgid "badblocks forced anyway.\n" +msgstr "Badblocks wird trotzdem erzwungen. Hoffentlich ist /etc/mtab nicht korrekt.\n" + +#: misc/badblocks.c:956 +#, c-format +msgid "invalid %s - %s" +msgstr "ungültige %s - %s" + +#: misc/badblocks.c:1015 +#, c-format +msgid "bad block size - %s" +msgstr "bad block Größe - %s" + +#: misc/badblocks.c:1070 +#, c-format +msgid "can't allocate memory for test_pattern - %s" +msgstr "Kann keinen Speicher für Testmuster reservieren - %s" + +#: misc/badblocks.c:1097 +msgid "Maximum of one test_pattern may be specified in read-only mode" +msgstr "Es darf im Nur-Lesen-Modus nur ein Testmuster angegeben werden" + +#: misc/badblocks.c:1103 +msgid "Random test_pattern is not allowed in read-only mode" +msgstr "Zufälliges Testmuster ist im Nur-Lesen-Modus nicht erlaubt" + +#: misc/badblocks.c:1117 +msgid "" +"Couldn't determine device size; you must specify\n" +"the size manually\n" +msgstr "Größe des Gerätes ist nicht feststellbar. Sie müssen sie manuell angeben.\n" + +#: misc/badblocks.c:1123 +msgid "while trying to determine device size" +msgstr "beim Versuch, die Gerätegröße festzustellen" + +#: misc/badblocks.c:1128 +msgid "last block" +msgstr "letzter Block" + +#: misc/badblocks.c:1134 +msgid "first block" +msgstr "erster Block" + +#: misc/badblocks.c:1137 +#, c-format +msgid "invalid starting block (%lu): must be less than %lu" +msgstr "Ungültiger Startblock (%lu): er muss kleiner als %lu sein" + +#: misc/badblocks.c:1193 +msgid "while creating in-memory bad blocks list" +msgstr "erstelle Bad-Block-Liste im Speicher" + +#: misc/badblocks.c:1208 +msgid "while adding to in-memory bad block list" +msgstr "füge zur Bad-Block-Liste im Speicher hinzu" + +#: misc/badblocks.c:1232 +#, c-format +msgid "Pass completed, %u bad blocks found.\n" +msgstr "Durchgang beendet, %u defekte Blöcke gefunden.\n" + +#: misc/chattr.c:85 +#, c-format +msgid "Usage: %s [-RVf] [-+=AacDdijsSu] [-v version] files...\n" +msgstr "Aufruf: %s [-RVf] [-+=AacDdijsSu] [-v Version] Dateien...\n" + +#: misc/chattr.c:152 +#, c-format +msgid "bad version - %s\n" +msgstr "falsche Version - %s\n" + +#: misc/chattr.c:198 +#: misc/lsattr.c:113 +#, c-format +msgid "while trying to stat %s" +msgstr "beim Auslesen des Status von %s" + +#: misc/chattr.c:204 +#: misc/chattr.c:222 +#, c-format +msgid "Flags of %s set as " +msgstr "Flags von %s wie folgt gesetzt: " + +#: misc/chattr.c:214 +#, c-format +msgid "while reading flags on %s" +msgstr "beim Lesens der Flags in %s" + +#: misc/chattr.c:231 +#, c-format +msgid "while setting flags on %s" +msgstr "beim Setzen der Flags in %s" + +#: misc/chattr.c:239 +#, c-format +msgid "Version of %s set as %lu\n" +msgstr "Version von %s gesetzt auf %lu\n" + +#: misc/chattr.c:243 +#, c-format +msgid "while setting version on %s" +msgstr "beim Setzen der Version in %s" + +#: misc/chattr.c:263 +#, c-format +msgid "Couldn't allocate path variable in chattr_dir_proc" +msgstr "Konnte Pfad-Variable in chattr_dir_proc nicht reservieren" + +#: misc/chattr.c:302 +msgid "= is incompatible with - and +\n" +msgstr "= ist inkompatibel mit - und +\n" + +#: misc/chattr.c:310 +msgid "Must use '-v', =, - or +\n" +msgstr "Benutze »-v«, =, - oder +\n" + +#: misc/dumpe2fs.c:53 +#, c-format +msgid "Usage: %s [-bfhixV] [-ob superblock] [-oB blocksize] device\n" +msgstr "Aufruf: %s [-bfhixV] [-ob Superblock] [-oB Blockgröße] Gerät\n" + +#: misc/dumpe2fs.c:168 +#, c-format +msgid "Group %lu: (Blocks " +msgstr "Gruppe %lu: (Blöcke " + +#: misc/dumpe2fs.c:173 +#, c-format +msgid " Checksum 0x%04x, unused inodes %d\n" +msgstr " Prüfsumme 0x%04x, %d ungenutzte Inodes\n" + +#: misc/dumpe2fs.c:178 +#, c-format +msgid " %s superblock at " +msgstr " %s Superblock in " + +#: misc/dumpe2fs.c:179 +msgid "Primary" +msgstr "Primary" + +#: misc/dumpe2fs.c:179 +msgid "Backup" +msgstr "Backup" + +#: misc/dumpe2fs.c:183 +#, c-format +msgid ", Group descriptors at " +msgstr ", Gruppendeskriptoren in " + +#: misc/dumpe2fs.c:187 +#, c-format +msgid "" +"\n" +" Reserved GDT blocks at " +msgstr "" +"\n" +" reservierte GDT Blöcke bei " + +#: misc/dumpe2fs.c:194 +#, c-format +msgid " Group descriptor at " +msgstr ", Gruppendeskriptor in " + +#: misc/dumpe2fs.c:200 +msgid " Block bitmap at " +msgstr " Block bitmap in " + +#: misc/dumpe2fs.c:205 +msgid ", Inode bitmap at " +msgstr ", Inode Bitmap in " + +#: misc/dumpe2fs.c:210 +msgid "" +"\n" +" Inode table at " +msgstr "" +"\n" +" Inode-Tabelle in " + +#: misc/dumpe2fs.c:217 +#, c-format +msgid "" +"\n" +" %u free blocks, %u free inodes, %u directories%s" +msgstr "" +"\n" +" %u freie Blöcke, %u freie Inodes, %u Verzeichnisse%s" + +#: misc/dumpe2fs.c:224 +#, c-format +msgid ", %u unused inodes\n" +msgstr ", %u ungenutzte Inodes\n" + +#: misc/dumpe2fs.c:227 +msgid " Free blocks: " +msgstr " Freie Blöcke: " + +#: misc/dumpe2fs.c:237 +msgid " Free inodes: " +msgstr " Freie Inodes: " + +#: misc/dumpe2fs.c:264 +msgid "while printing bad block list" +msgstr "beim Ausgeben der »Bad Block«-Liste" + +#: misc/dumpe2fs.c:270 +#, c-format +msgid "Bad blocks: %u" +msgstr "Bad Blocks: %u" + +#: misc/dumpe2fs.c:292 +#: misc/tune2fs.c:279 +msgid "while reading journal inode" +msgstr "beim Lesen des Journal-Inodes" + +#: misc/dumpe2fs.c:295 +msgid "Journal size: " +msgstr "Journalgrösse: " + +#: misc/dumpe2fs.c:319 +#: misc/tune2fs.c:200 +msgid "while reading journal superblock" +msgstr "beim Lesen des Journal-Superblocks" + +#: misc/dumpe2fs.c:327 +msgid "Couldn't find journal superblock magic numbers" +msgstr "Konnte die magische Nummer des Journal-Superblocks nicht finden" + +#: misc/dumpe2fs.c:331 +#, c-format +msgid "" +"\n" +"Journal block size: %u\n" +"Journal length: %u\n" +"Journal first block: %u\n" +"Journal sequence: 0x%08x\n" +"Journal start: %u\n" +"Journal number of users: %u\n" +msgstr "" +"\n" +"Journal Blockgröße: %u\n" +"Journal Länge: %u\n" +"Journal Startblock: %u\n" +"Journal Sequenz: 0x%08x\n" +"Journal Start: %u\n" +"Journal Anzahl Nutzer: %u\n" + +#: misc/dumpe2fs.c:344 +#, c-format +msgid "Journal users: %s\n" +msgstr "Jounalnutzer: %s\n" + +#: misc/dumpe2fs.c:360 +#: misc/mke2fs.c:693 +#: misc/tune2fs.c:868 +#, c-format +msgid "Couldn't allocate memory to parse options!\n" +msgstr "Speicher zum Parsen der Optionen konnte nicht reserviert werden!\n" + +#: misc/dumpe2fs.c:386 +#, c-format +msgid "Invalid superblock parameter: %s\n" +msgstr "Ungültiger Superblock-Parameter: %s\n" + +#: misc/dumpe2fs.c:401 +#, c-format +msgid "Invalid blocksize parameter: %s\n" +msgstr "Ungültiger Blockgrössen-Parameter: %s\n" + +#: misc/dumpe2fs.c:412 +#, c-format +msgid "" +"\n" +"Bad extended option(s) specified: %s\n" +"\n" +"Extended options are separated by commas, and may take an argument which\n" +"\tis set off by an equals ('=') sign.\n" +"\n" +"Valid extended options are:\n" +"\tsuperblock=\n" +"\tblocksize=\n" +msgstr "" +"\n" +"Falsche erweiterte Optionen angegeben: %s\n" +"\n" +"Erweiterte Optionen werden durch Kommatas getrennt. Manche erwarten ein\n" +"\tArgument, welches mit Gleichheitszeichen (»=«) zugewiesen wird.\n" +"\n" +"Gültige erweiterte Optionen sind:\n" +"\tsuperblock=\n" +"\tblocksize=\n" +"\n" + +#: misc/dumpe2fs.c:471 +#: misc/mke2fs.c:1355 +#, c-format +msgid "\tUsing %s\n" +msgstr "\tBenutze %s\n" + +#: misc/dumpe2fs.c:507 +#: misc/e2image.c:674 +#: misc/tune2fs.c:1518 +#: resize/main.c:311 +#, c-format +msgid "Couldn't find valid filesystem superblock.\n" +msgstr "Kann keinen gültigen Dateisystem-Superblock finden.\n" + +#: misc/dumpe2fs.c:532 +#, c-format +msgid "" +"\n" +"%s: %s: error reading bitmaps: %s\n" +msgstr "" +"\n" +"%s: %s: Fehler beim Lesen von Bitmaps: %s\n" + +#: misc/e2image.c:52 +#, c-format +msgid "Usage: %s [-rsI] device image_file\n" +msgstr "Aufruf: %s [-r] Gerätedatei\n" + +#: misc/e2image.c:64 +msgid "Couldn't allocate header buffer\n" +msgstr "Header-Puffer konnte nicht zugewiesen werden\n" + +#: misc/e2image.c:83 +#, c-format +msgid "short write (only %d bytes) for writing image header" +msgstr "short write (only %d bytes) for writing image header" + +#: misc/e2image.c:102 +msgid "while writing superblock" +msgstr "beim Schreiben des Superblocks" + +#: misc/e2image.c:110 +msgid "while writing inode table" +msgstr "beim Schreiben der Inode-Tabelle" + +#: misc/e2image.c:117 +msgid "while writing block bitmap" +msgstr "beim Schreiben der Block-Bitmap" + +#: misc/e2image.c:124 +msgid "while writing inode bitmap" +msgstr "beim Schreiben der Inode-Bitmap" + +#: misc/e2label.c:57 +#, c-format +msgid "e2label: cannot open %s\n" +msgstr "e2label: Kann %s nicht öffnen.\n" + +#: misc/e2label.c:62 +#, c-format +msgid "e2label: cannot seek to superblock\n" +msgstr "e2label: cannot seek to superblock\n" + +#: misc/e2label.c:67 +#, c-format +msgid "e2label: error reading superblock\n" +msgstr "e2label: Lesefehler im Superblock\n" + +#: misc/e2label.c:71 +#, c-format +msgid "e2label: not an ext2 filesystem\n" +msgstr "e2label: Kein ext2 Dateisystem\n" + +#: misc/e2label.c:96 +#: misc/tune2fs.c:1653 +#, c-format +msgid "Warning: label too long, truncating.\n" +msgstr "Warnung: Name zu lang, kürze ihn.\n" + +#: misc/e2label.c:99 +#, c-format +msgid "e2label: cannot seek to superblock again\n" +msgstr "e2label: cannot seek to superblock again\n" + +#: misc/e2label.c:104 +#, c-format +msgid "e2label: error writing superblock\n" +msgstr "e2label: Fehler beim Schreiben des Superblocks\n" + +#: misc/e2label.c:116 +#: misc/tune2fs.c:541 +#, c-format +msgid "Usage: e2label device [newlabel]\n" +msgstr "Aufruf: e2label Gerät [neuer_Name]\n" + +#: misc/e2undo.c:35 +#, c-format +msgid "Usage: %s \n" +msgstr "Aufruf: %s \n" + +#: misc/e2undo.c:52 +msgid "Failed to read the file system data \n" +msgstr "Die Dateisystemdaten konnten nicht gelesenb werden \n" + +#: misc/e2undo.c:62 +#: misc/e2undo.c:83 +#: misc/e2undo.c:108 +#: misc/e2undo.c:204 +#, c-format +msgid "Failed tdb_fetch %s\n" +msgstr "tdb_fetch von %s ist misslungen\n" + +#: misc/e2undo.c:70 +#, c-format +msgid "The file system Mount time didn't match %u\n" +msgstr "Die Zeit des letzten Einhängens des Dateisystems war nicht %u\n" + +#: misc/e2undo.c:89 +msgid "The file system UUID didn't match \n" +msgstr "Die UUID des Dateisystems stimmte nicht überein \n" + +#: misc/e2undo.c:161 +#, c-format +msgid "Failed tdb_open %s\n" +msgstr "tdb_open von %s ist misslungen\n" + +#: misc/e2undo.c:167 +#, c-format +msgid "Error while determining whether %s is mounted.\n" +msgstr "Fehler beim Überprüfen, ob %s eingehängt ist.\n" + +#: misc/e2undo.c:173 +msgid "e2undo should only be run on unmounted file system\n" +msgstr "e2undo sollte nur auf nicht-eingehängten Dateisystemen laufen\n" + +#: misc/e2undo.c:182 +#, c-format +msgid "Failed to open %s\n" +msgstr "%s konnte nicht geöffnet werden\n" + +#: misc/e2undo.c:208 +#, c-format +msgid "Replayed transaction of size %zd at location %ld\n" +msgstr "Zurückgespielte Transaktion der Größe %zd an Position %ld\n" + +#: misc/e2undo.c:214 +#, c-format +msgid "Failed write %s\n" +msgstr "Gescheitertes Schreiben von %s\n" + +#: misc/fsck.c:347 +#, c-format +msgid "WARNING: couldn't open %s: %s\n" +msgstr "WARNUNG: Konnte %s nicht öffnen: %s\n" + +#: misc/fsck.c:357 +#, c-format +msgid "WARNING: bad format on line %d of %s\n" +msgstr "WARNUNG: falsches Format in Zeile %d von %s\n" + +#: misc/fsck.c:372 +msgid "" +"\a\a\aWARNING: Your /etc/fstab does not contain the fsck passno\n" +"\tfield. I will kludge around things for you, but you\n" +"\tshould fix your /etc/fstab file as soon as you can.\n" +"\n" +msgstr "" +"\a\a\aWARNUNG: Ihre /etc/fstab enthält kein »fsck passno«\n" +"\tFeld. Ich werde dieses ignorieren, aber Sie\n" +"\tsollten ihre /etc/fstab so schnell wie möglich korrigieren.\n" +"\n" + +#: misc/fsck.c:481 +#, c-format +msgid "fsck: %s: not found\n" +msgstr "fsck: %s: nicht gefunden\n" + +#: misc/fsck.c:597 +#, c-format +msgid "%s: wait: No more child process?!?\n" +msgstr "%s: wait: kein Kindprozess mehr?!?\n" + +#: misc/fsck.c:619 +#, c-format +msgid "Warning... %s for device %s exited with signal %d.\n" +msgstr "Warnung... %s für Gerät %s wurde mit Signal %d beendet.\n" + +#: misc/fsck.c:625 +#, c-format +msgid "%s %s: status is %x, should never happen.\n" +msgstr "%s %s: Status ist %x, sollte nie vorkommen.\n" + +#: misc/fsck.c:664 +#, c-format +msgid "Finished with %s (exit status %d)\n" +msgstr "Beendet mit %s (exit status %d)\n" + +#: misc/fsck.c:724 +#, c-format +msgid "%s: Error %d while executing fsck.%s for %s\n" +msgstr "%s: Fehler %d bei Ausführung von fsck.%s für %s\n" + +#: misc/fsck.c:745 +msgid "" +"Either all or none of the filesystem types passed to -t must be prefixed\n" +"with 'no' or '!'.\n" +msgstr "" +"Bei -t müssen entweder allen oder keinem Dateisystem ein »no« bzw. »!«\n" +"vorangestellt werden.\n" + +#: misc/fsck.c:764 +msgid "Couldn't allocate memory for filesystem types\n" +msgstr "Kann keinen Speicher für Dateisystemtypen reservieren.\n" + +#: misc/fsck.c:887 +#, c-format +msgid "%s: skipping bad line in /etc/fstab: bind mount with nonzero fsck pass number\n" +msgstr "" +"%s: überspringe die ungültige Zeile in /etc/fstab: bind mount mit\n" +" Durchgangsnummer für fsck, die nicht Null ist\n" + +#: misc/fsck.c:914 +#, c-format +msgid "fsck: cannot check %s: fsck.%s not found\n" +msgstr "fsck: kann %s nicht überprüfen: fsck.%s nicht gefunden\n" + +#: misc/fsck.c:970 +msgid "Checking all file systems.\n" +msgstr "Überprüfe alle Dateisysteme.\n" + +#: misc/fsck.c:1061 +#, c-format +msgid "--waiting-- (pass %d)\n" +msgstr "--warten-- (Durchgang %d)\n" + +#: misc/fsck.c:1081 +msgid "Usage: fsck [-AMNPRTV] [ -C [ fd ] ] [-t fstype] [fs-options] [filesys ...]\n" +msgstr "Aufruf: fsck [-AMNPRTV] [ -C [ fd ] ] [-t Datesystemtyp] [FS-Optionen] [Dateisystem...]\n" + +#: misc/fsck.c:1123 +#, c-format +msgid "%s: too many devices\n" +msgstr "%s: zu viele Geräte\n" + +#: misc/fsck.c:1156 +#: misc/fsck.c:1242 +#, c-format +msgid "%s: too many arguments\n" +msgstr "%s: zu viele Argumente\n" + +#: misc/lsattr.c:73 +#, c-format +msgid "Usage: %s [-RVadlv] [files...]\n" +msgstr "Aufruf: %s [-RVadlv] [Dateien...]\n" + +#: misc/lsattr.c:83 +#, c-format +msgid "While reading flags on %s" +msgstr "Beim Lesen der Flags von %s" + +#: misc/lsattr.c:90 +#, c-format +msgid "While reading version on %s" +msgstr "Beim Lesen der Version von %s" + +#: misc/mke2fs.c:104 +#, c-format +msgid "" +"Usage: %s [-c|-l filename] [-b block-size] [-f fragment-size]\n" +"\t[-i bytes-per-inode] [-I inode-size] [-J journal-options]\n" +"\t[-G meta group size] [-N number-of-inodes]\n" +"\t[-m reserved-blocks-percentage] [-o creator-os]\n" +"\t[-g blocks-per-group] [-L volume-label] [-M last-mounted-directory]\n" +"\t[-O feature[,...]] [-r fs-revision] [-E extended-option[,...]]\n" +"\t[-T fs-type] [-U UUID] [-jnqvFSV] device [blocks-count]\n" +msgstr "" +"Aufruf: %s [-c|-l Dateiname] [-b Blockgröße] [-f Fragmentgröße]\n" +"\t[-i Bytes-pro-Inode] [-I Inodegrösse] [-J Journal-Optionen]\n" +"\t[-G Größe_der_Metagruppe] [-N Anzahl_der_Inodes]\n" +"\t[-m Reservierte-Blöcke-Prozent] [-o Erzeuger-OS]\n" +"\t[-g Blöcke-pro-Gruppe] [-L Volume-Label]\n" +"\t[-M letztes-eingehängtes-Verzeichnis] [-O Eigenschaft[,...]]\n" +"\t[-r fs-Revision] [-E erweiterte-Option[,...]]\n" +"\t[-T Fs-Typ] [-jnqvFSV] Gerät [Block-Anzahl]\n" + +#: misc/mke2fs.c:206 +#, c-format +msgid "Running command: %s\n" +msgstr "Führe aus: %s\n" + +#: misc/mke2fs.c:210 +#, c-format +msgid "while trying to run '%s'" +msgstr "während des Versuchs, »%s« auszuführen" + +#: misc/mke2fs.c:217 +msgid "while processing list of bad blocks from program" +msgstr "beim Auswerten der »Bad Block«-Liste vom Programm" + +#: misc/mke2fs.c:244 +#, c-format +msgid "Block %d in primary superblock/group descriptor area bad.\n" +msgstr "Block %d im primären Superblock/Gruppendeskriptorbereich defekt.\n" + +#: misc/mke2fs.c:246 +#, c-format +msgid "Blocks %u through %u must be good in order to build a filesystem.\n" +msgstr "" +"Die Blöcke %u bis einschließlich %u müssen in Ordung sein, um ein\n" +"\tDateisystem zu erstellen.\n" + +#: misc/mke2fs.c:249 +msgid "Aborting....\n" +msgstr "Breche ab...\n" + +#: misc/mke2fs.c:269 +#, c-format +msgid "" +"Warning: the backup superblock/group descriptors at block %u contain\n" +"\tbad blocks.\n" +"\n" +msgstr "" +"Warnung: die Sicherung des Superblock bzw. Gruppendeskriptors in Block %u enthält\n" +"\tdefekte Blöcke.\n" +"\n" + +#: misc/mke2fs.c:288 +msgid "while marking bad blocks as used" +msgstr "beim Markieren von defekten Blöcken als »belegt«" + +#: misc/mke2fs.c:346 +msgid "done \n" +msgstr "erledigt \n" + +#: misc/mke2fs.c:360 +msgid "Writing inode tables: " +msgstr "Schreibe Inode-Tabellen: " + +#: misc/mke2fs.c:383 +#, c-format +msgid "" +"\n" +"Could not write %d blocks in inode table starting at %u: %s\n" +msgstr "" +"\n" +"Konnte %d Blöcke nicht in Inoden-Tabelle schreiben, beginnend bei %u: %s\n" + +#: misc/mke2fs.c:407 +msgid "while creating root dir" +msgstr "beim Erstellen des Wurzelverzeichnisses" + +#: misc/mke2fs.c:414 +msgid "while reading root inode" +msgstr "beim Lesen des Root-Inode" + +#: misc/mke2fs.c:428 +msgid "while setting root inode ownership" +msgstr "beim Setzen des Root-Inode-Eigentümers" + +#: misc/mke2fs.c:446 +msgid "while creating /lost+found" +msgstr "beim Erstellen von /lost+found" + +#: misc/mke2fs.c:453 +msgid "while looking up /lost+found" +msgstr "beim Suchen von /lost+found" + +#: misc/mke2fs.c:466 +msgid "while expanding /lost+found" +msgstr "beim Expandieren von /lost+found" + +#: misc/mke2fs.c:481 +msgid "while setting bad block inode" +msgstr "beim Setzen des »Bad Block«-Inodes" + +#: misc/mke2fs.c:508 +#, c-format +msgid "Out of memory erasing sectors %d-%d\n" +msgstr "Speicher voll beim Löschen der Sektoren %d-%d\n" + +#: misc/mke2fs.c:518 +#, c-format +msgid "Warning: could not read block 0: %s\n" +msgstr "Warnung: konnte Block %s nicht lesen\n" + +#: misc/mke2fs.c:534 +#, c-format +msgid "Warning: could not erase sector %d: %s\n" +msgstr "Warnung: konnte Sektor %d: %s nicht löschen\n" + +#: misc/mke2fs.c:550 +msgid "while initializing journal superblock" +msgstr "beim Initialisieren des Journal-Superblocks" + +#: misc/mke2fs.c:556 +msgid "Zeroing journal device: " +msgstr "Überschreibe Journal-Device mit Nullen: " + +#: misc/mke2fs.c:569 +#, c-format +msgid "while zeroing journal device (block %u, count %d)" +msgstr "beim Überschreiben des Journal-Device mit Nullen (Block %u, Nr. %d)" + +#: misc/mke2fs.c:585 +msgid "while writing journal superblock" +msgstr "beim Schreiben des Journal-Superblocks" + +#: misc/mke2fs.c:601 +#, c-format +msgid "" +"warning: %u blocks unused.\n" +"\n" +msgstr "" +"Warnung: %u Blöcke unbenutzt.\n" +"\n" + +#: misc/mke2fs.c:606 +#, c-format +msgid "Filesystem label=%s\n" +msgstr "Dateisystem-Label=%s\n" + +#: misc/mke2fs.c:607 +msgid "OS type: " +msgstr "OS-Typ: " + +#: misc/mke2fs.c:612 +#, c-format +msgid "Block size=%u (log=%u)\n" +msgstr "Blockgröße=%u (log=%u)\n" + +#: misc/mke2fs.c:614 +#, c-format +msgid "Fragment size=%u (log=%u)\n" +msgstr "Fragmentgröße=%u (log=%u)\n" + +#: misc/mke2fs.c:616 +#, c-format +msgid "%u inodes, %u blocks\n" +msgstr "%u Inodes, %u Blöcke\n" + +#: misc/mke2fs.c:618 +#, c-format +msgid "%u blocks (%2.2f%%) reserved for the super user\n" +msgstr "%u Blöcke (%2.2f%%) reserviert für den Superuser\n" + +#: misc/mke2fs.c:621 +#, c-format +msgid "First data block=%u\n" +msgstr "Erster Datenblock=%u\n" + +#: misc/mke2fs.c:623 +#, c-format +msgid "Maximum filesystem blocks=%lu\n" +msgstr "Maximale Dateisystem-Blöcke=%lu\n" + +#: misc/mke2fs.c:627 +#, c-format +msgid "%u block groups\n" +msgstr "%u Blockgruppen\n" + +#: misc/mke2fs.c:629 +#, c-format +msgid "%u block group\n" +msgstr "%u Blockgruppe\n" + +#: misc/mke2fs.c:630 +#, c-format +msgid "%u blocks per group, %u fragments per group\n" +msgstr "%u Blöcke pro Gruppe, %u Fragmente pro Gruppe\n" + +#: misc/mke2fs.c:632 +#, c-format +msgid "%u inodes per group\n" +msgstr "%u Inodes pro Gruppe\n" + +#: misc/mke2fs.c:639 +#, c-format +msgid "Superblock backups stored on blocks: " +msgstr "Superblock-Sicherungskopien gespeichert in den Blöcken: " + +#: misc/mke2fs.c:718 +#, c-format +msgid "Invalid stride parameter: %s\n" +msgstr "Ungültiger \"stride\"-Parameter: %s\n" + +#: misc/mke2fs.c:733 +#, c-format +msgid "Invalid stripe-width parameter: %s\n" +msgstr "Ungültiger Stripebreite-Parameter: %s\n" + +#: misc/mke2fs.c:755 +#, c-format +msgid "Invalid resize parameter: %s\n" +msgstr "Ungültiger \"resize\"-Parameter: %s\n" + +#: misc/mke2fs.c:762 +#, c-format +msgid "The resize maximum must be greater than the filesystem size.\n" +msgstr "Das Maximum der Vergrösserung muss oberhalb als der Dateisystem-Grösse liegen.\n" + +#: misc/mke2fs.c:786 +#, c-format +msgid "On-line resizing not supported with revision 0 filesystems\n" +msgstr "" +"Online-Grössenänderungen werden bei Revison 0 Dateisystemen nicht\n" +"\tunterstützt\n" + +#: misc/mke2fs.c:808 +#, c-format +msgid "" +"\n" +"Bad option(s) specified: %s\n" +"\n" +"Extended options are separated by commas, and may take an argument which\n" +"\tis set off by an equals ('=') sign.\n" +"\n" +"Valid extended options are:\n" +"\tstride=\n" +"\tstripe-width=\n" +"\tresize=\n" +"\tlazy_itable_init=<0 to disable, 1 to enable>\n" +"\ttest_fs\n" +"\n" +msgstr "" +"\n" +"Ungültige Option(en) angegeben: %s\n" +"\n" +"Erweiterte Optionen werden durch Kommatas getrennt. Manche erwarten ein\n" +"\tArgument, welches mit Gleichheitszeichen (»=«) zugewiesen wird.\n" +"\n" +"\terhalten welches mit Gleichheitszeichen (»=«) zugewiesen wird.\n" +"\n" +"gültige erweiterte Optionen sind:\n" +"\tstride=\n" +"\tstripe-width=\n" +"\tresize=\n" +"\tlazy_itable_init=<0 für Ab-, 1 für Einschalten>\n" +"\ttest_fs\n" +"\n" + +#: misc/mke2fs.c:824 +#, c-format +msgid "" +"\n" +"Warning: RAID stripe-width %u not an even multiple of stride %u.\n" +"\n" +msgstr "" +"\n" +"Warnung: RAID Stripe-Breite %u ist kein ganzzahliges Vielfaches von\n" +"\tStride %u.\n" +"\n" + +#: misc/mke2fs.c:856 +#, c-format +msgid "" +"Syntax error in mke2fs config file (%s, line #%d)\n" +"\t%s\n" +msgstr "" +"Syntax Fehler in der Konfigurationsdatei von mkefs (%s, Zeile %d)\n" +"\t%s\n" + +#: misc/mke2fs.c:869 +#: misc/tune2fs.c:353 +#, c-format +msgid "Invalid filesystem option set: %s\n" +msgstr "Unvollständige Dateisystem-Option gesetzt: %s\n" + +#: misc/mke2fs.c:979 +#, c-format +msgid "" +"\n" +"Warning! Your mke2fs.conf file does not define the %s filesystem type.\n" +msgstr "" +"\n" +"Warnung: Ihre mke2fs.conf Datei definiert den Typ des Dateisystems auf %s nicht.\n" + +#: misc/mke2fs.c:982 +#, c-format +msgid "" +"You probably need to install an updated mke2fs.conf file.\n" +"\n" +msgstr "" +"Sie müssen wahrscheinlich eine aktualisierte mke2fs.conf Datei installieren.\n" +"\n" + +#: misc/mke2fs.c:1177 +#, c-format +msgid "invalid block size - %s" +msgstr "bad block Größe - %s" + +#: misc/mke2fs.c:1181 +#, c-format +msgid "Warning: blocksize %d not usable on most systems.\n" +msgstr "Warnung: Blockgröße %d ist auf den meisten Systemen unbrauchbar.\n" + +#: misc/mke2fs.c:1197 +#, c-format +msgid "invalid fragment size - %s" +msgstr "falsche Fragmentgröße - %s" + +#: misc/mke2fs.c:1203 +#, c-format +msgid "Warning: fragments not supported. Ignoring -f option\n" +msgstr "Warnung: Fragmente werden nicht unterstützt. Ignoriere -f Option\n" + +#: misc/mke2fs.c:1210 +msgid "Illegal number for blocks per group" +msgstr "unzulässige Angabe für Blöcke pro Gruppe" + +#: misc/mke2fs.c:1215 +msgid "blocks per group must be multiple of 8" +msgstr "Anzahl der Blöcke pro Gruppe muss ein Vielfaches von 8 sein" + +#: misc/mke2fs.c:1223 +msgid "Illegal number for flex_bg size" +msgstr "Illegale Zahl für flex_bg Größe" + +#: misc/mke2fs.c:1229 +msgid "flex_bg size must be a power of 2" +msgstr "flex_bg Größe muss eine Zweierpotenz sein" + +#: misc/mke2fs.c:1239 +#, c-format +msgid "invalid inode ratio %s (min %d/max %d)" +msgstr "Unzulässiges Inode-Verhältnis %s (Min %d/Max %d" + +#: misc/mke2fs.c:1256 +msgid "in malloc for bad_blocks_filename" +msgstr "in malloc for bad_blocks_filename" + +#: misc/mke2fs.c:1265 +#, c-format +msgid "invalid reserved blocks percent - %s" +msgstr "Unzulässige \"Reservierte Blöcke\"-Prozentangabe - %s" + +#: misc/mke2fs.c:1283 +#, c-format +msgid "bad revision level - %s" +msgstr "ungültiges Intervall - %s" + +#: misc/mke2fs.c:1295 +#, c-format +msgid "invalid inode size - %s" +msgstr "Unzulässige Inode-Größe - %s" + +#: misc/mke2fs.c:1315 +#, c-format +msgid "bad num inodes - %s" +msgstr "ungültiges Intervall - %s" + +#: misc/mke2fs.c:1380 +#: misc/mke2fs.c:2052 +#, c-format +msgid "while trying to open journal device %s\n" +msgstr "beim Versuch, das Journal-Device %s zu öffnen\n" + +#: misc/mke2fs.c:1386 +#, c-format +msgid "Journal dev blocksize (%d) smaller than minimum blocksize %d\n" +msgstr "Journal-Device Blockgröße (%d) kleiner als Minimum-Blockgröße %d\n" + +#: misc/mke2fs.c:1392 +#, c-format +msgid "Using journal device's blocksize: %d\n" +msgstr "Verwende die Blockgrösse des Geräts: %d\n" + +#: misc/mke2fs.c:1401 +#, c-format +msgid "%d-byte blocks too big for system (max %d)" +msgstr "%d-Byte Blöcke zu groß für das System (max %d)" + +#: misc/mke2fs.c:1405 +#, c-format +msgid "Warning: %d-byte blocks too big for system (max %d), forced to continue\n" +msgstr "Warnung: %d-byte Blöcke sind zu groß für das System (max %d), fahre dennoch fort\n" + +#: misc/mke2fs.c:1413 +#, c-format +msgid "invalid blocks count - %s" +msgstr "ungültige Anzahl Blöcke - %s" + +#: misc/mke2fs.c:1423 +msgid "filesystem" +msgstr "Dateisystem" + +#: misc/mke2fs.c:1459 +#, c-format +msgid "" +"%s: Size of device %s too big to be expressed in 32 bits\n" +"\tusing a blocksize of %d.\n" +msgstr "" +"%s: Größe von Gerät %s lässt sich in 32 Bits nicht darstellen\n" +"\teine Blockgröße von %d wird verwendet.\n" + +#: misc/mke2fs.c:1468 +#: resize/main.c:371 +msgid "while trying to determine filesystem size" +msgstr "beim Bestimmen der Dateisystemgröße" + +#: misc/mke2fs.c:1475 +msgid "" +"Couldn't determine device size; you must specify\n" +"the size of the filesystem\n" +msgstr "" +"Konnte die Gerätegröße nicht ermitteln. Geben\n" +"Sie die Größe des Dateisystems an\n" + +#: misc/mke2fs.c:1482 +msgid "" +"Device size reported to be zero. Invalid partition specified, or\n" +"\tpartition table wasn't reread after running fdisk, due to\n" +"\ta modified partition being busy and in use. You may need to reboot\n" +"\tto re-read your partition table.\n" +msgstr "" +"Zurückgegebene Gerätegröße ist gleich null. Unvollständige Partition\n" +"\tangegeben oder die Partitionstabelle wurde nach einem fdisk-Lauf\n" +"\tnicht wieder eingelesen, weil eine veränderte Partition in Gebrauch\n" +"\tund gesperrt ist. Sie könnten gezwungen sein, neu zu booten, um die\n" +"\tPartitionstabelle neu einzulesen.\n" + +#: misc/mke2fs.c:1500 +msgid "Filesystem larger than apparent device size." +msgstr "Dateisystem ist größer als augenscheinlich das Gerät selbst." + +#: misc/mke2fs.c:1506 +#, c-format +msgid "Failed to parse fs types list\n" +msgstr "Analyse der Liste von Dateisystemen war nicht möglich\n" + +#: misc/mke2fs.c:1542 +msgid "fs_types for mke2fs.conf resolution: " +msgstr "fs_types für mke2fs.conf Lösung: " + +#: misc/mke2fs.c:1549 +#, c-format +msgid "Filesystem features not supported with revision 0 filesystems\n" +msgstr "" +"Dateisystem-Eigenschaften werden für Dateisysteme der Revision 0 nicht\n" +"\tunterstützt\n" + +#: misc/mke2fs.c:1556 +#, c-format +msgid "Sparse superblocks not supported with revision 0 filesystems\n" +msgstr "" +"Verteilte Superblöcke werden für Dateisysteme der Revision 0 nicht\n" +"\tunterstützt\n" + +#: misc/mke2fs.c:1568 +#, c-format +msgid "Journals not supported with revision 0 filesystems\n" +msgstr "Journale werden für Dateisysteme der Revision 0 nicht unterstützt\n" + +#: misc/mke2fs.c:1586 +#, c-format +msgid "" +"The resize_inode and meta_bg features are not compatible.\n" +"They can not be both enabled simultaneously.\n" +msgstr "" +"Die Eigenschaften resize_inode und meta_bg sind nicht kompatibel.\n" +"Sie können nicht gleichzeitig aktiviert werden.\n" + +#: misc/mke2fs.c:1603 +msgid "while trying to determine hardware sector size" +msgstr "beim Ermitteln der Hardware-Sektorgröße" + +#: misc/mke2fs.c:1661 +msgid "reserved online resize blocks not supported on non-sparse filesystem" +msgstr "" +"Für Online-Grössenänderungen reservierte Blöcke werden auf Dateisystemen\n" +"\tohne Unterstützung für Lückenkompression nicht unterstützt" + +#: misc/mke2fs.c:1670 +msgid "blocks per group count out of range" +msgstr "Anzahl der Blöcke pro Gruppe ausserhaalb des gültigen Bereichs" + +#: misc/mke2fs.c:1685 +msgid "Flex_bg feature not enabled, so flex_bg size may not be specified" +msgstr "Eigenschaft flex_bg wurde nicht aktiviert, daher darf flex_bg Grösse nicht angegeben werden" + +#: misc/mke2fs.c:1697 +#, c-format +msgid "invalid inode size %d (min %d/max %d)" +msgstr "ungültige Inode-Größe %d (min %d/max %d)" + +#: misc/mke2fs.c:1711 +#, c-format +msgid "too many inodes (%llu), raise inode ratio?" +msgstr "zu viele Inodes (%llu), Inode-Verhältnis erhöhen?" + +#: misc/mke2fs.c:1716 +#, c-format +msgid "too many inodes (%llu), specify < 2^32 inodes" +msgstr "zu viele Inodes (%llu), sie müssen weniger als 2^32 Inodes angeben" + +#: misc/mke2fs.c:1731 +#, c-format +msgid "" +"inode_size (%u) * inodes_count (%u) too big for a\n" +"\tfilesystem with %lu blocks, specify higher inode_ratio (-i)\n" +"\tor lower inode count (-N).\n" +msgstr "" +"inode_size (%u) * inodes_count (%u) is zu gross für ein\n" +"\tDateisystem mit %lu Blöcken, geben Sie bitte entweder ein höheres\n" +"\tinode_ratio (-i) oder eine niedrigere Anzahl an Inodes (-N) an.\n" + +#: misc/mke2fs.c:1828 +#: misc/tune2fs.c:1462 +#, c-format +msgid "while trying to delete %s" +msgstr "beim Versuch, %s zu löschen" + +#: misc/mke2fs.c:1837 +#, c-format +msgid "" +"Overwriting existing filesystem; this can be undone using the command:\n" +" e2undo %s %s\n" +"\n" +msgstr "" +"Überschreibe das bestehende Dateisystem; dies kann rückgängig gemacht werden\n" +"durch den Befehl:\n" +" e2undo %s %s\n" +"\n" + +#: misc/mke2fs.c:1885 +msgid "while setting up superblock" +msgstr "beim Erstellen des Superblocks" + +#: misc/mke2fs.c:1936 +#, c-format +msgid "unknown os - %s" +msgstr "unbekanntes OS - %s" + +#: misc/mke2fs.c:1990 +msgid "while trying to allocate filesystem tables" +msgstr "beim Zuordnen von Dateisystemtabellen" + +#: misc/mke2fs.c:2021 +#, c-format +msgid "while zeroing block %u at end of filesystem" +msgstr "beim Nullen von Block %u am Ende des Dateisystems" + +#: misc/mke2fs.c:2034 +msgid "while reserving blocks for online resize" +msgstr "beim Lesen des Bad-Block-Inodes" + +#: misc/mke2fs.c:2045 +#: misc/tune2fs.c:477 +msgid "journal" +msgstr "Journal" + +#: misc/mke2fs.c:2057 +#, c-format +msgid "Adding journal to device %s: " +msgstr "Erstelle Journal auf Gerät %s: " + +#: misc/mke2fs.c:2064 +#, c-format +msgid "" +"\n" +"\twhile trying to add journal to device %s" +msgstr "" +"\n" +"\tbeim Erstellen des Journals auf Gerät %s" + +#: misc/mke2fs.c:2069 +#: misc/mke2fs.c:2095 +#: misc/tune2fs.c:506 +#: misc/tune2fs.c:520 +#, c-format +msgid "done\n" +msgstr "erledigt\n" + +#: misc/mke2fs.c:2083 +#, c-format +msgid "Creating journal (%u blocks): " +msgstr "Erstelle Journal (%u Blöcke): " + +#: misc/mke2fs.c:2100 +#, c-format +msgid "Writing superblocks and filesystem accounting information: " +msgstr "Schreibe Superblöcke und Dateisystem-Accountinginformationen: " + +#: misc/mke2fs.c:2105 +#, c-format +msgid "" +"\n" +"Warning, had trouble writing out superblocks." +msgstr "" +"\n" +"Warnung: Probleme beim Schreiben der Superblöcke." + +#: misc/mke2fs.c:2108 +#, c-format +msgid "" +"done\n" +"\n" +msgstr "" +"erledigt\n" +"\n" + +#: misc/mklost+found.c:49 +#, c-format +msgid "Usage: mklost+found\n" +msgstr "Aufruf: mklost+found\n" + +#: misc/partinfo.c:39 +#, c-format +msgid "" +"Usage: %s device...\n" +"\n" +"Prints out the partition information for each given device.\n" +"For example: %s /dev/hda\n" +"\n" +msgstr "" +"Aufruf: %s Gerät...\n" +"\n" +"Gibt Informationen über die Partitionen jedes angegebenen Gerätes aus.\n" +"Zum Beispiel: %s /dev/hda\n" +"\n" + +#: misc/partinfo.c:49 +#, c-format +msgid "Cannot open %s: %s" +msgstr "Kann %s nicht öffnen: %s" + +#: misc/partinfo.c:55 +#, c-format +msgid "Cannot get geometry of %s: %s" +msgstr "Geometrie von %s kann nicht ermittelt werden: %s" + +#: misc/partinfo.c:63 +#, c-format +msgid "Cannot get size of %s: %s" +msgstr "Grösse von %s kann nicht gelesen werden: %s" + +#: misc/partinfo.c:69 +#, c-format +msgid "%s: h=%3d s=%3d c=%4d start=%8d size=%8lu end=%8d\n" +msgstr "%s: h=%3d s=%3d c=%4d Start=%8d Grösse=%8lu Ende=%8d\n" + +#: misc/tune2fs.c:96 +msgid "Please run e2fsck on the filesystem.\n" +msgstr "Lassen Sie bitte e2fsck über das Dateisystem laufen.\n" + +#: misc/tune2fs.c:103 +#, c-format +msgid "" +"Usage: %s [-c max_mounts_count] [-e errors_behavior] [-g group]\n" +"\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n" +"\t[-m reserved_blocks_percent] [-o [^]mount_options[,...]] \n" +"\t[-r reserved_blocks_count] [-u user] [-C mount_count] [-L volume_label]\n" +"\t[-M last_mounted_dir] [-O [^]feature[,...]]\n" +"\t[-E extended-option[,...]] [-T last_check_time] [-U UUID]\n" +"\t[ -I new_inode_size ] device\n" +msgstr "" +"Aufruf: %s [-c max-Anzahl-Mounts] [-e Fehler-Verhalten] [-g Gruppe]\n" +"\t[-i Intervall[d|m|w]] [-j] [-J Journal-Optionen] [-l]\n" +"\t[-m reservierte_Blöcke_Prozent] [-o [^]Einhäng_Optionen[,...]]\n" +"\t[-r Anzahl_reservierte_Blöcke] [-u Benutzer] [-C Anzahl_Einhängen]\n" +"\t[-L Volume_Label] [-M letztes_eingehängtes_Verzeichnis]\n" +"\t[-O [^]Eigenschaft[,...]] [-E erweiterte-Option[,...]]\n" +"\t[-T letzter_Prüfzeitpunkt] [-U UUID] [-I neue_Inodegrösse] Gerät\n" + +#: misc/tune2fs.c:188 +msgid "while trying to open external journal" +msgstr "beim Öffnen des externen Journals" + +#: misc/tune2fs.c:192 +#, c-format +msgid "%s is not a journal device.\n" +msgstr "%s ist kein Journal-Gerät.\n" + +#: misc/tune2fs.c:207 +msgid "Journal superblock not found!\n" +msgstr "Journal-Superblock nicht gefunden!\n" + +#: misc/tune2fs.c:219 +msgid "Filesystem's UUID not found on journal device.\n" +msgstr "UUID des Dateisystems auf Journal-Gerät nicht gefunden.\n" + +#: misc/tune2fs.c:240 +msgid "Journal NOT removed\n" +msgstr "Journal NICHT gelöscht\n" + +#: misc/tune2fs.c:246 +msgid "Journal removed\n" +msgstr "Journal gelöscht\n" + +#: misc/tune2fs.c:286 +msgid "while reading bitmaps" +msgstr "beim Lesen von Bitmaps" + +#: misc/tune2fs.c:294 +msgid "while clearing journal inode" +msgstr "beim Bereinigen des Journal-Inodes" + +#: misc/tune2fs.c:305 +msgid "while writing journal inode" +msgstr "beim Schreiben des Journal-Inodes" + +#: misc/tune2fs.c:320 +#, c-format +msgid "Invalid mount option set: %s\n" +msgstr "Ungültige Einhänge-Option gesetzt: %s\n" + +#: misc/tune2fs.c:356 +#, c-format +msgid "Clearing filesystem feature '%s' not supported.\n" +msgstr "Das Zurücksetzen von Dateisystem-Eigenschaft »%s« wird nicht unterstützt.\n" + +#: misc/tune2fs.c:362 +#, c-format +msgid "Setting filesystem feature '%s' not supported.\n" +msgstr "Das Setzen der Dateisystem-Eigenschaft »%s« wird nicht unterstützt.\n" + +#: misc/tune2fs.c:371 +msgid "" +"The has_journal feature may only be cleared when the filesystem is\n" +"unmounted or mounted read-only.\n" +msgstr "" +"Die has_jounal Eigenschaft kann nur zurückgesetzt werden, wenn das\n" +"Dateisystem nicht oder im Nur-Lesen-Modus eingehängt ist.\n" + +#: misc/tune2fs.c:379 +msgid "" +"The needs_recovery flag is set. Please run e2fsck before clearing\n" +"the has_journal flag.\n" +msgstr "" +"Das needs_recovery Flag ist gesetzt. Bitte starten sie e2fsck vor\n" +"der Zurücksetzung des has_journal Flags.\n" + +#: misc/tune2fs.c:412 +msgid "" +"Clearing the flex_bg flag would cause the the filesystem to be\n" +"inconsistent.\n" +msgstr "" +"Das Zurücksetzen der Kennung flex_bg würde das Dateisystem inkonsistent\n" +"machen.\n" + +#: misc/tune2fs.c:423 +msgid "" +"The huge_file feature may only be cleared when the filesystem is\n" +"unmounted or mounted read-only.\n" +msgstr "" +"Die huge_file Eigenschaft kann nur zurückgesetzt werden, wenn das\n" +"Dateisystem nicht oder im Nur-Lesen-Modus eingehängt ist.\n" + +#: misc/tune2fs.c:451 +#, c-format +msgid "(and reboot afterwards!)\n" +msgstr "(und hinterher das System neu starten!)\n" + +#: misc/tune2fs.c:472 +msgid "The filesystem already has a journal.\n" +msgstr "Das Dateisystem hat schon ein Journal.\n" + +#: misc/tune2fs.c:490 +#, c-format +msgid "" +"\n" +"\twhile trying to open journal on %s\n" +msgstr "" +"\n" +"\tbeim Öffnen des Journals auf %s\n" + +#: misc/tune2fs.c:494 +#, c-format +msgid "Creating journal on device %s: " +msgstr "Erstelle Journal auf Gerät %s: " + +#: misc/tune2fs.c:502 +#, c-format +msgid "while adding filesystem to journal on %s" +msgstr "beim Hinzufügen des Dateisystems zum Journal auf %s" + +#: misc/tune2fs.c:508 +msgid "Creating journal inode: " +msgstr "Erstelle Journal-Inode: " + +#: misc/tune2fs.c:517 +msgid "" +"\n" +"\twhile trying to create journal file" +msgstr "" +"\n" +"\tbeim Erstellen der Journaldatei" + +#: misc/tune2fs.c:584 +#, c-format +msgid "Couldn't parse date/time specifier: %s" +msgstr "Konnte Datum/Zeit nicht parsen: %s" + +#: misc/tune2fs.c:608 +#: misc/tune2fs.c:621 +#, c-format +msgid "bad mounts count - %s" +msgstr "Ungültiger Mounts-Zähler - %s" + +#: misc/tune2fs.c:637 +#, c-format +msgid "bad error behavior - %s" +msgstr "ungültiges Fehler-Verhalten - %s" + +#: misc/tune2fs.c:664 +#, c-format +msgid "bad gid/group name - %s" +msgstr "ungültige(r) GID oder Gruppenname - %s" + +#: misc/tune2fs.c:697 +#, c-format +msgid "bad interval - %s" +msgstr "ungültiges Intervall - %s" + +#: misc/tune2fs.c:725 +#, c-format +msgid "bad reserved block ratio - %s" +msgstr "ungültiges Reservierte-Blöcke-Verhältnis - %s" + +#: misc/tune2fs.c:740 +msgid "-o may only be specified once" +msgstr "-o darf nur eimal angegeben werden" + +#: misc/tune2fs.c:750 +msgid "-O may only be specified once" +msgstr "-O darf nur eimal angegeben werden" + +#: misc/tune2fs.c:760 +#, c-format +msgid "bad reserved blocks count - %s" +msgstr "ungültige Anzahl von reservierten Blöcken - %s" + +#: misc/tune2fs.c:789 +#, c-format +msgid "bad uid/user name - %s" +msgstr "ungültige(r) UID/Benutzername - %s" + +#: misc/tune2fs.c:806 +#, c-format +msgid "bad inode size - %s" +msgstr "Unzulässige Inodegröße - %s" + +#: misc/tune2fs.c:813 +#, c-format +msgid "Inode size must be a power of two- %s" +msgstr "Inodegrösse muss eine Zweierpotenz sein- %s" + +#: misc/tune2fs.c:900 +#, c-format +msgid "Invalid RAID stride: %s\n" +msgstr "Ungültiger RAID Stride: %s\n" + +#: misc/tune2fs.c:915 +#, c-format +msgid "Invalid RAID stripe-width: %s\n" +msgstr "Ungültige RAID Stripe-Breite: %s\n" + +#: misc/tune2fs.c:930 +#, c-format +msgid "Invalid hash algorithm: %s\n" +msgstr "Ungültiger Hashalgorithmus: %s\n" + +#: misc/tune2fs.c:936 +#, c-format +msgid "Setting default hash algorithm to %s (%d)\n" +msgstr "Der standard Hashalgorithmus wird auf %s (%d) gesetzt\n" + +#: misc/tune2fs.c:944 +#, c-format +msgid "" +"\n" +"Bad options specified.\n" +"\n" +"Extended options are separated by commas, and may take an argument which\n" +"\tis set off by an equals ('=') sign.\n" +"\n" +"Valid extended options are:\n" +"\tstride=\n" +"\tstripe_width=\n" +"\thash_alg=\n" +"\ttest_fs\n" +"\t^test_fs\n" +msgstr "" +"\n" +"Ungültige Optionen wurden angegeben.\n" +"\n" +"Erweiterte Optionen werden mit Kommatas getrennt angegeben und erwarten\n" +"\teventuell ein Argument, welches mit Gleichheitszeichen (»=«)\n" +"\tzugewiesenwird.\n" +"\n" +"Gültige erweiterte Optionen sind:\n" +"\tstride=\n" +"\tstripe-width=\n" +"\thash_alg=\n" +"\ttest_fs\n" +"\t^test_fs\n" + +#: misc/tune2fs.c:1384 +#: misc/tune2fs.c:1389 +#: resize/resize2fs.c:760 +msgid "blocks to be moved" +msgstr "zu verschiebende Blöcke" + +#: misc/tune2fs.c:1471 +#, fuzzy, c-format +msgid "" +"To undo the tune2fs operation please run the command\n" +" e2undo %s %s\n" +"\n" +msgstr "" +"Um die Aktionen von tune2fs rückgängig zu machen, starten Sie bitte den\n" +"Befehl\n" +" e2undo %s %s\n" +"\n" + +#: misc/tune2fs.c:1529 +#, c-format +msgid "The inode size is already %d\n" +msgstr "Die Inodegrösse ist bereits %d\n" + +#: misc/tune2fs.c:1534 +#, c-format +msgid "Shrinking the inode size is not supported\n" +msgstr "Das Schrumpfen der Inodegrösse wird nicht unterstützt\n" + +#: misc/tune2fs.c:1577 +#, c-format +msgid "Setting maximal mount count to %d\n" +msgstr "Setze die maximale Mount-Anzahl auf %d\n" + +#: misc/tune2fs.c:1583 +#, c-format +msgid "Setting current mount count to %d\n" +msgstr "Setze die derzeitige Mount-Anzahl auf %d\n" + +#: misc/tune2fs.c:1588 +#, c-format +msgid "Setting error behavior to %d\n" +msgstr "Setze das Fehler-Verhalten auf %d\n" + +#: misc/tune2fs.c:1593 +#, c-format +msgid "Setting reserved blocks gid to %lu\n" +msgstr "Setze die GID für reservierte Blöcke auf %lu\n" + +#: misc/tune2fs.c:1598 +#, c-format +msgid "Setting interval between checks to %lu seconds\n" +msgstr "Setze das Intervall zwischen Checks auf %lu Sekunden\n" + +#: misc/tune2fs.c:1605 +#, c-format +msgid "Setting reserved blocks percentage to %g%% (%u blocks)\n" +msgstr "Setze den Prozentsatz reservierter Böcke auf %g%% (%u Blöcke)\n" + +#: misc/tune2fs.c:1612 +#, c-format +msgid "reserved blocks count is too big (%lu)" +msgstr "Anzahl der reservierten Blöcke ist zu gross (%lu)" + +#: misc/tune2fs.c:1618 +#, c-format +msgid "Setting reserved blocks count to %lu\n" +msgstr "Setze die Anzahl der reservierten Blöcke auf %lu\n" + +#: misc/tune2fs.c:1624 +msgid "" +"\n" +"The filesystem already has sparse superblocks.\n" +msgstr "" +"\n" +"Das Dateisystem hat bereits verteilte Superblöcke.\n" + +#: misc/tune2fs.c:1631 +#, c-format +msgid "" +"\n" +"Sparse superblock flag set. %s" +msgstr "" +"\n" +"Kennzeichen für verteilten Superblock gesetzt. %s" + +#: misc/tune2fs.c:1636 +msgid "" +"\n" +"Clearing the sparse superflag not supported.\n" +msgstr "" +"\n" +"Das Zurücksetzen des Kennzeichens für »verteilter Superblock« wird nicht\n" +"\tunterstützt.\n" + +#: misc/tune2fs.c:1643 +#, c-format +msgid "Setting time filesystem last checked to %s\n" +msgstr "Setze die Zeit des letzten Dateisystemchecks auf %s\n" + +#: misc/tune2fs.c:1649 +#, c-format +msgid "Setting reserved blocks uid to %lu\n" +msgstr "Setze die UID für reservierte Blöcke auf %lu\n" + +#: misc/tune2fs.c:1700 +msgid "Invalid UUID format\n" +msgstr "Ungültiges UUID Format\n" + +#: misc/tune2fs.c:1712 +msgid "The inode size may only be changed when the filesystem is unmounted.\n" +msgstr "" +"Die Grösse der Inodes kann nur geändert werden, wenn das Dateisystem\n" +"nicht eingehängt ist.\n" + +#: misc/tune2fs.c:1719 +msgid "" +"Changing the inode size not supported for filesystems with the flex_bg\n" +"feature enabled.\n" +msgstr "" + +#: misc/tune2fs.c:1731 +msgid "" +"Error in resizing the inode size.\n" +"Run e2undo to undo the file system changes. \n" +msgstr "" +"Fehler beim Verändern der Inodegrösse.\n" +"Starten Sie e2undo um die Änderungen am Dateisystem rückgängig zu machen. \n" + +#: misc/tune2fs.c:1735 +#, c-format +msgid "Setting inode size %lu\n" +msgstr "Setze Inode-Größe auf %lu\n" + +#: misc/tune2fs.c:1745 +#, c-format +msgid "Setting stride size to %d\n" +msgstr "Setze Stride-Größe auf %d\n" + +#: misc/tune2fs.c:1750 +#, c-format +msgid "Setting stripe width to %d\n" +msgstr "Setze die Stripe-Breite auf %d\n" + +#: misc/util.c:72 +msgid "Proceed anyway? (y,n) " +msgstr "Trotzdem fortsetzen? (j,n) " + +#: misc/util.c:93 +#, c-format +msgid "Could not stat %s --- %s\n" +msgstr "Status für %s konnte nicht ermittelt werden --- %s\n" + +#: misc/util.c:96 +msgid "" +"\n" +"The device apparently does not exist; did you specify it correctly?\n" +msgstr "" +"\n" +"Das Gerät existiert offensichtlich nicht; haben Sie es richtig angegeben?\n" + +#: misc/util.c:107 +#, c-format +msgid "%s is not a block special device.\n" +msgstr "%s ist kein spezielles Block-Gerät.\n" + +#: misc/util.c:136 +#, c-format +msgid "%s is entire device, not just one partition!\n" +msgstr "%s ist das ganze Gerät, nicht nur eine Partition!\n" + +#: misc/util.c:158 +msgid "mke2fs forced anyway. Hope /etc/mtab is incorrect.\n" +msgstr "mke2fs trotzdem erzwungen. Hoffentlich ist /etc/mtab ungültig.\n" + +#: misc/util.c:163 +#, c-format +msgid "will not make a %s here!\n" +msgstr "werde dort kein %s erstellen!\n" + +#: misc/util.c:170 +msgid "mke2fs forced anyway.\n" +msgstr "mke2fs wird sowieso erzwungen.\n" + +#: misc/util.c:186 +msgid "Couldn't allocate memory to parse journal options!\n" +msgstr "Konnte keinen Speicher zur Analyse der Journal-Optionen anfordern!\n" + +#: misc/util.c:228 +msgid "" +"\n" +"Bad journal options specified.\n" +"\n" +"Journal options are separated by commas, and may take an argument which\n" +"\tis set off by an equals ('=') sign.\n" +"\n" +"Valid journal options are:\n" +"\tsize=\n" +"\tdevice=\n" +"\n" +"The journal size must be between 1024 and 10240000 filesystem blocks.\n" +"\n" +msgstr "" +"\n" +"Ungültige Journal-Optionen wurden angegeben.\n" +"\n" +"Journal-Optionen werden durch Kommatas getrennt. Manche erwarten ein\n" +"\tArgument, welches mit Gleichheitszeichen (»=«) zugewiesen wird.\n" +"\n" +"Gültige Journal-Optionen sind:\n" +"\tsize=\n" +"\tdevice=\n" +"\n" +"Die Grösse des Journals muss zwischen 1024 und 10240000 Dateisystem-Blöcken\n" +"\tliegen.\n" +"\n" + +#: misc/util.c:258 +msgid "" +"\n" +"Filesystem too small for a journal\n" +msgstr "" +"\n" +"Das Dateisystem ist zu klein für ein Journal\n" + +#: misc/util.c:265 +#, c-format +msgid "" +"\n" +"The requested journal size is %d blocks; it must be\n" +"between 1024 and 10240000 blocks. Aborting.\n" +msgstr "" +"\n" +"Die angegebene Journalgröße beträgt %d Blöcke. Sie muss aber zwischen\n" +"1024 und 102400 Dateisystem-Blöcken liegen. Abbruch! \n" + +#: misc/util.c:273 +msgid "" +"\n" +"Journal size too big for filesystem.\n" +msgstr "" +"\n" +"Das Journal ist zu groß für dieses Dateisystem.\n" + +#: misc/util.c:283 +#, c-format +msgid "" +"This filesystem will be automatically checked every %d mounts or\n" +"%g days, whichever comes first. Use tune2fs -c or -i to override.\n" +msgstr "" +"Das Dateisystem wird automatisch nach jeweils %d Einhäng-Vorgängen bzw.\n" +"alle %g Tage überprüft, je nachdem, was zuerst eintritt. Dies kann durch\n" +"tune2fs -c oder -i geändert werden.\n" + +#: misc/uuidgen.c:31 +#, c-format +msgid "Usage: %s [-r] [-t]\n" +msgstr "Aufruf: %s [-r] [-t]\n" + +#: resize/extent.c:196 +msgid "# Extent dump:\n" +msgstr "# Extent dump:\n" + +#: resize/extent.c:197 +#, c-format +msgid "#\tNum=%d, Size=%d, Cursor=%d, Sorted=%d\n" +msgstr "#\tNum=%d, Size=%d, Cursor=%d, Sorted=%d\n" + +#: resize/extent.c:200 +#, c-format +msgid "#\t\t %u -> %u (%d)\n" +msgstr "#\t\t %u -> %u (%d)\n" + +#: resize/main.c:42 +#, c-format +msgid "" +"Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] [-p] device [new_size]\n" +"\n" +msgstr "" +"Aufruf: %s [-d Debug_Optionen] [-f] [-F] [-M] [-P] [-p] Gerät [neue_Größe]\n" +"\n" + +#: resize/main.c:64 +msgid "Extending the inode table" +msgstr "Vergrößere die Inode-Tabelle" + +#: resize/main.c:67 +msgid "Relocating blocks" +msgstr "Verteile die Blöcke neu" + +#: resize/main.c:70 +msgid "Scanning inode table" +msgstr "Prüfe die Inode-Tabelle" + +#: resize/main.c:73 +msgid "Updating inode references" +msgstr "Aktualisiere die Inode-Referenzen" + +#: resize/main.c:76 +msgid "Moving inode table" +msgstr "Verschiebe die Inode-Tabelle" + +#: resize/main.c:79 +msgid "Unknown pass?!?" +msgstr "Unbekannter Durchgang?!?" + +#: resize/main.c:82 +#, c-format +msgid "Begin pass %d (max = %lu)\n" +msgstr "Start von Durchgang %d (max = %lu)\n" + +#: resize/main.c:264 +#, c-format +msgid "while opening %s" +msgstr "beim Öffnen von %s" + +# c-format +#: resize/main.c:276 +#, c-format +msgid "while getting stat information for %s" +msgstr "beim Ermitteln der Statusinformation für %s" + +#: resize/main.c:337 +#, c-format +msgid "" +"%s: The combination of flex_bg and\n" +"\t!resize_inode features is not supported by resize2fs.\n" +msgstr "" +"%s: Die Kombination der Eigenschaften flex_bg und\n" +"t!resize_inode wird von resize2fs nicht unterestützt.\n" + +#: resize/main.c:345 +#, c-format +msgid "Estimated minimum size of the filesystem: %u\n" +msgstr "Geschätzte minimale Grösse des Dateisystems: %u\n" + +#: resize/main.c:381 +#, c-format +msgid "Invalid new size: %s\n" +msgstr "Unzulässige neue Größe: %s\n" + +#: resize/main.c:394 +msgid "Invalid stride length" +msgstr "Ungültige Stride-Länge" + +#: resize/main.c:418 +#, c-format +msgid "" +"The containing partition (or device) is only %u (%dk) blocks.\n" +"You requested a new size of %u blocks.\n" +"\n" +msgstr "" +"Die Partition (oder das Gerät) ist nur %u (%dk) Blöcke groß.\n" +"Die gewünschte Größe war %u Blöcke.\n" +"\n" + +#: resize/main.c:425 +#, c-format +msgid "" +"The filesystem is already %u blocks long. Nothing to do!\n" +"\n" +msgstr "" +"Das Dateisystem ist schon %u Blöcke groß. Nichts zu tun!\n" +"\n" + +#: resize/main.c:436 +#, c-format +msgid "" +"Please run 'e2fsck -f %s' first.\n" +"\n" +msgstr "" +"Bitte zuerst »e2fsck -f %s« laufen lassen.\n" +"\n" + +#: resize/main.c:447 +#, c-format +msgid "while trying to resize %s" +msgstr "beim Versuch, die Größe von %s zu ändern" + +#: resize/main.c:452 +#, c-format +msgid "" +"The filesystem on %s is now %u blocks long.\n" +"\n" +msgstr "" +"Das Dateisystem auf %s ist nun %u Blöcke groß.\n" +"\n" + +#: resize/online.c:37 +#, c-format +msgid "Filesystem at %s is mounted on %s; on-line resizing required\n" +msgstr "Das Dateisystem auf %s ist auf %s eingehängt; Online-Grössenveränderung nötig\n" + +#: resize/online.c:41 +#, c-format +msgid "On-line shrinking from %u to %u not supported.\n" +msgstr "Die Online-Verkleinerung von %u auf %u wird nicht unterstützt.\n" + +#: resize/online.c:61 +msgid "Filesystem does not support online resizing" +msgstr "Das Dateisystem unterstützt keine Online-Grössenveränderung" + +#: resize/online.c:68 +#, c-format +msgid "while trying to open mountpoint %s" +msgstr "beim Versuch, Einhängpunkt %s zu öffnen" + +#: resize/online.c:76 +msgid "Permission denied to resize filesystem" +msgstr "Zugriff verweigert für die Grössenänderung des Dateisystems" + +#: resize/online.c:79 +msgid "Kernel does not support online resizing" +msgstr "Der Kernel unterstützt die Online-Vergrösserung nicht" + +#: resize/online.c:82 +msgid "While checking for on-line resizing support" +msgstr "Beim Überprüfen, ob Online-Vergrösserung unterstützt wird" + +#: resize/online.c:111 +#, c-format +msgid "Performing an on-line resize of %s to %u (%dk) blocks.\n" +msgstr "Führe eine Online-Grössenänderung von %s auf %u (%dk) Blöcke durch.\n" + +#: resize/online.c:121 +msgid "While trying to extend the last group" +msgstr "Beim Versuch, die letzte Gruppe zu erweitern" + +#: resize/online.c:180 +#, c-format +msgid "While trying to add group #%d" +msgstr "Beim Versuch, Gruppe %d hinzu zu fügen" + +#: resize/online.c:191 +#, c-format +msgid "Filesystem at %s is mounted on %s, and on-line resizing is not supported on this system.\n" +msgstr "Dateisystem auf %s ist auf %s eingehängt und Online-Grössenänderung wird auf diesem System nicht unterstützt.\n" + +#: resize/resize2fs.c:322 +#, c-format +msgid "inodes (%llu) must be less than %u" +msgstr "Die Anzahl der Indoes (%llu) muss unter %u liegen" + +#: resize/resize2fs.c:755 +msgid "reserved blocks" +msgstr "reservierte Blöcke" + +#: resize/resize2fs.c:765 +msgid "meta-data blocks" +msgstr "Metadaten-Blöcke" + +#: resize/resize2fs.c:1703 +#, c-format +msgid "Should never happen: resize inode corrupt!\n" +msgstr "Das sollte niemals passieren: Die zu verändernde Inode ist defekt!\n" + +#~ msgid "@S doesn't have has_@j flag, but has ext3 @j %s.\n" +#~ msgstr "@S hat kein has_@j Flag, aber ein ext3 @j %s.\n" +#~ msgid "Error while deleting extent: %m\n" +#~ msgstr "Fehler während des Löschens der Erweiterung: %m\n" +#~ msgid "Recreate journal to make the filesystem ext3 again?\n" +#~ msgstr "" +#~ "Soll das Journal wiederhergestellt werden, damit das Dateisystem\n" +#~ "\twieder ext3 ist?\n" +#~ msgid "while retrying to write block bitmaps for %s" +#~ msgstr "" +#~ "während des wiederholten Versuches, Block-Bitmaps für %s zu schreiben." +#~ msgid "writing inode bitmaps" +#~ msgstr "Schreibe Inoden-Bitmaps" +#~ msgid "%s failed for %s: %s\n" +#~ msgstr "%s ist für %s gescheitert: %s\n" +#~ msgid "open" +#~ msgstr "offen" +#~ msgid "HDIO_GETGEO ioctl" +#~ msgstr "HDIO_GETGEO Ioctl" +#~ msgid "BLKGETSIZE ioctl" +#~ msgstr "BLKGETSIZE Ioctl" + diff --git a/patches/sles/11/rpm/libcom_err-compile_et_permissions.patch b/patches/sles/11/rpm/libcom_err-compile_et_permissions.patch new file mode 100644 index 0000000..528f303 --- /dev/null +++ b/patches/sles/11/rpm/libcom_err-compile_et_permissions.patch @@ -0,0 +1,13 @@ +Index: e2fsprogs-1.41.7/lib/et/compile_et.sh.in +=================================================================== +--- e2fsprogs-1.41.7.orig/lib/et/compile_et.sh.in ++++ e2fsprogs-1.41.7/lib/et/compile_et.sh.in +@@ -51,7 +51,7 @@ if test -f ${BASE}.h && cmp -s ${BASE}.h + rm -f ${BASE}.h.$$ + else + mv -f ${BASE}.h.$$ ${BASE}.h +- chmod -w ${BASE}.h ++# chmod -w ${BASE}.h + fi + $AWK -f "${DIR}/et_c.awk" "outfile=${BASE}.c.$$" "outfn=${BASE}.c" "$ROOT.et" + if test -f ${BASE}.c && cmp -s ${BASE}.c.$$ ${BASE}.c ; then diff --git a/patches/sles/11/system-blkid.patch b/patches/sles/11/system-blkid.patch new file mode 100644 index 0000000..fffe7fc --- /dev/null +++ b/patches/sles/11/system-blkid.patch @@ -0,0 +1,10 @@ +--- e2fsprogs-1.41.12/e2fsck/Makefile.in.dist ++++ e2fsprogs-1.41.12/e2fsck/Makefile.in +@@ -366,7 +366,6 @@ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \ +- $(top_srcdir)/lib/blkid/blkid.h $(top_builddir)/lib/blkid/blkid_types.h \ + $(srcdir)/problem.h $(srcdir)/lfsck.h + journal.o: $(srcdir)/journal.c $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ diff --git a/patches/sles/e2fsprogs-SLES10--m-support.patch b/patches/sles/e2fsprogs-SLES10--m-support.patch new file mode 100644 index 0000000..635eeaf --- /dev/null +++ b/patches/sles/e2fsprogs-SLES10--m-support.patch @@ -0,0 +1,43 @@ +Index: e2fsprogs/misc/fsck.8.in +=================================================================== +--- e2fsprogs.orig/misc/fsck.8.in ++++ e2fsprogs/misc/fsck.8.in +@@ -8,7 +8,7 @@ fsck \- check and repair a Linux file sy + .SH SYNOPSIS + .B fsck + [ +-.B \-sAVRTMNP ++.B \-sAVRTmMNP + ] + [ + .B \-C +@@ -233,7 +233,7 @@ a progress bar at a time. GUI front-end + .IR fd , + in which case the progress bar information will be sent to that file descriptor. + .TP +-.B \-M ++.B \-m or \-M + Do not check mounted filesystems and return an exit code of 0 + for mounted filesystems. + .TP +Index: e2fsprogs/misc/fsck.c +=================================================================== +--- e2fsprogs.orig/misc/fsck.c ++++ e2fsprogs/misc/fsck.c +@@ -1074,7 +1074,7 @@ static int check_all(NOARGS) + + static void usage(NOARGS) + { +- fputs(_("Usage: fsck [-AMNPRTV] [ -C [ fd ] ] [-t fstype] [fs-options] [filesys ...]\n"), stderr); ++ fputs(_("Usage: fsck [-AmMNPRTV] [ -C [ fd ] ] [-t fstype] [fs-options] [filesys ...]\n"), stderr); + exit(EXIT_USAGE); + } + +@@ -1196,6 +1196,7 @@ static void PRS(int argc, char *argv[]) + case 'T': + notitle++; + break; ++ case 'm': + case 'M': + ignore_mounted++; + break; diff --git a/patches/sles/libcom_err-no-init_error_table.patch b/patches/sles/libcom_err-no-init_error_table.patch new file mode 100644 index 0000000..059a142 --- /dev/null +++ b/patches/sles/libcom_err-no-init_error_table.patch @@ -0,0 +1,35 @@ +SLES upstream patch to remove init_error_table() (not thread safe). + +Index: e2fsprogs/lib/et/com_err.h +=================================================================== +--- e2fsprogs.orig/lib/et/com_err.h ++++ e2fsprogs/lib/et/com_err.h +@@ -42,7 +42,10 @@ extern void (*set_com_err_hook (void (*) + (const char *, long, const char *, va_list); + extern void (*reset_com_err_hook (void)) (const char *, long, + const char *, va_list); ++#if 0 + extern int init_error_table(const char * const *msgs, long base, int count); ++#endif ++#define init_error_table(...) PLEASE_DO_NOT_USE_init_error_table_FUNCTION + + extern errcode_t add_error_table(const struct error_table * et); + extern errcode_t remove_error_table(const struct error_table * et); +Index: e2fsprogs/lib/et/init_et.c +=================================================================== +--- e2fsprogs.orig/lib/et/init_et.c ++++ e2fsprogs/lib/et/init_et.c +@@ -16,6 +16,7 @@ + * express or implied warranty. + */ + ++#if 0 + #include + #include + #ifdef HAVE_STDLIB_H +@@ -50,3 +51,5 @@ int init_error_table(const char * const + _et_dynamic_list = &new_et->etl; + return 0; + } ++#endif ++ diff --git a/patches/sles/libcom_err-no-static-buffer.patch b/patches/sles/libcom_err-no-static-buffer.patch new file mode 100644 index 0000000..7b1f1ae --- /dev/null +++ b/patches/sles/libcom_err-no-static-buffer.patch @@ -0,0 +1,33 @@ +SLES upstream patch to remove the use of a static error buffer. + +Index: e2fsprogs/lib/et/error_message.c +=================================================================== +--- e2fsprogs.orig/lib/et/error_message.c ++++ e2fsprogs/lib/et/error_message.c +@@ -148,25 +148,7 @@ const char * error_message (errcode_t co + } + et_list_unlock(); + oops: +- strcpy (buffer, "Unknown code "); +- if (table_num) { +- strcat (buffer, error_table_name (table_num)); +- strcat (buffer, " "); +- } +- for (cp = buffer; *cp; cp++) +- ; +- if (offset >= 100) { +- *cp++ = '0' + offset / 100; +- offset %= 100; +- started++; +- } +- if (started || offset >= 10) { +- *cp++ = '0' + offset / 10; +- offset %= 10; +- } +- *cp++ = '0' + offset; +- *cp = '\0'; +- return(buffer); ++ return "Unknown code"; + } + + /*