From 7259d451c48eb883c94d3e6808b340556f69225b Mon Sep 17 00:00:00 2001 From: YZBruh Date: Wed, 2 Oct 2024 21:37:57 +0300 Subject: [PATCH] pmt: initial 2.9.1 update --- .github/workflows/build.yml | 45 +- CHANGELOG.md | 17 +- Makefile | 26 - Makefile.inc | 121 - README.md | 115 +- SETUP-DEBS.md | 24 - build/bash/check-makefiles | 37 - build/bash/clean-makefiles | 44 - build/bash/functions | 37 - build/bash/gen-header | 29 - build/bash/gen-makefiles | 66 - build/bash/vars | 33 - build/config/INS_STAT.mk | 1 - build/config/Makefile | 66 - build/config/UNINS_STAT.mk | 1 - build/config/env.mk | 10 +- build/deb/DEBIAN/control_32 | 9 - build/deb/DEBIAN/control_64 | 9 - .../data/data/com.termux/files/usr/bin/dummy | 0 .../com.termux/files/usr/share/man/man8/dummy | 0 build/deb/deb.mk | 99 - build/deb/mandoc/pmt.8.gz | Bin 1193 -> 0 bytes build/main.mk | 147 - build/mandoc/mandoc | 154 + build/others/makefile.androidmk | 64 - build/others/makefile.main | 26 - build/others/makefile.outdir | 152 - build/others/makefile.sourcedir | 182 - build/tools/clean-makefiles.mk | 31 - build/tools/gen-makefiles.mk | 31 - build/tools/save-gen-vars.mk | 26 - build/tools/update-makefiles.mk | 24 - build/util/utils.mk | 58 - build/workflow/build.config | 4 +- build/workflow/relnotes | 13 +- include/PartitionManager/Deprecates.h | 17 +- include/PartitionManager/FileSystemUtils.h | 25 + include/PartitionManager/HelpFn.h | 5 +- include/PartitionManager/PartSizeMacros.h | 26 + include/PartitionManager/PartitionManager.h | 36 +- include/PartitionManager/StringKeys.h | 23 +- include/PartitionManager/VersionFnVars.h | 10 +- include/e2fsprogs/blkid/blkidP.h | 204 + include/e2fsprogs/blkid/blkid_local.h | 110 + include/e2fsprogs/blkid/blkid_types.h | 45 + include/e2fsprogs/blkid/list.h | 184 + include/e2fsprogs/blkid/probe.h | 852 ++++ include/e2fsprogs/config.h | 678 +++ include/e2fsprogs/dirpaths.h | 10 + include/e2fsprogs/e2p/e2p.h | 92 + include/e2fsprogs/e2p/project.h | 27 + include/e2fsprogs/et/com_err.h | 68 + include/e2fsprogs/et/error_table.h | 29 + include/e2fsprogs/et/internal.h | 19 + include/e2fsprogs/ext2fs/bitops.h | 606 +++ include/e2fsprogs/ext2fs/bmap64.h | 106 + include/e2fsprogs/ext2fs/brel.h | 86 + include/e2fsprogs/ext2fs/compiler.h | 26 + include/e2fsprogs/ext2fs/crc16.c | 74 + include/e2fsprogs/ext2fs/crc16.h | 26 + include/e2fsprogs/ext2fs/crc32c_defs.h | 59 + include/e2fsprogs/ext2fs/crc32c_table.h | 1044 +++++ include/e2fsprogs/ext2fs/dosio.h | 157 + include/e2fsprogs/ext2fs/e2image.h | 37 + include/e2fsprogs/ext2fs/ext2_err.h | 201 + include/e2fsprogs/ext2fs/ext2_ext_attr.h | 73 + include/e2fsprogs/ext2fs/ext2_fs.h | 1189 +++++ include/e2fsprogs/ext2fs/ext2_io.h | 179 + include/e2fsprogs/ext2fs/ext2_types.h | 45 + include/e2fsprogs/ext2fs/ext2fs.h | 2191 +++++++++ include/e2fsprogs/ext2fs/ext2fsP.h | 210 + include/e2fsprogs/ext2fs/ext3_extents.h | 127 + include/e2fsprogs/ext2fs/ext4_acl.h | 62 + include/e2fsprogs/ext2fs/fast_commit.h | 190 + include/e2fsprogs/ext2fs/fiemap.h | 93 + include/e2fsprogs/ext2fs/hashmap.h | 42 + include/e2fsprogs/ext2fs/irel.h | 114 + include/e2fsprogs/ext2fs/jfs_compat.h | 113 + include/e2fsprogs/ext2fs/kernel-jbd.h | 456 ++ include/e2fsprogs/ext2fs/kernel-list.h | 111 + include/e2fsprogs/ext2fs/qcow2.h | 114 + include/e2fsprogs/ext2fs/rbtree.h | 183 + include/e2fsprogs/ext2fs/tdb.h | 215 + include/e2fsprogs/ext2fs/utf8data.h | 4109 ++++++++++++++++ include/e2fsprogs/ext2fs/utf8n.h | 120 + include/e2fsprogs/magic.h | 166 + include/e2fsprogs/misc/create_inode.h | 57 + include/e2fsprogs/misc/mke2fs.h | 30 + include/e2fsprogs/misc/util.h | 29 + include/e2fsprogs/support/argv_parse.h | 43 + include/e2fsprogs/support/common.h | 36 + include/e2fsprogs/support/cstring.h | 6 + include/e2fsprogs/support/devname.h | 19 + include/e2fsprogs/support/dict.h | 147 + include/e2fsprogs/support/dqblk_v2.h | 31 + include/e2fsprogs/support/nls-enable.h | 21 + include/e2fsprogs/support/plausible.h | 29 + include/e2fsprogs/support/print_fs_flags.h | 5 + include/e2fsprogs/support/prof_err.h | 49 + include/e2fsprogs/support/profile.h | 107 + include/e2fsprogs/support/profile_helpers.h | 28 + include/e2fsprogs/support/quotaio.h | 268 ++ include/e2fsprogs/support/quotaio_tree.h | 64 + include/e2fsprogs/support/quotaio_v2.h | 69 + include/e2fsprogs/support/sort_r.h | 325 ++ include/e2fsprogs/uuid/uuid.h | 103 + include/e2fsprogs/uuid/uuidP.h | 71 + include/e2fsprogs/uuid/uuid_types.h | 45 + include/e2fsprogs/uuid/uuidd.h | 54 + include/e2fsprogs/version.h | 13 + jni/Android.mk | 336 ++ .../Application.mk | 2 +- jni/Makefile | 157 - jni/{ => PartitionManager}/Debug.cpp | 0 jni/{ => PartitionManager}/GetState.cpp | 0 jni/{ => PartitionManager}/Help.cpp | 39 +- jni/{ => PartitionManager}/LanguageTools.cpp | 25 +- jni/{ => PartitionManager}/Languages.cpp | 98 +- jni/{ => PartitionManager}/ListPartitions.cpp | 71 +- .../PartitionManager.cpp | 282 +- jni/PartitionManager/PartitionTool.cpp | 92 + jni/{ => PartitionManager}/Root.cpp | 0 jni/PartitionManager/Tools.cpp | 347 ++ jni/{ => PartitionManager}/Version.cpp | 33 +- jni/PartitionTool.cpp | 52 - jni/Tools.cpp | 243 - jni/e2fsprogs/NOTICE | 849 ++++ jni/e2fsprogs/lib/blkid/cache.c | 209 + jni/e2fsprogs/lib/blkid/cache.o | Bin 0 -> 3640 bytes jni/e2fsprogs/lib/blkid/dev.c | 254 + jni/e2fsprogs/lib/blkid/dev.o | Bin 0 -> 3720 bytes jni/e2fsprogs/lib/blkid/devname.c | 561 +++ jni/e2fsprogs/lib/blkid/devname.o | Bin 0 -> 12432 bytes jni/e2fsprogs/lib/blkid/devno.c | 242 + jni/e2fsprogs/lib/blkid/devno.o | Bin 0 -> 4256 bytes jni/e2fsprogs/lib/blkid/getsize.c | 217 + jni/e2fsprogs/lib/blkid/getsize.o | Bin 0 -> 2088 bytes jni/e2fsprogs/lib/blkid/llseek.c | 147 + jni/e2fsprogs/lib/blkid/llseek.o | Bin 0 -> 1280 bytes jni/e2fsprogs/lib/blkid/probe.c | 1841 ++++++++ jni/e2fsprogs/lib/blkid/probe.o | Bin 0 -> 46912 bytes jni/e2fsprogs/lib/blkid/read.c | 494 ++ jni/e2fsprogs/lib/blkid/read.o | Bin 0 -> 6656 bytes jni/e2fsprogs/lib/blkid/resolve.c | 140 + jni/e2fsprogs/lib/blkid/resolve.o | Bin 0 -> 2464 bytes jni/e2fsprogs/lib/blkid/save.c | 213 + jni/e2fsprogs/lib/blkid/save.o | Bin 0 -> 4248 bytes jni/e2fsprogs/lib/blkid/tag.c | 471 ++ jni/e2fsprogs/lib/blkid/tag.o | Bin 0 -> 7136 bytes jni/e2fsprogs/lib/blkid/version.c | 50 + jni/e2fsprogs/lib/blkid/version.o | Bin 0 -> 2240 bytes jni/e2fsprogs/lib/e2p/crypto_mode.c | 74 + jni/e2fsprogs/lib/e2p/crypto_mode.o | Bin 0 -> 2848 bytes jni/e2fsprogs/lib/e2p/encoding.c | 118 + jni/e2fsprogs/lib/e2p/encoding.o | Bin 0 -> 3776 bytes jni/e2fsprogs/lib/e2p/errcode.c | 48 + jni/e2fsprogs/lib/e2p/errcode.o | Bin 0 -> 2608 bytes jni/e2fsprogs/lib/e2p/feature.c | 445 ++ jni/e2fsprogs/lib/e2p/feature.o | Bin 0 -> 9624 bytes jni/e2fsprogs/lib/e2p/fgetflags.c | 117 + jni/e2fsprogs/lib/e2p/fgetflags.o | Bin 0 -> 2040 bytes jni/e2fsprogs/lib/e2p/fgetproject.c | 63 + jni/e2fsprogs/lib/e2p/fgetproject.o | Bin 0 -> 1480 bytes jni/e2fsprogs/lib/e2p/fgetversion.c | 74 + jni/e2fsprogs/lib/e2p/fgetversion.o | Bin 0 -> 1520 bytes jni/e2fsprogs/lib/e2p/fsetflags.c | 118 + jni/e2fsprogs/lib/e2p/fsetflags.o | Bin 0 -> 2040 bytes jni/e2fsprogs/lib/e2p/fsetproject.c | 69 + jni/e2fsprogs/lib/e2p/fsetproject.o | Bin 0 -> 1592 bytes jni/e2fsprogs/lib/e2p/fsetversion.c | 71 + jni/e2fsprogs/lib/e2p/fsetversion.o | Bin 0 -> 1480 bytes jni/e2fsprogs/lib/e2p/getflags.c | 71 + jni/e2fsprogs/lib/e2p/getflags.o | Bin 0 -> 1368 bytes jni/e2fsprogs/lib/e2p/getversion.c | 41 + jni/e2fsprogs/lib/e2p/getversion.o | Bin 0 -> 1160 bytes jni/e2fsprogs/lib/e2p/hashstr.c | 72 + jni/e2fsprogs/lib/e2p/hashstr.o | Bin 0 -> 2768 bytes jni/e2fsprogs/lib/e2p/iod.c | 76 + jni/e2fsprogs/lib/e2p/iod.o | Bin 0 -> 1888 bytes jni/e2fsprogs/lib/e2p/ljs.c | 134 + jni/e2fsprogs/lib/e2p/ljs.o | Bin 0 -> 5248 bytes jni/e2fsprogs/lib/e2p/ls.c | 491 ++ jni/e2fsprogs/lib/e2p/ls.o | Bin 0 -> 25696 bytes jni/e2fsprogs/lib/e2p/mntopts.c | 150 + jni/e2fsprogs/lib/e2p/mntopts.o | Bin 0 -> 4896 bytes jni/e2fsprogs/lib/e2p/ostype.c | 79 + jni/e2fsprogs/lib/e2p/ostype.o | Bin 0 -> 2368 bytes jni/e2fsprogs/lib/e2p/parse_num.c | 91 + jni/e2fsprogs/lib/e2p/parse_num.o | Bin 0 -> 1712 bytes jni/e2fsprogs/lib/e2p/pe.c | 40 + jni/e2fsprogs/lib/e2p/pe.o | Bin 0 -> 1696 bytes jni/e2fsprogs/lib/e2p/percent.c | 67 + jni/e2fsprogs/lib/e2p/percent.o | Bin 0 -> 1128 bytes jni/e2fsprogs/lib/e2p/pf.c | 79 + jni/e2fsprogs/lib/e2p/pf.o | Bin 0 -> 4008 bytes jni/e2fsprogs/lib/e2p/ps.c | 32 + jni/e2fsprogs/lib/e2p/ps.o | Bin 0 -> 1560 bytes jni/e2fsprogs/lib/e2p/setflags.c | 77 + jni/e2fsprogs/lib/e2p/setflags.o | Bin 0 -> 1360 bytes jni/e2fsprogs/lib/e2p/setversion.c | 40 + jni/e2fsprogs/lib/e2p/setversion.o | Bin 0 -> 1152 bytes jni/e2fsprogs/lib/e2p/uuid.c | 85 + jni/e2fsprogs/lib/e2p/uuid.o | Bin 0 -> 2600 bytes jni/e2fsprogs/lib/et/com_err.c | 105 + jni/e2fsprogs/lib/et/com_err.o | Bin 0 -> 4112 bytes jni/e2fsprogs/lib/et/com_right.c | 120 + jni/e2fsprogs/lib/et/com_right.o | Bin 0 -> 2272 bytes jni/e2fsprogs/lib/et/error_message.c | 355 ++ jni/e2fsprogs/lib/et/error_message.o | Bin 0 -> 8968 bytes jni/e2fsprogs/lib/et/et_name.c | 43 + jni/e2fsprogs/lib/et/et_name.o | Bin 0 -> 1736 bytes jni/e2fsprogs/lib/et/init_et.c | 53 + jni/e2fsprogs/lib/et/init_et.o | Bin 0 -> 1384 bytes jni/e2fsprogs/lib/ext2fs/alloc.c | 554 +++ jni/e2fsprogs/lib/ext2fs/alloc.o | Bin 0 -> 11320 bytes jni/e2fsprogs/lib/ext2fs/alloc_sb.c | 81 + jni/e2fsprogs/lib/ext2fs/alloc_sb.o | Bin 0 -> 2064 bytes jni/e2fsprogs/lib/ext2fs/alloc_stats.c | 165 + jni/e2fsprogs/lib/ext2fs/alloc_stats.o | Bin 0 -> 6872 bytes jni/e2fsprogs/lib/ext2fs/alloc_tables.c | 278 ++ jni/e2fsprogs/lib/ext2fs/alloc_tables.o | Bin 0 -> 6544 bytes jni/e2fsprogs/lib/ext2fs/atexit.c | 116 + jni/e2fsprogs/lib/ext2fs/atexit.o | Bin 0 -> 3544 bytes jni/e2fsprogs/lib/ext2fs/badblocks.c | 328 ++ jni/e2fsprogs/lib/ext2fs/badblocks.o | Bin 0 -> 6944 bytes jni/e2fsprogs/lib/ext2fs/bb_compat.c | 64 + jni/e2fsprogs/lib/ext2fs/bb_inode.c | 270 ++ jni/e2fsprogs/lib/ext2fs/bb_inode.o | Bin 0 -> 4480 bytes jni/e2fsprogs/lib/ext2fs/bitmaps.c | 320 ++ jni/e2fsprogs/lib/ext2fs/bitmaps.o | Bin 0 -> 8600 bytes jni/e2fsprogs/lib/ext2fs/bitops.c | 148 + jni/e2fsprogs/lib/ext2fs/bitops.o | Bin 0 -> 3408 bytes jni/e2fsprogs/lib/ext2fs/blkmap64_ba.c | 492 ++ jni/e2fsprogs/lib/ext2fs/blkmap64_ba.o | Bin 0 -> 9144 bytes jni/e2fsprogs/lib/ext2fs/blkmap64_rb.c | 998 ++++ jni/e2fsprogs/lib/ext2fs/blkmap64_rb.o | Bin 0 -> 14600 bytes jni/e2fsprogs/lib/ext2fs/blknum.c | 606 +++ jni/e2fsprogs/lib/ext2fs/blknum.o | Bin 0 -> 13256 bytes jni/e2fsprogs/lib/ext2fs/block.c | 659 +++ jni/e2fsprogs/lib/ext2fs/block.o | Bin 0 -> 9904 bytes jni/e2fsprogs/lib/ext2fs/bmap.c | 499 ++ jni/e2fsprogs/lib/ext2fs/bmap.o | Bin 0 -> 8064 bytes jni/e2fsprogs/lib/ext2fs/bmove.c | 167 + jni/e2fsprogs/lib/ext2fs/brel_ma.c | 199 + jni/e2fsprogs/lib/ext2fs/check_desc.c | 104 + jni/e2fsprogs/lib/ext2fs/check_desc.o | Bin 0 -> 3328 bytes jni/e2fsprogs/lib/ext2fs/closefs.c | 521 ++ jni/e2fsprogs/lib/ext2fs/closefs.o | Bin 0 -> 8408 bytes jni/e2fsprogs/lib/ext2fs/crc16.c | 74 + jni/e2fsprogs/lib/ext2fs/crc16.o | Bin 0 -> 1864 bytes jni/e2fsprogs/lib/ext2fs/crc32c.c | 938 ++++ jni/e2fsprogs/lib/ext2fs/crc32c.o | Bin 0 -> 19256 bytes jni/e2fsprogs/lib/ext2fs/csum.c | 1011 ++++ jni/e2fsprogs/lib/ext2fs/csum.o | Bin 0 -> 17400 bytes jni/e2fsprogs/lib/ext2fs/dblist.c | 403 ++ jni/e2fsprogs/lib/ext2fs/dblist.o | Bin 0 -> 7632 bytes jni/e2fsprogs/lib/ext2fs/dblist_dir.c | 88 + jni/e2fsprogs/lib/ext2fs/dblist_dir.o | Bin 0 -> 2184 bytes jni/e2fsprogs/lib/ext2fs/digest_encode.c | 187 + jni/e2fsprogs/lib/ext2fs/digest_encode.o | Bin 0 -> 2456 bytes jni/e2fsprogs/lib/ext2fs/dir_iterate.c | 315 ++ jni/e2fsprogs/lib/ext2fs/dir_iterate.o | Bin 0 -> 5280 bytes jni/e2fsprogs/lib/ext2fs/dirblock.c | 113 + jni/e2fsprogs/lib/ext2fs/dirblock.o | Bin 0 -> 2968 bytes jni/e2fsprogs/lib/ext2fs/dirhash.c | 307 ++ jni/e2fsprogs/lib/ext2fs/dirhash.o | Bin 0 -> 5576 bytes jni/e2fsprogs/lib/ext2fs/dosio.c | 459 ++ jni/e2fsprogs/lib/ext2fs/dupfs.c | 122 + jni/e2fsprogs/lib/ext2fs/dupfs.o | Bin 0 -> 3160 bytes jni/e2fsprogs/lib/ext2fs/expanddir.c | 143 + jni/e2fsprogs/lib/ext2fs/expanddir.o | Bin 0 -> 3424 bytes jni/e2fsprogs/lib/ext2fs/ext2_err.c | 237 + jni/e2fsprogs/lib/ext2fs/ext2_err.o | Bin 0 -> 15104 bytes jni/e2fsprogs/lib/ext2fs/ext_attr.c | 1777 +++++++ jni/e2fsprogs/lib/ext2fs/ext_attr.o | Bin 0 -> 31888 bytes jni/e2fsprogs/lib/ext2fs/extent.c | 1877 ++++++++ jni/e2fsprogs/lib/ext2fs/extent.o | Bin 0 -> 23128 bytes jni/e2fsprogs/lib/ext2fs/fallocate.c | 873 ++++ jni/e2fsprogs/lib/ext2fs/fallocate.o | Bin 0 -> 13536 bytes jni/e2fsprogs/lib/ext2fs/fileio.c | 666 +++ jni/e2fsprogs/lib/ext2fs/fileio.o | Bin 0 -> 11416 bytes jni/e2fsprogs/lib/ext2fs/finddev.c | 218 + jni/e2fsprogs/lib/ext2fs/finddev.o | Bin 0 -> 3712 bytes jni/e2fsprogs/lib/ext2fs/flushb.c | 88 + jni/e2fsprogs/lib/ext2fs/flushb.o | Bin 0 -> 1488 bytes jni/e2fsprogs/lib/ext2fs/freefs.c | 108 + jni/e2fsprogs/lib/ext2fs/freefs.o | Bin 0 -> 3128 bytes jni/e2fsprogs/lib/ext2fs/gen_bitmap.c | 650 +++ jni/e2fsprogs/lib/ext2fs/gen_bitmap.o | Bin 0 -> 15608 bytes jni/e2fsprogs/lib/ext2fs/gen_bitmap64.c | 981 ++++ jni/e2fsprogs/lib/ext2fs/gen_bitmap64.o | Bin 0 -> 19520 bytes jni/e2fsprogs/lib/ext2fs/gen_crc32ctable.c | 117 + jni/e2fsprogs/lib/ext2fs/get_num_dirs.c | 50 + jni/e2fsprogs/lib/ext2fs/get_num_dirs.o | Bin 0 -> 1440 bytes jni/e2fsprogs/lib/ext2fs/get_pathname.c | 171 + jni/e2fsprogs/lib/ext2fs/get_pathname.o | Bin 0 -> 4248 bytes jni/e2fsprogs/lib/ext2fs/getsectsize.c | 151 + jni/e2fsprogs/lib/ext2fs/getsectsize.o | Bin 0 -> 2168 bytes jni/e2fsprogs/lib/ext2fs/getsize.c | 315 ++ jni/e2fsprogs/lib/ext2fs/getsize.o | Bin 0 -> 2728 bytes jni/e2fsprogs/lib/ext2fs/hashmap.c | 109 + jni/e2fsprogs/lib/ext2fs/hashmap.o | Bin 0 -> 2928 bytes jni/e2fsprogs/lib/ext2fs/i_block.c | 90 + jni/e2fsprogs/lib/ext2fs/i_block.o | Bin 0 -> 2208 bytes jni/e2fsprogs/lib/ext2fs/icount.c | 921 ++++ jni/e2fsprogs/lib/ext2fs/icount.o | Bin 0 -> 12680 bytes jni/e2fsprogs/lib/ext2fs/imager.c | 470 ++ jni/e2fsprogs/lib/ext2fs/imager.o | Bin 0 -> 7136 bytes jni/e2fsprogs/lib/ext2fs/ind_block.c | 67 + jni/e2fsprogs/lib/ext2fs/ind_block.o | Bin 0 -> 1520 bytes jni/e2fsprogs/lib/ext2fs/initialize.c | 671 +++ jni/e2fsprogs/lib/ext2fs/initialize.o | Bin 0 -> 15016 bytes jni/e2fsprogs/lib/ext2fs/inline.c | 118 + jni/e2fsprogs/lib/ext2fs/inline.o | Bin 0 -> 17072 bytes jni/e2fsprogs/lib/ext2fs/inline_data.c | 842 ++++ jni/e2fsprogs/lib/ext2fs/inline_data.o | Bin 0 -> 11056 bytes jni/e2fsprogs/lib/ext2fs/inode.c | 1122 +++++ jni/e2fsprogs/lib/ext2fs/inode.o | Bin 0 -> 18992 bytes jni/e2fsprogs/lib/ext2fs/io_manager.c | 152 + jni/e2fsprogs/lib/ext2fs/io_manager.o | Bin 0 -> 3968 bytes jni/e2fsprogs/lib/ext2fs/irel_ma.c | 377 ++ jni/e2fsprogs/lib/ext2fs/ismounted.c | 472 ++ jni/e2fsprogs/lib/ext2fs/ismounted.o | Bin 0 -> 7232 bytes jni/e2fsprogs/lib/ext2fs/link.c | 646 +++ jni/e2fsprogs/lib/ext2fs/link.o | Bin 0 -> 12520 bytes jni/e2fsprogs/lib/ext2fs/llseek.c | 145 + jni/e2fsprogs/lib/ext2fs/llseek.o | Bin 0 -> 1144 bytes jni/e2fsprogs/lib/ext2fs/lookup.c | 70 + jni/e2fsprogs/lib/ext2fs/lookup.o | Bin 0 -> 1832 bytes jni/e2fsprogs/lib/ext2fs/mkdir.c | 200 + jni/e2fsprogs/lib/ext2fs/mkdir.o | Bin 0 -> 4232 bytes jni/e2fsprogs/lib/ext2fs/mkjournal.c | 654 +++ jni/e2fsprogs/lib/ext2fs/mkjournal.o | Bin 0 -> 12760 bytes jni/e2fsprogs/lib/ext2fs/mmp.c | 488 ++ jni/e2fsprogs/lib/ext2fs/mmp.o | Bin 0 -> 7648 bytes jni/e2fsprogs/lib/ext2fs/namei.c | 227 + jni/e2fsprogs/lib/ext2fs/namei.o | Bin 0 -> 4544 bytes jni/e2fsprogs/lib/ext2fs/native.c | 28 + jni/e2fsprogs/lib/ext2fs/native.o | Bin 0 -> 952 bytes jni/e2fsprogs/lib/ext2fs/newdir.c | 126 + jni/e2fsprogs/lib/ext2fs/newdir.o | Bin 0 -> 3024 bytes jni/e2fsprogs/lib/ext2fs/nls_utf8.c | 1000 ++++ jni/e2fsprogs/lib/ext2fs/nls_utf8.o | Bin 0 -> 71832 bytes jni/e2fsprogs/lib/ext2fs/nt_io.c | 1494 ++++++ jni/e2fsprogs/lib/ext2fs/openfs.c | 590 +++ jni/e2fsprogs/lib/ext2fs/openfs.o | Bin 0 -> 11736 bytes jni/e2fsprogs/lib/ext2fs/progress.c | 103 + jni/e2fsprogs/lib/ext2fs/progress.o | Bin 0 -> 4120 bytes jni/e2fsprogs/lib/ext2fs/punch.c | 513 ++ jni/e2fsprogs/lib/ext2fs/punch.o | Bin 0 -> 7576 bytes jni/e2fsprogs/lib/ext2fs/qcow2.c | 272 ++ jni/e2fsprogs/lib/ext2fs/qcow2.h | 114 + jni/e2fsprogs/lib/ext2fs/qcow2.o | Bin 0 -> 5752 bytes jni/e2fsprogs/lib/ext2fs/rbtree.c | 383 ++ jni/e2fsprogs/lib/ext2fs/rbtree.h | 183 + jni/e2fsprogs/lib/ext2fs/rbtree.o | Bin 0 -> 5920 bytes jni/e2fsprogs/lib/ext2fs/read_bb.c | 102 + jni/e2fsprogs/lib/ext2fs/read_bb.o | Bin 0 -> 2392 bytes jni/e2fsprogs/lib/ext2fs/read_bb_file.c | 109 + jni/e2fsprogs/lib/ext2fs/read_bb_file.o | Bin 0 -> 2616 bytes jni/e2fsprogs/lib/ext2fs/res_gdt.c | 239 + jni/e2fsprogs/lib/ext2fs/res_gdt.o | Bin 0 -> 4472 bytes jni/e2fsprogs/lib/ext2fs/rw_bitmaps.c | 682 +++ jni/e2fsprogs/lib/ext2fs/rw_bitmaps.o | Bin 0 -> 15504 bytes jni/e2fsprogs/lib/ext2fs/sha256.c | 254 + jni/e2fsprogs/lib/ext2fs/sha256.o | Bin 0 -> 4392 bytes jni/e2fsprogs/lib/ext2fs/sha512.c | 302 ++ jni/e2fsprogs/lib/ext2fs/sha512.o | Bin 0 -> 7280 bytes jni/e2fsprogs/lib/ext2fs/sparse_io.c | 554 +++ jni/e2fsprogs/lib/ext2fs/sparse_io.o | Bin 0 -> 2336 bytes jni/e2fsprogs/lib/ext2fs/swapfs.c | 490 ++ jni/e2fsprogs/lib/ext2fs/swapfs.o | Bin 0 -> 13160 bytes jni/e2fsprogs/lib/ext2fs/symlink.c | 212 + jni/e2fsprogs/lib/ext2fs/symlink.o | Bin 0 -> 4632 bytes jni/e2fsprogs/lib/ext2fs/tdb.c | 4174 +++++++++++++++++ jni/e2fsprogs/lib/ext2fs/tdb.h | 215 + jni/e2fsprogs/lib/ext2fs/tdbtool.c | 621 +++ jni/e2fsprogs/lib/ext2fs/test_io.c | 557 +++ jni/e2fsprogs/lib/ext2fs/test_io.o | Bin 0 -> 16064 bytes jni/e2fsprogs/lib/ext2fs/tst_badblocks.c | 369 ++ jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c | 732 +++ jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct | 51 + jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds | 150 + jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp | 313 ++ jni/e2fsprogs/lib/ext2fs/tst_bitops.c | 288 ++ jni/e2fsprogs/lib/ext2fs/tst_byteswap.c | 93 + jni/e2fsprogs/lib/ext2fs/tst_cmds.ct | 6 + jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c | 81 + jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c | 63 + jni/e2fsprogs/lib/ext2fs/tst_getsize.c | 47 + jni/e2fsprogs/lib/ext2fs/tst_inode_size.c | 89 + jni/e2fsprogs/lib/ext2fs/tst_iscan.c | 227 + jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c | 72 + jni/e2fsprogs/lib/ext2fs/tst_super_size.c | 160 + jni/e2fsprogs/lib/ext2fs/tst_types.c | 64 + jni/e2fsprogs/lib/ext2fs/undo_io.c | 1108 +++++ jni/e2fsprogs/lib/ext2fs/undo_io.o | Bin 0 -> 18592 bytes jni/e2fsprogs/lib/ext2fs/unix_io.c | 1511 ++++++ jni/e2fsprogs/lib/ext2fs/unix_io.o | Bin 0 -> 23800 bytes jni/e2fsprogs/lib/ext2fs/unlink.c | 100 + jni/e2fsprogs/lib/ext2fs/unlink.o | Bin 0 -> 2176 bytes jni/e2fsprogs/lib/ext2fs/valid_blk.c | 68 + jni/e2fsprogs/lib/ext2fs/valid_blk.o | Bin 0 -> 1624 bytes jni/e2fsprogs/lib/ext2fs/version.c | 57 + jni/e2fsprogs/lib/ext2fs/version.o | Bin 0 -> 2264 bytes jni/e2fsprogs/lib/misc/create_inode.c | 1092 +++++ jni/e2fsprogs/lib/misc/create_inode.o | Bin 0 -> 25504 bytes jni/e2fsprogs/lib/support/devname.c | 65 + jni/e2fsprogs/lib/support/devname.o | Bin 0 -> 1936 bytes jni/e2fsprogs/lib/support/dict.c | 1542 ++++++ jni/e2fsprogs/lib/support/dict.o | Bin 0 -> 7440 bytes jni/e2fsprogs/lib/support/mkquota.c | 706 +++ jni/e2fsprogs/lib/support/mkquota.o | Bin 0 -> 14792 bytes jni/e2fsprogs/lib/support/parse_qtype.c | 90 + jni/e2fsprogs/lib/support/parse_qtype.o | Bin 0 -> 2904 bytes jni/e2fsprogs/lib/support/plausible.c | 287 ++ jni/e2fsprogs/lib/support/plausible.o | Bin 0 -> 8232 bytes jni/e2fsprogs/lib/support/prof_err.c | 85 + jni/e2fsprogs/lib/support/prof_err.o | Bin 0 -> 4416 bytes jni/e2fsprogs/lib/support/profile.c | 1910 ++++++++ jni/e2fsprogs/lib/support/profile.o | Bin 0 -> 22336 bytes jni/e2fsprogs/lib/support/profile_helpers.c | 317 ++ jni/e2fsprogs/lib/support/profile_helpers.o | Bin 0 -> 5336 bytes jni/e2fsprogs/lib/support/quotaio.c | 412 ++ jni/e2fsprogs/lib/support/quotaio.o | Bin 0 -> 13752 bytes jni/e2fsprogs/lib/support/quotaio_tree.c | 687 +++ jni/e2fsprogs/lib/support/quotaio_tree.o | Bin 0 -> 16664 bytes jni/e2fsprogs/lib/support/quotaio_v2.c | 389 ++ jni/e2fsprogs/lib/support/quotaio_v2.o | Bin 0 -> 9504 bytes jni/e2fsprogs/lib/uuid/clear.c | 44 + jni/e2fsprogs/lib/uuid/clear.o | Bin 0 -> 976 bytes jni/e2fsprogs/lib/uuid/compare.c | 56 + jni/e2fsprogs/lib/uuid/compare.o | Bin 0 -> 1456 bytes jni/e2fsprogs/lib/uuid/copy.c | 46 + jni/e2fsprogs/lib/uuid/copy.o | Bin 0 -> 1048 bytes jni/e2fsprogs/lib/uuid/gen_uuid.c | 682 +++ jni/e2fsprogs/lib/uuid/gen_uuid.o | Bin 0 -> 21304 bytes jni/e2fsprogs/lib/uuid/isnull.c | 49 + jni/e2fsprogs/lib/uuid/isnull.o | Bin 0 -> 1064 bytes jni/e2fsprogs/lib/uuid/pack.c | 70 + jni/e2fsprogs/lib/uuid/pack.o | Bin 0 -> 1232 bytes jni/e2fsprogs/lib/uuid/parse.c | 80 + jni/e2fsprogs/lib/uuid/parse.o | Bin 0 -> 2104 bytes jni/e2fsprogs/lib/uuid/unpack.c | 64 + jni/e2fsprogs/lib/uuid/unpack.o | Bin 0 -> 1296 bytes jni/e2fsprogs/lib/uuid/unparse.c | 77 + jni/e2fsprogs/lib/uuid/unparse.o | Bin 0 -> 2448 bytes jni/e2fsprogs/lib/uuid/uuid_time.c | 167 + jni/e2fsprogs/lib/uuid/uuid_time.o | Bin 0 -> 1712 bytes jni/e2fsprogs/mke2fs/default_profile.c | 47 + jni/e2fsprogs/mke2fs/default_profile.o | Bin 0 -> 1784 bytes jni/e2fsprogs/mke2fs/mk_hugefiles.c | 491 ++ jni/e2fsprogs/mke2fs/mk_hugefiles.o | Bin 0 -> 17872 bytes jni/e2fsprogs/mke2fs/mke2fs.c | 3518 ++++++++++++++ jni/e2fsprogs/mke2fs/mke2fs.o | Bin 0 -> 140008 bytes jni/e2fsprogs/mke2fs/util.c | 330 ++ jni/e2fsprogs/mke2fs/util.o | Bin 0 -> 11056 bytes out/Makefile | 152 - pmt-termux.sh | 192 +- 459 files changed, 86355 insertions(+), 2404 deletions(-) delete mode 100755 Makefile delete mode 100755 Makefile.inc delete mode 100755 SETUP-DEBS.md delete mode 100755 build/bash/check-makefiles delete mode 100755 build/bash/clean-makefiles delete mode 100755 build/bash/functions delete mode 100755 build/bash/gen-header delete mode 100755 build/bash/gen-makefiles delete mode 100755 build/bash/vars delete mode 100755 build/config/INS_STAT.mk delete mode 100755 build/config/Makefile delete mode 100755 build/config/UNINS_STAT.mk delete mode 100755 build/deb/DEBIAN/control_32 delete mode 100755 build/deb/DEBIAN/control_64 delete mode 100755 build/deb/data/data/com.termux/files/usr/bin/dummy delete mode 100755 build/deb/data/data/com.termux/files/usr/share/man/man8/dummy delete mode 100755 build/deb/deb.mk delete mode 100755 build/deb/mandoc/pmt.8.gz delete mode 100755 build/main.mk create mode 100755 build/mandoc/mandoc delete mode 100755 build/others/makefile.androidmk delete mode 100755 build/others/makefile.main delete mode 100755 build/others/makefile.outdir delete mode 100755 build/others/makefile.sourcedir delete mode 100755 build/tools/clean-makefiles.mk delete mode 100755 build/tools/gen-makefiles.mk delete mode 100755 build/tools/save-gen-vars.mk delete mode 100755 build/tools/update-makefiles.mk delete mode 100755 build/util/utils.mk create mode 100755 include/PartitionManager/FileSystemUtils.h create mode 100755 include/PartitionManager/PartSizeMacros.h create mode 100755 include/e2fsprogs/blkid/blkidP.h create mode 100755 include/e2fsprogs/blkid/blkid_local.h create mode 100755 include/e2fsprogs/blkid/blkid_types.h create mode 100755 include/e2fsprogs/blkid/list.h create mode 100755 include/e2fsprogs/blkid/probe.h create mode 100755 include/e2fsprogs/config.h create mode 100755 include/e2fsprogs/dirpaths.h create mode 100755 include/e2fsprogs/e2p/e2p.h create mode 100755 include/e2fsprogs/e2p/project.h create mode 100755 include/e2fsprogs/et/com_err.h create mode 100755 include/e2fsprogs/et/error_table.h create mode 100755 include/e2fsprogs/et/internal.h create mode 100755 include/e2fsprogs/ext2fs/bitops.h create mode 100755 include/e2fsprogs/ext2fs/bmap64.h create mode 100755 include/e2fsprogs/ext2fs/brel.h create mode 100755 include/e2fsprogs/ext2fs/compiler.h create mode 100755 include/e2fsprogs/ext2fs/crc16.c create mode 100755 include/e2fsprogs/ext2fs/crc16.h create mode 100755 include/e2fsprogs/ext2fs/crc32c_defs.h create mode 100755 include/e2fsprogs/ext2fs/crc32c_table.h create mode 100755 include/e2fsprogs/ext2fs/dosio.h create mode 100755 include/e2fsprogs/ext2fs/e2image.h create mode 100755 include/e2fsprogs/ext2fs/ext2_err.h create mode 100755 include/e2fsprogs/ext2fs/ext2_ext_attr.h create mode 100755 include/e2fsprogs/ext2fs/ext2_fs.h create mode 100755 include/e2fsprogs/ext2fs/ext2_io.h create mode 100755 include/e2fsprogs/ext2fs/ext2_types.h create mode 100755 include/e2fsprogs/ext2fs/ext2fs.h create mode 100755 include/e2fsprogs/ext2fs/ext2fsP.h create mode 100755 include/e2fsprogs/ext2fs/ext3_extents.h create mode 100755 include/e2fsprogs/ext2fs/ext4_acl.h create mode 100755 include/e2fsprogs/ext2fs/fast_commit.h create mode 100755 include/e2fsprogs/ext2fs/fiemap.h create mode 100755 include/e2fsprogs/ext2fs/hashmap.h create mode 100755 include/e2fsprogs/ext2fs/irel.h create mode 100755 include/e2fsprogs/ext2fs/jfs_compat.h create mode 100755 include/e2fsprogs/ext2fs/kernel-jbd.h create mode 100755 include/e2fsprogs/ext2fs/kernel-list.h create mode 100755 include/e2fsprogs/ext2fs/qcow2.h create mode 100755 include/e2fsprogs/ext2fs/rbtree.h create mode 100755 include/e2fsprogs/ext2fs/tdb.h create mode 100755 include/e2fsprogs/ext2fs/utf8data.h create mode 100755 include/e2fsprogs/ext2fs/utf8n.h create mode 100755 include/e2fsprogs/magic.h create mode 100755 include/e2fsprogs/misc/create_inode.h create mode 100755 include/e2fsprogs/misc/mke2fs.h create mode 100755 include/e2fsprogs/misc/util.h create mode 100755 include/e2fsprogs/support/argv_parse.h create mode 100755 include/e2fsprogs/support/common.h create mode 100755 include/e2fsprogs/support/cstring.h create mode 100755 include/e2fsprogs/support/devname.h create mode 100755 include/e2fsprogs/support/dict.h create mode 100755 include/e2fsprogs/support/dqblk_v2.h create mode 100755 include/e2fsprogs/support/nls-enable.h create mode 100755 include/e2fsprogs/support/plausible.h create mode 100755 include/e2fsprogs/support/print_fs_flags.h create mode 100755 include/e2fsprogs/support/prof_err.h create mode 100755 include/e2fsprogs/support/profile.h create mode 100755 include/e2fsprogs/support/profile_helpers.h create mode 100755 include/e2fsprogs/support/quotaio.h create mode 100755 include/e2fsprogs/support/quotaio_tree.h create mode 100755 include/e2fsprogs/support/quotaio_v2.h create mode 100755 include/e2fsprogs/support/sort_r.h create mode 100755 include/e2fsprogs/uuid/uuid.h create mode 100755 include/e2fsprogs/uuid/uuidP.h create mode 100755 include/e2fsprogs/uuid/uuid_types.h create mode 100755 include/e2fsprogs/uuid/uuidd.h create mode 100755 include/e2fsprogs/version.h create mode 100755 jni/Android.mk rename build/others/makefile.applicationmk => jni/Application.mk (98%) delete mode 100755 jni/Makefile rename jni/{ => PartitionManager}/Debug.cpp (100%) rename jni/{ => PartitionManager}/GetState.cpp (100%) rename jni/{ => PartitionManager}/Help.cpp (68%) rename jni/{ => PartitionManager}/LanguageTools.cpp (83%) rename jni/{ => PartitionManager}/Languages.cpp (69%) rename jni/{ => PartitionManager}/ListPartitions.cpp (53%) rename jni/{ => PartitionManager}/PartitionManager.cpp (69%) create mode 100755 jni/PartitionManager/PartitionTool.cpp rename jni/{ => PartitionManager}/Root.cpp (100%) create mode 100755 jni/PartitionManager/Tools.cpp rename jni/{ => PartitionManager}/Version.cpp (61%) delete mode 100755 jni/PartitionTool.cpp delete mode 100755 jni/Tools.cpp create mode 100755 jni/e2fsprogs/NOTICE create mode 100755 jni/e2fsprogs/lib/blkid/cache.c create mode 100755 jni/e2fsprogs/lib/blkid/cache.o create mode 100755 jni/e2fsprogs/lib/blkid/dev.c create mode 100755 jni/e2fsprogs/lib/blkid/dev.o create mode 100755 jni/e2fsprogs/lib/blkid/devname.c create mode 100755 jni/e2fsprogs/lib/blkid/devname.o create mode 100755 jni/e2fsprogs/lib/blkid/devno.c create mode 100755 jni/e2fsprogs/lib/blkid/devno.o create mode 100755 jni/e2fsprogs/lib/blkid/getsize.c create mode 100755 jni/e2fsprogs/lib/blkid/getsize.o create mode 100755 jni/e2fsprogs/lib/blkid/llseek.c create mode 100755 jni/e2fsprogs/lib/blkid/llseek.o create mode 100755 jni/e2fsprogs/lib/blkid/probe.c create mode 100755 jni/e2fsprogs/lib/blkid/probe.o create mode 100755 jni/e2fsprogs/lib/blkid/read.c create mode 100755 jni/e2fsprogs/lib/blkid/read.o create mode 100755 jni/e2fsprogs/lib/blkid/resolve.c create mode 100755 jni/e2fsprogs/lib/blkid/resolve.o create mode 100755 jni/e2fsprogs/lib/blkid/save.c create mode 100755 jni/e2fsprogs/lib/blkid/save.o create mode 100755 jni/e2fsprogs/lib/blkid/tag.c create mode 100755 jni/e2fsprogs/lib/blkid/tag.o create mode 100755 jni/e2fsprogs/lib/blkid/version.c create mode 100755 jni/e2fsprogs/lib/blkid/version.o create mode 100755 jni/e2fsprogs/lib/e2p/crypto_mode.c create mode 100755 jni/e2fsprogs/lib/e2p/crypto_mode.o create mode 100755 jni/e2fsprogs/lib/e2p/encoding.c create mode 100755 jni/e2fsprogs/lib/e2p/encoding.o create mode 100755 jni/e2fsprogs/lib/e2p/errcode.c create mode 100755 jni/e2fsprogs/lib/e2p/errcode.o create mode 100755 jni/e2fsprogs/lib/e2p/feature.c create mode 100755 jni/e2fsprogs/lib/e2p/feature.o create mode 100755 jni/e2fsprogs/lib/e2p/fgetflags.c create mode 100755 jni/e2fsprogs/lib/e2p/fgetflags.o create mode 100755 jni/e2fsprogs/lib/e2p/fgetproject.c create mode 100755 jni/e2fsprogs/lib/e2p/fgetproject.o create mode 100755 jni/e2fsprogs/lib/e2p/fgetversion.c create mode 100755 jni/e2fsprogs/lib/e2p/fgetversion.o create mode 100755 jni/e2fsprogs/lib/e2p/fsetflags.c create mode 100755 jni/e2fsprogs/lib/e2p/fsetflags.o create mode 100755 jni/e2fsprogs/lib/e2p/fsetproject.c create mode 100755 jni/e2fsprogs/lib/e2p/fsetproject.o create mode 100755 jni/e2fsprogs/lib/e2p/fsetversion.c create mode 100755 jni/e2fsprogs/lib/e2p/fsetversion.o create mode 100755 jni/e2fsprogs/lib/e2p/getflags.c create mode 100755 jni/e2fsprogs/lib/e2p/getflags.o create mode 100755 jni/e2fsprogs/lib/e2p/getversion.c create mode 100755 jni/e2fsprogs/lib/e2p/getversion.o create mode 100755 jni/e2fsprogs/lib/e2p/hashstr.c create mode 100755 jni/e2fsprogs/lib/e2p/hashstr.o create mode 100755 jni/e2fsprogs/lib/e2p/iod.c create mode 100755 jni/e2fsprogs/lib/e2p/iod.o create mode 100755 jni/e2fsprogs/lib/e2p/ljs.c create mode 100755 jni/e2fsprogs/lib/e2p/ljs.o create mode 100755 jni/e2fsprogs/lib/e2p/ls.c create mode 100755 jni/e2fsprogs/lib/e2p/ls.o create mode 100755 jni/e2fsprogs/lib/e2p/mntopts.c create mode 100755 jni/e2fsprogs/lib/e2p/mntopts.o create mode 100755 jni/e2fsprogs/lib/e2p/ostype.c create mode 100755 jni/e2fsprogs/lib/e2p/ostype.o create mode 100755 jni/e2fsprogs/lib/e2p/parse_num.c create mode 100755 jni/e2fsprogs/lib/e2p/parse_num.o create mode 100755 jni/e2fsprogs/lib/e2p/pe.c create mode 100755 jni/e2fsprogs/lib/e2p/pe.o create mode 100755 jni/e2fsprogs/lib/e2p/percent.c create mode 100755 jni/e2fsprogs/lib/e2p/percent.o create mode 100755 jni/e2fsprogs/lib/e2p/pf.c create mode 100755 jni/e2fsprogs/lib/e2p/pf.o create mode 100755 jni/e2fsprogs/lib/e2p/ps.c create mode 100755 jni/e2fsprogs/lib/e2p/ps.o create mode 100755 jni/e2fsprogs/lib/e2p/setflags.c create mode 100755 jni/e2fsprogs/lib/e2p/setflags.o create mode 100755 jni/e2fsprogs/lib/e2p/setversion.c create mode 100755 jni/e2fsprogs/lib/e2p/setversion.o create mode 100755 jni/e2fsprogs/lib/e2p/uuid.c create mode 100755 jni/e2fsprogs/lib/e2p/uuid.o create mode 100755 jni/e2fsprogs/lib/et/com_err.c create mode 100755 jni/e2fsprogs/lib/et/com_err.o create mode 100755 jni/e2fsprogs/lib/et/com_right.c create mode 100755 jni/e2fsprogs/lib/et/com_right.o create mode 100755 jni/e2fsprogs/lib/et/error_message.c create mode 100755 jni/e2fsprogs/lib/et/error_message.o create mode 100755 jni/e2fsprogs/lib/et/et_name.c create mode 100755 jni/e2fsprogs/lib/et/et_name.o create mode 100755 jni/e2fsprogs/lib/et/init_et.c create mode 100755 jni/e2fsprogs/lib/et/init_et.o create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc.c create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc.o create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_sb.c create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_sb.o create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_stats.c create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_stats.o create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_tables.c create mode 100755 jni/e2fsprogs/lib/ext2fs/alloc_tables.o create mode 100755 jni/e2fsprogs/lib/ext2fs/atexit.c create mode 100755 jni/e2fsprogs/lib/ext2fs/atexit.o create mode 100755 jni/e2fsprogs/lib/ext2fs/badblocks.c create mode 100755 jni/e2fsprogs/lib/ext2fs/badblocks.o create mode 100755 jni/e2fsprogs/lib/ext2fs/bb_compat.c create mode 100755 jni/e2fsprogs/lib/ext2fs/bb_inode.c create mode 100755 jni/e2fsprogs/lib/ext2fs/bb_inode.o create mode 100755 jni/e2fsprogs/lib/ext2fs/bitmaps.c create mode 100755 jni/e2fsprogs/lib/ext2fs/bitmaps.o create mode 100755 jni/e2fsprogs/lib/ext2fs/bitops.c create mode 100755 jni/e2fsprogs/lib/ext2fs/bitops.o create mode 100755 jni/e2fsprogs/lib/ext2fs/blkmap64_ba.c create mode 100755 jni/e2fsprogs/lib/ext2fs/blkmap64_ba.o create mode 100755 jni/e2fsprogs/lib/ext2fs/blkmap64_rb.c create mode 100755 jni/e2fsprogs/lib/ext2fs/blkmap64_rb.o create mode 100755 jni/e2fsprogs/lib/ext2fs/blknum.c create mode 100755 jni/e2fsprogs/lib/ext2fs/blknum.o create mode 100755 jni/e2fsprogs/lib/ext2fs/block.c create mode 100755 jni/e2fsprogs/lib/ext2fs/block.o create mode 100755 jni/e2fsprogs/lib/ext2fs/bmap.c create mode 100755 jni/e2fsprogs/lib/ext2fs/bmap.o create mode 100755 jni/e2fsprogs/lib/ext2fs/bmove.c create mode 100755 jni/e2fsprogs/lib/ext2fs/brel_ma.c create mode 100755 jni/e2fsprogs/lib/ext2fs/check_desc.c create mode 100755 jni/e2fsprogs/lib/ext2fs/check_desc.o create mode 100755 jni/e2fsprogs/lib/ext2fs/closefs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/closefs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/crc16.c create mode 100755 jni/e2fsprogs/lib/ext2fs/crc16.o create mode 100755 jni/e2fsprogs/lib/ext2fs/crc32c.c create mode 100755 jni/e2fsprogs/lib/ext2fs/crc32c.o create mode 100755 jni/e2fsprogs/lib/ext2fs/csum.c create mode 100755 jni/e2fsprogs/lib/ext2fs/csum.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dblist.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dblist.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dblist_dir.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dblist_dir.o create mode 100755 jni/e2fsprogs/lib/ext2fs/digest_encode.c create mode 100755 jni/e2fsprogs/lib/ext2fs/digest_encode.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dir_iterate.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dir_iterate.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dirblock.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dirblock.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dirhash.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dirhash.o create mode 100755 jni/e2fsprogs/lib/ext2fs/dosio.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dupfs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/dupfs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/expanddir.c create mode 100755 jni/e2fsprogs/lib/ext2fs/expanddir.o create mode 100755 jni/e2fsprogs/lib/ext2fs/ext2_err.c create mode 100755 jni/e2fsprogs/lib/ext2fs/ext2_err.o create mode 100755 jni/e2fsprogs/lib/ext2fs/ext_attr.c create mode 100755 jni/e2fsprogs/lib/ext2fs/ext_attr.o create mode 100755 jni/e2fsprogs/lib/ext2fs/extent.c create mode 100755 jni/e2fsprogs/lib/ext2fs/extent.o create mode 100755 jni/e2fsprogs/lib/ext2fs/fallocate.c create mode 100755 jni/e2fsprogs/lib/ext2fs/fallocate.o create mode 100755 jni/e2fsprogs/lib/ext2fs/fileio.c create mode 100755 jni/e2fsprogs/lib/ext2fs/fileio.o create mode 100755 jni/e2fsprogs/lib/ext2fs/finddev.c create mode 100755 jni/e2fsprogs/lib/ext2fs/finddev.o create mode 100755 jni/e2fsprogs/lib/ext2fs/flushb.c create mode 100755 jni/e2fsprogs/lib/ext2fs/flushb.o create mode 100755 jni/e2fsprogs/lib/ext2fs/freefs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/freefs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/gen_bitmap.c create mode 100755 jni/e2fsprogs/lib/ext2fs/gen_bitmap.o create mode 100755 jni/e2fsprogs/lib/ext2fs/gen_bitmap64.c create mode 100755 jni/e2fsprogs/lib/ext2fs/gen_bitmap64.o create mode 100755 jni/e2fsprogs/lib/ext2fs/gen_crc32ctable.c create mode 100755 jni/e2fsprogs/lib/ext2fs/get_num_dirs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/get_num_dirs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/get_pathname.c create mode 100755 jni/e2fsprogs/lib/ext2fs/get_pathname.o create mode 100755 jni/e2fsprogs/lib/ext2fs/getsectsize.c create mode 100755 jni/e2fsprogs/lib/ext2fs/getsectsize.o create mode 100755 jni/e2fsprogs/lib/ext2fs/getsize.c create mode 100755 jni/e2fsprogs/lib/ext2fs/getsize.o create mode 100755 jni/e2fsprogs/lib/ext2fs/hashmap.c create mode 100755 jni/e2fsprogs/lib/ext2fs/hashmap.o create mode 100755 jni/e2fsprogs/lib/ext2fs/i_block.c create mode 100755 jni/e2fsprogs/lib/ext2fs/i_block.o create mode 100755 jni/e2fsprogs/lib/ext2fs/icount.c create mode 100755 jni/e2fsprogs/lib/ext2fs/icount.o create mode 100755 jni/e2fsprogs/lib/ext2fs/imager.c create mode 100755 jni/e2fsprogs/lib/ext2fs/imager.o create mode 100755 jni/e2fsprogs/lib/ext2fs/ind_block.c create mode 100755 jni/e2fsprogs/lib/ext2fs/ind_block.o create mode 100755 jni/e2fsprogs/lib/ext2fs/initialize.c create mode 100755 jni/e2fsprogs/lib/ext2fs/initialize.o create mode 100755 jni/e2fsprogs/lib/ext2fs/inline.c create mode 100755 jni/e2fsprogs/lib/ext2fs/inline.o create mode 100755 jni/e2fsprogs/lib/ext2fs/inline_data.c create mode 100755 jni/e2fsprogs/lib/ext2fs/inline_data.o create mode 100755 jni/e2fsprogs/lib/ext2fs/inode.c create mode 100755 jni/e2fsprogs/lib/ext2fs/inode.o create mode 100755 jni/e2fsprogs/lib/ext2fs/io_manager.c create mode 100755 jni/e2fsprogs/lib/ext2fs/io_manager.o create mode 100755 jni/e2fsprogs/lib/ext2fs/irel_ma.c create mode 100755 jni/e2fsprogs/lib/ext2fs/ismounted.c create mode 100755 jni/e2fsprogs/lib/ext2fs/ismounted.o create mode 100755 jni/e2fsprogs/lib/ext2fs/link.c create mode 100755 jni/e2fsprogs/lib/ext2fs/link.o create mode 100755 jni/e2fsprogs/lib/ext2fs/llseek.c create mode 100755 jni/e2fsprogs/lib/ext2fs/llseek.o create mode 100755 jni/e2fsprogs/lib/ext2fs/lookup.c create mode 100755 jni/e2fsprogs/lib/ext2fs/lookup.o create mode 100755 jni/e2fsprogs/lib/ext2fs/mkdir.c create mode 100755 jni/e2fsprogs/lib/ext2fs/mkdir.o create mode 100755 jni/e2fsprogs/lib/ext2fs/mkjournal.c create mode 100755 jni/e2fsprogs/lib/ext2fs/mkjournal.o create mode 100755 jni/e2fsprogs/lib/ext2fs/mmp.c create mode 100755 jni/e2fsprogs/lib/ext2fs/mmp.o create mode 100755 jni/e2fsprogs/lib/ext2fs/namei.c create mode 100755 jni/e2fsprogs/lib/ext2fs/namei.o create mode 100755 jni/e2fsprogs/lib/ext2fs/native.c create mode 100755 jni/e2fsprogs/lib/ext2fs/native.o create mode 100755 jni/e2fsprogs/lib/ext2fs/newdir.c create mode 100755 jni/e2fsprogs/lib/ext2fs/newdir.o create mode 100755 jni/e2fsprogs/lib/ext2fs/nls_utf8.c create mode 100755 jni/e2fsprogs/lib/ext2fs/nls_utf8.o create mode 100755 jni/e2fsprogs/lib/ext2fs/nt_io.c create mode 100755 jni/e2fsprogs/lib/ext2fs/openfs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/openfs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/progress.c create mode 100755 jni/e2fsprogs/lib/ext2fs/progress.o create mode 100755 jni/e2fsprogs/lib/ext2fs/punch.c create mode 100755 jni/e2fsprogs/lib/ext2fs/punch.o create mode 100755 jni/e2fsprogs/lib/ext2fs/qcow2.c create mode 100755 jni/e2fsprogs/lib/ext2fs/qcow2.h create mode 100755 jni/e2fsprogs/lib/ext2fs/qcow2.o create mode 100755 jni/e2fsprogs/lib/ext2fs/rbtree.c create mode 100755 jni/e2fsprogs/lib/ext2fs/rbtree.h create mode 100755 jni/e2fsprogs/lib/ext2fs/rbtree.o create mode 100755 jni/e2fsprogs/lib/ext2fs/read_bb.c create mode 100755 jni/e2fsprogs/lib/ext2fs/read_bb.o create mode 100755 jni/e2fsprogs/lib/ext2fs/read_bb_file.c create mode 100755 jni/e2fsprogs/lib/ext2fs/read_bb_file.o create mode 100755 jni/e2fsprogs/lib/ext2fs/res_gdt.c create mode 100755 jni/e2fsprogs/lib/ext2fs/res_gdt.o create mode 100755 jni/e2fsprogs/lib/ext2fs/rw_bitmaps.c create mode 100755 jni/e2fsprogs/lib/ext2fs/rw_bitmaps.o create mode 100755 jni/e2fsprogs/lib/ext2fs/sha256.c create mode 100755 jni/e2fsprogs/lib/ext2fs/sha256.o create mode 100755 jni/e2fsprogs/lib/ext2fs/sha512.c create mode 100755 jni/e2fsprogs/lib/ext2fs/sha512.o create mode 100755 jni/e2fsprogs/lib/ext2fs/sparse_io.c create mode 100755 jni/e2fsprogs/lib/ext2fs/sparse_io.o create mode 100755 jni/e2fsprogs/lib/ext2fs/swapfs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/swapfs.o create mode 100755 jni/e2fsprogs/lib/ext2fs/symlink.c create mode 100755 jni/e2fsprogs/lib/ext2fs/symlink.o create mode 100755 jni/e2fsprogs/lib/ext2fs/tdb.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tdb.h create mode 100755 jni/e2fsprogs/lib/ext2fs/tdbtool.c create mode 100755 jni/e2fsprogs/lib/ext2fs/test_io.c create mode 100755 jni/e2fsprogs/lib/ext2fs/test_io.o create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_badblocks.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_bitops.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_byteswap.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_cmds.ct create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_getsize.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_inode_size.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_iscan.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_super_size.c create mode 100755 jni/e2fsprogs/lib/ext2fs/tst_types.c create mode 100755 jni/e2fsprogs/lib/ext2fs/undo_io.c create mode 100755 jni/e2fsprogs/lib/ext2fs/undo_io.o create mode 100755 jni/e2fsprogs/lib/ext2fs/unix_io.c create mode 100755 jni/e2fsprogs/lib/ext2fs/unix_io.o create mode 100755 jni/e2fsprogs/lib/ext2fs/unlink.c create mode 100755 jni/e2fsprogs/lib/ext2fs/unlink.o create mode 100755 jni/e2fsprogs/lib/ext2fs/valid_blk.c create mode 100755 jni/e2fsprogs/lib/ext2fs/valid_blk.o create mode 100755 jni/e2fsprogs/lib/ext2fs/version.c create mode 100755 jni/e2fsprogs/lib/ext2fs/version.o create mode 100755 jni/e2fsprogs/lib/misc/create_inode.c create mode 100755 jni/e2fsprogs/lib/misc/create_inode.o create mode 100755 jni/e2fsprogs/lib/support/devname.c create mode 100755 jni/e2fsprogs/lib/support/devname.o create mode 100755 jni/e2fsprogs/lib/support/dict.c create mode 100755 jni/e2fsprogs/lib/support/dict.o create mode 100755 jni/e2fsprogs/lib/support/mkquota.c create mode 100755 jni/e2fsprogs/lib/support/mkquota.o create mode 100755 jni/e2fsprogs/lib/support/parse_qtype.c create mode 100755 jni/e2fsprogs/lib/support/parse_qtype.o create mode 100755 jni/e2fsprogs/lib/support/plausible.c create mode 100755 jni/e2fsprogs/lib/support/plausible.o create mode 100755 jni/e2fsprogs/lib/support/prof_err.c create mode 100755 jni/e2fsprogs/lib/support/prof_err.o create mode 100755 jni/e2fsprogs/lib/support/profile.c create mode 100755 jni/e2fsprogs/lib/support/profile.o create mode 100755 jni/e2fsprogs/lib/support/profile_helpers.c create mode 100755 jni/e2fsprogs/lib/support/profile_helpers.o create mode 100755 jni/e2fsprogs/lib/support/quotaio.c create mode 100755 jni/e2fsprogs/lib/support/quotaio.o create mode 100755 jni/e2fsprogs/lib/support/quotaio_tree.c create mode 100755 jni/e2fsprogs/lib/support/quotaio_tree.o create mode 100755 jni/e2fsprogs/lib/support/quotaio_v2.c create mode 100755 jni/e2fsprogs/lib/support/quotaio_v2.o create mode 100755 jni/e2fsprogs/lib/uuid/clear.c create mode 100755 jni/e2fsprogs/lib/uuid/clear.o create mode 100755 jni/e2fsprogs/lib/uuid/compare.c create mode 100755 jni/e2fsprogs/lib/uuid/compare.o create mode 100755 jni/e2fsprogs/lib/uuid/copy.c create mode 100755 jni/e2fsprogs/lib/uuid/copy.o create mode 100755 jni/e2fsprogs/lib/uuid/gen_uuid.c create mode 100755 jni/e2fsprogs/lib/uuid/gen_uuid.o create mode 100755 jni/e2fsprogs/lib/uuid/isnull.c create mode 100755 jni/e2fsprogs/lib/uuid/isnull.o create mode 100755 jni/e2fsprogs/lib/uuid/pack.c create mode 100755 jni/e2fsprogs/lib/uuid/pack.o create mode 100755 jni/e2fsprogs/lib/uuid/parse.c create mode 100755 jni/e2fsprogs/lib/uuid/parse.o create mode 100755 jni/e2fsprogs/lib/uuid/unpack.c create mode 100755 jni/e2fsprogs/lib/uuid/unpack.o create mode 100755 jni/e2fsprogs/lib/uuid/unparse.c create mode 100755 jni/e2fsprogs/lib/uuid/unparse.o create mode 100755 jni/e2fsprogs/lib/uuid/uuid_time.c create mode 100755 jni/e2fsprogs/lib/uuid/uuid_time.o create mode 100755 jni/e2fsprogs/mke2fs/default_profile.c create mode 100755 jni/e2fsprogs/mke2fs/default_profile.o create mode 100755 jni/e2fsprogs/mke2fs/mk_hugefiles.c create mode 100755 jni/e2fsprogs/mke2fs/mk_hugefiles.o create mode 100755 jni/e2fsprogs/mke2fs/mke2fs.c create mode 100755 jni/e2fsprogs/mke2fs/mke2fs.o create mode 100755 jni/e2fsprogs/mke2fs/util.c create mode 100755 jni/e2fsprogs/mke2fs/util.o delete mode 100755 out/Makefile diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f104d2e..261a5a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,22 +15,16 @@ jobs: id: cleanup uses: rokibhasansagar/slimhub_actions@main - - name: Setup GitHub CLI - id: setup-gh + - name: Update and setup packages + id: general-packages-progress run: | type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y) curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ && sudo apt update \ - && sudo apt install gh -y - - - name: Update and setup packages - id: general-packages-progress - run: | - sudo apt update \ && sudo apt upgrade -y \ - && sudo apt install make xz-utils aria2 gawk -y + && sudo apt install make xz-utils aria2 gawk gh -y - name: Save spefic version variables id: save-vars @@ -46,7 +40,6 @@ jobs: sudo chmod -R 777 pmt echo "PMT_SRCDIR=/home/pmt" >> $GITHUB_ENV echo "NDK_DIR=/home/ndk/android-ndk" >> $GITHUB_ENV - echo "NDK_IN_DIR=/home/ndk" >> $GITHUB_ENV sudo mkdir -p "/home/ndk" && cd "/home/ndk" && sudo chmod 777 "/home/ndk" - name: Setup Android NDK @@ -65,9 +58,6 @@ jobs: run: | make gen-ndk-makefiles export NDK_PROJECT_PATH=${PWD} - export NDK_ROOT_DIR=${{ env.NDK_DIR }} - echo "NDK_ROOT_DIR=${NDK_ROOT_DIR}" >> $GITHUB_ENV - bash build/bash/gen-header cd ${{ env.NDK_DIR }} ./ndk-build working-directory: ${{ env.PMT_SRCDIR }} @@ -75,23 +65,19 @@ jobs: - name: Last small transactions id: small-transactions run: | - curdate="$(date +%Y%m%d)" - export CC_64="${{ env.NDK_DIR }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" - export CC_VERSION=$(${CC_64} --version | head -n 1) - . build/workflow/build.config - . build/workflow/relnotes > /home/pmt/release_body.txt + export CXX_VERSION=$(${CXX_64} --version | head -n 1) + echo "CXX_VERSION=${CXX_VERSION}" >> $GITHUB_ENV + . ${{ env.PMT_SRCDIR }}/build/workflow/build.config + . ${{ env.PMT_SRCDIR }}/build/workflow/relnotes > /home/pmt/release_body.txt + cd ${{ env.PMT_SRCDIR }} zip -rq pmt-objs-local.zip obj/local/arm64-v8a obj/local/armeabi-v7a - for arch in arm64-v8a armeabi-v7a; do - mkdir -p out/binary - mv libs/${arch}/pmt out/binary - [[ "${arch}" == "arm64-v8a" ]] && make deb FOR_THIS=64 - [[ "${arch}" == "armeabi-v7a" ]] && make deb FOR_THIS=32 - mv out/debpackage/*.deb ${PWD} - rm -rf out/debpackage - xz out/binary/pmt - mv out/binary/pmt.xz ${PWD}/pmt-${arch}-${curdate}.xz - done - working-directory: ${{ env.PMT_SRCDIR }} + xz libs/arm64-v8a/pmt + xz libs/armeabi-v7a/pmt + mv libs/arm64-v8a/pmt.xz ${PWD}/pmt-arm64-v8a-$(date +%Y%m%d).xz + mv libs/armeabi-v7a/pmt.xz ${PWD}/pmt-armeabi-v7a-$(date +%Y%m%d).xz + cp build/mandoc/mandoc pmt.8 + gzip -c pmt.8 > mandoc.gz + working-directory: ${{ env.NDK_DIR }} - name: Upload to release id: upload-to-rels @@ -101,6 +87,7 @@ jobs: /home/pmt/pmt*.xz /home/pmt/pmt*.deb /home/pmt/pmt-objs-local.zip + /home/pmt/mandoc.gz name: Partition Manager ${{ env.PMT_VERSION }} Release tag_name: ${{ env.PMT_VERSION }} body_path: /home/pmt/release_body.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e186f6..e5ec2f4 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,11 @@ -### Version 2.8.0 Changelog +### Version 2.9.0 Changelog - - Base switched to C++ - - Static libraries deprecated - - A certain size-change replacement failure problem has been fixed - - Flash problem corrected in sizes under 1KB - - Unrelated ones were filtered while logical sections list - - Some memory leaks were fixed - - More properly code + - All dependencies related to e2fsprogs were added into pmt for built-in mke2fs + - Partition size displaying feature added + - Make compilation system deprecated, only Android NDK can be used - Some small fixes - - Some tiny additions - - Writed script for managing binary + - Some minor changes on compilation system ``` -END OF 2.8.0 UPDATE CHANGELOG +END OF 2.9.0 UPDATE CHANGELOG ``` diff --git a/Makefile b/Makefile deleted file mode 100755 index af3eb70..0000000 --- a/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -THIS_IS = main -NDK_PROG ?= false -FORCE_GEN ?= false - -# include needed variables -include Makefile.inc -include $(TOOLS)/gen-makefiles.mk -include $(TOOLS)/clean-makefiles.mk - -include $(BUILD)/main.mk \ No newline at end of file diff --git a/Makefile.inc b/Makefile.inc deleted file mode 100755 index 7b9d8ec..0000000 --- a/Makefile.inc +++ /dev/null @@ -1,121 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# speficy -VERSION := 2.8.0 -VERSION_CODE := 280 -TARGET := pmt - -# device arch info -ARCH := $(shell uname -m) - -# current directory -OUT_DIRNAME ?= out -SOURCE_DIRNAME ?= jni - -# others needed important variables -ifeq ($(THIS_IS),src) - BUILD := ../build - SOURCE_DIR := $(CURDIR) - OUT_DIR := ../$(OUT_DIRNAME) - DEBUTILS_DIR := $(BUILD)/deb -else ifeq ($(THIS_IS),debutils) - BUILD := .. - SOURCE_DIR := ../../$(SOURCE_DIRNAME) - OUT_DIR := ../../$(OUT_DIRNAME) - DEBUTILS_DIR := $(BUILD)/deb -else ifeq ($(THIS_IS),out) - BUILD := ../build - SOURCE_DIR := ../$(SOURCE_DIRNAME) - OUT_DIR := $(CURDIR) - DEBUTILS_DIR := $(BÜILD)/deb -else ifeq ($(THIS_IS),main) - BUILD := $(CURDIR)/build - SOURCE_DIR := $(CURDIR)/$(SOURCE_DIRNAME) - OUT_DIR := $(CURDIR)/$(OUT_DIRNAME) - DEBUTILS_DIR := $(BUILD)/deb -endif - -BINARY_DIR := $(OUT_DIR)/binary -PACKAGE_DIR := $(OUT_DIR)/package -DEB_DIR := $(OUT_DIR)/debpackage -TOOLS := $(BUILD)/tools -UTILS := $(BUILD)/util -BASH_DIR := $(BUILD)/bash -OTHERS := $(BUILD)/others -TERMUX_USR := /data/data/com.termux/files/usr -TERMUX_BIN := $(TERMUX_USR)/bin -LINUX_BIN := /usr/bin -DEBTERMUX_USR := $(DEBUTILS_DIR)/template$(TERMUX_USR) - -ifneq ($(wildcard $(LINUX_BIN)),) - BIN := $(LINUX_BIN) -else - BIN := $(TERMUX_BIN) -endif - -include $(UTILS)/utils.mk - -ifneq ($(shell basename $(SOURCE_DIR)),$(SOURCE_DIRNAME)) - $(error The index name specified with the current source directory name is not the same! Something's wrong) -endif - -ifneq ($(shell basename $(OUT_DIR)),$(OUT_DIRNAME)) - $(error The index name specified with the current output directory name is not the same! Something's wrong) -endif - -# sources -SRCS := $(wildcard $(SOURCE_DIR)/*.cpp) -OBJS = $(SRCS:.cpp=.o) - -# other directories in the out directory -IN_OUT_DIR := \ - $(BINARY_DIR) \ - $(PACKAGE_DIR) \ - $(STATICLIB_DIR) - -# list of file/directory to be checked when the deb pack is created -DEB_CHECKS := \ - $(DEBUTILS_DIR)/ \ - $(DEBUTILS_DIR)/DEBIAN \ - $(DEBUTILS_DIR)/DEBIAN/control_32 \ - $(DEBUTILS_DIR)/DEBIAN/control_64 \ - $(DEBUTILS_DIR)/mandoc \ - $(DEBUTILS_DIR)/mandoc/$(TARGET).8.gz \ - $(DEBUTILS_DIR)/data \ - $(DEBUTILS_DIR)/data/data \ - $(DEBUTILS_DIR)/data/data/com.termux \ - $(DEBUTILS_DIR)/data/data/com.termux/files \ - $(DEBUTILS_DIR)/data/data/com.termux/files/usr \ - $(DEBUTILS_DIR)/data/data/com.termux/files/usr/bin \ - $(DEBUTILS_DIR)/data/data/com.termux/files/usr/share \ - $(DEBUTILS_DIR)/data/data/com.termux/files/usr/share/man \ - $(DEBUTILS_DIR)/data/data/com.termux/files/usr/share/man/man8 - -# for running make with silent mode -MAKE_HIDE := @ $(MAKE) -SILENT := -s -E := @ echo -E_NS := echo -P := printf - -# color definations -RESET := \033[0m -RED := \033[0;31m -GREEN := \033[0;32m -YELLOW := \033[0;33m - -# end \ No newline at end of file diff --git a/README.md b/README.md index 85bfad9..c51ce41 100755 --- a/README.md +++ b/README.md @@ -2,18 +2,17 @@ [![Commit reviewed](https://github.com/ShawkTeam/pmt/actions/workflows/check_commits.yml/badge.svg)](https://github.com/ShawkTeam/pmt/actions/workflows/check_commits.yml) -This binary, written with C++, is for writing/reading and formatting on Android partitions. - -#### Presented arguments (options) +This binary, written with C++, is for writing/reading, formatting and getting size on Android partitions. ``` Usage: pmt [OPTIONS] backup PARTITION [OUTPUT] [OPTIONS]... or: pmt [OPTIONS] flash PARTITION FILE [OPTIONS]... or: pmt [OPTIONS] format PARTITION FILE_SYSTEM[ext/2/3/4] [OPTIONS]... + or: pmt [OPTIONS] partition-size PARTITION [OPTIONS]... Options: -l, --logical It is meant to determine whether the target partition is logical. - -c, --context It is meant to specify a custom /dev context. Only classic partitions (default: /dev/block/by-name). + -P, --search-path It is meant to specify a custom partition search path. Only classic partitions (default: /dev/block/by-name). -p, --list List partitions. -s, --silent Information and warning messages are silenced in normal work. -f, --force Force mode. Some things are ignored. @@ -23,54 +22,49 @@ Options: --help See this help message. Examples: - pmt backup boot_a -c /dev/block/platform/bootdevice/by-name + pmt backup boot_a -P /dev/block/platform/bootdevice/by-name pmt flash boot_a /sdcard/twrp/boot.img -c /dev/block/platform/bootdevice/by-name pmt format system_a ext4 --logical - pmt -c /dev/block/platform/bootdevice/by-name --list + pmt -P /dev/block/platform/bootdevice/by-name --list Report bugs and suggestions to ``` #### Some notes -- pmt supports multiple languages. [See languages.](https://github.com/ShawkTeam/pmt/blob/2.8.0/LANGUAGES.md) -- [Add language.](https://github.com/ShawkTeam/pmt/blob/2.8.0/ADD-LANGUAGES.md) +- pmt supports multiple languages. [See languages.](https://github.com/ShawkTeam/pmt/blob/2.9.0/LANGUAGES.md) +- [Add language.](https://github.com/ShawkTeam/pmt/blob/2.9.0/ADD-LANGUAGES.md) - Feel free to ask any questions you want. - Packages are available in publications. - If the logical partition flag is not used, a classic partition is tried to be processing by default. -- [Click to see special version changes.](https://github.com/ShawkTeam/pmt/blob/2.8.0/CHANGELOG.md) +- [Click to see special version changes.](https://github.com/ShawkTeam/pmt/blob/2.9.0/CHANGELOG.md) - We are always open to your suggestions and support (developing)! -### How is it built? -Make or Android NDK is required to build. +### How to build? +Partition Manager only buildable with Android NDK (make compilation system deprecated). -##### Build with NDK - [Download Android NDK](https://developer.android.com/ndk/downloads) and extract the NDK package. - Clone this repository. And get access to it. ``` -git clone https://github.com/ShawkTeam/pmt -b 2.8.0 +git clone https://github.com/ShawkTeam/pmt -b 2.9.0 cd pmt ``` - Set the NDK working directory variable. ``` -make gen-ndk-makefiles -# If you fail the audit etc, use FORCE_GEN. -# Example: - make gen-ndk-makefiles FORCE_GEN=true +export NDK_PROJECT_PATH="${PWD}" # or where the source directory is everywhere +export NDK_ROOT_DIR= # Note that if the NDK is in the directory -# Required by Android NDK -export NDK_PROJECT_PATH="${PWD}" +# Generate clang version header +bash build/bash/gen-header ``` - Go to the NDK directory and start the build ``` -# Required for creating clang version information and directory access -export NDK_ROOT_DIR="${PWD}" -cd "${NDK_PROJECT_PATH}" \ -&& bash build/bash/gen-header \ -&& cd "${NDK_ROOT_DIR}" - -# Start build ./ndk-build + +# Permission denied? Change mode and retry +(sudo) chmod +x ndk-build +# OR +(sudo) chmod 755 ndk-build ``` - The output files will be inside the `pmt` folder. Binaries are available in two architectures within the `libs` folder. `arm64-v8a` (64-bit) and `armeabi-v7a` (32-bit). ``` @@ -87,77 +81,40 @@ cd "${NDK_PROJECT_PATH}" \ pmt pmt ``` -##### Build with Makefiles +### Manage pmt with termux script + - Download script. ``` -# Setup environment -pkg update \ -&& pkg upgrade -y \ -&& pkg install make clang binutils xz-utils -y - -# Start build -make - -# To specify clang, just use PMT_CXX= next to the command (and same logic in AR) -# Example: - make PMT_CXX=${PWD}/../toolchain/bin/clang-18 - make PMT_AR=${PWD}/../toolchain/bin/ar - make PMT_CXX=${PWD}/../toolchain/bin/clang-18 PMT_AR=${PWD}/../toolchain/bin/ar - -# Speficying extra compiler flags on cmd. Example: - make PMT_EXTRA_CXXFLAGS="-O2" - -# Use termux :D - -# Cleaning working directory -make clean - -# Rebuild -make rebuild - -# Install -make install - -# Uninstall -make uninstall - -# Re-install (install & uninstall) -make reinstall - -# Manage pmt with termux script -## Download script -curl -LSs https://github.com/ShawkTeam/pmt/raw/2.8.0/pmt-termux.sh > pmt-termux.sh - +curl -LSs https://github.com/ShawkTeam/pmt/raw/2.9.0/pmt-termux.sh > pmt-termux.sh +``` + - Some informations... +``` ## View script help bash pmt-termux.sh # --help (optional) ## The commands will be told to you anyway. Ask your questions from the telegram group. - -``` - - For the make installable debian package: - -``` -make deb - -# Examples - make deb FOR_THIS=64 - make deb FOR_THIS=32 ``` ### How to use ``` -# Run +# Directly access root shell /system/bin/su + +# If you are using termux, use with +# tsu (sudo) will be a better choice +pkg install -y tsu # install tsu (sudo) + +sudo ``` - If you have installed the deb package of pmt, installed it with a makefile, or installed it to `$PATH` using any path, just the name of the pmt is enough (or the file name if you did it manually) ``` -pmt <...> +(sudo) pmt ``` -- If you have not done this type of institution, pmt is in the directory where you are present you can run with `./`. +- If you have not done this type of institution, pmt is in the directory where you are present you can run with `(sudo) ./`. ``` -./pmt <...> # or whatever the file name is +(sudo) ./pmt # or whatever the file name is ``` ### Notes diff --git a/SETUP-DEBS.md b/SETUP-DEBS.md deleted file mode 100755 index 08a9258..0000000 --- a/SETUP-DEBS.md +++ /dev/null @@ -1,24 +0,0 @@ -### Installing pmt deb packages in Termux - -It's pretty simple. - -###### Package selection - - If the device is 64 bit, you should choose `arm64-v8a` package. If not, choose `armeabi-v7a` package. - - And of course download it. - -###### Setup - - Access downloads or wherever the package is located. - ``` - # Access downloads - cd /sdcard/Download - ``` - - Now it's time to set up. - ``` - Syntax: - apt install ./pmt-.deb - - Examples: - apt install ./pmt-armeabi-v7a.deb - apt install ./pmt-arm64-v8a.deb - ``` - - And enjoy! diff --git a/build/bash/check-makefiles b/build/bash/check-makefiles deleted file mode 100755 index dcda562..0000000 --- a/build/bash/check-makefiles +++ /dev/null @@ -1,37 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -[ ! "${THIS_IS}" = "main" ] \ -&& abort "The caller is not the main makefile. Something's wrong." - -try_with="Try with force mode (FORCE_GEN=true)." - -if [ "${NDK_PROG}" = "true" ]; then - mfiles=("${SOURCE_DIR}/Android.mk" "${SOURCE_DIR}/Application.mk") -else - mfiles=("${OUT_DIR}/Makefile" "${SOURCE_DIR}/Makefile") -fi - -for mfile in ${mfiles[@]}; do - - [ -f "${mfile}" ] && \ - if [ "${FORCE_GEN}" = "true" ]; then - rm -f "${mfile}" - else - abort "$(output=$(dirname ${mfile}) && basename "${output}")/$(basename ${mfile}) exits." - fi - -done diff --git a/build/bash/clean-makefiles b/build/bash/clean-makefiles deleted file mode 100755 index f5a2bfc..0000000 --- a/build/bash/clean-makefiles +++ /dev/null @@ -1,44 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -. build/bash/vars -. build/bash/functions - -[ ! "${THIS_IS}" = "main" ] \ -&& abort "The caller is not the main makefile. Something's wrong." - -if [ "${NDK_PROG}" = "true" ]; then - - [ "${UPDATE_MAKEFILES}" = "true" ] \ - || print " - Removing Android.mk..." \ - && print " - Removing Application.mk..." - - rm -f ${SOURCE_DIR}/Application.mk \ - ${SOURCE_DIR}/Android.mk - -else - - [ "${UPDATE_MAKEFILES}" = "true" ] \ - || print " - Info: Main makefile won't be deleted." \ - && print " - Removing output directory makefile..." \ - && print " - Removing source directory makefile..." - - rm -f ${SOURCE_DIR}/Makefile \ - ${OUT_DIR}/Makefile - -fi - -[ "${UPDATE_MAKEFILES}" = "true" ] || print " - Success." \ No newline at end of file diff --git a/build/bash/functions b/build/bash/functions deleted file mode 100755 index 28aeb40..0000000 --- a/build/bash/functions +++ /dev/null @@ -1,37 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function abort() -{ - [ -n "${@}" ] \ - && echo -e " - ${RED}${BOLD}Error:${BOLD_RESET}${RESET} ${@}" - exit 1 -} - -function read_file() -{ - cat "${1}" >> "${2}" \ - || abort "failed to read/write ${1}/${2}" -} - -function gen() -{ - [ "${FORCE_GEN}" = "true" -a "${UPDATE_MAKEFILES}" = "true" ] \ - && rm -f "${1}" - touch "${1}" || abort "failed to generate: ${1}" -} - -function print() { echo -e "${@}"; } diff --git a/build/bash/gen-header b/build/bash/gen-header deleted file mode 100755 index 24ade04..0000000 --- a/build/bash/gen-header +++ /dev/null @@ -1,29 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -[ -z ${NDK_ROOT_DIR} ] \ -&& echo "Please set NDK_ROOT_DIR variable!" \ -&& exit 1 - -[ -z ${NDK_PROJECT_PATH} ] \ -&& echo "Please set NDK_PROJECT_PATH variable!" \ -&& exit 1 - -CXX_IS="${NDK_ROOT_DIR}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++" -CXX_VERS=$(${CXX_IS} --version | head -n 1) - -mkdir -p ${NDK_PROJECT_PATH}/include/PartitionManager/generated -echo -e "#define __NDK_CXX_VERSION__ \"${CXX_VERS}\"" > ${NDK_PROJECT_PATH}/include/PartitionManager/generated/clang-version.h diff --git a/build/bash/gen-makefiles b/build/bash/gen-makefiles deleted file mode 100755 index ce1c5dc..0000000 --- a/build/bash/gen-makefiles +++ /dev/null @@ -1,66 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -. build/bash/vars -. build/bash/functions - -[ ! "${UPDATE_MAKEFILES}" = "true" ] \ -&& . build/bash/check-makefiles -[ ! "${THIS_IS}" = "main" ] \ -&& abort "The caller is not the main makefile. Something's wrong." - -if [ "${UPDATE_MAKEFILES}" = "true" ]; then - GENR="Re-generating" -else - GENR="Generating" -fi - -if [ "${NDK_PROG}" = "true" ]; then - - gen "${SOURCE_DIR}/Android.mk" - gen "${SOURCE_DIR}/Application.mk" - -else - - gen "${CUR_DIR}/Makefile" - gen "${OUT_DIR}/Makefile" - gen "${SOURCE_DIR}/Makefile" - -fi - -if [ "${NDK_PROG}" = "true" ]; then - - print " - ${GENR} Android.mk..." - read_file "${OTHERS}/makefile.androidmk" "${SOURCE_DIR}/Android.mk" - - print " - ${GENR} Application.mk" - read_file "${OTHERS}/makefile.applicationmk" "${SOURCE_DIR}/Application.mk" - -else - - print " - Re-generating main makefile..." - rm -f "${CUR_DIR}/Makefile" - read_file "${OTHERS}/makefile.main" "${CUR_DIR}/Makefile" - - print " - ${GENR} output directory makefile..." - read_file "${OTHERS}/makefile.outdir" "${OUT_DIR}/Makefile" - - print " - ${GENR} source directory makefile..." - read_file "${OTHERS}/makefile.sourcedir" "${SOURCE_DIR}/Makefile" - -fi - -print " - Success." \ No newline at end of file diff --git a/build/bash/vars b/build/bash/vars deleted file mode 100755 index 2add984..0000000 --- a/build/bash/vars +++ /dev/null @@ -1,33 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -. build/bash/additional-vars - -CUR_DIR=$(pwd) -SOURCE_DIR=${CUR_DIR}/${SOURCE_DIRNAME} -OUT_DIR=${CUR_DIR}/${OUT_DIRNAME} -BUILD=${CUR_DIR}/build -BASH_DIR=$(pwd) -OTHERS=${BUILD}/others -TOOLS=${BUILD}/tools - -# font types, colors etc -BOLD="\e[1m" -BOLD_RESET="\e[0m" -RESET="\033[0m" -RED="\033[0;31m" -GREEN="\033[0;32m" -YELLOW="\033[0;33m" \ No newline at end of file diff --git a/build/config/INS_STAT.mk b/build/config/INS_STAT.mk deleted file mode 100755 index 8a28605..0000000 --- a/build/config/INS_STAT.mk +++ /dev/null @@ -1 +0,0 @@ -INSTALL_SUCCESS := true diff --git a/build/config/Makefile b/build/config/Makefile deleted file mode 100755 index 1e08def..0000000 --- a/build/config/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include env.mk - -######################################### -# # -# Apply Configuration # -# # -# Warning: please do not edit # -# # -######################################### - -CXX = clang++ -AR = ar -CXXFLAGS ?= \ - -O3 \ - -I../include \ - -std=c++20 \ - -Wall \ - -Wextra \ - -Werror \ - -Wno-vla-cxx-extension \ - -Wno-nullability-completeness \ - -Wno-writable-strings \ - -Wno-unused-parameter \ - -Wno-unused-command-line-argument \ - -Wno-nullability-extension \ - -Wno-reorder-init-list \ - -Wno-gnu-zero-variadic-macro-arguments \ - $(PMT_EXTRA_CXXFLAGS) - -# set compiler setting (clang and ar) -ifneq ($(PMT_CXX),) - CXX ?= $(PMT_CXX) -endif - -ifneq ($(PMT_AR),) - AR ?= $(PMT_AR) -endif - -# compiler flags settings -ifeq ($(PMT_ENABLE_DEBUG),true) - CXXFLAGS += \ - -gdwarf-5 \ - -fsanitize=address -endif - -# write current env configuration to oldenv.mk -all: - @ echo "CXX := $(CXX)" > oldenv.mk - @ echo "AR := $(AR)" >> oldenv.mk - @ echo "CXXFLAGS := $(CXXFLAGS)" >> oldenv.mk diff --git a/build/config/UNINS_STAT.mk b/build/config/UNINS_STAT.mk deleted file mode 100755 index bd83d04..0000000 --- a/build/config/UNINS_STAT.mk +++ /dev/null @@ -1 +0,0 @@ -UNINSTALLED_SUCCESS := diff --git a/build/config/env.mk b/build/config/env.mk index 2cd6a48..db23d8b 100755 --- a/build/config/env.mk +++ b/build/config/env.mk @@ -18,21 +18,15 @@ # # # Configuration Flags # # # -# Warning: you can edit # +# you can edit # # # ######################################### -# speficy c++ compiler (cxx) -PMT_CXX ?= - -# speficy ar -PMT_AR ?= - # addionital compiler flags PMT_EXTRA_CXXFLAGS ?= # debugging mode (binary). it's enabling address sanitizer and source level debug information with dwarf version 5 -PMT_ENABLE_DEBUG ?= +PMT_ENABLE_DEBUG ?= true ######################################### ######################################### diff --git a/build/deb/DEBIAN/control_32 b/build/deb/DEBIAN/control_32 deleted file mode 100755 index 370599d..0000000 --- a/build/deb/DEBIAN/control_32 +++ /dev/null @@ -1,9 +0,0 @@ -Source: pmt -Package: pmt -Version: 2.8.0 -Architecture: arm -Description: pmt is for reading, writing and formatting partitions of android devices -Section: misc -Priority: optional -Maintainer: YZBruh -Standards-Version: 4.5.0 diff --git a/build/deb/DEBIAN/control_64 b/build/deb/DEBIAN/control_64 deleted file mode 100755 index 651dfbd..0000000 --- a/build/deb/DEBIAN/control_64 +++ /dev/null @@ -1,9 +0,0 @@ -Source: pmt -Package: pmt -Version: 2.8.0 -Architecture: aarch64 -Description: pmt is for reading, writing and formatting partitions of android devices -Section: misc -Priority: optional -Maintainer: YZBruh -Standards-Version: 4.5.0 diff --git a/build/deb/data/data/com.termux/files/usr/bin/dummy b/build/deb/data/data/com.termux/files/usr/bin/dummy deleted file mode 100755 index e69de29..0000000 diff --git a/build/deb/data/data/com.termux/files/usr/share/man/man8/dummy b/build/deb/data/data/com.termux/files/usr/share/man/man8/dummy deleted file mode 100755 index e69de29..0000000 diff --git a/build/deb/deb.mk b/build/deb/deb.mk deleted file mode 100755 index a1d7ace..0000000 --- a/build/deb/deb.mk +++ /dev/null @@ -1,99 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##### -# sub-make for making deb package -##### - -THIS_IS := debutils - -# include needed variables -include ../../Makefile.inc - -TEMP_DIR := $(DEBUTILS_DIR)/template - -ifeq ($(FOR_THIS),64) - DEB_ARCH_NAME := arm64-v8a -else ifeq ($(FOR_THIS),32) - DEB_ARCH_NAME := armeabi-v7a -endif - -ifneq ($(wildcard /dev/block/by-name),) - SUDO := su -c -else ifeq ($(wildcard /system/build.prop),) - SUDO := sudo -else - SUDO := -endif - -PROGRESS_LIST := \ - startup \ - $(DEB_CHECKS) \ - check_binary \ - prepare \ - make_debian_pack - -# make deb package -all: $(PROGRESS_LIST) - -startup: - $(E) " --------- Making deb package --------- " - @ rm -rf $(TEMP_DIR) - $(E) " - Checking files and directories (only neededs)..." - -prepare: - $(E) " - Copying files..." - @ cp -r $(DEBUTILS_DIR)/data $(TEMP_DIR) || exit 1 - @ rm -f $(DEBTERMUX_USR)/share/man/man8/dummy - @ rm -f $(DEBTERMUX_USR)/bin/dummy - @ mkdir $(TEMP_DIR)/DEBIAN - -check_binary: - @ if [ ! -f "$(BINARY_DIR)/$(TARGET)" ]; then \ - $(E_NS) " - $(TARGET) not builded! Please build and retry."; \ - exit 1; \ - fi - $(E) " - Generating template directory..." - @ mkdir $(TEMP_DIR) - $(E) " - Generating debian package directory..." - @ mkdir $(DEB_DIR) - -make_debian_pack: - @ abort() { \ - [ -d $(TEMP_DIR) ] \ - && rm -rf $(TEMP_DIR); \ - [ -d $(DEB_DIR) ] \ - && rm -rf $(DEB_DIR); \ - exit 1; \ - }; \ - if [ ! "$(FOR_THIS)" = "64" ] && [ ! "$(FOR_THIS)" = "32" ]; then \ - $(E_NS) " - Invalid arch number: $(FOR_THIS) [maybe null]" && abort; \ - fi; \ - $(E_NS) " - Selected arm-$(FOR_THIS) package control file."; \ - cp $(DEBUTILS_DIR)/DEBIAN/control_$(FOR_THIS) $(TEMP_DIR)/DEBIAN/control || abort; \ - cp $(DEBUTILS_DIR)/mandoc/$(TARGET).8.gz $(DEBTERMUX_USR)/share/man/man8 || abort; \ - cp $(BINARY_DIR)/$(TARGET) $(DEBTERMUX_USR)/bin || abort; \ - $(E_NS) " - Starting dpkg-deb..."; \ - sleep 2; \ - $(SUDO) chmod -R 755 *; \ - dpkg-deb -Z xz -b $(TEMP_DIR) $(DEB_DIR)/$(TARGET)-$(DEB_ARCH_NAME).deb || abort; \ - rm -rf $(TEMP_DIR); \ - $(E_NS) " - Done!" - -$(DEBUTILS_DIR)/%: - @ [ ! -e "$@" ] && $(E_NS) " - Check failed! Not found: $@" && exit 1 - -# end diff --git a/build/deb/mandoc/pmt.8.gz b/build/deb/mandoc/pmt.8.gz deleted file mode 100755 index 4748beb33ee203c3f96e8b289c96c2c92b5b1f08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1193 zcmV;a1XlYWiwFoLfz@UN18{A0E;s<4R&8(7FcAKpUvcUu5Nm?QJ|I9y-6&A8wN;Y= zgCgW4ZfY%wgYB%8m;cUVCvDOK5@OQS*mw8b+jE!r%K@El>E^?^s@I-pj~BAqDv_-X zojyE0qd8MX7$Hl#VkOJCvPw?zQY5_8Jf*r!xgxXXG^$vFpH^~0Z@JRe^wfVy_pHL8 z6%Fn`br@S&Q^B@WN<+2g01=v2BIm@vCcH8vN=jr=<${$7r;RXc=ctA89mq`!B4fj# z&tOsEwCZaTGyA~p-`be!Nf2x{8=twLeW|h_ZXBi@{CNGf8P;*c3>Bi|@guFOtI%az$M#T`y6v{53i%|YpQaU%b|0*c2< z8jM1kglN?$oP;M1<=rHDJ-d$R-Dt5GO{2*;q}hTlX44mwXfm7P^pZx?8+tRDzBnO{ z!od;$S}B_Y0u{EXJZ&l%a$EW?h!qs;h@olOh6{*5m&g7?`+Uqjn1`=vI=UKr z{y9~J@s>jxm8p^<{hg^4Ntru~@Mbzg<#t9NJ%2*qXLDDmpY}Fp$!%TP>-lIAxe7wz zI+|ZcKRZp|_q|VluwLa%uMdr1PAI)Uy48WUOeL~lD0=nzZIJK3s}A-$w0 z344Itz+FqKPUG$X*K(_qEr)BKS2){-z8HrWi;1hquBjLthPjhDc0md{OH3+DEj1lG zDzHPJKz0jy+kRO|+W?>5VNwmp#M%XO@!-Lp@IFlpZJ1q3N*hXmX~z;5vdpmnXf0zb z0t_qZI@Z_?C=>*mE5UN{jbkw8a~E^lK+o5ew_Keg|K)0aLhf$a3Z2n_g0DBMS;r zez&8JPcxf(f+A|HhP`i1_fo!Mb#9(G{UFX|avQ|kVaW=9|1g~DAb0Sti{%oh9_mpZ zx^LL2?FL};qZe91$!h>S; zXR1RD!H=X?3We%eeF$@Rl&c-QJ^-io(q(sK+|1>ny1m&I9qJ(e`2FZ=emUN+;AY`c zET#F(XqfaFQ{~LqA_i89YrH;oEOKsJh-Qjggg~bWQ)yr}s&aO|D6;>=b^Rl~)p#=j z8k9ey;eNmNH2)din%muKD>1spi+kZk_Dg41R=L_iuCZBSZZ}c8k+58vuQPgY zkME(Nxq9vZ&#zyF-hx+B8SEkO1q1xd_yrHbHQU@qoE7u~@4`wX8V~RSJM5%in?YNP H{0RU6Dk@0J diff --git a/build/main.mk b/build/main.mk deleted file mode 100755 index f916df6..0000000 --- a/build/main.mk +++ /dev/null @@ -1,147 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -UPDATE_MAKEFILES = false -CLS_ADTS := rm -f $(BUILD)/bash/additional-vars - -all: getvars - $(MAKE_HIDE) $(SILENT) -C $(BUILD)/config $$(cat $(BUILD)/goals.txt) || exit 1 - @ rm -f $(BUILD)/goals.txt - $(MAKE_HIDE) $(SILENT) -C $(SOURCE_DIRNAME) INC_OLDENV=true || exit 1 - -getvars: - @ touch $(BUILD)/goals.txt - @ $(foreach var,$(sort $(.VARIABLES)),\ - $(if $(filter command line,$(origin $(var))), \ - echo "$(var)=$($(var))" >> goals.txt;)) - -.PHONY: rebuild -rebuild: - $(MAKE_HIDE) $(SILENT) clean - $(E) - $(MAKE_HIDE) $(SILENT) - -# cleaner functions -.PHONY: clean -clean: - $(E) "Cleaning directories..." - @ if [ -d $(BINARY_DIR) ]; then \ - $(E_NS) "==> $(OUT_DIRNAME)/`basename $(BINARY_DIR)`"; \ - fi - @ if [ -d $(PACKAGE_DIR) ]; then \ - $(E_NS) "==> $(OUT_DIRNAME)/`basename $(PACKAGE_DIR)`"; \ - fi - @ if [ -d $(DEB_DIR) ]; then \ - $(E_NS) "==> $(OUT_DIRNAME)/`basename $(DEB_DIR)`"; \ - fi - @ rm -rf $(IN_OUT_DIR) - @ rm -rf $(DEB_DIR) - @ sleep 2 - $(MAKE_HIDE) $(SILENT) -C $(SOURCE_DIRNAME) clean INC_OLDENV=false || exit 1 - @ sleep 1 - $(E) "Success." - -# helper function -.PHONY: help -help: - $(E) " ------- Partition Manager help ------- " \ - && $(E_NS) - $(E) " Commands:" - $(E) " $(MAKE) ==> Build Partition Manager." - $(E) " $(MAKE) deb ==> Generate debian package for termux." - $(E) " $(MAKE) clean ==> Clear builded binary." - $(E) " $(MAKE) rebuild ==> Re-build Partition Manager (clean and make)." - $(E) " $(MAKE) install ==> It installs $(TARGET) into termux." - $(E) " $(MAKE) uninstall ==> It uninstalls $(TARGET) into termux." - $(E) " $(MAKE) reinstall ==> It uninstall and reinstalls $(TARGET)." - $(E) " $(MAKE) gen-makefiles ==> Generate makefiles for build." - $(E) " $(MAKE) gen-ndk-makefiles ==> Generate NDK makefiles for build." - $(E) " $(MAKE) clean-makefiles ==> Cleanup makefiles." - $(E) " $(MAKE) clean-ndk-makefiles ==> Cleanup NDK makefiles." - $(E) " $(MAKE) update-makefiles ==> Re-generate makefiles." - $(E) " $(MAKE) update-ndk-makefiles ==> Re-generate NDK makefiles." - $(E) " $(MAKE) help ==> Display this help message." && $(E_NS) - -# deb maker -.PHONY: deb -deb: - $(MAKE_HIDE) $(SILENT) -C $(DEBUTILS_DIR) -f deb.mk FOR_THIS=$(FOR_THIS) || exit 1 - @ $(P) "" - -# install pmt in to termux -.PHONY: install -install: - $(eval PROG := $@) - $(MAKE_HIDE) $(SILENT) -C $(OUT_DIRNAME) install PROG=$(PROG) || exit 1 - -# uninstall pmt in to termux -.PHONY: uninstall -uninstall: - $(eval PROG := $@) - $(MAKE_HIDE) $(SILENT) -C $(OUT_DIRNAME) uninstall PROG=$(PROG) || exit 1 - -.PHONY: reinstall -reinstall: - $(MAKE_HIDE) $(SILENT) uninstall - $(MAKE_HIDE) $(SILENT) install - -# clean ndk makefiles -.PHONY: gen-ndk-makefiles -gen-ndk-makefiles: - $(eval NDK_PROG = true) - $(call save-gen-vars) - $(call gen-ndk-mfiles) - @ $(CLS_ADTS) - -.PHONY: gen-makefiles -gen-makefiles: - $(call save-gen-vars) - $(call gen-mfiles) - @ $(CLS_ADTS) - -.PHONY: update-ndk-makefiles -update-ndk-makefiles: - $(E) " ------ Updating NDK makefiles ------ " - $(eval NDK_PROG = true) - $(eval UPDATE_MAKEFILES = true) - $(call save-gen-vars) - $(call clean-ndk-mfiles) - $(call gen-ndk-mfiles) - @ $(CLS_ADTS) - -.PHONY: update-makefiles -update-makefiles: - $(E) " ------ Updating makefiles ------ " - $(eval UPDATE_MAKEFILES = true) - $(call save-gen-vars) - $(call clean-ndk-mfiles) - $(call gen-mfiles) - @ $(CLS_ADTS) - -.PHONY: clean-ndk-makefiles -clean-ndk-makefiles: - $(eval NDK_PROG = true) - $(call save-gen-vars) - $(call clean-ndk-mfiles) - @ $(CLS_ADTS) - -.PHONY: clean-makefiles -clean-makefiles: - $(call save-gen-vars) - $(call clean-mfiles) - @ $(CLS_ADTS) - -# end diff --git a/build/mandoc/mandoc b/build/mandoc/mandoc new file mode 100755 index 0000000..ffefbfa --- /dev/null +++ b/build/mandoc/mandoc @@ -0,0 +1,154 @@ +.\" By YZBruh + +.\" Copyright 2024 Partition Manager +.\" +.\" Licensed under the Apache License, Version 2.0 (the "License"); +.\" you may not use this file except in compliance with the License. +.\" You may obtain a copy of the License at +.\" +.\" http://www.apache.org/licenses/LICENSE-2.0 +.\" +.\" Unless required by applicable law or agreed to in writing, software +.\" distributed under the License is distributed on an "AS IS" BASIS, +.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.\" See the License for the specific language governing permissions and +.\" limitations under the License. +.\" +.TH "PMT" "8" "September 2024" "PMT 2.9.0" "Partition Manager" +.SH NAME +.B pmt +\- Android Partition Manager Tool +.SH SYNOSIS +.B pmt +[ +.I {OPTIONS} +.B backup +.I PARTITION {OUTPUT} {OPTIONS}... +] +[ +.I {OPTIONS} +.B flash +.I PARTITION FILE {OPTIONS}... +] +[ +.I {OPTIONS} +.B format +.I PARTITION FILE_SYSTEM{ext/2/3/4} {OPTIONS}... +] +[ +.I {OPTIONS} +.B partition-size +.I PARTITION {OPTIONS}... +] +[ +.B \-l +| +.B \-\-logical +] +[ +.B \-P +| +.B \-\-search\-path +.I search\-path +] +[ +.B \-p +| +.B \-\-list +] +[ +.B \-s +| +.B \-\-silent +] +[ +.B \-V +| +.B \-\-verbose +] +[ +.B \-f +| +.B \-\-force +] +[ +.B \-S +| +.B \-\-set\-language +] +[ +.B \-v +| +.B \-\-version +] +[ +.B \-\-help +] +.SH DESCRIPTION +.B pmt +is a tool made to read android parts, make flash and format. Written with C++ language. It was first created as only a hobby but subsequently serialized +.PP +.SH OPTIONS +.sp +\fB\-l\fP, \fB\-\-logical\fP +.RS 4 +It is meant to determine whether the target partition is logical. +.RE +.sp +\fB\-c\fP, \fB\-\-context\fP +.RS 4 +It is meant to specify a custom /dev context. Only classic partitions (default: /dev/block/by-name) +.RE +.sp +\fB\-p\fP, \fB\-\-list\fP +.RS 4 +List partitions. +.RE +.sp +\fB\-s\fP, \fB\-\-silent\fP +.RS 4 +Information and warning messages are silenced in normal work. +.RE +.sp +\fB\-V\fP, \fB\-\-verbose +.RS 4 +Verbose mode. Print detailed informations etc. +.RE +.sp +\fB\-f\fP, \fB\-\-force\fP +.RS 4 +Force mode. Some things are ignored. +.RE +.sp +\fB\-S\fP, \fB\-\-set\-language\fP +.RS 4 +Set current language. +.RE +.sp +\fB\-v\fP, \fB\-\-version\fP +.RS 4 +See version info. +.RE +.sp +\fB\-\-help\fP +.RS 4 +See help message. +.SH EXAMPLES +.B pmt +backup boot_a -c /dev/block/platform/bootdevice/by-name +.sp +.B pmt +flash boot_a /sdcard/twrp/boot.img -c /dev/block/platform/bootdevice/by-name +.sp +.B pmt +format system_a ext4 --logical +.sp +.B pmt +-c /dev/block/platform/bootdevice/by-name --list +.SH AUTHOR +This version of +.B pmt +has been written by YZBruh +.SH BUGS +Report bugs to +.PP diff --git a/build/others/makefile.androidmk b/build/others/makefile.androidmk deleted file mode 100755 index fb68c03..0000000 --- a/build/others/makefile.androidmk +++ /dev/null @@ -1,64 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -######## -# 2.8.0 -######## - -LOCAL_PATH := $(call my-dir) - -include $(LOCAL_PATH)/../build/config/env.mk - -PMT_CXXFLAGS = \ - -O3 \ - -std=c++14 \ - -Wall \ - -Wextra \ - -Werror \ - -Wno-vla-cxx-extension \ - -Wno-nullability-completeness \ - -Wno-writable-strings \ - -Wno-unused-parameter \ - -Wno-unused-command-line-argument \ - -Wno-nullability-extension \ - -Wno-reorder-init-list \ - -Wno-gnu-zero-variadic-macro-arguments \ - -D__NDK_BUILD \ - $(PMT_EXTRA_CXXFLAGS) - -ifneq ($(PMT_ENABLE_DEBUG),) - PMT_CXXFLAGS += -gdwarf-5 -fsanitize=address -endif - -include $(CLEAR_VARS) - -LOCAL_MODULE := pmt -LOCAL_SRC_FILES := \ - Debug.cpp \ - Root.cpp \ - PartitionManager.cpp \ - PartitionTool.cpp \ - ListPartitions.cpp \ - Version.cpp \ - GetState.cpp \ - Tools.cpp \ - LanguageTools.cpp \ - Languages.cpp \ - Help.cpp -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include -LOCAL_CFLAGS := $(PMT_CXXFLAGS) - -include $(BUILD_EXECUTABLE) diff --git a/build/others/makefile.main b/build/others/makefile.main deleted file mode 100755 index af3eb70..0000000 --- a/build/others/makefile.main +++ /dev/null @@ -1,26 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -THIS_IS = main -NDK_PROG ?= false -FORCE_GEN ?= false - -# include needed variables -include Makefile.inc -include $(TOOLS)/gen-makefiles.mk -include $(TOOLS)/clean-makefiles.mk - -include $(BUILD)/main.mk \ No newline at end of file diff --git a/build/others/makefile.outdir b/build/others/makefile.outdir deleted file mode 100755 index 4f51c95..0000000 --- a/build/others/makefile.outdir +++ /dev/null @@ -1,152 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##### -# sub-make for installing-uninstalling -##### - -THIS_IS := out - -# include needed variables -include ../Makefile.inc --include $(BUILD)/config/INS_STAT.mk --include $(BUILD)/config/UNINS_STAT.mk - -INSTALL_PROGRESS_LIST := \ - really_termux \ - welcome \ - check_ins_stat \ - deb_installer \ - really_builded \ - install_binary - -UNINSTALL_PROGRESS_LIST := \ - really_termux \ - welcome \ - check_unins_stat \ - uninstall_$(TARGET) - -# create an empty target -all: - $(P) "" - -# installer -.PHONY: install -install: $(INSTALL_PROGRESS_LIST) - -# uninstaller -.PHONY: uninstall -uninstall: $(UNINSTALL_PROGRESS_LIST) - -install_binary: - $(E) " - Installing binary..." - if cp $(BINARY_DIR)/$(TARGET) /data/data/com.termux/files/usr/bin/$(TARGET); then \ - $(E_NS) " - Setting up permissions..."; \ - else \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi; \ - if chmod 777 $(TERMUX_BIN)/$(TARGET); then \ - $(E_NS) " - Saving current status..."; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi; \ - $(P) " - Success.\n\n"; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - $(E_NS) "UNINSTALLED_SUCCESS := " > $(BUILD)/config/UNINS_STAT.mk - @ exit 0 - -uninstall_$(TARGET): - if [ -f $(TERMUX_USR)/share/man/man8/$(TARGET).8.gz ]; then \ - $(E_NS) " - It was found to be established by $(TARGET)'s deb pack. It's removed with apt..."; \ - apt remove -y $(TARGET) || exit 1; \ - $(P) " - Success.\n\n"; \ - $(E_NS) "UNINSTALLED_SUCCESS := true" > $(BUILD)/config/UNINS_STAT.mk; \ - $(E_NS) "INSTALL_SUCCESS := " > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) " - It was found that pmt was manually established (with this makefile or copying). Manually removed..."; \ - if rm $(TERMUX_BIN)/$(TARGET); then \ - $(P) " - Success.\n\n"; \ - $(E_NS) "UNINSTALLED_SUCCESS := true" > $(BUILD)/config/UNINS_STAT.mk; \ - $(E_NS) "INSTALL_SUCCESS := " > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) "UNINSTALLED_SUCCESS := false" > $(BUILD)/config/UNINS_STAT.mk; \ - exit 1; \ - fi; \ - fi - -deb_installer: - if [ -f $(DEB_DIR)/*.deb ]; then \ - $(E_NS) " - The created deb pack was found. It's setup..."; \ - cd $(DEB_DIR) || exit 1; \ - apt install ./*.deb || exit 1; \ - if [ ! "$?" = "0" ]; then \ - cd $(CUR_DIR); \ - $(P) " - Success.\n\n"; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - $(E_NS) "UNINSTALLED_SUCCESS := " > $(BUILD)/config/UNINS_STAT.mk; \ - cd ..; \ - exit 0; \ - else \ - cd $(CUR_DIR); \ - $(P) " - $(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) installing failed!\n"; \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - cd ..; \ - exit 1; \ - fi; \ - fi - -check_ins_stat: - @ if [ ! "$(INSTALL_SUCCESS)" = "true" ] && [ ! "$(INSTALL_SUCCESS)" = "" ]; then \ - $(P) " - $(YELLOW)$(BOLD)Warning:$(BOLD_RESET)$(RESET) a previously-stayed failed installation process found\n"; \ - fi - -check_unins_stat: - @ if [ ! "$(UNINSTALL_SUCCESS)" = "true" ] && [ ! "$(UNINSTALL_SUCCESS)" = "" ]; then \ - $(P) " - $(YELLOW)$(BOLD)Warning:$(BOLD_RESET)$(RESET) a previously-stayed failed uninstallation process found\n"; \ - fi - -welcome: - $(E) " ----------- $(TARGET) $(PROG)er ----------- " - @ if [ "$(PROG)" = "uninstall" ]; then \ - if [ ! -f $(TERMUX_BIN)/$(TARGET) ]; then \ - $(E_NS) " - $(TARGET) already $(PROG)ed"; \ - exit 1; \ - fi; \ - fi - @ if [ "$(PROG)" = "install" ]; then \ - if [ -f $(TERMUX_BIN)/$(TARGET) ]; then \ - $(E_NS) " - $(TARGET) already $(PROG)ed"; \ - exit 1; \ - fi; \ - fi - -really_termux: - @ if [ ! -f $(TERMUX_BIN)/termux-open ]; then \ - $(P) "$(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) This function is only available on Termux.\n"; \ - exit 1; \ - fi - -really_builded: - if [ ! -f $(BINARY_DIR)/$(TARGET) ]; then \ - $(P) " - $(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) Package not builded! Please build package and try again \n"; \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi - -# end diff --git a/build/others/makefile.sourcedir b/build/others/makefile.sourcedir deleted file mode 100755 index 56aabd4..0000000 --- a/build/others/makefile.sourcedir +++ /dev/null @@ -1,182 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##### -# sub-make for building package -##### - -THIS_IS = src - -include ../Makefile.inc - -ifeq ($(INC_OLDENV),true) - include $(BUILD)/config/oldenv.mk -endif - -INCLUDE_DIR := $(realpath ../include) -PMT_INCDIR := $(INCLUDE_DIR)/pmt - -# the presence of all source files that are on this list will be checked -SRCS_REQ := \ - place-holder/Debug.cpp \ - place-holder/Help.cpp \ - place-holder/GetState.cpp \ - place-holder/LanguageTools.cpp \ - place-holder/Languages.cpp \ - place-holder/PartitionTool.cpp \ - place-holder/PartitionManager.cpp \ - place-holder/Root.cpp \ - place-holder/Tools.cpp \ - place-holder/Version.cpp - -# objects to be used when executable file is created -OBJS_EXEC := \ - $(SOURCE_DIR)/PartitionManager.o \ - $(SOURCE_DIR)/Help.o \ - $(SOURCE_DIR)/Version.o \ - $(SOURCE_DIR)/GetState.o \ - $(SOURCE_DIR)/Tools.o \ - $(SOURCE_DIR)/Languages.o \ - $(SOURCE_DIR)/LanguageTools.o - -HEADERS_REQ := \ - $(PMT_INCDIR)/PartitionManager/Deprecates.h \ - $(PMT_INCDIR)/PartitionManager/HelpFn.h \ - $(PMT_INCDIR)/PartitionManager/PartitionManager.h \ - $(PMT_INCDIR)/PartitionManager/StringKeys.h \ - $(PMT_INCDIR)/PartitionManager/VersionFnVars.h - -PROGRESS_LIST := \ - welcome \ - wait \ - $(SRCS_REQ) \ - $(HEADERS_REQ) \ - pr_obj \ - $(OBJS) \ - make_outdirs \ - pr_sts \ - $(STATIC_LIBS) \ - make_executable \ - wait \ - end_progress - -# all target for building -all: $(PROGRESS_LIST) - -welcome: - @ rm -f $(BUILD)/config/oldenv.mk - @ echo " ---- Partition Manager Builder ---- " \ - && $(E_NS) - $(E) " - Version: $(VERSION)" - $(E) " - Version code: $(VERSION_CODE)" \ - && $(E_NS) - $(E) " -------------------------------- " \ - && $(E_NS) - $(E) " - Checking required source files..." - -pr_obj: - $(E) " - Building objects..." - -pr_sts: - $(E) " - Making static libraries..." - -wait: - @ sleep 2 - -make_outdirs: - @ rm -rf $(IN_OUT_DIR) - @ mkdir -p $(BINARY_DIR) - @ mkdir -p $(PACKAGE_DIR) - @ mkdir -p $(STATICLIB_DIR) - -place-holder/%.cpp: - $(E) " CHK $(SOURCE_DIRNAME)/`basename $@`" - @ if [ ! -f "$(SOURCE_DIR)/`basename $@`" ]; then \ - $(E_NS) " ==> Couldn't found required source file: $(SOURCE_DIRNAME)/`basename $@`"; \ - exit 1; \ - fi - -$(PMT_INCDIR)/%.h: - $(E) " CHK include/PartitionManager/`basename $@`" - @ if [ ! -f "$(INCLUDE_DIR)/PartitionManager/`basename $@`" ]; then \ - $(E_NS) " ==> Couldn't found required header file: include/PartitionManager/`basename $@`"; \ - exit 1; \ - fi - -$(SOURCE_DIR)/%.o: $(SOURCE_DIR)/%.cpp - $(E) " CXX $(SOURCE_DIRNAME)/`basename $@`" - @ $(CXX) -x c++ $(CXXFLAGS) -c "$<" || exit 1 - -pmt_root: - $(E) " AR lib$@.a" - @ $(AR) rcs "lib$@.a" "$(SOURCE_DIR)/Root.o" - -pmt_debug: - $(E) " AR lib$@.a" - @ $(AR) rcs "lib$@.a" "$(SOURCE_DIR)/Debug.o" - -pmt_listpartitions: - $(E) " AR lib$@.a" - @ $(AR) rcs "lib$@.a" "$(SOURCE_DIR)/ListPartitions.o" - -pmt_partitiontool: - $(E) " AR lib$@.a" - @ $(AR) rcs "lib$@.a" "$(SOURCE_DIR)/PartitionTool.o" - -make_executable: - $(E) " - Making executable file..." - $(E) " LD $(TARGET)" - @ $(CXX) $(CXXFLAGS) -L$(SOURCE_DIR) $(foreach st,$(STATIC_LIBS),$(shell echo -n -l$(st) )) -o $(TARGET) $(OBJS_EXEC) || exit 1 - -end_progress: - @ abort_build() { \ - [ -d "$(PACKAGE_DIR)" ] \ - && rm -rf "$(PACKAGE_DIR)"; \ - [ -d "$(BINARY_DIR)" ] \ - && rm -rf "$(BINARY_DIR)"; \ - [ -d "$(STATICLIB_DIR)" ] \ - && rm -rf "$(STATICLIB_DIR)"; \ - exit 1; \ - }; \ - mv $(TARGET) $(BINARY_DIR) || abort_build; \ - mv *.a $(STATICLIB_DIR) || abort_build; \ - $(E_NS) " - Generating package..."; \ - cp $(BINARY_DIR)/$(TARGET) $(PACKAGE_DIR) || abort_build; \ - $(E_NS) " XZ $(OUT_DIRNAME)/package/$(TARGET)-`date +%Y%m%d`.xz" - xz $(PACKAGE_DIR)/$(TARGET) || abort_build; \ - sleep 1; \ - mv $(PACKAGE_DIR)/$(TARGET).xz $(PACKAGE_DIR)/$(TARGET)-`date +%Y%m%d`.xz || abort_build - $(E) " - Success" && $(E_NS) - @ sleep 1 - $(E) " ----------------------------------- " - -.PHONY: clean -clean: - $(eval STATICLIBS = $(wildcard $(SOURCE_DIR)/*.a)) - $(eval OBJS = $(wildcard $(SOURCE_DIR)/*.o)) - $(info Cleaning files...) - $(foreach obj, \ - $(OBJS), \ - $(call m_stat_nn,$(SOURCE_DIRNAME)/$(shell basename $(obj))) \ - $(call erase,$(obj)) \ - ) - $(foreach lib, \ - $(STATICLIBS), \ - $(call m_stat_nn,$(SOURCE_DIRNAME)/$(shell basename $(lib))) \ - $(call erase,$(lib)) \ - ) - -# end \ No newline at end of file diff --git a/build/tools/clean-makefiles.mk b/build/tools/clean-makefiles.mk deleted file mode 100755 index fde4bff..0000000 --- a/build/tools/clean-makefiles.mk +++ /dev/null @@ -1,31 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -################## -# See "erase" funtion for build/util/utils.mk -################## - -include $(TOOLS)/save-gen-vars.mk - -define clean-ndk-mfiles - @ [ "$(UPDATE_MAKEFILES)" = "true" ] || printf " ------ Cleaning NDK Makefiles ------ \n" - @ cat $(BASH_DIR)/clean-makefiles | $(BIN)/bash -endef - -define clean-mfiles - @ [ "$(UPDATE_MAKEFILES)" = "true" ] || printf " ------ Cleaning Makefiles ------ \n" - @ cat $(BASH_DIR)/clean-makefiles | $(BIN)/bash -endef diff --git a/build/tools/gen-makefiles.mk b/build/tools/gen-makefiles.mk deleted file mode 100755 index 352b3f8..0000000 --- a/build/tools/gen-makefiles.mk +++ /dev/null @@ -1,31 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -################## -# See "save-gen-vars" funtion for build/tools/save-gen-vars.mk -################## - -include $(TOOLS)/save-gen-vars.mk - -define gen-ndk-mfiles - @ [ "$(UPDATE_MAKEFILES)" = "true" ] || printf " ------ Generating NDK Makefiles ------ \n" - @ cat $(BASH_DIR)/gen-makefiles | $(BIN)/bash -endef - -define gen-mfiles - @ [ "$(UPDATE_MAKEFILES)" = "true" ] || printf " ------ Generating Makefiles ------ \n" - @ cat $(BASH_DIR)/gen-makefiles | $(BIN)/bash -endef diff --git a/build/tools/save-gen-vars.mk b/build/tools/save-gen-vars.mk deleted file mode 100755 index 245a966..0000000 --- a/build/tools/save-gen-vars.mk +++ /dev/null @@ -1,26 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -define save-gen-vars - @ rm -f $(BASH_DIR)/additional-vars - $(call touch,$(BASH_DIR)/additional-vars) - @ echo "NDK_PROG=$(NDK_PROG)" >> $(BASH_DIR)/additional-vars - @ echo "FORCE_GEN=$(FORCE_GEN)" >> $(BASH_DIR)/additional-vars - @ echo "THIS_IS=$(THIS_IS)" >> $(BASH_DIR)/additional-vars - @ echo "UPDATE_MAKEFILES=$(UPDATE_MAKEFILES)" >> $(BASH_DIR)/additional-vars - @ echo "SOURCE_DIRNAME=$(SOURCE_DIRNAME)" >> $(BASH_DIR)/additional-vars - @ echo "OUT_DIRNAME=$(OUT_DIRNAME)" >> $(BASH_DIR)/additional-vars -endef diff --git a/build/tools/update-makefiles.mk b/build/tools/update-makefiles.mk deleted file mode 100755 index f7d8f32..0000000 --- a/build/tools/update-makefiles.mk +++ /dev/null @@ -1,24 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ifneq ($(THIS_IS),main) - $(error The caller is not the main makefile. Something's wrong) -endif - -UPDATE_MAKEFILES = true - -include $(TOOLS)/clean-makefiles.mk -include $(TOOLS)/gen-makefiles.mk diff --git a/build/util/utils.mk b/build/util/utils.mk deleted file mode 100755 index adaac35..0000000 --- a/build/util/utils.mk +++ /dev/null @@ -1,58 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# generate any text based empty file. Usage: $(call touch,) -define touch - @ [ ! "$(FORCE_GEN)" = "true" ] || rm -f "$1" - @ touch "$1" || exit 1 -endef - -# copy files. Usage: $(call copy,,) -define copy - cp "$1" "$2" || exit 1 -endef - -# copy dirs. Usage: $(call copydir,,) -define copydir - cp -r "$1" "$2" || exit 1 -endef - -# file/dir are deleted. usage: $(call erase,) -define erase - rm -rf "$1" -endef - -# make directories. usage: $(call mdir,,) -define mdir - [ -z $2 ] || printf " - Generating `basename $1` dir...\n"; \ - mkdir -p "$1" || exit 1; -endef - -# make status. usage: $(call m_stat,"",) -define m_stat - printf " $1 $2" -endef - -# make status (not newline and using make functions). usage: $(call m_stat_nn,"") -define m_stat_nn - $(info ==> $(1)) -endef - -# Get file content and if speficed write target, write speficed file. Usage: $(call cat,,) -define cat - [ -z "$2" ] && cat "$1" || exit 1 - [ -n "$2" ] && cat "$1" >> "$2" || exit 1 -endef diff --git a/build/workflow/build.config b/build/workflow/build.config index f541b30..45090cc 100755 --- a/build/workflow/build.config +++ b/build/workflow/build.config @@ -1,5 +1,5 @@ -export PMT_VERSION="2.8.0" -export PMT_VERSION_CODE=280 +export PMT_VERSION="2.9.0" +export PMT_VERSION_CODE=290 export NDK_VERSION="r27" export NDK_IS="android-ndk" export NDK_LINK="https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip" \ No newline at end of file diff --git a/build/workflow/relnotes b/build/workflow/relnotes index f0f0b50..5717335 100755 --- a/build/workflow/relnotes +++ b/build/workflow/relnotes @@ -1,11 +1,10 @@ echo -e "\`${CC_VERSION}\` -Version/Version Code: \`${PMT_VERSION}\`/\`${PMT_VERSION_CODE}\` -Supported architectures: \`arm64-v8a\` (64-bit) and \`armeabi-v7a\` (32-bit) +Version and code: \`${PMT_VERSION}\`/\`${PMT_VERSION_CODE}\` +Supported architectures: \`arm64-v8a\` (64-bit), \`armeabi-v7a\` (32-bit) Notes: -Builded with Android NDK ${NDK_VERSION} -Packages are compressed with xz. -Builded debian packages for termux. [Click](https://github.com/ShawkTeam/pmt/blob/${PMT_VERSION}/SETUP-DEBS.md) for guide. -Report bugs and suggestions. -[Click](https://github.com/ShawkTeam/pmt/blob/${PMT_VERSION}/CHANGELOG.md) for viewing version ${PMT_VERSION} changelog." + - Builded with Android NDK \`${NDK_VERSION}\` + - Packages are compressed with \`xz\`. + - Report bugs and suggestions. + - [Click](https://github.com/ShawkTeam/pmt/blob/${PMT_VERSION}/CHANGELOG.md) for viewing version \`${PMT_VERSION}\` changelog." diff --git a/include/PartitionManager/Deprecates.h b/include/PartitionManager/Deprecates.h index fd1121d..e7eca8b 100755 --- a/include/PartitionManager/Deprecates.h +++ b/include/PartitionManager/Deprecates.h @@ -16,8 +16,7 @@ * limitations under the License. */ -#ifndef __PMT_DEPRECATES_H -#define __PMT_DEPRECATES_H +#pragma once #define deprecated_opt 1 #define changed_opt 2 @@ -40,7 +39,8 @@ #define v260 "2.6.0" #define v270 "2.7.0" #define v280 "2.8.0" -#define vUNK NULL +#define v290 "2.9.0" +#define vUNK nullptr struct pmt_deprecates { int depr_type; @@ -57,15 +57,16 @@ static struct pmt_deprecates depr_table[] = { {deprecated_opt, 'r', not_changed, "format", not_changed_long, v210}, {deprecated_opt, 'L', not_changed, "license", not_changed_long, v250}, {changed_opt, 'D', 'p', "list", not_changed_long, v210}, + {changed_opt, 'c', 'P', "context", "search-path", v290}, {end_depr_pointer, not_changed, not_changed, not_changed_long, not_changed_long, vUNK} }; static void -__deprecated_opt_handle(int opt, const string opt_long, const char* depr_msg) +__process_deprecated_opts(int opt, const string& opt_long, const char* depr_msg) { static string long_e_msg; - if (opt_long == "") + if (opt_long.empty()) long_e_msg = PartitionManager::Display::UsingDispString->not_changed_opt; else long_e_msg = opt_long; @@ -91,12 +92,10 @@ __deprecated_opt_handle(int opt, const string opt_long, const char* depr_msg) } } - } } -#define DEPR_HANDLE(x, y, z) __deprecated_opt_handle(x, y, z) - -#endif /* __PMT_DEPRECATES_H */ +#define DEPR_HANDLE(x, y, z) \ + __process_deprecated_opts(x, y, z) /* end of code */ diff --git a/include/PartitionManager/FileSystemUtils.h b/include/PartitionManager/FileSystemUtils.h new file mode 100755 index 0000000..93af138 --- /dev/null +++ b/include/PartitionManager/FileSystemUtils.h @@ -0,0 +1,25 @@ +/* By YZBruh */ + +/* + * Copyright 2024 Partition Manager + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +extern "C" { + int mke2fs_main(int argc, char* argv[]); +} + +/* end of code */ \ No newline at end of file diff --git a/include/PartitionManager/HelpFn.h b/include/PartitionManager/HelpFn.h index 80867ba..5898726 100755 --- a/include/PartitionManager/HelpFn.h +++ b/include/PartitionManager/HelpFn.h @@ -16,8 +16,7 @@ * limitations under the License. */ -#ifndef __PMT_HELP_MSGS_H -#define __PMT_HELP_MSGS_H +#pragma once namespace PartitionManager { namespace Functions { @@ -25,6 +24,4 @@ namespace PartitionManager { } } -#endif - /* end */ diff --git a/include/PartitionManager/PartSizeMacros.h b/include/PartitionManager/PartSizeMacros.h new file mode 100755 index 0000000..105faae --- /dev/null +++ b/include/PartitionManager/PartSizeMacros.h @@ -0,0 +1,26 @@ +/* By YZBruh */ + +/** + * Copyright 2024 Partition Manager + * + * Licensed under the Apache License, Version 2.0 (the "License"; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#define VIEW_AS_BYTE 1 +#define VIEW_AS_KIB 2 +#define VIEW_AS_MIB 3 +#define VIEW_AS_GIB 4 + +/* end of code */ diff --git a/include/PartitionManager/PartitionManager.h b/include/PartitionManager/PartitionManager.h index d6f73d0..3bbaa04 100755 --- a/include/PartitionManager/PartitionManager.h +++ b/include/PartitionManager/PartitionManager.h @@ -16,12 +16,11 @@ * limitations under the License. */ -#if !defined(__clang__) && !defined(__NDK_BUILD) - #error "Your compiler is NOT clang. Please build with LLVM clang." -#endif +#pragma once -#ifndef __PMT_H_ -#define __PMT_H_ +#if !defined(__clang__) && !defined(__NDK_BUILD) + #error "Your compiler is NOT clang. Please build with (LLVM) clang." +#endif #ifdef INC_MAIN_LIBS #include @@ -30,8 +29,10 @@ #include #include #include - #include + #ifdef IS_MAIN + #include + #endif #if !defined(HELP) || !defined(VERSIONING) #include #include @@ -52,7 +53,9 @@ #include #endif #ifdef INC_TOOLS_REQS - #include + #include + + typedef unsigned short ushort_t; #endif #ifdef INC_LIBGEN #include @@ -68,16 +71,17 @@ typedef enum { LOG_LEVEL_DEBUG } LogLevel; -/* fast error processing without errno entry +/** + * Fast error processing without errno entry * but errno can be given in the entrance */ -char* strqerror(int errno_macro = errno); +extern "C" char* strqerror(int errno_macro = errno); /* create a special namespace */ namespace PartitionManager { namespace Strings { extern string OutputName; - extern string CustomContext; + extern string CustomSearchPath; extern string TargetPartition; extern string TargetFlashFile; extern string TargetFormatFS; @@ -86,19 +90,24 @@ namespace PartitionManager { extern string CurrentLanguage; } /* namespace Strings */ + namespace Integers { + extern int PartSizeViewType; + } /* namespace Integers */ + namespace Booleans { extern bool UseLogical; - extern bool UseCustomContext; + extern bool UseCustomSearchPath; extern bool UsesSlots; extern bool UsesLogical; + extern bool OnlyViewSize; extern bool SilentEnabled; extern bool FlashMode; extern bool BackupMode; extern bool FormatMode; + extern bool PartSizeViewMode; extern bool ForceMode; extern bool VerboseMode; extern bool InstalledOnTermux; - extern bool ActivateRoot; } /* namespace Booleans */ namespace Display { @@ -135,6 +144,7 @@ namespace PartitionManager { #define LOGD(fmt, ...) \ PartitionManager::Functions::DisplayLog(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) +/* verbose logging macros */ #define VLOGF(fmt, ...) \ PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) #define VLOGE(fmt, ...) \ @@ -144,6 +154,4 @@ namespace PartitionManager { #define VLOGD(fmt, ...) \ PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) -#endif - /* end of code */ diff --git a/include/PartitionManager/StringKeys.h b/include/PartitionManager/StringKeys.h index 44ed27f..4146427 100755 --- a/include/PartitionManager/StringKeys.h +++ b/include/PartitionManager/StringKeys.h @@ -16,8 +16,7 @@ * limitations under the License. */ -#ifndef __PMT_STRINGKEYS_ -#define __PMT_STRINGKEYS_ +#pragma once /* The struct is a very good option for setting the languages of texts etc. */ struct langdb_general { @@ -38,9 +37,10 @@ struct langdb_general { const char* _Nonnull expected_backup_arg; const char* _Nonnull expected_flash_arg; const char* _Nonnull expected_format_arg; + const char* _Nonnull expected_partsz_arg; const char* _Nonnull missing_operand; const char* _Nonnull multiple_wiewers; - const char* _Nonnull common_symbol_rule; + const char* _Nonnull symbol_rule; const char* _Nonnull req_part_name; const char* _Nonnull part_not_found; const char* _Nonnull unsupported_fs; @@ -48,16 +48,19 @@ struct langdb_general { const char* _Nonnull ffile_more_part; const char* _Nonnull cannot_get_bsz; const char* _Nonnull format_fail; + const char* _Nonnull fail_get_psize; const char* _Nonnull depr_backup_opt; const char* _Nonnull depr_flash_opt; const char* _Nonnull depr_format_opt; const char* _Nonnull depr_Vlicense_opt; const char* _Nonnull depr_ch_list_opt; + const char* _Nonnull depr_ch_sp_opt; const char* _Nonnull not_spec_opt; const char* _Nonnull some_spec; const char* _Nonnull logical_warn; const char* _Nonnull ab_warn; const char* _Nonnull out_not_spec; + const char* _Nonnull no_found_on_process; const char* _Nonnull please_rerun; const char* _Nonnull part_disk_sz; const char* _Nonnull flash_file_sz; @@ -74,6 +77,7 @@ struct langdb_general { const char* _Nonnull warn; const char* _Nonnull fatal; const char* _Nonnull is_requires_arg; + const char* _Nonnull only_partsz_args; const char* _Nonnull unknw_arg; const char* _Nonnull switching_lang; const char* _Nonnull welcome; @@ -88,9 +92,13 @@ struct langdb_general { const char* _Nonnull compiler_str; const char* _Nonnull version_str; const char* _Nonnull bin_str; + const char* _Nonnull part_name; + const char* _Nonnull part_type; const char* _Nonnull fs_str; const char* _Nonnull unknw_str; const char* _Nonnull by_str; + const char* _Nonnull yes; + const char* _Nonnull no; }; /* docs etc. */ @@ -110,10 +118,15 @@ struct langdb_docs { const char* _Nonnull docs_strs_l13; const char* _Nonnull docs_strs_l14; const char* _Nonnull docs_strs_l15; + const char* _Nonnull docs_strs_l16; + const char* _Nonnull docs_strs_l17; + const char* _Nonnull docs_strs_l18; + const char* _Nonnull docs_strs_l19; + const char* _Nonnull docs_strs_l20; + const char* _Nonnull docs_strs_l21; + const char* _Nonnull docs_strs_l22; const char* _Nonnull or_str; const char* _Nonnull usage_docstr; }; -#endif /* __PMT_STRINGKEYS_ */ - /* end of code */ diff --git a/include/PartitionManager/VersionFnVars.h b/include/PartitionManager/VersionFnVars.h index a369583..f07b00e 100755 --- a/include/PartitionManager/VersionFnVars.h +++ b/include/PartitionManager/VersionFnVars.h @@ -16,18 +16,18 @@ * limitations under the License. */ -#ifndef __PMT_VERSIONING_H -#define __PMT_VERSIONING_H +#pragma once #ifdef __NDK_BUILD #include #include #endif +#include /* versioning */ #define PMT_MAJOR 2 -#define PMT_MINOR 8 -#define PMT_PATCHLEVEL 0 +#define PMT_MINOR 9 +#define PMT_PATCHLEVEL 1 namespace PartitionManager { namespace Functions { @@ -35,6 +35,4 @@ namespace PartitionManager { } } -#endif - /* end */ diff --git a/include/e2fsprogs/blkid/blkidP.h b/include/e2fsprogs/blkid/blkidP.h new file mode 100755 index 0000000..1414fe1 --- /dev/null +++ b/include/e2fsprogs/blkid/blkidP.h @@ -0,0 +1,204 @@ +/* + * blkidP.h - Internal interfaces for libblkid + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _BLKID_BLKIDP_H +#define _BLKID_BLKIDP_H + +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif + +#include + +#include + +#ifdef __GNUC__ +#define __BLKID_ATTR(x) __attribute__(x) +#else +#define __BLKID_ATTR(x) +#endif + + +/* + * This describes the attributes of a specific device. + * We can traverse all of the tags by bid_tags (linking to the tag bit_names). + * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag + * values, if they exist. + */ +struct blkid_struct_dev +{ + struct list_head bid_devs; /* All devices in the cache */ + struct list_head bid_tags; /* All tags for this device */ + blkid_cache bid_cache; /* Dev belongs to this cache */ + char *bid_name; /* Device inode pathname */ + char *bid_type; /* Preferred device TYPE */ + int bid_pri; /* Device priority */ + dev_t bid_devno; /* Device major/minor number */ + time_t bid_time; /* Last update time of device */ + unsigned int bid_flags; /* Device status bitflags */ + char *bid_label; /* Shortcut to device LABEL */ + char *bid_uuid; /* Shortcut to binary UUID */ +}; + +#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ +#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ + +/* + * Each tag defines a NAME=value pair for a particular device. The tags + * are linked via bit_names for a single device, so that traversing the + * names list will get you a list of all tags associated with a device. + * They are also linked via bit_values for all devices, so one can easily + * search all tags with a given NAME for a specific value. + */ +struct blkid_struct_tag +{ + struct list_head bit_tags; /* All tags for this device */ + struct list_head bit_names; /* All tags with given NAME */ + char *bit_name; /* NAME of tag (shared) */ + char *bit_val; /* value of tag */ + blkid_dev bit_dev; /* pointer to device */ +}; +typedef struct blkid_struct_tag *blkid_tag; + +/* + * Minimum number of seconds between device probes, even when reading + * from the cache. This is to avoid re-probing all devices which were + * just probed by another program that does not share the cache. + */ +#define BLKID_PROBE_MIN 2 + +/* + * Time in seconds an entry remains verified in the in-memory cache + * before being reverified (in case of long-running processes that + * keep a cache in memory and continue to use it for a long time). + */ +#define BLKID_PROBE_INTERVAL 200 + +/* This describes an entire blkid cache file and probed devices. + * We can traverse all of the found devices via bic_list. + * We can traverse all of the tag types by bic_tags, which hold empty tags + * for each tag type. Those tags can be used as list_heads for iterating + * through all devices with a specific tag type (e.g. LABEL). + */ +struct blkid_struct_cache +{ + struct list_head bic_devs; /* List head of all devices */ + struct list_head bic_tags; /* List head of all tag types */ + time_t bic_time; /* Last probe time */ + time_t bic_ftime; /* Mod time of the cachefile */ + unsigned int bic_flags; /* Status flags of the cache */ + char *bic_filename; /* filename of cache */ +}; + +#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */ +#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */ + +extern char *blkid_strdup(const char *s); +extern char *blkid_strndup(const char *s, const int length); + +#define BLKID_CACHE_FILE "/etc/blkid.tab" + +#define BLKID_ERR_IO 5 +#define BLKID_ERR_PROC 9 +#define BLKID_ERR_MEM 12 +#define BLKID_ERR_CACHE 14 +#define BLKID_ERR_DEV 19 +#define BLKID_ERR_PARAM 22 +#define BLKID_ERR_BIG 27 + +/* + * Priority settings for different types of devices + */ +#define BLKID_PRI_DM 40 +#define BLKID_PRI_EVMS 30 +#define BLKID_PRI_LVM 20 +#define BLKID_PRI_MD 10 + +#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG) +#define CONFIG_BLKID_DEBUG +#endif + +#define DEBUG_CACHE 0x0001 +#define DEBUG_DUMP 0x0002 +#define DEBUG_DEV 0x0004 +#define DEBUG_DEVNAME 0x0008 +#define DEBUG_DEVNO 0x0010 +#define DEBUG_PROBE 0x0020 +#define DEBUG_READ 0x0040 +#define DEBUG_RESOLVE 0x0080 +#define DEBUG_SAVE 0x0100 +#define DEBUG_TAG 0x0200 +#define DEBUG_INIT 0x8000 +#define DEBUG_ALL 0xFFFF + +#ifdef CONFIG_BLKID_DEBUG +#include +extern int blkid_debug_mask; +#define DBG(m,x) if ((m) & blkid_debug_mask) x; +#else +#define DBG(m,x) +#endif + +#ifdef CONFIG_BLKID_DEBUG +extern void blkid_debug_dump_dev(blkid_dev dev); +extern void blkid_debug_dump_tag(blkid_tag tag); +#endif + +static inline int blkidP_is_disk_device(mode_t mode) +{ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + return S_ISBLK(mode) || S_ISCHR(mode); +#else + return S_ISBLK(mode); +#endif +} + +/* devno.c */ +struct dir_list { + char *name; + struct dir_list *next; +}; +extern void blkid__scan_dir(const char *, dev_t, struct dir_list **, char **); + +/* lseek.c */ +extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); + +/* read.c */ +extern void blkid_read_cache(blkid_cache cache); + +/* save.c */ +extern int blkid_flush_cache(blkid_cache cache); + +/* + * Functions to create and find a specific tag type: tag.c + */ +extern void blkid_free_tag(blkid_tag tag); +extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); +extern int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength); + +/* + * Functions to create and find a specific tag type: dev.c + */ +extern blkid_dev blkid_new_dev(void); +extern void blkid_free_dev(blkid_dev dev); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLKID_BLKIDP_H */ diff --git a/include/e2fsprogs/blkid/blkid_local.h b/include/e2fsprogs/blkid/blkid_local.h new file mode 100755 index 0000000..81f3098 --- /dev/null +++ b/include/e2fsprogs/blkid/blkid_local.h @@ -0,0 +1,110 @@ +/* + * blkid.h - Interface for libblkid, a library to identify block devices + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _BLKID_BLKID_H +#define _BLKID_BLKID_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLKID_VERSION "1.0.0" +#define BLKID_DATE "12-Feb-2003" + +typedef struct blkid_struct_dev *blkid_dev; +typedef struct blkid_struct_cache *blkid_cache; +typedef __s64 blkid_loff_t; + +typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; +typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; + +/* + * Flags for blkid_get_dev + * + * BLKID_DEV_CREATE Create an empty device structure if not found + * in the cache. + * BLKID_DEV_VERIFY Make sure the device structure corresponds + * with reality. + * BLKID_DEV_FIND Just look up a device entry, and return NULL + * if it is not found. + * BLKID_DEV_NORMAL Get a valid device structure, either from the + * cache or by probing the device. + */ +#define BLKID_DEV_FIND 0x0000 +#define BLKID_DEV_CREATE 0x0001 +#define BLKID_DEV_VERIFY 0x0002 +#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) + +/* cache.c */ +extern void blkid_put_cache(blkid_cache cache); +extern int blkid_get_cache(blkid_cache *cache, const char *filename); +extern void blkid_gc_cache(blkid_cache cache); + +/* dev.c */ +extern const char *blkid_dev_devname(blkid_dev dev); + +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); +extern int blkid_dev_set_search(blkid_dev_iterate iter, + char *search_type, char *search_value); +extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); +extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); + +/* devno.c */ +extern char *blkid_devno_to_devname(dev_t devno); + +/* devname.c */ +extern int blkid_probe_all(blkid_cache cache); +extern int blkid_probe_all_new(blkid_cache cache); +extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, + int flags); + +/* getsize.c */ +extern blkid_loff_t blkid_get_dev_size(int fd); + +/* probe.c */ +int blkid_known_fstype(const char *fstype); +extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev); + +/* read.c */ + +/* resolve.c */ +extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname, + const char *devname); +extern char *blkid_get_devname(blkid_cache cache, const char *token, + const char *value); + +/* tag.c */ +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); +extern int blkid_tag_next(blkid_tag_iterate iterate, + const char **type, const char **value); +extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); +extern int blkid_dev_has_tag(blkid_dev dev, const char *type, + const char *value); +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, + const char *type, + const char *value); +extern int blkid_parse_tag_string(const char *token, char **ret_type, + char **ret_val); + +/* version.c */ +extern int blkid_parse_version_string(const char *ver_string); +extern int blkid_get_library_version(const char **ver_string, + const char **date_string); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLKID_BLKID_H */ diff --git a/include/e2fsprogs/blkid/blkid_types.h b/include/e2fsprogs/blkid/blkid_types.h new file mode 100755 index 0000000..297a69d --- /dev/null +++ b/include/e2fsprogs/blkid/blkid_types.h @@ -0,0 +1,45 @@ +/* + * If linux/types.h is already been included, assume it has defined + * everything we need. (cross fingers) Other header files may have + * also defined the types that we need. + */ +#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \ + !defined(_EXT2_TYPES_H) && !defined(_UUID_TYPES_H)) +#define _BLKID_TYPES_H + +typedef unsigned char __u8; +typedef __signed__ char __s8; +typedef unsigned short __u16; +typedef __signed__ short __s16; +typedef unsigned int __u32; +typedef __signed__ int __s32; +typedef unsigned long long __u64; +typedef __signed__ long long __s64; +#endif + +#include //uintptr_t + +/* endian checking stuff */ +#ifndef EXT2_ENDIAN_H_ +#define EXT2_ENDIAN_H_ + +#ifdef __CHECKER__ +#ifndef __bitwise +#define __bitwise __attribute__((bitwise)) +#endif +#define __force __attribute__((force)) +#else +#ifndef __bitwise +#define __bitwise +#endif +#define __force +#endif + +typedef __u16 __bitwise __le16; +typedef __u32 __bitwise __le32; +typedef __u64 __bitwise __le64; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __be64; + +#endif /* EXT2_ENDIAN_H_ */ diff --git a/include/e2fsprogs/blkid/list.h b/include/e2fsprogs/blkid/list.h new file mode 100755 index 0000000..eb1c513 --- /dev/null +++ b/include/e2fsprogs/blkid/list.h @@ -0,0 +1,184 @@ +#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD_INIT) +#define _BLKID_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +#include +#else +#ifdef HAVE_STDINT_H +#include +#endif +#endif + +#ifdef __GNUC__ +#define _INLINE_ static __inline__ +#else /* For Watcom C */ +#define _INLINE_ static inline +#endif + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +_INLINE_ void __list_add(struct list_head * add, + struct list_head * prev, + struct list_head * next) +{ + next->prev = add; + add->next = next; + add->prev = prev; + prev->next = add; +} + +/** + * list_add - add a new entry + * @add: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +_INLINE_ void list_add(struct list_head *add, struct list_head *head) +{ + __list_add(add, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @add: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head) +{ + __list_add(add, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +_INLINE_ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * + * list_empty() on @entry does not return true after this, @entry is + * in an undefined state. + */ +_INLINE_ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +_INLINE_ void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +_INLINE_ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +_INLINE_ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(intptr_t)(&((type *)0)->member))) + +/** + * list_for_each - iterate over elements in a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_safe - iterate over elements in a list, but don't dereference + * pos after the body is done (in case it is freed) + * @pos: the &struct list_head to use as a loop counter. + * @pnext: the &struct list_head to use as a pointer to the next item. + * @head: the head for your list (not included in iteration). + */ +#define list_for_each_safe(pos, pnext, head) \ + for (pos = (head)->next, pnext = pos->next; pos != (head); \ + pos = pnext, pnext = pos->next) + +#undef _INLINE_ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLKID_LIST_H */ diff --git a/include/e2fsprogs/blkid/probe.h b/include/e2fsprogs/blkid/probe.h new file mode 100755 index 0000000..063a5b5 --- /dev/null +++ b/include/e2fsprogs/blkid/probe.h @@ -0,0 +1,852 @@ +/* + * probe.h - constants and on-disk structures for extracting device data + * + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _BLKID_PROBE_H +#define _BLKID_PROBE_H + +#include + +#include + +struct blkid_magic; + +#define SB_BUFFER_SIZE 0x11000 + +struct blkid_probe { + int fd; + blkid_cache cache; + blkid_dev dev; + unsigned char *sbbuf; + size_t sb_valid; + unsigned char *buf; + size_t buf_max; +}; + +typedef int (*blkid_probe_t)(struct blkid_probe *probe, + struct blkid_magic *id, unsigned char *buf); + +struct blkid_magic { + const char *bim_type; /* type name for this magic */ + long bim_kboff; /* kilobyte offset of superblock */ + unsigned bim_sboff; /* byte offset within superblock */ + unsigned bim_len; /* length of magic */ + const char *bim_magic; /* magic string */ + blkid_probe_t bim_probe; /* probe function */ +}; + +/* + * Structures for each of the content types we want to extract information + * from. We do not necessarily need the magic field here, because we have + * already identified the content type before we get this far. It may still + * be useful if there are probe functions which handle multiple content types. + */ +struct ext2_super_block { + __u32 s_inodes_count; + __u32 s_blocks_count; + __u32 s_r_blocks_count; + __u32 s_free_blocks_count; + __u32 s_free_inodes_count; + __u32 s_first_data_block; + __u32 s_log_block_size; + __u32 s_dummy3[7]; + unsigned char s_magic[2]; + __u16 s_state; + __u32 s_dummy5[8]; + __u32 s_feature_compat; + __u32 s_feature_incompat; + __u32 s_feature_ro_compat; + unsigned char s_uuid[16]; + char s_volume_name[16]; + char s_last_mounted[64]; + __u32 s_algorithm_usage_bitmap; + __u8 s_prealloc_blocks; + __u8 s_prealloc_dir_blocks; + __u16 s_reserved_gdt_blocks; + __u8 s_journal_uuid[16]; + __u32 s_journal_inum; + __u32 s_journal_dev; + __u32 s_last_orphan; + __u32 s_hash_seed[4]; + __u8 s_def_hash_version; + __u8 s_jnl_backup_type; + __u16 s_reserved_word_pad; + __u32 s_default_mount_opts; + __u32 s_first_meta_bg; + __u32 s_mkfs_time; + __u32 s_jnl_blocks[17]; + __u32 s_blocks_count_hi; + __u32 s_r_blocks_count_hi; + __u32 s_free_blocks_hi; + __u16 s_min_extra_isize; + __u16 s_want_extra_isize; + __u32 s_flags; + __u16 s_raid_stride; + __u16 s_mmp_interval; + __u64 s_mmp_block; + __u32 s_raid_stripe_width; + __u32 s_reserved[163]; +}; + +/* for s_flags */ +#define EXT2_FLAGS_TEST_FILESYS 0x0004 + +/* for s_feature_compat */ +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 + +/* for s_feature_ro_compat */ +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 +#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 +#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 + +/* for s_feature_incompat */ +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 + +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP +#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP + +#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT3_FEATURE_INCOMPAT_RECOVER| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP +#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP + + +struct xfs_super_block { + unsigned char xs_magic[4]; + __u32 xs_blocksize; + __u64 xs_dblocks; + __u64 xs_rblocks; + __u32 xs_dummy1[2]; + unsigned char xs_uuid[16]; + __u32 xs_dummy2[15]; + char xs_fname[12]; + __u32 xs_dummy3[2]; + __u64 xs_icount; + __u64 xs_ifree; + __u64 xs_fdblocks; +}; + +struct reiserfs_super_block { + __u32 rs_blocks_count; + __u32 rs_free_blocks; + __u32 rs_root_block; + __u32 rs_journal_block; + __u32 rs_journal_dev; + __u32 rs_orig_journal_size; + __u32 rs_dummy2[5]; + __u16 rs_blocksize; + __u16 rs_dummy3[3]; + unsigned char rs_magic[12]; + __u32 rs_dummy4[5]; + unsigned char rs_uuid[16]; + char rs_label[16]; +}; + +struct reiser4_super_block { + unsigned char rs4_magic[16]; + __u16 rs4_dummy[2]; + unsigned char rs4_uuid[16]; + unsigned char rs4_label[16]; + __u64 rs4_dummy2; +}; + +struct jfs_super_block { + unsigned char js_magic[4]; + __u32 js_version; + __u64 js_size; + __u32 js_bsize; /* 4: aggregate block size in bytes */ + __u16 js_l2bsize; /* 2: log2 of s_bsize */ + __u16 js_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ + __u32 js_pbsize; /* 4: hardware/LVM block size in bytes */ + __u16 js_l2pbsize; /* 2: log2 of s_pbsize */ + __u16 js_pad; /* 2: padding necessary for alignment */ + __u32 js_dummy2[26]; + unsigned char js_uuid[16]; + unsigned char js_label[16]; + unsigned char js_loguuid[16]; +}; + +struct romfs_super_block { + unsigned char ros_magic[8]; + __u32 ros_dummy1[2]; + unsigned char ros_volume[16]; +}; + +struct cramfs_super_block { + __u8 magic[4]; + __u32 size; + __u32 flags; + __u32 future; + __u8 signature[16]; + struct cramfs_info { + __u32 crc; + __u32 edition; + __u32 blocks; + __u32 files; + } info; + __u8 name[16]; +}; + +struct swap_id_block { +/* unsigned char sws_boot[1024]; */ + __u32 sws_version; + __u32 sws_lastpage; + __u32 sws_nrbad; + unsigned char sws_uuid[16]; + char sws_volume[16]; + unsigned char sws_pad[117]; + __u32 sws_badpg; +}; + +/* Yucky misaligned values */ +struct vfat_super_block { +/* 00*/ unsigned char vs_ignored[3]; +/* 03*/ unsigned char vs_sysid[8]; +/* 0b*/ unsigned char vs_sector_size[2]; +/* 0d*/ __u8 vs_cluster_size; +/* 0e*/ __u16 vs_reserved; +/* 10*/ __u8 vs_fats; +/* 11*/ unsigned char vs_dir_entries[2]; +/* 13*/ unsigned char vs_sectors[2]; +/* 15*/ unsigned char vs_media; +/* 16*/ __u16 vs_fat_length; +/* 18*/ __u16 vs_secs_track; +/* 1a*/ __u16 vs_heads; +/* 1c*/ __u32 vs_hidden; +/* 20*/ __u32 vs_total_sect; +/* 24*/ __u32 vs_fat32_length; +/* 28*/ __u16 vs_flags; +/* 2a*/ __u8 vs_version[2]; +/* 2c*/ __u32 vs_root_cluster; +/* 30*/ __u16 vs_insfo_sector; +/* 32*/ __u16 vs_backup_boot; +/* 34*/ __u16 vs_reserved2[6]; +/* 40*/ unsigned char vs_unknown[3]; +/* 43*/ unsigned char vs_serno[4]; +/* 47*/ unsigned char vs_label[11]; +/* 52*/ unsigned char vs_magic[8]; +/* 5a*/ unsigned char vs_dummy2[164]; +/*1fe*/ unsigned char vs_pmagic[2]; +}; + +/* Yucky misaligned values */ +struct msdos_super_block { +/* 00*/ unsigned char ms_ignored[3]; +/* 03*/ unsigned char ms_sysid[8]; +/* 0b*/ unsigned char ms_sector_size[2]; +/* 0d*/ __u8 ms_cluster_size; +/* 0e*/ __u16 ms_reserved; +/* 10*/ __u8 ms_fats; +/* 11*/ unsigned char ms_dir_entries[2]; +/* 13*/ unsigned char ms_sectors[2]; +/* 15*/ unsigned char ms_media; +/* 16*/ __u16 ms_fat_length; +/* 18*/ __u16 ms_secs_track; +/* 1a*/ __u16 ms_heads; +/* 1c*/ __u32 ms_hidden; +/* 20*/ __u32 ms_total_sect; +/* 24*/ unsigned char ms_unknown[3]; +/* 27*/ unsigned char ms_serno[4]; +/* 2b*/ unsigned char ms_label[11]; +/* 36*/ unsigned char ms_magic[8]; +/* 3d*/ unsigned char ms_dummy2[192]; +/*1fe*/ unsigned char ms_pmagic[2]; +}; + +struct vfat_dir_entry { + __u8 name[11]; + __u8 attr; + __u16 time_creat; + __u16 date_creat; + __u16 time_acc; + __u16 date_acc; + __u16 cluster_high; + __u16 time_write; + __u16 date_write; + __u16 cluster_low; + __u32 size; +}; + +/* maximum number of clusters */ +#define FAT12_MAX 0xFF4 +#define FAT16_MAX 0xFFF4 +#define FAT32_MAX 0x0FFFFFF6 + +struct minix_super_block { + __u16 ms_ninodes; + __u16 ms_nzones; + __u16 ms_imap_blocks; + __u16 ms_zmap_blocks; + __u16 ms_firstdatazone; + __u16 ms_log_zone_size; + __u32 ms_max_size; + unsigned char ms_magic[2]; + __u16 ms_state; + __u32 ms_zones; +}; + +struct mdp_superblock_s { + __u32 md_magic; + __u32 major_version; + __u32 minor_version; + __u32 patch_version; + __u32 gvalid_words; + __u32 set_uuid0; + __u32 ctime; + __u32 level; + __u32 size; + __u32 nr_disks; + __u32 raid_disks; + __u32 md_minor; + __u32 not_persistent; + __u32 set_uuid1; + __u32 set_uuid2; + __u32 set_uuid3; +}; + +struct hfs_super_block { + char h_magic[2]; + char h_dummy[18]; + __u32 h_blksize; +}; + +struct ocfs_volume_header { + unsigned char minor_version[4]; + unsigned char major_version[4]; + unsigned char signature[128]; + char mount[128]; + unsigned char mount_len[2]; +}; + +struct ocfs_volume_label { + unsigned char disk_lock[48]; + char label[64]; + unsigned char label_len[2]; + unsigned char vol_id[16]; + unsigned char vol_id_len[2]; +}; + +#define ocfsmajor(o) ((__u32)o.major_version[0] \ + + (((__u32) o.major_version[1]) << 8) \ + + (((__u32) o.major_version[2]) << 16) \ + + (((__u32) o.major_version[3]) << 24)) +#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8)) +#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8)) + +#define OCFS_MAGIC "OracleCFS" + +struct ocfs2_super_block { + unsigned char signature[8]; + unsigned char s_dummy1[184]; + unsigned char s_dummy2[80]; + char s_label[64]; + unsigned char s_uuid[16]; +}; + +#define OCFS2_MIN_BLOCKSIZE 512 +#define OCFS2_MAX_BLOCKSIZE 4096 + +#define OCFS2_SUPER_BLOCK_BLKNO 2 + +#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2" + +struct oracle_asm_disk_label { + char dummy[32]; + char dl_tag[8]; + char dl_id[24]; +}; + +#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK" +#define ORACLE_ASM_DISK_LABEL_OFFSET 32 + +struct iso_volume_descriptor { + unsigned char vd_type; + unsigned char vd_id[5]; + unsigned char vd_version; + unsigned char flags; + unsigned char system_id[32]; + unsigned char volume_id[32]; + unsigned char unused[8]; + unsigned char space_size[8]; + unsigned char escape_sequences[8]; +}; + +/* Common gfs/gfs2 constants: */ +#define GFS_MAGIC 0x01161970 +#define GFS_DEFAULT_BSIZE 4096 +#define GFS_SUPERBLOCK_OFFSET (0x10 * GFS_DEFAULT_BSIZE) +#define GFS_METATYPE_SB 1 +#define GFS_FORMAT_SB 100 +#define GFS_LOCKNAME_LEN 64 + +/* gfs1 constants: */ +#define GFS_FORMAT_FS 1309 +#define GFS_FORMAT_MULTI 1401 +/* gfs2 constants: */ +#define GFS2_FORMAT_FS 1801 +#define GFS2_FORMAT_MULTI 1900 + +struct gfs2_meta_header { + __u32 mh_magic; + __u32 mh_type; + __u64 __pad0; /* Was generation number in gfs1 */ + __u32 mh_format; + __u32 __pad1; /* Was incarnation number in gfs1 */ +}; + +struct gfs2_inum { + __u64 no_formal_ino; + __u64 no_addr; +}; + +struct gfs2_sb { + struct gfs2_meta_header sb_header; + + __u32 sb_fs_format; + __u32 sb_multihost_format; + __u32 __pad0; /* Was superblock flags in gfs1 */ + + __u32 sb_bsize; + __u32 sb_bsize_shift; + __u32 __pad1; /* Was journal segment size in gfs1 */ + + struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ + struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ + struct gfs2_inum sb_root_dir; + + char sb_lockproto[GFS_LOCKNAME_LEN]; + char sb_locktable[GFS_LOCKNAME_LEN]; + /* In gfs1, quota and license dinodes followed */ +}; + +struct ntfs_super_block { + __u8 jump[3]; + __u8 oem_id[8]; + __u8 bios_parameter_block[25]; + __u16 unused[2]; + __u64 number_of_sectors; + __u64 mft_cluster_location; + __u64 mft_mirror_cluster_location; + __s8 cluster_per_mft_record; + __u8 reserved1[3]; + __s8 cluster_per_index_record; + __u8 reserved2[3]; + __u64 volume_serial; + __u16 checksum; +}; + +struct master_file_table_record { + __u32 magic; + __u16 usa_ofs; + __u16 usa_count; + __u64 lsn; + __u16 sequence_number; + __u16 link_count; + __u16 attrs_offset; + __u16 flags; + __u32 bytes_in_use; + __u32 bytes_allocated; +} __attribute__((__packed__)); + +struct file_attribute { + __u32 type; + __u32 len; + __u8 non_resident; + __u8 name_len; + __u16 name_offset; + __u16 flags; + __u16 instance; + __u32 value_len; + __u16 value_offset; +} __attribute__((__packed__)); + +#define MFT_RECORD_VOLUME 3 +#define MFT_RECORD_ATTR_VOLUME_NAME 0x60 +#define MFT_RECORD_ATTR_VOLUME_INFO 0x70 +#define MFT_RECORD_ATTR_OBJECT_ID 0x40 +#define MFT_RECORD_ATTR_END 0xffffffffu + +/* HFS / HFS+ */ +struct hfs_finder_info { + __u32 boot_folder; + __u32 start_app; + __u32 open_folder; + __u32 os9_folder; + __u32 reserved; + __u32 osx_folder; + __u8 id[8]; +} __attribute__((packed)); + +struct hfs_mdb { + __u8 signature[2]; + __u32 cr_date; + __u32 ls_Mod; + __u16 atrb; + __u16 nm_fls; + __u16 vbm_st; + __u16 alloc_ptr; + __u16 nm_al_blks; + __u32 al_blk_size; + __u32 clp_size; + __u16 al_bl_st; + __u32 nxt_cnid; + __u16 free_bks; + __u8 label_len; + __u8 label[27]; + __u32 vol_bkup; + __u16 vol_seq_num; + __u32 wr_cnt; + __u32 xt_clump_size; + __u32 ct_clump_size; + __u16 num_root_dirs; + __u32 file_count; + __u32 dir_count; + struct hfs_finder_info finder_info; + __u8 embed_sig[2]; + __u16 embed_startblock; + __u16 embed_blockcount; +} __attribute__((packed)); + + +#define HFS_NODE_LEAF 0xff +#define HFSPLUS_POR_CNID 1 + +struct hfsplus_bnode_descriptor { + __u32 next; + __u32 prev; + __u8 type; + __u8 height; + __u16 num_recs; + __u16 reserved; +} __attribute__((packed)); + +struct hfsplus_bheader_record { + __u16 depth; + __u32 root; + __u32 leaf_count; + __u32 leaf_head; + __u32 leaf_tail; + __u16 node_size; +} __attribute__((packed)); + +struct hfsplus_catalog_key { + __u16 key_len; + __u32 parent_id; + __u16 unicode_len; + __u8 unicode[255 * 2]; +} __attribute__((packed)); + +struct hfsplus_extent { + __u32 start_block; + __u32 block_count; +} __attribute__((packed)); + +#define HFSPLUS_EXTENT_COUNT 8 +struct hfsplus_fork { + __u64 total_size; + __u32 clump_size; + __u32 total_blocks; + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; +} __attribute__((packed)); + +struct hfsplus_vol_header { + __u8 signature[2]; + __u16 version; + __u32 attributes; + __u32 last_mount_vers; + __u32 reserved; + __u32 create_date; + __u32 modify_date; + __u32 backup_date; + __u32 checked_date; + __u32 file_count; + __u32 folder_count; + __u32 blocksize; + __u32 total_blocks; + __u32 free_blocks; + __u32 next_alloc; + __u32 rsrc_clump_sz; + __u32 data_clump_sz; + __u32 next_cnid; + __u32 write_count; + __u64 encodings_bmp; + struct hfs_finder_info finder_info; + struct hfsplus_fork alloc_file; + struct hfsplus_fork ext_file; + struct hfsplus_fork cat_file; + struct hfsplus_fork attr_file; + struct hfsplus_fork start_file; +} __attribute__((packed)); + + +/* this is lvm's label_header & pv_header combined. */ + +#define LVM2_ID_LEN 32 + +struct lvm2_pv_label_header { + /* label_header */ + __u8 id[8]; /* LABELONE */ + __u64 sector_xl; /* Sector number of this label */ + __u32 crc_xl; /* From next field to end of sector */ + __u32 offset_xl; /* Offset from start of struct to contents */ + __u8 type[8]; /* LVM2 001 */ + /* pv_header */ + __u8 pv_uuid[LVM2_ID_LEN]; +} __attribute__ ((packed)); + + +/* + * this is a very generous portion of the super block, giving us + * room to translate 14 chunks with 3 stripes each. + */ +#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048 +#define BTRFS_LABEL_SIZE 256 +#define BTRFS_UUID_SIZE 16 +#define BTRFS_FSID_SIZE 16 +#define BTRFS_CSUM_SIZE 32 + +struct btrfs_dev_item { + /* the internal btrfs device id */ + __u64 devid; + + /* size of the device */ + __u64 total_bytes; + + /* bytes used */ + __u64 bytes_used; + + /* optimal io alignment for this device */ + __u32 io_align; + + /* optimal io width for this device */ + __u32 io_width; + + /* minimal io size for this device */ + __u32 sector_size; + + /* type and info about this device */ + __u64 type; + + /* expected generation for this device */ + __u64 generation; + + /* + * starting byte of this partition on the device, + * to allow for stripe alignment in the future + */ + __u64 start_offset; + + /* grouping information for allocation decisions */ + __u32 dev_group; + + /* seek speed 0-100 where 100 is fastest */ + __u8 seek_speed; + + /* bandwidth 0-100 where 100 is fastest */ + __u8 bandwidth; + + /* btrfs generated uuid for this device */ + __u8 uuid[BTRFS_UUID_SIZE]; + + /* uuid of FS who owns this device */ + __u8 fsid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +/* + * the super block basically lists the main trees of the FS + * it currently lacks any block count etc etc + */ +struct btrfs_super_block { + __u8 csum[BTRFS_CSUM_SIZE]; + /* the first 3 fields must match struct btrfs_header */ + __u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ + __u64 bytenr; /* this block number */ + __u64 flags; + + /* allowed to be different from the btrfs_header from here own down */ + __u64 magic; + __u64 generation; + __u64 root; + __u64 chunk_root; + __u64 log_root; + + /* this will help find the new super based on the log root */ + __u64 log_root_transid; + __u64 total_bytes; + __u64 bytes_used; + __u64 root_dir_objectid; + __u64 num_devices; + __u32 sectorsize; + __u32 nodesize; + __u32 leafsize; + __u32 stripesize; + __u32 sys_chunk_array_size; + __u64 chunk_root_generation; + __u64 compat_flags; + __u64 compat_ro_flags; + __u64 incompat_flags; + __u16 csum_type; + __u8 root_level; + __u8 chunk_root_level; + __u8 log_root_level; + struct btrfs_dev_item dev_item; + + char label[BTRFS_LABEL_SIZE]; + + /* future expansion */ + __u64 reserved[32]; + __u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; +} __attribute__ ((__packed__)); + +#define F2FS_MAX_EXTENSION 64 /* # of extension entries */ + +struct f2fs_super_block { + __u32 magic; /* Magic Number */ + __u16 major_ver; /* Major Version */ + __u16 minor_ver; /* Minor Version */ + __u32 log_sectorsize; /* log2 sector size in bytes */ + __u32 log_sectors_per_block; /* log2 # of sectors per block */ + __u32 log_blocksize; /* log2 block size in bytes */ + __u32 log_blocks_per_seg; /* log2 # of blocks per segment */ + __u32 segs_per_sec; /* # of segments per section */ + __u32 secs_per_zone; /* # of sections per zone */ + __u32 checksum_offset; /* checksum offset inside super block */ + __u64 block_count; /* total # of user blocks */ + __u32 section_count; /* total # of sections */ + __u32 segment_count; /* total # of segments */ + __u32 segment_count_ckpt; /* # of segments for checkpoint */ + __u32 segment_count_sit; /* # of segments for SIT */ + __u32 segment_count_nat; /* # of segments for NAT */ + __u32 segment_count_ssa; /* # of segments for SSA */ + __u32 segment_count_main; /* # of segments for main area */ + __u32 segment0_blkaddr; /* start block address of segment 0 */ + __u32 cp_blkaddr; /* start block address of checkpoint */ + __u32 sit_blkaddr; /* start block address of SIT */ + __u32 nat_blkaddr; /* start block address of NAT */ + __u32 ssa_blkaddr; /* start block address of SSA */ + __u32 main_blkaddr; /* start block address of main area */ + __u32 root_ino; /* root inode number */ + __u32 node_ino; /* node inode number */ + __u32 meta_ino; /* meta inode number */ + __u8 uuid[16]; /* 128-bit uuid for volume */ + __u16 volume_name[512]; /* volume name */ + __u32 extension_count; /* # of extensions below */ + __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */ +} __attribute__((__packed__)); + +struct exfat_super_block { + uint8_t jump[3]; + uint8_t oem_name[8]; + uint8_t __unused1[53]; + uint64_t block_start; + uint64_t block_count; + uint32_t fat_block_start; + uint32_t fat_block_count; + uint32_t cluster_block_start; + uint32_t cluster_count; + uint32_t rootdir_cluster; + uint8_t volume_serial[4]; + struct { + uint8_t vermin; + uint8_t vermaj; + } version; + uint16_t volume_state; + uint8_t block_bits; + uint8_t bpc_bits; + uint8_t fat_count; + uint8_t drive_no; + uint8_t allocated_percent; +} __attribute__((__packed__)); + +struct exfat_entry_label { + uint8_t type; + uint8_t length; + uint8_t name[30]; +} __attribute__((__packed__)); + +#define BLOCK_SIZE(sb) (1 << (sb)->block_bits) +#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits) + +#define EXFAT_FIRST_DATA_CLUSTER 2 +#define EXFAT_LAST_DATA_CLUSTER 0xffffff6 +#define EXFAT_ENTRY_SIZE 32 + +#define EXFAT_ENTRY_EOD 0x00 +#define EXFAT_ENTRY_LABEL 0x83 + +/* + * Byte swap functions + */ +#ifdef __GNUC__ +#define _INLINE_ static __inline__ +#else /* For Watcom C */ +#define _INLINE_ static inline +#endif + +_INLINE_ __u16 blkid_swab16(__u16 val) +{ + return (val >> 8) | (val << 8); +} + +_INLINE_ __u32 blkid_swab32(__u32 val) +{ + return ((val>>24) | ((val>>8)&0xFF00) | + ((val<<8)&0xFF0000) | (val<<24)); +} + +_INLINE_ __u64 blkid_swab64(__u64 val) +{ + return (blkid_swab32(val >> 32) | + (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); +} + +#ifdef WORDS_BIGENDIAN +#define blkid_le16(x) blkid_swab16(x) +#define blkid_le32(x) blkid_swab32(x) +#define blkid_le64(x) blkid_swab64(x) +#define blkid_be16(x) (x) +#define blkid_be32(x) (x) +#define blkid_be64(x) (x) +#else +#define blkid_le16(x) (x) +#define blkid_le32(x) (x) +#define blkid_le64(x) (x) +#define blkid_be16(x) blkid_swab16(x) +#define blkid_be32(x) blkid_swab32(x) +#define blkid_be64(x) blkid_swab64(x) +#endif + +#undef _INLINE_ + +#endif /* _BLKID_PROBE_H */ diff --git a/include/e2fsprogs/config.h b/include/e2fsprogs/config.h new file mode 100755 index 0000000..636b534 --- /dev/null +++ b/include/e2fsprogs/config.h @@ -0,0 +1,678 @@ +/* lib/config.h. Generated from config.h.in by configure. */ +/* lib/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if debugging the blkid library */ +/* #undef CONFIG_BLKID_DEBUG */ + +/* Define to 1 to compile findfs */ +/* #undef CONFIG_BUILD_FINDFS */ + +/* Define to 1 for features for use by ext4 developers */ +/* #undef CONFIG_DEVELOPER_FEATURES */ + +/* Define to 1 if using dlopen to access libarchive */ +#define CONFIG_DLOPEN_LIBARCHIVE 1 + +/* Define to 1 if debugging ext3/4 journal code */ +/* #undef CONFIG_JBD_DEBUG */ + +/* Define to 1 to enable mmp support */ +#define CONFIG_MMP 1 + +/* Define to 1 to enable tdb support */ +#define CONFIG_TDB 1 + +/* Define to 1 if the testio I/O manager should be enabled */ +#define CONFIG_TESTIO_DEBUG 1 + +/* Define to 1 to disable use of backtrace */ +/* #undef DISABLE_BACKTRACE */ + +/* Define to 1 to enable bitmap stats. */ +#define ENABLE_BMAP_STATS 1 + +/* Define to 1 to enable bitmap stats. */ +/* #undef ENABLE_BMAP_STATS_OPS */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +/* #undef ENABLE_NLS */ + +/* Define to the version of FUSE to use */ +#define FUSE_USE_VERSION 29 + +/* Define to 1 if you have the `add_key' function. */ +/* #undef HAVE_ADD_KEY */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARCHIVE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ATTR_XATTR_H */ + +/* Define to 1 if you have the `backtrace' function. */ +#define HAVE_BACKTRACE 1 + +/* Define to 1 if blkid has blkid_probe_enable_partitions */ +// #define HAVE_BLKID_PROBE_ENABLE_PARTITIONS 1 + +/* Define to 1 if blkid has blkid_probe_get_topology */ +/* #undef HAVE_BLKID_PROBE_GET_TOPOLOGY */ + +/* Define to 1 if blkid has blkid_topology_get_dax */ +/* #undef HAVE_BLKID_TOPOLOGY_GET_DAX */ + +/* Define to 1 if you have the BSD-style 'qsort_r' function. */ +/* #undef HAVE_BSD_QSORT_R */ + +/* Define to 1 if you have the Mac OS X function + CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define to 1 if you have the `chflags' function. */ +/* #undef HAVE_CHFLAGS */ + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +/* #undef HAVE_DCGETTEXT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the `dlopen' function. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_EXECINFO_H 1 + +/* Define to 1 if Ext2 ioctls present */ +#define HAVE_EXT2_IOCTLS 1 + +/* Define to 1 if you have the `fadvise64' function. */ +/* #undef HAVE_FADVISE64 */ + +/* Define to 1 if you have the `fallocate' function. */ +#define HAVE_FALLOCATE 1 + +/* Define to 1 if you have the `fallocate64' function. */ +#define HAVE_FALLOCATE64 1 + +/* Define to 1 if you have the `fchown' function. */ +#define HAVE_FCHOWN 1 + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the `fdatasync' function. */ +#define HAVE_FDATASYNC 1 + +/* Define to 1 if fsmap_sizeof() is declared in linux/fsmap.h */ +/* #undef HAVE_FSMAP_SIZEOF */ + +/* Define to 1 if you have the `fstat64' function. */ +#define HAVE_FSTAT64 1 + +/* Define to 1 if you have the `fsync' function. */ +#define HAVE_FSYNC 1 + +/* Define to 1 if you have the `ftruncate64' function. */ +#define HAVE_FTRUNCATE64 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FUSE_H 1 + +/* Define to 1 if you have the `futimes' function. */ +#define HAVE_FUTIMES 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getdtablesize' function. */ +/* #undef HAVE_GETDTABLESIZE */ + +/* Define to 1 if you have the `getentropy' function. */ +#define HAVE_GETENTROPY 1 + +/* Define to 1 if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the `getmntinfo' function. */ +/* #undef HAVE_GETMNTINFO */ + +/* Define to 1 if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrandom' function. */ +#define HAVE_GETRANDOM 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +/* #undef HAVE_GETTEXT */ + +/* Define to 1 if you have the GNU-style 'qsort_r' function. */ +/* #undef HAVE_GNU_QSORT_R */ + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `jrand48' function. */ +#define HAVE_JRAND48 1 + +/* Define to 1 if you have the `keyctl' function. */ +/* #undef HAVE_KEYCTL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_FALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_FD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_FSMAP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_LOOP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_MAJOR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the `llistxattr' function. */ +#define HAVE_LLISTXATTR 1 + +/* Define to 1 if you have the `llseek' function. */ +/* #undef HAVE_LLSEEK */ + +/* Define to 1 if llseek declared in unistd.h */ +/* #undef HAVE_LLSEEK_PROTOTYPE */ + +/* Define to 1 if you have the `lseek64' function. */ +#define HAVE_LSEEK64 1 + +/* Define to 1 if lseek64 declared in unistd.h */ +#define HAVE_LSEEK64_PROTOTYPE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MAGIC_H 1 + +/* Define to 1 if you have the `mallinfo' function. */ +#define HAVE_MALLINFO 1 + +/* Define to 1 if you have the `mallinfo2' function. */ +/* #undef HAVE_MALLINFO2 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `mbstowcs' function. */ +#define HAVE_MBSTOWCS 1 + +/* Define to 1 if you have the `memalign' function. */ +#define HAVE_MEMALIGN 1 + +/* Define to 1 if you have the `mempcpy' function. */ +#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MINIX_CONFIG_H */ + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MNTENT_H 1 + +/* Define to 1 if mount supports nodev. */ +#define HAVE_MOUNT_NODEV 1 + +/* Define to 1 if mount supports nosuid. */ +#define HAVE_MOUNT_NOSUID 1 + +/* Define to 1 if you have the `msync' function. */ +#define HAVE_MSYNC 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NET_IF_DL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the `open64' function. */ +#define HAVE_OPEN64 1 + +/* Define to 1 if optreset for getopt is present */ +/* #undef HAVE_OPTRESET */ + +/* Define to 1 if you have the `pathconf' function. */ +#define HAVE_PATHCONF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PATHS_H 1 + +/* Define to 1 if you have the `posix_fadvise' function. */ +#define HAVE_POSIX_FADVISE 1 + +/* Define to 1 if you have the `posix_fadvise64' function. */ +#define HAVE_POSIX_FADVISE64 1 + +/* Define to 1 if you have the `posix_memalign' function. */ +#define HAVE_POSIX_MEMALIGN 1 + +/* Define to 1 if you have the `prctl' function. */ +#define HAVE_PRCTL 1 + +/* Define to 1 if you have the `pread' function. */ +#define HAVE_PREAD 1 + +/* Define to 1 if you have the `pread64' function. */ +#define HAVE_PREAD64 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if you have the `pwrite' function. */ +#define HAVE_PWRITE 1 + +/* Define to 1 if you have the `pwrite64' function. */ +#define HAVE_PWRITE64 1 + +/* Define to 1 if you have the `qsort_r' function. */ +/* #undef HAVE_QSORT_R */ + +/* Define to 1 if dirent has d_reclen */ +#define HAVE_RECLEN_DIRENT 1 + +/* Define to 1 if if struct sockaddr contains sa_len */ +/* #undef HAVE_SA_LEN */ + +/* Define to 1 if you have the `secure_getenv' function. */ +/* #undef HAVE_SECURE_GETENV */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SEMAPHORE_H 1 + +/* Define to 1 if sem_init() exists */ +/* #undef HAVE_SEM_INIT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setmntent' function. */ +#define HAVE_SETMNTENT 1 + +/* Define to 1 if you have the `setresgid' function. */ +#define HAVE_SETRESGID 1 + +/* Define to 1 if you have the `setresuid' function. */ +#define HAVE_SETRESUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `srandom' function. */ +#define HAVE_SRANDOM 1 + +/* Define to 1 if struct stat has st_flags */ +/* #undef HAVE_STAT_FLAGS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strptime' function. */ +#define HAVE_STRPTIME 1 + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if `st_atim' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_ATIM 1 + +/* Define to 1 if you have the `sync_file_range' function. */ +#define HAVE_SYNC_FILE_RANGE 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ACL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_DISKLABEL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_DISK_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_KEY_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MKDEV_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PRCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RANDOM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SYSCALL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SYSMACROS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if ssize_t declared */ +#define HAVE_TYPE_SSIZE_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `usleep' function. */ +#define HAVE_USLEEP 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the `valloc' function. */ +/* #undef HAVE_VALLOC */ + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `__secure_getenv' function. */ +/* #undef HAVE___SECURE_GETENV */ + +/* package name for gettext */ +#define PACKAGE "e2fsprogs" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* If the compiler supports a TLS storage class define it to that here */ +#define TLS __thread + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# define _HPUX_ALT_XOPEN_SOCKET_API 1 +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +/* # undef _MINIX */ +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# define _OPENBSD_SOURCE 1 +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +/* # undef _POSIX_SOURCE */ +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +/* # undef _POSIX_1_SOURCE */ +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# define __STDC_WANT_IEC_60559_BFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# define __STDC_WANT_IEC_60559_DFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# define __STDC_WANT_LIB_EXT2__ 1 +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# define __STDC_WANT_MATH_SPEC_FUNCS__ 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +/* # undef _XOPEN_SOURCE */ +#endif + + +/* Define to 1 to build uuidd */ +#define USE_UUIDD 1 + +/* version for gettext */ +#define VERSION "0.14.1" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 if Apple Darwin libintl workaround is needed */ +/* #undef _INTL_REDIRECT_MACROS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +#include diff --git a/include/e2fsprogs/dirpaths.h b/include/e2fsprogs/dirpaths.h new file mode 100755 index 0000000..09022ff --- /dev/null +++ b/include/e2fsprogs/dirpaths.h @@ -0,0 +1,10 @@ +/* + * This file contains the path names for various directories as + * controlled by the configure script. + */ + +/* Where to put the messages file for internationalization support */ +#define LOCALEDIR "/usr/share/locale" + +/* Where to find the mke2fs.conf and e2fsck.conf files */ +#define ROOT_SYSCONFDIR "/etc" diff --git a/include/e2fsprogs/e2p/e2p.h b/include/e2fsprogs/e2p/e2p.h new file mode 100755 index 0000000..5f4793e --- /dev/null +++ b/include/e2fsprogs/e2p/e2p.h @@ -0,0 +1,92 @@ +/* + * e2p.h --- header file for the e2p library + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include /* Needed by dirent.h on netbsd */ +#include +#include + +#include + +#define E2P_FEATURE_COMPAT 0 +#define E2P_FEATURE_INCOMPAT 1 +#define E2P_FEATURE_RO_INCOMPAT 2 +#define E2P_FEATURE_TYPE_MASK 0x03 + +#define E2P_FEATURE_NEGATE_FLAG 0x80 + +#define E2P_FS_FEATURE 0 +#define E2P_JOURNAL_FEATURE 1 + +/* `options' for print_flags() */ + +#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */ + + +int fgetflags (const char * name, unsigned long * flags); +int fgetversion (const char * name, unsigned long * version); +int fsetflags (const char * name, unsigned long flags); +int fsetversion (const char * name, unsigned long version); +int fgetproject(const char *name, unsigned long *project); +int fsetproject(const char *name, unsigned long project); +int getflags (int fd, unsigned long * flags); +int getversion (int fd, unsigned long * version); +int iterate_on_dir (const char * dir_name, + int (*func) (const char *, struct dirent *, void *), + void * private_arg); +void list_super(struct ext2_super_block * s); +void list_super2(struct ext2_super_block * s, FILE *f); +void print_fs_errors (FILE * f, unsigned short errors); +void print_flags (FILE * f, unsigned long flags, unsigned options); +void print_fs_state (FILE * f, unsigned short state); +int setflags (int fd, unsigned long flags); +int setversion (int fd, unsigned long version); + +#define E2P_LIST_JOURNAL_FLAG_FC 0x1 +void e2p_list_journal_super(FILE *f, char *journal_sb_buf, + int exp_block_size, int flags); + +void e2p_feature_to_string(int compat, unsigned int mask, char *buf, + size_t buf_len); +const char *e2p_feature2string(int compat, unsigned int mask); +const char *e2p_jrnl_feature2string(int compat, unsigned int mask); +int e2p_string2feature(char *string, int *compat, unsigned int *mask); +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask); +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array); +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err); + +int e2p_is_null_uuid(void *uu); +void e2p_uuid_to_str(void *uu, char *out); +const char *e2p_uuid2str(void *uu); + +const char *e2p_hash2string(int num); +int e2p_string2hash(char *string); + +const char *e2p_mntopt2string(unsigned int mask); +int e2p_string2mntopt(char *string, unsigned int *mask); +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok); + +unsigned long parse_num_blocks(const char *arg, int log_block_size); +unsigned long long parse_num_blocks2(const char *arg, int log_block_size); + +char *e2p_os2string(int os_type); +int e2p_string2os(char *str); + +unsigned int e2p_percent(int percent, unsigned int base); + +const char *e2p_encmode2string(int num); +int e2p_string2encmode(char *string); + +int e2p_str2encoding(const char *string); +const char *e2p_encoding2str(int encoding); +int e2p_get_encoding_flags(int encoding); +int e2p_str2encoding_flags(int encoding, char *param, __u16 *flags); + +const char *e2p_errcode2str(unsigned int err); diff --git a/include/e2fsprogs/e2p/project.h b/include/e2fsprogs/e2p/project.h new file mode 100755 index 0000000..253425a --- /dev/null +++ b/include/e2fsprogs/e2p/project.h @@ -0,0 +1,27 @@ +/* + * project.h + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include + +#if defined(__linux__) && !defined(FS_IOC_FSGETXATTR) +#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr) +#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) + +/* + * Structure for FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR. + */ +struct fsxattr { + __u32 fsx_xflags; /* xflags field value (get/set) */ + __u32 fsx_extsize; /* extsize field value (get/set)*/ + __u32 fsx_nextents; /* nextents field value (get) */ + __u32 fsx_projid; /* project identifier (get/set) */ + unsigned char fsx_pad[12]; +}; +#endif + diff --git a/include/e2fsprogs/et/com_err.h b/include/e2fsprogs/et/com_err.h new file mode 100755 index 0000000..27a36ea --- /dev/null +++ b/include/e2fsprogs/et/com_err.h @@ -0,0 +1,68 @@ +/* + * Header file for common error description library. + * + * Copyright 1988, Student Information Processing Board of the + * Massachusetts Institute of Technology. + * + * For copyright and distribution info, see the documentation supplied + * with this package. + */ + +#if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__) + +#ifdef __GNUC__ +#define COM_ERR_ATTR(x) __attribute__(x) +#else +#define COM_ERR_ATTR(x) +#endif + +#include +#include + +typedef long errcode_t; + +struct error_table { + char const * const * msgs; + long base; + int n_msgs; +}; +struct et_list; + +extern void com_err (const char *, long, const char *, ...) + COM_ERR_ATTR((format(printf, 3, 4))); + +extern void com_err_va (const char *whoami, errcode_t code, const char *fmt, + va_list args) + COM_ERR_ATTR((format(printf, 3, 0))); + +extern char const *error_message (long); +extern void (*com_err_hook) (const char *, long, const char *, va_list); +extern void (*set_com_err_hook (void (*) (const char *, long, + const char *, va_list))) + (const char *, long, const char *, va_list); +extern void (*reset_com_err_hook (void)) (const char *, long, + const char *, va_list); +extern int init_error_table(const char * const *msgs, long base, int count); +extern char *(*set_com_err_gettext (char *(*) (const char *))) + (const char *); + +extern errcode_t add_error_table(const struct error_table * et); +extern errcode_t remove_error_table(const struct error_table * et); +extern void add_to_error_table(struct et_list *new_table); + +/* Provided for Heimdall compatibility */ +extern const char *com_right(struct et_list *list, long code); +extern const char *com_right_r(struct et_list *list, long code, char *str, size_t len); +extern void initialize_error_table_r(struct et_list **list, + const char **messages, + int num_errors, + long base); +extern void free_error_table(struct et_list *et); + +/* Provided for compatibility with other com_err libraries */ +extern int et_list_lock(void); +extern int et_list_unlock(void); + +#define __COM_ERR_H +#define __COM_ERR_H__ +#endif /* !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)*/ diff --git a/include/e2fsprogs/et/error_table.h b/include/e2fsprogs/et/error_table.h new file mode 100755 index 0000000..24e4762 --- /dev/null +++ b/include/e2fsprogs/et/error_table.h @@ -0,0 +1,29 @@ +/* + * Copyright 1988 by the Student Information Processing Board of the + * Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#ifndef _ET_H + +struct et_list { + struct et_list *next; + const struct error_table *table; +}; +extern struct et_list *_et_list, *_et_dynamic_list; + +#define ERRCODE_RANGE 8 /* # of bits to shift table number */ +#define BITS_PER_CHAR 6 /* # bits to shift per character in name */ + +extern const char *error_table_name(errcode_t num); + +#define _ET_H +#endif diff --git a/include/e2fsprogs/et/internal.h b/include/e2fsprogs/et/internal.h new file mode 100755 index 0000000..d16f373 --- /dev/null +++ b/include/e2fsprogs/et/internal.h @@ -0,0 +1,19 @@ +/* + * internal include file for com_err package + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include + +#ifdef NEED_SYS_ERRLIST +extern char const * const sys_errlist[]; +extern const int sys_nerr; +#endif diff --git a/include/e2fsprogs/ext2fs/bitops.h b/include/e2fsprogs/ext2fs/bitops.h new file mode 100755 index 0000000..9edf594 --- /dev/null +++ b/include/e2fsprogs/ext2fs/bitops.h @@ -0,0 +1,606 @@ +/* + * bitops.h --- Bitmap frobbing code. The byte swapping routines are + * also included here. + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifdef WORDS_BIGENDIAN +#define ext2fs_cpu_to_le64(x) ((__force __le64)ext2fs_swab64((__u64)(x))) +#define ext2fs_le64_to_cpu(x) ext2fs_swab64((__force __u64)(__le64)(x)) +#define ext2fs_cpu_to_le32(x) ((__force __le32)ext2fs_swab32((__u32)(x))) +#define ext2fs_le32_to_cpu(x) ext2fs_swab32((__force __u32)(__le32)(x)) +#define ext2fs_cpu_to_le16(x) ((__force __le16)ext2fs_swab16((__u16)(x))) +#define ext2fs_le16_to_cpu(x) ext2fs_swab16((__force __u16)(__le16)(x)) + +#define ext2fs_cpu_to_be64(x) ((__force __be64)(__u64)(x)) +#define ext2fs_be64_to_cpu(x) ((__force __u64)(__be64)(x)) +#define ext2fs_cpu_to_be32(x) ((__force __be32)(__u32)(x)) +#define ext2fs_be32_to_cpu(x) ((__force __u32)(__be32)(x)) +#define ext2fs_cpu_to_be16(x) ((__force __be16)(__u16)(x)) +#define ext2fs_be16_to_cpu(x) ((__force __u16)(__be16)(x)) +#else +#define ext2fs_cpu_to_le64(x) ((__force __le64)(__u64)(x)) +#define ext2fs_le64_to_cpu(x) ((__force __u64)(__le64)(x)) +#define ext2fs_cpu_to_le32(x) ((__force __le32)(__u32)(x)) +#define ext2fs_le32_to_cpu(x) ((__force __u32)(__le32)(x)) +#define ext2fs_cpu_to_le16(x) ((__force __le16)(__u16)(x)) +#define ext2fs_le16_to_cpu(x) ((__force __u16)(__le16)(x)) + +#define ext2fs_cpu_to_be64(x) ((__force __be64)ext2fs_swab64((__u64)(x))) +#define ext2fs_be64_to_cpu(x) ext2fs_swab64((__force __u64)(__be64)(x)) +#define ext2fs_cpu_to_be32(x) ((__force __be32)ext2fs_swab32((__u32)(x))) +#define ext2fs_be32_to_cpu(x) ext2fs_swab32((__force __u32)(__be32)(x)) +#define ext2fs_cpu_to_be16(x) ((__force __be16)ext2fs_swab16((__u16)(x))) +#define ext2fs_be16_to_cpu(x) ext2fs_swab16((__force __u16)(__be16)(x)) +#endif + +/* + * EXT2FS bitmap manipulation routines. + */ + +/* Support for sending warning messages from the inline subroutines */ +extern const char *ext2fs_block_string; +extern const char *ext2fs_inode_string; +extern const char *ext2fs_mark_string; +extern const char *ext2fs_unmark_string; +extern const char *ext2fs_test_string; +extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, + const char *description); +extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, + int code, unsigned long arg); + +#ifdef NO_INLINE_FUNCS +extern void ext2fs_fast_set_bit(unsigned int nr,void * addr); +extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr); +extern void ext2fs_fast_set_bit64(__u64 nr,void * addr); +extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr); +extern __u16 ext2fs_swab16(__u16 val); +extern __u32 ext2fs_swab32(__u32 val); +extern __u64 ext2fs_swab64(__u64 val); + +extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); +extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); + +extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); +extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); + +extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); + +extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap); +extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap); + +extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +#endif + +/* These functions routines moved to gen_bitmap.c */ +extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode, int num); +extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 bitno); +extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno); +extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno); +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map); +extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap); +extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap); + +/* 64-bit versions */ + +#ifdef NO_INLINE_FUNCS +extern int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); +extern int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); +extern int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); + +extern int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); + +extern void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); +extern void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); +extern int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block); + +extern void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t start, + blk64_t end, + blk64_t *out); +extern errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t start, + ext2_ino_t end, + ext2_ino_t *out); +extern errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t start, + blk64_t end, + blk64_t *out); +extern errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t start, + ext2_ino_t end, + ext2_ino_t *out); +extern blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap); +extern blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap); + +extern int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num); +extern void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num); +extern void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num); +#endif + +/* These routines moved to gen_bitmap64.c */ +extern void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap); +extern errcode_t ext2fs_compare_generic_bmap(errcode_t neq, + ext2fs_generic_bitmap bm1, + ext2fs_generic_bitmap bm2); +extern void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap); +extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap, + blk64_t bitno); +extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap, + blk64_t bitno); +extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap, + blk64_t bitno); +extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, unsigned int num); +extern __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap); +extern __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap); +extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, unsigned int num); +extern void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, unsigned int num); +extern void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, unsigned int num); +extern errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 start, __u64 end, + __u64 *out); +extern errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 start, __u64 end, + __u64 *out); + +/* + * The inline routines themselves... + * + * If NO_INLINE_FUNCS is defined, then we won't try to do inline + * functions at all; they will be included as normal functions in + * inline.c + */ + +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +#ifdef INCLUDE_INLINE_FUNCS +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ extern inline +#else +#define _INLINE_ inline +#endif +#else /* !INCLUDE_INLINE FUNCS */ +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ inline +#else /* not C99 */ +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif /* __GNUC__ */ +#endif /* __STDC_VERSION__ >= 199901L */ +#endif /* INCLUDE_INLINE_FUNCS */ + +/* + * Fast bit set/clear functions that doesn't need to return the + * previous bit value. + */ + +_INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr) +{ + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + *ADDR |= (unsigned char) (1 << (nr & 0x07)); +} + +_INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr) +{ + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + *ADDR &= (unsigned char) ~(1 << (nr & 0x07)); +} + + +_INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr) +{ + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + *ADDR |= (unsigned char) (1 << (nr & 0x07)); +} + +_INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr) +{ + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + *ADDR &= (unsigned char) ~(1 << (nr & 0x07)); +} + +_INLINE_ __u16 ext2fs_swab16(__u16 val) +{ + return (val >> 8) | (__u16) (val << 8); +} + +_INLINE_ __u32 ext2fs_swab32(__u32 val) +{ + return ((val>>24) | ((val>>8)&0xFF00) | + ((val<<8)&0xFF0000) | (val<<24)); +} + +_INLINE_ __u64 ext2fs_swab64(__u64 val) +{ + return (ext2fs_swab32((__u32) (val >> 32)) | + (((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32)); +} + +_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block); +} + +_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode); +} + +_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode); +} + +_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap) +{ + return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap) +{ + return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap) +{ + return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap) +{ + return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + return ext2fs_test_block_bitmap_range(bitmap, block, num); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + ext2fs_mark_block_bitmap_range(bitmap, block, num); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + ext2fs_unmark_block_bitmap_range(bitmap, block, num); +} + +/* 64-bit versions */ + +_INLINE_ int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block); +} + +_INLINE_ int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, block); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block); +} + +_INLINE_ int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t block) +{ + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode); +} + +_INLINE_ void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode); +} + +_INLINE_ int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t start, + blk64_t end, + blk64_t *out) +{ + __u64 o; + errcode_t rv; + + rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap, + start, end, &o); + if (!rv) + *out = o; + return rv; +} + +_INLINE_ errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t start, + ext2_ino_t end, + ext2_ino_t *out) +{ + __u64 o; + errcode_t rv; + + rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap, + start, end, &o); + if (!rv) + *out = (ext2_ino_t) o; + return rv; +} + +_INLINE_ errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap, + blk64_t start, + blk64_t end, + blk64_t *out) +{ + __u64 o; + errcode_t rv; + + rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap, + start, end, &o); + if (!rv) + *out = o; + return rv; +} + +_INLINE_ errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap, + ext2_ino_t start, + ext2_ino_t end, + ext2_ino_t *out) +{ + __u64 o; + errcode_t rv; + + rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap, + start, end, &o); + if (!rv) + *out = (ext2_ino_t) o; + return rv; +} + +_INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap) +{ + return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap) +{ + return (ext2_ino_t) ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap) +{ + return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap) +{ + return (ext2_ino_t) ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap); +} + +_INLINE_ int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num) +{ + return ext2fs_test_block_bitmap_range2(bitmap, block, num); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num) +{ + ext2fs_mark_block_bitmap_range2(bitmap, block, num); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap, + blk64_t block, + unsigned int num) +{ + ext2fs_unmark_block_bitmap_range2(bitmap, block, num); +} + +#undef _INLINE_ +#endif + +extern int ext2fs_set_bit(unsigned int nr,void * addr); +extern int ext2fs_clear_bit(unsigned int nr, void * addr); +extern int ext2fs_test_bit(unsigned int nr, const void * addr); +extern int ext2fs_set_bit64(__u64 nr,void * addr); +extern int ext2fs_clear_bit64(__u64 nr, void * addr); +extern int ext2fs_test_bit64(__u64 nr, const void * addr); +extern unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes); diff --git a/include/e2fsprogs/ext2fs/bmap64.h b/include/e2fsprogs/ext2fs/bmap64.h new file mode 100755 index 0000000..de33454 --- /dev/null +++ b/include/e2fsprogs/ext2fs/bmap64.h @@ -0,0 +1,106 @@ +/* + * bmap64.h --- 64-bit bitmap structure + * + * Copyright (C) 2007, 2008 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +struct ext2_bmap_statistics { + int type; + struct timeval created; + +#ifdef ENABLE_BMAP_STATS_OPS + unsigned long copy_count; + unsigned long resize_count; + unsigned long mark_count; + unsigned long unmark_count; + unsigned long test_count; + unsigned long mark_ext_count; + unsigned long unmark_ext_count; + unsigned long test_ext_count; + unsigned long set_range_count; + unsigned long get_range_count; + unsigned long clear_count; + + blk64_t last_marked; + blk64_t last_tested; + blk64_t mark_back; + blk64_t test_back; + + unsigned long mark_seq; + unsigned long test_seq; +#endif /* ENABLE_BMAP_STATS_OPS */ +}; + + +struct ext2fs_struct_generic_bitmap_64 { + errcode_t magic; + ext2_filsys fs; + struct ext2_bitmap_ops *bitmap_ops; + int flags; + __u64 start, end; + __u64 real_end; + int cluster_bits; + char *description; + void *private; + errcode_t base_error_code; +#ifdef ENABLE_BMAP_STATS + struct ext2_bmap_statistics stats; +#endif +}; + +typedef struct ext2fs_struct_generic_bitmap_64 *ext2fs_generic_bitmap_64; + +#define EXT2FS_IS_32_BITMAP(bmap) \ + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \ + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \ + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP)) + +#define EXT2FS_IS_64_BITMAP(bmap) \ + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \ + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \ + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64)) + +struct ext2_bitmap_ops { + int type; + /* Generic bmap operators */ + errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap_64 bmap); + void (*free_bmap)(ext2fs_generic_bitmap_64 bitmap); + errcode_t (*copy_bmap)(ext2fs_generic_bitmap_64 src, + ext2fs_generic_bitmap_64 dest); + errcode_t (*resize_bmap)(ext2fs_generic_bitmap_64 bitmap, + __u64 new_end, + __u64 new_real_end); + /* bit set/test operators */ + int (*mark_bmap)(ext2fs_generic_bitmap_64 bitmap, __u64 arg); + int (*unmark_bmap)(ext2fs_generic_bitmap_64 bitmap, __u64 arg); + int (*test_bmap)(ext2fs_generic_bitmap_64 bitmap, __u64 arg); + void (*mark_bmap_extent)(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num); + void (*unmark_bmap_extent)(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num); + int (*test_clear_bmap_extent)(ext2fs_generic_bitmap_64 bitmap, + __u64 arg, unsigned int num); + errcode_t (*set_bmap_range)(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *in); + errcode_t (*get_bmap_range)(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *out); + void (*clear_bmap)(ext2fs_generic_bitmap_64 bitmap); + void (*print_stats)(ext2fs_generic_bitmap_64); + + /* Find the first zero bit between start and end, inclusive. + * May be NULL, in which case a generic function is used. */ + errcode_t (*find_first_zero)(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out); + /* Find the first set bit between start and end, inclusive. + * May be NULL, in which case a generic function is used. */ + errcode_t (*find_first_set)(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out); +}; + +extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray; +extern struct ext2_bitmap_ops ext2fs_blkmap64_rbtree; diff --git a/include/e2fsprogs/ext2fs/brel.h b/include/e2fsprogs/ext2fs/brel.h new file mode 100755 index 0000000..9fdddd4 --- /dev/null +++ b/include/e2fsprogs/ext2fs/brel.h @@ -0,0 +1,86 @@ +/* + * brel.h + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +struct ext2_block_relocate_entry { + blk64_t new; + __s16 offset; + __u16 flags; + union { + blk64_t block_ref; + ext2_ino_t inode_ref; + } owner; +}; + +#define RELOCATE_TYPE_REF 0x0007 +#define RELOCATE_BLOCK_REF 0x0001 +#define RELOCATE_INODE_REF 0x0002 + +typedef struct ext2_block_relocation_table *ext2_brel; + +struct ext2_block_relocation_table { + __u32 magic; + char *name; + blk64_t current; + void *priv_data; + + /* + * Add a block relocation entry. + */ + errcode_t (*put)(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent); + + /* + * Get a block relocation entry. + */ + errcode_t (*get)(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent); + + /* + * Initialize for iterating over the block relocation entries. + */ + errcode_t (*start_iter)(ext2_brel brel); + + /* + * The iterator function for the inode relocation entries. + * Returns an inode number of 0 when out of entries. + */ + errcode_t (*next)(ext2_brel brel, blk64_t *old, + struct ext2_block_relocate_entry *ent); + + /* + * Move the inode relocation table from one block number to + * another. + */ + errcode_t (*move)(ext2_brel brel, blk64_t old, blk_t new); + + /* + * Remove a block relocation entry. + */ + errcode_t (*delete)(ext2_brel brel, blk64_t old); + + + /* + * Free the block relocation table. + */ + errcode_t (*free)(ext2_brel brel); +}; + +errcode_t ext2fs_brel_memarray_create(char *name, blk64_t max_block, + ext2_brel *brel); + +#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent)) +#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent)) +#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel))) +#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent)) +#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new)) +#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old)) +#define ext2fs_brel_free(brel) ((brel)->free((brel))) + diff --git a/include/e2fsprogs/ext2fs/compiler.h b/include/e2fsprogs/ext2fs/compiler.h new file mode 100755 index 0000000..3bb3521 --- /dev/null +++ b/include/e2fsprogs/ext2fs/compiler.h @@ -0,0 +1,26 @@ +#ifndef _EXT2FS_COMPILER_H +#define _EXT2FS_COMPILER_H + +#include + +#ifdef __GNUC__ + +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GNUC_PREREQ(maj, min) 0 +#endif +#endif + +#define container_of(ptr, type, member) ({ \ + __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#else +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) +#endif + + +#endif /* _EXT2FS_COMPILER_H */ diff --git a/include/e2fsprogs/ext2fs/crc16.c b/include/e2fsprogs/ext2fs/crc16.c new file mode 100755 index 0000000..2fdeb24 --- /dev/null +++ b/include/e2fsprogs/ext2fs/crc16.c @@ -0,0 +1,74 @@ +/* + * crc16.c + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif +#include + +#include "crc16.h" + +/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */ +static __u16 const crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +/** + * Compute the CRC-16 for the data buffer + * + * @param crc previous CRC value + * @param buffer data pointer + * @param len number of bytes in the buffer + * @return the updated CRC value + */ +crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len) +{ + const unsigned char *cp = buffer; + + while (len--) + /* + * for an unknown reason, PPC treats __u16 as signed + * and keeps doing sign extension on the value. + * Instead, use only the low 16 bits of an unsigned + * int for holding the CRC value to avoid this. + */ + crc = (((crc >> 8) & 0xffU) ^ + crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU; + return crc; +} diff --git a/include/e2fsprogs/ext2fs/crc16.h b/include/e2fsprogs/ext2fs/crc16.h new file mode 100755 index 0000000..322e68d --- /dev/null +++ b/include/e2fsprogs/ext2fs/crc16.h @@ -0,0 +1,26 @@ +/* + * crc16.h - CRC-16 routine + * + * Implements the standard CRC-16: + * Width 16 + * Poly 0x8005 (x16 + x15 + x2 + 1) + * Init 0 + * + * Copyright (c) 2005 Ben Gardner + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#ifndef __CRC16_H +#define __CRC16_H + +/* for an unknown reason, PPC treats __u16 as signed and keeps doing sign + * extension on the value. Instead, use only the low 16 bits of an + * unsigned int for holding the CRC value to avoid this. + */ +typedef unsigned int crc16_t; + +extern crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len); + +#endif /* __CRC16_H */ diff --git a/include/e2fsprogs/ext2fs/crc32c_defs.h b/include/e2fsprogs/ext2fs/crc32c_defs.h new file mode 100755 index 0000000..3f9a09e --- /dev/null +++ b/include/e2fsprogs/ext2fs/crc32c_defs.h @@ -0,0 +1,59 @@ +/* + * There are multiple 16-bit CRC polynomials in common use, but this is + * *the* standard CRC-32 polynomial, first popularized by Ethernet. + * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 + */ +#define CRCPOLY_LE 0xedb88320 +#define CRCPOLY_BE 0x04c11db7 + +/* + * This is the CRC32c polynomial, as outlined by Castagnoli. + * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+ + * x^8+x^6+x^0 + */ +#define CRC32C_POLY_LE 0x82F63B78 +#define CRC32C_POLY_BE 0x1EDC6F41 + +/* How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. */ +/* For less performance-sensitive, use 4 */ +#ifndef CRC_LE_BITS +# define CRC_LE_BITS 64 +#endif +#ifndef CRC_BE_BITS +# define CRC_BE_BITS 64 +#endif + +/* + * Little-endian CRC computation. Used with serial bit streams sent + * lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC. + */ +#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \ + CRC_LE_BITS & CRC_LE_BITS-1 +# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}" +#endif + +/* + * Big-endian CRC computation. Used with serial bit streams sent + * msbit-first. Be sure to use cpu_to_be32() to append the computed CRC. + */ +#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \ + CRC_BE_BITS & CRC_BE_BITS-1 +# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}" +#endif + + +#define ___constant_swab32(x) \ + ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))) + + +#if (__GNUC__ >= 3) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif diff --git a/include/e2fsprogs/ext2fs/crc32c_table.h b/include/e2fsprogs/ext2fs/crc32c_table.h new file mode 100755 index 0000000..07b56d4 --- /dev/null +++ b/include/e2fsprogs/ext2fs/crc32c_table.h @@ -0,0 +1,1044 @@ +/* this file is generated - do not edit */ + +static const uint32_t crc32table_be[8][256] = {{ +tobe(0x00000000L), tobe(0x04c11db7L), tobe(0x09823b6eL), tobe(0x0d4326d9L), +tobe(0x130476dcL), tobe(0x17c56b6bL), tobe(0x1a864db2L), tobe(0x1e475005L), +tobe(0x2608edb8L), tobe(0x22c9f00fL), tobe(0x2f8ad6d6L), tobe(0x2b4bcb61L), +tobe(0x350c9b64L), tobe(0x31cd86d3L), tobe(0x3c8ea00aL), tobe(0x384fbdbdL), +tobe(0x4c11db70L), tobe(0x48d0c6c7L), tobe(0x4593e01eL), tobe(0x4152fda9L), +tobe(0x5f15adacL), tobe(0x5bd4b01bL), tobe(0x569796c2L), tobe(0x52568b75L), +tobe(0x6a1936c8L), tobe(0x6ed82b7fL), tobe(0x639b0da6L), tobe(0x675a1011L), +tobe(0x791d4014L), tobe(0x7ddc5da3L), tobe(0x709f7b7aL), tobe(0x745e66cdL), +tobe(0x9823b6e0L), tobe(0x9ce2ab57L), tobe(0x91a18d8eL), tobe(0x95609039L), +tobe(0x8b27c03cL), tobe(0x8fe6dd8bL), tobe(0x82a5fb52L), tobe(0x8664e6e5L), +tobe(0xbe2b5b58L), tobe(0xbaea46efL), tobe(0xb7a96036L), tobe(0xb3687d81L), +tobe(0xad2f2d84L), tobe(0xa9ee3033L), tobe(0xa4ad16eaL), tobe(0xa06c0b5dL), +tobe(0xd4326d90L), tobe(0xd0f37027L), tobe(0xddb056feL), tobe(0xd9714b49L), +tobe(0xc7361b4cL), tobe(0xc3f706fbL), tobe(0xceb42022L), tobe(0xca753d95L), +tobe(0xf23a8028L), tobe(0xf6fb9d9fL), tobe(0xfbb8bb46L), tobe(0xff79a6f1L), +tobe(0xe13ef6f4L), tobe(0xe5ffeb43L), tobe(0xe8bccd9aL), tobe(0xec7dd02dL), +tobe(0x34867077L), tobe(0x30476dc0L), tobe(0x3d044b19L), tobe(0x39c556aeL), +tobe(0x278206abL), tobe(0x23431b1cL), tobe(0x2e003dc5L), tobe(0x2ac12072L), +tobe(0x128e9dcfL), tobe(0x164f8078L), tobe(0x1b0ca6a1L), tobe(0x1fcdbb16L), +tobe(0x018aeb13L), tobe(0x054bf6a4L), tobe(0x0808d07dL), tobe(0x0cc9cdcaL), +tobe(0x7897ab07L), tobe(0x7c56b6b0L), tobe(0x71159069L), tobe(0x75d48ddeL), +tobe(0x6b93dddbL), tobe(0x6f52c06cL), tobe(0x6211e6b5L), tobe(0x66d0fb02L), +tobe(0x5e9f46bfL), tobe(0x5a5e5b08L), tobe(0x571d7dd1L), tobe(0x53dc6066L), +tobe(0x4d9b3063L), tobe(0x495a2dd4L), tobe(0x44190b0dL), tobe(0x40d816baL), +tobe(0xaca5c697L), tobe(0xa864db20L), tobe(0xa527fdf9L), tobe(0xa1e6e04eL), +tobe(0xbfa1b04bL), tobe(0xbb60adfcL), tobe(0xb6238b25L), tobe(0xb2e29692L), +tobe(0x8aad2b2fL), tobe(0x8e6c3698L), tobe(0x832f1041L), tobe(0x87ee0df6L), +tobe(0x99a95df3L), tobe(0x9d684044L), tobe(0x902b669dL), tobe(0x94ea7b2aL), +tobe(0xe0b41de7L), tobe(0xe4750050L), tobe(0xe9362689L), tobe(0xedf73b3eL), +tobe(0xf3b06b3bL), tobe(0xf771768cL), tobe(0xfa325055L), tobe(0xfef34de2L), +tobe(0xc6bcf05fL), tobe(0xc27dede8L), tobe(0xcf3ecb31L), tobe(0xcbffd686L), +tobe(0xd5b88683L), tobe(0xd1799b34L), tobe(0xdc3abdedL), tobe(0xd8fba05aL), +tobe(0x690ce0eeL), tobe(0x6dcdfd59L), tobe(0x608edb80L), tobe(0x644fc637L), +tobe(0x7a089632L), tobe(0x7ec98b85L), tobe(0x738aad5cL), tobe(0x774bb0ebL), +tobe(0x4f040d56L), tobe(0x4bc510e1L), tobe(0x46863638L), tobe(0x42472b8fL), +tobe(0x5c007b8aL), tobe(0x58c1663dL), tobe(0x558240e4L), tobe(0x51435d53L), +tobe(0x251d3b9eL), tobe(0x21dc2629L), tobe(0x2c9f00f0L), tobe(0x285e1d47L), +tobe(0x36194d42L), tobe(0x32d850f5L), tobe(0x3f9b762cL), tobe(0x3b5a6b9bL), +tobe(0x0315d626L), tobe(0x07d4cb91L), tobe(0x0a97ed48L), tobe(0x0e56f0ffL), +tobe(0x1011a0faL), tobe(0x14d0bd4dL), tobe(0x19939b94L), tobe(0x1d528623L), +tobe(0xf12f560eL), tobe(0xf5ee4bb9L), tobe(0xf8ad6d60L), tobe(0xfc6c70d7L), +tobe(0xe22b20d2L), tobe(0xe6ea3d65L), tobe(0xeba91bbcL), tobe(0xef68060bL), +tobe(0xd727bbb6L), tobe(0xd3e6a601L), tobe(0xdea580d8L), tobe(0xda649d6fL), +tobe(0xc423cd6aL), tobe(0xc0e2d0ddL), tobe(0xcda1f604L), tobe(0xc960ebb3L), +tobe(0xbd3e8d7eL), tobe(0xb9ff90c9L), tobe(0xb4bcb610L), tobe(0xb07daba7L), +tobe(0xae3afba2L), tobe(0xaafbe615L), tobe(0xa7b8c0ccL), tobe(0xa379dd7bL), +tobe(0x9b3660c6L), tobe(0x9ff77d71L), tobe(0x92b45ba8L), tobe(0x9675461fL), +tobe(0x8832161aL), tobe(0x8cf30badL), tobe(0x81b02d74L), tobe(0x857130c3L), +tobe(0x5d8a9099L), tobe(0x594b8d2eL), tobe(0x5408abf7L), tobe(0x50c9b640L), +tobe(0x4e8ee645L), tobe(0x4a4ffbf2L), tobe(0x470cdd2bL), tobe(0x43cdc09cL), +tobe(0x7b827d21L), tobe(0x7f436096L), tobe(0x7200464fL), tobe(0x76c15bf8L), +tobe(0x68860bfdL), tobe(0x6c47164aL), tobe(0x61043093L), tobe(0x65c52d24L), +tobe(0x119b4be9L), tobe(0x155a565eL), tobe(0x18197087L), tobe(0x1cd86d30L), +tobe(0x029f3d35L), tobe(0x065e2082L), tobe(0x0b1d065bL), tobe(0x0fdc1becL), +tobe(0x3793a651L), tobe(0x3352bbe6L), tobe(0x3e119d3fL), tobe(0x3ad08088L), +tobe(0x2497d08dL), tobe(0x2056cd3aL), tobe(0x2d15ebe3L), tobe(0x29d4f654L), +tobe(0xc5a92679L), tobe(0xc1683bceL), tobe(0xcc2b1d17L), tobe(0xc8ea00a0L), +tobe(0xd6ad50a5L), tobe(0xd26c4d12L), tobe(0xdf2f6bcbL), tobe(0xdbee767cL), +tobe(0xe3a1cbc1L), tobe(0xe760d676L), tobe(0xea23f0afL), tobe(0xeee2ed18L), +tobe(0xf0a5bd1dL), tobe(0xf464a0aaL), tobe(0xf9278673L), tobe(0xfde69bc4L), +tobe(0x89b8fd09L), tobe(0x8d79e0beL), tobe(0x803ac667L), tobe(0x84fbdbd0L), +tobe(0x9abc8bd5L), tobe(0x9e7d9662L), tobe(0x933eb0bbL), tobe(0x97ffad0cL), +tobe(0xafb010b1L), tobe(0xab710d06L), tobe(0xa6322bdfL), tobe(0xa2f33668L), +tobe(0xbcb4666dL), tobe(0xb8757bdaL), tobe(0xb5365d03L), tobe(0xb1f740b4L)}, +{ +tobe(0x00000000L), tobe(0xd219c1dcL), tobe(0xa0f29e0fL), tobe(0x72eb5fd3L), +tobe(0x452421a9L), tobe(0x973de075L), tobe(0xe5d6bfa6L), tobe(0x37cf7e7aL), +tobe(0x8a484352L), tobe(0x5851828eL), tobe(0x2abadd5dL), tobe(0xf8a31c81L), +tobe(0xcf6c62fbL), tobe(0x1d75a327L), tobe(0x6f9efcf4L), tobe(0xbd873d28L), +tobe(0x10519b13L), tobe(0xc2485acfL), tobe(0xb0a3051cL), tobe(0x62bac4c0L), +tobe(0x5575babaL), tobe(0x876c7b66L), tobe(0xf58724b5L), tobe(0x279ee569L), +tobe(0x9a19d841L), tobe(0x4800199dL), tobe(0x3aeb464eL), tobe(0xe8f28792L), +tobe(0xdf3df9e8L), tobe(0x0d243834L), tobe(0x7fcf67e7L), tobe(0xadd6a63bL), +tobe(0x20a33626L), tobe(0xf2baf7faL), tobe(0x8051a829L), tobe(0x524869f5L), +tobe(0x6587178fL), tobe(0xb79ed653L), tobe(0xc5758980L), tobe(0x176c485cL), +tobe(0xaaeb7574L), tobe(0x78f2b4a8L), tobe(0x0a19eb7bL), tobe(0xd8002aa7L), +tobe(0xefcf54ddL), tobe(0x3dd69501L), tobe(0x4f3dcad2L), tobe(0x9d240b0eL), +tobe(0x30f2ad35L), tobe(0xe2eb6ce9L), tobe(0x9000333aL), tobe(0x4219f2e6L), +tobe(0x75d68c9cL), tobe(0xa7cf4d40L), tobe(0xd5241293L), tobe(0x073dd34fL), +tobe(0xbabaee67L), tobe(0x68a32fbbL), tobe(0x1a487068L), tobe(0xc851b1b4L), +tobe(0xff9ecfceL), tobe(0x2d870e12L), tobe(0x5f6c51c1L), tobe(0x8d75901dL), +tobe(0x41466c4cL), tobe(0x935fad90L), tobe(0xe1b4f243L), tobe(0x33ad339fL), +tobe(0x04624de5L), tobe(0xd67b8c39L), tobe(0xa490d3eaL), tobe(0x76891236L), +tobe(0xcb0e2f1eL), tobe(0x1917eec2L), tobe(0x6bfcb111L), tobe(0xb9e570cdL), +tobe(0x8e2a0eb7L), tobe(0x5c33cf6bL), tobe(0x2ed890b8L), tobe(0xfcc15164L), +tobe(0x5117f75fL), tobe(0x830e3683L), tobe(0xf1e56950L), tobe(0x23fca88cL), +tobe(0x1433d6f6L), tobe(0xc62a172aL), tobe(0xb4c148f9L), tobe(0x66d88925L), +tobe(0xdb5fb40dL), tobe(0x094675d1L), tobe(0x7bad2a02L), tobe(0xa9b4ebdeL), +tobe(0x9e7b95a4L), tobe(0x4c625478L), tobe(0x3e890babL), tobe(0xec90ca77L), +tobe(0x61e55a6aL), tobe(0xb3fc9bb6L), tobe(0xc117c465L), tobe(0x130e05b9L), +tobe(0x24c17bc3L), tobe(0xf6d8ba1fL), tobe(0x8433e5ccL), tobe(0x562a2410L), +tobe(0xebad1938L), tobe(0x39b4d8e4L), tobe(0x4b5f8737L), tobe(0x994646ebL), +tobe(0xae893891L), tobe(0x7c90f94dL), tobe(0x0e7ba69eL), tobe(0xdc626742L), +tobe(0x71b4c179L), tobe(0xa3ad00a5L), tobe(0xd1465f76L), tobe(0x035f9eaaL), +tobe(0x3490e0d0L), tobe(0xe689210cL), tobe(0x94627edfL), tobe(0x467bbf03L), +tobe(0xfbfc822bL), tobe(0x29e543f7L), tobe(0x5b0e1c24L), tobe(0x8917ddf8L), +tobe(0xbed8a382L), tobe(0x6cc1625eL), tobe(0x1e2a3d8dL), tobe(0xcc33fc51L), +tobe(0x828cd898L), tobe(0x50951944L), tobe(0x227e4697L), tobe(0xf067874bL), +tobe(0xc7a8f931L), tobe(0x15b138edL), tobe(0x675a673eL), tobe(0xb543a6e2L), +tobe(0x08c49bcaL), tobe(0xdadd5a16L), tobe(0xa83605c5L), tobe(0x7a2fc419L), +tobe(0x4de0ba63L), tobe(0x9ff97bbfL), tobe(0xed12246cL), tobe(0x3f0be5b0L), +tobe(0x92dd438bL), tobe(0x40c48257L), tobe(0x322fdd84L), tobe(0xe0361c58L), +tobe(0xd7f96222L), tobe(0x05e0a3feL), tobe(0x770bfc2dL), tobe(0xa5123df1L), +tobe(0x189500d9L), tobe(0xca8cc105L), tobe(0xb8679ed6L), tobe(0x6a7e5f0aL), +tobe(0x5db12170L), tobe(0x8fa8e0acL), tobe(0xfd43bf7fL), tobe(0x2f5a7ea3L), +tobe(0xa22feebeL), tobe(0x70362f62L), tobe(0x02dd70b1L), tobe(0xd0c4b16dL), +tobe(0xe70bcf17L), tobe(0x35120ecbL), tobe(0x47f95118L), tobe(0x95e090c4L), +tobe(0x2867adecL), tobe(0xfa7e6c30L), tobe(0x889533e3L), tobe(0x5a8cf23fL), +tobe(0x6d438c45L), tobe(0xbf5a4d99L), tobe(0xcdb1124aL), tobe(0x1fa8d396L), +tobe(0xb27e75adL), tobe(0x6067b471L), tobe(0x128ceba2L), tobe(0xc0952a7eL), +tobe(0xf75a5404L), tobe(0x254395d8L), tobe(0x57a8ca0bL), tobe(0x85b10bd7L), +tobe(0x383636ffL), tobe(0xea2ff723L), tobe(0x98c4a8f0L), tobe(0x4add692cL), +tobe(0x7d121756L), tobe(0xaf0bd68aL), tobe(0xdde08959L), tobe(0x0ff94885L), +tobe(0xc3cab4d4L), tobe(0x11d37508L), tobe(0x63382adbL), tobe(0xb121eb07L), +tobe(0x86ee957dL), tobe(0x54f754a1L), tobe(0x261c0b72L), tobe(0xf405caaeL), +tobe(0x4982f786L), tobe(0x9b9b365aL), tobe(0xe9706989L), tobe(0x3b69a855L), +tobe(0x0ca6d62fL), tobe(0xdebf17f3L), tobe(0xac544820L), tobe(0x7e4d89fcL), +tobe(0xd39b2fc7L), tobe(0x0182ee1bL), tobe(0x7369b1c8L), tobe(0xa1707014L), +tobe(0x96bf0e6eL), tobe(0x44a6cfb2L), tobe(0x364d9061L), tobe(0xe45451bdL), +tobe(0x59d36c95L), tobe(0x8bcaad49L), tobe(0xf921f29aL), tobe(0x2b383346L), +tobe(0x1cf74d3cL), tobe(0xceee8ce0L), tobe(0xbc05d333L), tobe(0x6e1c12efL), +tobe(0xe36982f2L), tobe(0x3170432eL), tobe(0x439b1cfdL), tobe(0x9182dd21L), +tobe(0xa64da35bL), tobe(0x74546287L), tobe(0x06bf3d54L), tobe(0xd4a6fc88L), +tobe(0x6921c1a0L), tobe(0xbb38007cL), tobe(0xc9d35fafL), tobe(0x1bca9e73L), +tobe(0x2c05e009L), tobe(0xfe1c21d5L), tobe(0x8cf77e06L), tobe(0x5eeebfdaL), +tobe(0xf33819e1L), tobe(0x2121d83dL), tobe(0x53ca87eeL), tobe(0x81d34632L), +tobe(0xb61c3848L), tobe(0x6405f994L), tobe(0x16eea647L), tobe(0xc4f7679bL), +tobe(0x79705ab3L), tobe(0xab699b6fL), tobe(0xd982c4bcL), tobe(0x0b9b0560L), +tobe(0x3c547b1aL), tobe(0xee4dbac6L), tobe(0x9ca6e515L), tobe(0x4ebf24c9L)}, +{ +tobe(0x00000000L), tobe(0x01d8ac87L), tobe(0x03b1590eL), tobe(0x0269f589L), +tobe(0x0762b21cL), tobe(0x06ba1e9bL), tobe(0x04d3eb12L), tobe(0x050b4795L), +tobe(0x0ec56438L), tobe(0x0f1dc8bfL), tobe(0x0d743d36L), tobe(0x0cac91b1L), +tobe(0x09a7d624L), tobe(0x087f7aa3L), tobe(0x0a168f2aL), tobe(0x0bce23adL), +tobe(0x1d8ac870L), tobe(0x1c5264f7L), tobe(0x1e3b917eL), tobe(0x1fe33df9L), +tobe(0x1ae87a6cL), tobe(0x1b30d6ebL), tobe(0x19592362L), tobe(0x18818fe5L), +tobe(0x134fac48L), tobe(0x129700cfL), tobe(0x10fef546L), tobe(0x112659c1L), +tobe(0x142d1e54L), tobe(0x15f5b2d3L), tobe(0x179c475aL), tobe(0x1644ebddL), +tobe(0x3b1590e0L), tobe(0x3acd3c67L), tobe(0x38a4c9eeL), tobe(0x397c6569L), +tobe(0x3c7722fcL), tobe(0x3daf8e7bL), tobe(0x3fc67bf2L), tobe(0x3e1ed775L), +tobe(0x35d0f4d8L), tobe(0x3408585fL), tobe(0x3661add6L), tobe(0x37b90151L), +tobe(0x32b246c4L), tobe(0x336aea43L), tobe(0x31031fcaL), tobe(0x30dbb34dL), +tobe(0x269f5890L), tobe(0x2747f417L), tobe(0x252e019eL), tobe(0x24f6ad19L), +tobe(0x21fdea8cL), tobe(0x2025460bL), tobe(0x224cb382L), tobe(0x23941f05L), +tobe(0x285a3ca8L), tobe(0x2982902fL), tobe(0x2beb65a6L), tobe(0x2a33c921L), +tobe(0x2f388eb4L), tobe(0x2ee02233L), tobe(0x2c89d7baL), tobe(0x2d517b3dL), +tobe(0x762b21c0L), tobe(0x77f38d47L), tobe(0x759a78ceL), tobe(0x7442d449L), +tobe(0x714993dcL), tobe(0x70913f5bL), tobe(0x72f8cad2L), tobe(0x73206655L), +tobe(0x78ee45f8L), tobe(0x7936e97fL), tobe(0x7b5f1cf6L), tobe(0x7a87b071L), +tobe(0x7f8cf7e4L), tobe(0x7e545b63L), tobe(0x7c3daeeaL), tobe(0x7de5026dL), +tobe(0x6ba1e9b0L), tobe(0x6a794537L), tobe(0x6810b0beL), tobe(0x69c81c39L), +tobe(0x6cc35bacL), tobe(0x6d1bf72bL), tobe(0x6f7202a2L), tobe(0x6eaaae25L), +tobe(0x65648d88L), tobe(0x64bc210fL), tobe(0x66d5d486L), tobe(0x670d7801L), +tobe(0x62063f94L), tobe(0x63de9313L), tobe(0x61b7669aL), tobe(0x606fca1dL), +tobe(0x4d3eb120L), tobe(0x4ce61da7L), tobe(0x4e8fe82eL), tobe(0x4f5744a9L), +tobe(0x4a5c033cL), tobe(0x4b84afbbL), tobe(0x49ed5a32L), tobe(0x4835f6b5L), +tobe(0x43fbd518L), tobe(0x4223799fL), tobe(0x404a8c16L), tobe(0x41922091L), +tobe(0x44996704L), tobe(0x4541cb83L), tobe(0x47283e0aL), tobe(0x46f0928dL), +tobe(0x50b47950L), tobe(0x516cd5d7L), tobe(0x5305205eL), tobe(0x52dd8cd9L), +tobe(0x57d6cb4cL), tobe(0x560e67cbL), tobe(0x54679242L), tobe(0x55bf3ec5L), +tobe(0x5e711d68L), tobe(0x5fa9b1efL), tobe(0x5dc04466L), tobe(0x5c18e8e1L), +tobe(0x5913af74L), tobe(0x58cb03f3L), tobe(0x5aa2f67aL), tobe(0x5b7a5afdL), +tobe(0xec564380L), tobe(0xed8eef07L), tobe(0xefe71a8eL), tobe(0xee3fb609L), +tobe(0xeb34f19cL), tobe(0xeaec5d1bL), tobe(0xe885a892L), tobe(0xe95d0415L), +tobe(0xe29327b8L), tobe(0xe34b8b3fL), tobe(0xe1227eb6L), tobe(0xe0fad231L), +tobe(0xe5f195a4L), tobe(0xe4293923L), tobe(0xe640ccaaL), tobe(0xe798602dL), +tobe(0xf1dc8bf0L), tobe(0xf0042777L), tobe(0xf26dd2feL), tobe(0xf3b57e79L), +tobe(0xf6be39ecL), tobe(0xf766956bL), tobe(0xf50f60e2L), tobe(0xf4d7cc65L), +tobe(0xff19efc8L), tobe(0xfec1434fL), tobe(0xfca8b6c6L), tobe(0xfd701a41L), +tobe(0xf87b5dd4L), tobe(0xf9a3f153L), tobe(0xfbca04daL), tobe(0xfa12a85dL), +tobe(0xd743d360L), tobe(0xd69b7fe7L), tobe(0xd4f28a6eL), tobe(0xd52a26e9L), +tobe(0xd021617cL), tobe(0xd1f9cdfbL), tobe(0xd3903872L), tobe(0xd24894f5L), +tobe(0xd986b758L), tobe(0xd85e1bdfL), tobe(0xda37ee56L), tobe(0xdbef42d1L), +tobe(0xdee40544L), tobe(0xdf3ca9c3L), tobe(0xdd555c4aL), tobe(0xdc8df0cdL), +tobe(0xcac91b10L), tobe(0xcb11b797L), tobe(0xc978421eL), tobe(0xc8a0ee99L), +tobe(0xcdaba90cL), tobe(0xcc73058bL), tobe(0xce1af002L), tobe(0xcfc25c85L), +tobe(0xc40c7f28L), tobe(0xc5d4d3afL), tobe(0xc7bd2626L), tobe(0xc6658aa1L), +tobe(0xc36ecd34L), tobe(0xc2b661b3L), tobe(0xc0df943aL), tobe(0xc10738bdL), +tobe(0x9a7d6240L), tobe(0x9ba5cec7L), tobe(0x99cc3b4eL), tobe(0x981497c9L), +tobe(0x9d1fd05cL), tobe(0x9cc77cdbL), tobe(0x9eae8952L), tobe(0x9f7625d5L), +tobe(0x94b80678L), tobe(0x9560aaffL), tobe(0x97095f76L), tobe(0x96d1f3f1L), +tobe(0x93dab464L), tobe(0x920218e3L), tobe(0x906bed6aL), tobe(0x91b341edL), +tobe(0x87f7aa30L), tobe(0x862f06b7L), tobe(0x8446f33eL), tobe(0x859e5fb9L), +tobe(0x8095182cL), tobe(0x814db4abL), tobe(0x83244122L), tobe(0x82fceda5L), +tobe(0x8932ce08L), tobe(0x88ea628fL), tobe(0x8a839706L), tobe(0x8b5b3b81L), +tobe(0x8e507c14L), tobe(0x8f88d093L), tobe(0x8de1251aL), tobe(0x8c39899dL), +tobe(0xa168f2a0L), tobe(0xa0b05e27L), tobe(0xa2d9abaeL), tobe(0xa3010729L), +tobe(0xa60a40bcL), tobe(0xa7d2ec3bL), tobe(0xa5bb19b2L), tobe(0xa463b535L), +tobe(0xafad9698L), tobe(0xae753a1fL), tobe(0xac1ccf96L), tobe(0xadc46311L), +tobe(0xa8cf2484L), tobe(0xa9178803L), tobe(0xab7e7d8aL), tobe(0xaaa6d10dL), +tobe(0xbce23ad0L), tobe(0xbd3a9657L), tobe(0xbf5363deL), tobe(0xbe8bcf59L), +tobe(0xbb8088ccL), tobe(0xba58244bL), tobe(0xb831d1c2L), tobe(0xb9e97d45L), +tobe(0xb2275ee8L), tobe(0xb3fff26fL), tobe(0xb19607e6L), tobe(0xb04eab61L), +tobe(0xb545ecf4L), tobe(0xb49d4073L), tobe(0xb6f4b5faL), tobe(0xb72c197dL)}, +{ +tobe(0x00000000L), tobe(0xdc6d9ab7L), tobe(0xbc1a28d9L), tobe(0x6077b26eL), +tobe(0x7cf54c05L), tobe(0xa098d6b2L), tobe(0xc0ef64dcL), tobe(0x1c82fe6bL), +tobe(0xf9ea980aL), tobe(0x258702bdL), tobe(0x45f0b0d3L), tobe(0x999d2a64L), +tobe(0x851fd40fL), tobe(0x59724eb8L), tobe(0x3905fcd6L), tobe(0xe5686661L), +tobe(0xf7142da3L), tobe(0x2b79b714L), tobe(0x4b0e057aL), tobe(0x97639fcdL), +tobe(0x8be161a6L), tobe(0x578cfb11L), tobe(0x37fb497fL), tobe(0xeb96d3c8L), +tobe(0x0efeb5a9L), tobe(0xd2932f1eL), tobe(0xb2e49d70L), tobe(0x6e8907c7L), +tobe(0x720bf9acL), tobe(0xae66631bL), tobe(0xce11d175L), tobe(0x127c4bc2L), +tobe(0xeae946f1L), tobe(0x3684dc46L), tobe(0x56f36e28L), tobe(0x8a9ef49fL), +tobe(0x961c0af4L), tobe(0x4a719043L), tobe(0x2a06222dL), tobe(0xf66bb89aL), +tobe(0x1303defbL), tobe(0xcf6e444cL), tobe(0xaf19f622L), tobe(0x73746c95L), +tobe(0x6ff692feL), tobe(0xb39b0849L), tobe(0xd3ecba27L), tobe(0x0f812090L), +tobe(0x1dfd6b52L), tobe(0xc190f1e5L), tobe(0xa1e7438bL), tobe(0x7d8ad93cL), +tobe(0x61082757L), tobe(0xbd65bde0L), tobe(0xdd120f8eL), tobe(0x017f9539L), +tobe(0xe417f358L), tobe(0x387a69efL), tobe(0x580ddb81L), tobe(0x84604136L), +tobe(0x98e2bf5dL), tobe(0x448f25eaL), tobe(0x24f89784L), tobe(0xf8950d33L), +tobe(0xd1139055L), tobe(0x0d7e0ae2L), tobe(0x6d09b88cL), tobe(0xb164223bL), +tobe(0xade6dc50L), tobe(0x718b46e7L), tobe(0x11fcf489L), tobe(0xcd916e3eL), +tobe(0x28f9085fL), tobe(0xf49492e8L), tobe(0x94e32086L), tobe(0x488eba31L), +tobe(0x540c445aL), tobe(0x8861deedL), tobe(0xe8166c83L), tobe(0x347bf634L), +tobe(0x2607bdf6L), tobe(0xfa6a2741L), tobe(0x9a1d952fL), tobe(0x46700f98L), +tobe(0x5af2f1f3L), tobe(0x869f6b44L), tobe(0xe6e8d92aL), tobe(0x3a85439dL), +tobe(0xdfed25fcL), tobe(0x0380bf4bL), tobe(0x63f70d25L), tobe(0xbf9a9792L), +tobe(0xa31869f9L), tobe(0x7f75f34eL), tobe(0x1f024120L), tobe(0xc36fdb97L), +tobe(0x3bfad6a4L), tobe(0xe7974c13L), tobe(0x87e0fe7dL), tobe(0x5b8d64caL), +tobe(0x470f9aa1L), tobe(0x9b620016L), tobe(0xfb15b278L), tobe(0x277828cfL), +tobe(0xc2104eaeL), tobe(0x1e7dd419L), tobe(0x7e0a6677L), tobe(0xa267fcc0L), +tobe(0xbee502abL), tobe(0x6288981cL), tobe(0x02ff2a72L), tobe(0xde92b0c5L), +tobe(0xcceefb07L), tobe(0x108361b0L), tobe(0x70f4d3deL), tobe(0xac994969L), +tobe(0xb01bb702L), tobe(0x6c762db5L), tobe(0x0c019fdbL), tobe(0xd06c056cL), +tobe(0x3504630dL), tobe(0xe969f9baL), tobe(0x891e4bd4L), tobe(0x5573d163L), +tobe(0x49f12f08L), tobe(0x959cb5bfL), tobe(0xf5eb07d1L), tobe(0x29869d66L), +tobe(0xa6e63d1dL), tobe(0x7a8ba7aaL), tobe(0x1afc15c4L), tobe(0xc6918f73L), +tobe(0xda137118L), tobe(0x067eebafL), tobe(0x660959c1L), tobe(0xba64c376L), +tobe(0x5f0ca517L), tobe(0x83613fa0L), tobe(0xe3168dceL), tobe(0x3f7b1779L), +tobe(0x23f9e912L), tobe(0xff9473a5L), tobe(0x9fe3c1cbL), tobe(0x438e5b7cL), +tobe(0x51f210beL), tobe(0x8d9f8a09L), tobe(0xede83867L), tobe(0x3185a2d0L), +tobe(0x2d075cbbL), tobe(0xf16ac60cL), tobe(0x911d7462L), tobe(0x4d70eed5L), +tobe(0xa81888b4L), tobe(0x74751203L), tobe(0x1402a06dL), tobe(0xc86f3adaL), +tobe(0xd4edc4b1L), tobe(0x08805e06L), tobe(0x68f7ec68L), tobe(0xb49a76dfL), +tobe(0x4c0f7becL), tobe(0x9062e15bL), tobe(0xf0155335L), tobe(0x2c78c982L), +tobe(0x30fa37e9L), tobe(0xec97ad5eL), tobe(0x8ce01f30L), tobe(0x508d8587L), +tobe(0xb5e5e3e6L), tobe(0x69887951L), tobe(0x09ffcb3fL), tobe(0xd5925188L), +tobe(0xc910afe3L), tobe(0x157d3554L), tobe(0x750a873aL), tobe(0xa9671d8dL), +tobe(0xbb1b564fL), tobe(0x6776ccf8L), tobe(0x07017e96L), tobe(0xdb6ce421L), +tobe(0xc7ee1a4aL), tobe(0x1b8380fdL), tobe(0x7bf43293L), tobe(0xa799a824L), +tobe(0x42f1ce45L), tobe(0x9e9c54f2L), tobe(0xfeebe69cL), tobe(0x22867c2bL), +tobe(0x3e048240L), tobe(0xe26918f7L), tobe(0x821eaa99L), tobe(0x5e73302eL), +tobe(0x77f5ad48L), tobe(0xab9837ffL), tobe(0xcbef8591L), tobe(0x17821f26L), +tobe(0x0b00e14dL), tobe(0xd76d7bfaL), tobe(0xb71ac994L), tobe(0x6b775323L), +tobe(0x8e1f3542L), tobe(0x5272aff5L), tobe(0x32051d9bL), tobe(0xee68872cL), +tobe(0xf2ea7947L), tobe(0x2e87e3f0L), tobe(0x4ef0519eL), tobe(0x929dcb29L), +tobe(0x80e180ebL), tobe(0x5c8c1a5cL), tobe(0x3cfba832L), tobe(0xe0963285L), +tobe(0xfc14cceeL), tobe(0x20795659L), tobe(0x400ee437L), tobe(0x9c637e80L), +tobe(0x790b18e1L), tobe(0xa5668256L), tobe(0xc5113038L), tobe(0x197caa8fL), +tobe(0x05fe54e4L), tobe(0xd993ce53L), tobe(0xb9e47c3dL), tobe(0x6589e68aL), +tobe(0x9d1cebb9L), tobe(0x4171710eL), tobe(0x2106c360L), tobe(0xfd6b59d7L), +tobe(0xe1e9a7bcL), tobe(0x3d843d0bL), tobe(0x5df38f65L), tobe(0x819e15d2L), +tobe(0x64f673b3L), tobe(0xb89be904L), tobe(0xd8ec5b6aL), tobe(0x0481c1ddL), +tobe(0x18033fb6L), tobe(0xc46ea501L), tobe(0xa419176fL), tobe(0x78748dd8L), +tobe(0x6a08c61aL), tobe(0xb6655cadL), tobe(0xd612eec3L), tobe(0x0a7f7474L), +tobe(0x16fd8a1fL), tobe(0xca9010a8L), tobe(0xaae7a2c6L), tobe(0x768a3871L), +tobe(0x93e25e10L), tobe(0x4f8fc4a7L), tobe(0x2ff876c9L), tobe(0xf395ec7eL), +tobe(0xef171215L), tobe(0x337a88a2L), tobe(0x530d3accL), tobe(0x8f60a07bL)}, +{ +tobe(0x00000000L), tobe(0x490d678dL), tobe(0x921acf1aL), tobe(0xdb17a897L), +tobe(0x20f48383L), tobe(0x69f9e40eL), tobe(0xb2ee4c99L), tobe(0xfbe32b14L), +tobe(0x41e90706L), tobe(0x08e4608bL), tobe(0xd3f3c81cL), tobe(0x9afeaf91L), +tobe(0x611d8485L), tobe(0x2810e308L), tobe(0xf3074b9fL), tobe(0xba0a2c12L), +tobe(0x83d20e0cL), tobe(0xcadf6981L), tobe(0x11c8c116L), tobe(0x58c5a69bL), +tobe(0xa3268d8fL), tobe(0xea2bea02L), tobe(0x313c4295L), tobe(0x78312518L), +tobe(0xc23b090aL), tobe(0x8b366e87L), tobe(0x5021c610L), tobe(0x192ca19dL), +tobe(0xe2cf8a89L), tobe(0xabc2ed04L), tobe(0x70d54593L), tobe(0x39d8221eL), +tobe(0x036501afL), tobe(0x4a686622L), tobe(0x917fceb5L), tobe(0xd872a938L), +tobe(0x2391822cL), tobe(0x6a9ce5a1L), tobe(0xb18b4d36L), tobe(0xf8862abbL), +tobe(0x428c06a9L), tobe(0x0b816124L), tobe(0xd096c9b3L), tobe(0x999bae3eL), +tobe(0x6278852aL), tobe(0x2b75e2a7L), tobe(0xf0624a30L), tobe(0xb96f2dbdL), +tobe(0x80b70fa3L), tobe(0xc9ba682eL), tobe(0x12adc0b9L), tobe(0x5ba0a734L), +tobe(0xa0438c20L), tobe(0xe94eebadL), tobe(0x3259433aL), tobe(0x7b5424b7L), +tobe(0xc15e08a5L), tobe(0x88536f28L), tobe(0x5344c7bfL), tobe(0x1a49a032L), +tobe(0xe1aa8b26L), tobe(0xa8a7ecabL), tobe(0x73b0443cL), tobe(0x3abd23b1L), +tobe(0x06ca035eL), tobe(0x4fc764d3L), tobe(0x94d0cc44L), tobe(0xddddabc9L), +tobe(0x263e80ddL), tobe(0x6f33e750L), tobe(0xb4244fc7L), tobe(0xfd29284aL), +tobe(0x47230458L), tobe(0x0e2e63d5L), tobe(0xd539cb42L), tobe(0x9c34accfL), +tobe(0x67d787dbL), tobe(0x2edae056L), tobe(0xf5cd48c1L), tobe(0xbcc02f4cL), +tobe(0x85180d52L), tobe(0xcc156adfL), tobe(0x1702c248L), tobe(0x5e0fa5c5L), +tobe(0xa5ec8ed1L), tobe(0xece1e95cL), tobe(0x37f641cbL), tobe(0x7efb2646L), +tobe(0xc4f10a54L), tobe(0x8dfc6dd9L), tobe(0x56ebc54eL), tobe(0x1fe6a2c3L), +tobe(0xe40589d7L), tobe(0xad08ee5aL), tobe(0x761f46cdL), tobe(0x3f122140L), +tobe(0x05af02f1L), tobe(0x4ca2657cL), tobe(0x97b5cdebL), tobe(0xdeb8aa66L), +tobe(0x255b8172L), tobe(0x6c56e6ffL), tobe(0xb7414e68L), tobe(0xfe4c29e5L), +tobe(0x444605f7L), tobe(0x0d4b627aL), tobe(0xd65ccaedL), tobe(0x9f51ad60L), +tobe(0x64b28674L), tobe(0x2dbfe1f9L), tobe(0xf6a8496eL), tobe(0xbfa52ee3L), +tobe(0x867d0cfdL), tobe(0xcf706b70L), tobe(0x1467c3e7L), tobe(0x5d6aa46aL), +tobe(0xa6898f7eL), tobe(0xef84e8f3L), tobe(0x34934064L), tobe(0x7d9e27e9L), +tobe(0xc7940bfbL), tobe(0x8e996c76L), tobe(0x558ec4e1L), tobe(0x1c83a36cL), +tobe(0xe7608878L), tobe(0xae6deff5L), tobe(0x757a4762L), tobe(0x3c7720efL), +tobe(0x0d9406bcL), tobe(0x44996131L), tobe(0x9f8ec9a6L), tobe(0xd683ae2bL), +tobe(0x2d60853fL), tobe(0x646de2b2L), tobe(0xbf7a4a25L), tobe(0xf6772da8L), +tobe(0x4c7d01baL), tobe(0x05706637L), tobe(0xde67cea0L), tobe(0x976aa92dL), +tobe(0x6c898239L), tobe(0x2584e5b4L), tobe(0xfe934d23L), tobe(0xb79e2aaeL), +tobe(0x8e4608b0L), tobe(0xc74b6f3dL), tobe(0x1c5cc7aaL), tobe(0x5551a027L), +tobe(0xaeb28b33L), tobe(0xe7bfecbeL), tobe(0x3ca84429L), tobe(0x75a523a4L), +tobe(0xcfaf0fb6L), tobe(0x86a2683bL), tobe(0x5db5c0acL), tobe(0x14b8a721L), +tobe(0xef5b8c35L), tobe(0xa656ebb8L), tobe(0x7d41432fL), tobe(0x344c24a2L), +tobe(0x0ef10713L), tobe(0x47fc609eL), tobe(0x9cebc809L), tobe(0xd5e6af84L), +tobe(0x2e058490L), tobe(0x6708e31dL), tobe(0xbc1f4b8aL), tobe(0xf5122c07L), +tobe(0x4f180015L), tobe(0x06156798L), tobe(0xdd02cf0fL), tobe(0x940fa882L), +tobe(0x6fec8396L), tobe(0x26e1e41bL), tobe(0xfdf64c8cL), tobe(0xb4fb2b01L), +tobe(0x8d23091fL), tobe(0xc42e6e92L), tobe(0x1f39c605L), tobe(0x5634a188L), +tobe(0xadd78a9cL), tobe(0xe4daed11L), tobe(0x3fcd4586L), tobe(0x76c0220bL), +tobe(0xccca0e19L), tobe(0x85c76994L), tobe(0x5ed0c103L), tobe(0x17dda68eL), +tobe(0xec3e8d9aL), tobe(0xa533ea17L), tobe(0x7e244280L), tobe(0x3729250dL), +tobe(0x0b5e05e2L), tobe(0x4253626fL), tobe(0x9944caf8L), tobe(0xd049ad75L), +tobe(0x2baa8661L), tobe(0x62a7e1ecL), tobe(0xb9b0497bL), tobe(0xf0bd2ef6L), +tobe(0x4ab702e4L), tobe(0x03ba6569L), tobe(0xd8adcdfeL), tobe(0x91a0aa73L), +tobe(0x6a438167L), tobe(0x234ee6eaL), tobe(0xf8594e7dL), tobe(0xb15429f0L), +tobe(0x888c0beeL), tobe(0xc1816c63L), tobe(0x1a96c4f4L), tobe(0x539ba379L), +tobe(0xa878886dL), tobe(0xe175efe0L), tobe(0x3a624777L), tobe(0x736f20faL), +tobe(0xc9650ce8L), tobe(0x80686b65L), tobe(0x5b7fc3f2L), tobe(0x1272a47fL), +tobe(0xe9918f6bL), tobe(0xa09ce8e6L), tobe(0x7b8b4071L), tobe(0x328627fcL), +tobe(0x083b044dL), tobe(0x413663c0L), tobe(0x9a21cb57L), tobe(0xd32cacdaL), +tobe(0x28cf87ceL), tobe(0x61c2e043L), tobe(0xbad548d4L), tobe(0xf3d82f59L), +tobe(0x49d2034bL), tobe(0x00df64c6L), tobe(0xdbc8cc51L), tobe(0x92c5abdcL), +tobe(0x692680c8L), tobe(0x202be745L), tobe(0xfb3c4fd2L), tobe(0xb231285fL), +tobe(0x8be90a41L), tobe(0xc2e46dccL), tobe(0x19f3c55bL), tobe(0x50fea2d6L), +tobe(0xab1d89c2L), tobe(0xe210ee4fL), tobe(0x390746d8L), tobe(0x700a2155L), +tobe(0xca000d47L), tobe(0x830d6acaL), tobe(0x581ac25dL), tobe(0x1117a5d0L), +tobe(0xeaf48ec4L), tobe(0xa3f9e949L), tobe(0x78ee41deL), tobe(0x31e32653L)}, +{ +tobe(0x00000000L), tobe(0x1b280d78L), tobe(0x36501af0L), tobe(0x2d781788L), +tobe(0x6ca035e0L), tobe(0x77883898L), tobe(0x5af02f10L), tobe(0x41d82268L), +tobe(0xd9406bc0L), tobe(0xc26866b8L), tobe(0xef107130L), tobe(0xf4387c48L), +tobe(0xb5e05e20L), tobe(0xaec85358L), tobe(0x83b044d0L), tobe(0x989849a8L), +tobe(0xb641ca37L), tobe(0xad69c74fL), tobe(0x8011d0c7L), tobe(0x9b39ddbfL), +tobe(0xdae1ffd7L), tobe(0xc1c9f2afL), tobe(0xecb1e527L), tobe(0xf799e85fL), +tobe(0x6f01a1f7L), tobe(0x7429ac8fL), tobe(0x5951bb07L), tobe(0x4279b67fL), +tobe(0x03a19417L), tobe(0x1889996fL), tobe(0x35f18ee7L), tobe(0x2ed9839fL), +tobe(0x684289d9L), tobe(0x736a84a1L), tobe(0x5e129329L), tobe(0x453a9e51L), +tobe(0x04e2bc39L), tobe(0x1fcab141L), tobe(0x32b2a6c9L), tobe(0x299aabb1L), +tobe(0xb102e219L), tobe(0xaa2aef61L), tobe(0x8752f8e9L), tobe(0x9c7af591L), +tobe(0xdda2d7f9L), tobe(0xc68ada81L), tobe(0xebf2cd09L), tobe(0xf0dac071L), +tobe(0xde0343eeL), tobe(0xc52b4e96L), tobe(0xe853591eL), tobe(0xf37b5466L), +tobe(0xb2a3760eL), tobe(0xa98b7b76L), tobe(0x84f36cfeL), tobe(0x9fdb6186L), +tobe(0x0743282eL), tobe(0x1c6b2556L), tobe(0x311332deL), tobe(0x2a3b3fa6L), +tobe(0x6be31dceL), tobe(0x70cb10b6L), tobe(0x5db3073eL), tobe(0x469b0a46L), +tobe(0xd08513b2L), tobe(0xcbad1ecaL), tobe(0xe6d50942L), tobe(0xfdfd043aL), +tobe(0xbc252652L), tobe(0xa70d2b2aL), tobe(0x8a753ca2L), tobe(0x915d31daL), +tobe(0x09c57872L), tobe(0x12ed750aL), tobe(0x3f956282L), tobe(0x24bd6ffaL), +tobe(0x65654d92L), tobe(0x7e4d40eaL), tobe(0x53355762L), tobe(0x481d5a1aL), +tobe(0x66c4d985L), tobe(0x7decd4fdL), tobe(0x5094c375L), tobe(0x4bbcce0dL), +tobe(0x0a64ec65L), tobe(0x114ce11dL), tobe(0x3c34f695L), tobe(0x271cfbedL), +tobe(0xbf84b245L), tobe(0xa4acbf3dL), tobe(0x89d4a8b5L), tobe(0x92fca5cdL), +tobe(0xd32487a5L), tobe(0xc80c8addL), tobe(0xe5749d55L), tobe(0xfe5c902dL), +tobe(0xb8c79a6bL), tobe(0xa3ef9713L), tobe(0x8e97809bL), tobe(0x95bf8de3L), +tobe(0xd467af8bL), tobe(0xcf4fa2f3L), tobe(0xe237b57bL), tobe(0xf91fb803L), +tobe(0x6187f1abL), tobe(0x7aaffcd3L), tobe(0x57d7eb5bL), tobe(0x4cffe623L), +tobe(0x0d27c44bL), tobe(0x160fc933L), tobe(0x3b77debbL), tobe(0x205fd3c3L), +tobe(0x0e86505cL), tobe(0x15ae5d24L), tobe(0x38d64aacL), tobe(0x23fe47d4L), +tobe(0x622665bcL), tobe(0x790e68c4L), tobe(0x54767f4cL), tobe(0x4f5e7234L), +tobe(0xd7c63b9cL), tobe(0xccee36e4L), tobe(0xe196216cL), tobe(0xfabe2c14L), +tobe(0xbb660e7cL), tobe(0xa04e0304L), tobe(0x8d36148cL), tobe(0x961e19f4L), +tobe(0xa5cb3ad3L), tobe(0xbee337abL), tobe(0x939b2023L), tobe(0x88b32d5bL), +tobe(0xc96b0f33L), tobe(0xd243024bL), tobe(0xff3b15c3L), tobe(0xe41318bbL), +tobe(0x7c8b5113L), tobe(0x67a35c6bL), tobe(0x4adb4be3L), tobe(0x51f3469bL), +tobe(0x102b64f3L), tobe(0x0b03698bL), tobe(0x267b7e03L), tobe(0x3d53737bL), +tobe(0x138af0e4L), tobe(0x08a2fd9cL), tobe(0x25daea14L), tobe(0x3ef2e76cL), +tobe(0x7f2ac504L), tobe(0x6402c87cL), tobe(0x497adff4L), tobe(0x5252d28cL), +tobe(0xcaca9b24L), tobe(0xd1e2965cL), tobe(0xfc9a81d4L), tobe(0xe7b28cacL), +tobe(0xa66aaec4L), tobe(0xbd42a3bcL), tobe(0x903ab434L), tobe(0x8b12b94cL), +tobe(0xcd89b30aL), tobe(0xd6a1be72L), tobe(0xfbd9a9faL), tobe(0xe0f1a482L), +tobe(0xa12986eaL), tobe(0xba018b92L), tobe(0x97799c1aL), tobe(0x8c519162L), +tobe(0x14c9d8caL), tobe(0x0fe1d5b2L), tobe(0x2299c23aL), tobe(0x39b1cf42L), +tobe(0x7869ed2aL), tobe(0x6341e052L), tobe(0x4e39f7daL), tobe(0x5511faa2L), +tobe(0x7bc8793dL), tobe(0x60e07445L), tobe(0x4d9863cdL), tobe(0x56b06eb5L), +tobe(0x17684cddL), tobe(0x0c4041a5L), tobe(0x2138562dL), tobe(0x3a105b55L), +tobe(0xa28812fdL), tobe(0xb9a01f85L), tobe(0x94d8080dL), tobe(0x8ff00575L), +tobe(0xce28271dL), tobe(0xd5002a65L), tobe(0xf8783dedL), tobe(0xe3503095L), +tobe(0x754e2961L), tobe(0x6e662419L), tobe(0x431e3391L), tobe(0x58363ee9L), +tobe(0x19ee1c81L), tobe(0x02c611f9L), tobe(0x2fbe0671L), tobe(0x34960b09L), +tobe(0xac0e42a1L), tobe(0xb7264fd9L), tobe(0x9a5e5851L), tobe(0x81765529L), +tobe(0xc0ae7741L), tobe(0xdb867a39L), tobe(0xf6fe6db1L), tobe(0xedd660c9L), +tobe(0xc30fe356L), tobe(0xd827ee2eL), tobe(0xf55ff9a6L), tobe(0xee77f4deL), +tobe(0xafafd6b6L), tobe(0xb487dbceL), tobe(0x99ffcc46L), tobe(0x82d7c13eL), +tobe(0x1a4f8896L), tobe(0x016785eeL), tobe(0x2c1f9266L), tobe(0x37379f1eL), +tobe(0x76efbd76L), tobe(0x6dc7b00eL), tobe(0x40bfa786L), tobe(0x5b97aafeL), +tobe(0x1d0ca0b8L), tobe(0x0624adc0L), tobe(0x2b5cba48L), tobe(0x3074b730L), +tobe(0x71ac9558L), tobe(0x6a849820L), tobe(0x47fc8fa8L), tobe(0x5cd482d0L), +tobe(0xc44ccb78L), tobe(0xdf64c600L), tobe(0xf21cd188L), tobe(0xe934dcf0L), +tobe(0xa8ecfe98L), tobe(0xb3c4f3e0L), tobe(0x9ebce468L), tobe(0x8594e910L), +tobe(0xab4d6a8fL), tobe(0xb06567f7L), tobe(0x9d1d707fL), tobe(0x86357d07L), +tobe(0xc7ed5f6fL), tobe(0xdcc55217L), tobe(0xf1bd459fL), tobe(0xea9548e7L), +tobe(0x720d014fL), tobe(0x69250c37L), tobe(0x445d1bbfL), tobe(0x5f7516c7L), +tobe(0x1ead34afL), tobe(0x058539d7L), tobe(0x28fd2e5fL), tobe(0x33d52327L)}, +{ +tobe(0x00000000L), tobe(0x4f576811L), tobe(0x9eaed022L), tobe(0xd1f9b833L), +tobe(0x399cbdf3L), tobe(0x76cbd5e2L), tobe(0xa7326dd1L), tobe(0xe86505c0L), +tobe(0x73397be6L), tobe(0x3c6e13f7L), tobe(0xed97abc4L), tobe(0xa2c0c3d5L), +tobe(0x4aa5c615L), tobe(0x05f2ae04L), tobe(0xd40b1637L), tobe(0x9b5c7e26L), +tobe(0xe672f7ccL), tobe(0xa9259fddL), tobe(0x78dc27eeL), tobe(0x378b4fffL), +tobe(0xdfee4a3fL), tobe(0x90b9222eL), tobe(0x41409a1dL), tobe(0x0e17f20cL), +tobe(0x954b8c2aL), tobe(0xda1ce43bL), tobe(0x0be55c08L), tobe(0x44b23419L), +tobe(0xacd731d9L), tobe(0xe38059c8L), tobe(0x3279e1fbL), tobe(0x7d2e89eaL), +tobe(0xc824f22fL), tobe(0x87739a3eL), tobe(0x568a220dL), tobe(0x19dd4a1cL), +tobe(0xf1b84fdcL), tobe(0xbeef27cdL), tobe(0x6f169ffeL), tobe(0x2041f7efL), +tobe(0xbb1d89c9L), tobe(0xf44ae1d8L), tobe(0x25b359ebL), tobe(0x6ae431faL), +tobe(0x8281343aL), tobe(0xcdd65c2bL), tobe(0x1c2fe418L), tobe(0x53788c09L), +tobe(0x2e5605e3L), tobe(0x61016df2L), tobe(0xb0f8d5c1L), tobe(0xffafbdd0L), +tobe(0x17cab810L), tobe(0x589dd001L), tobe(0x89646832L), tobe(0xc6330023L), +tobe(0x5d6f7e05L), tobe(0x12381614L), tobe(0xc3c1ae27L), tobe(0x8c96c636L), +tobe(0x64f3c3f6L), tobe(0x2ba4abe7L), tobe(0xfa5d13d4L), tobe(0xb50a7bc5L), +tobe(0x9488f9e9L), tobe(0xdbdf91f8L), tobe(0x0a2629cbL), tobe(0x457141daL), +tobe(0xad14441aL), tobe(0xe2432c0bL), tobe(0x33ba9438L), tobe(0x7cedfc29L), +tobe(0xe7b1820fL), tobe(0xa8e6ea1eL), tobe(0x791f522dL), tobe(0x36483a3cL), +tobe(0xde2d3ffcL), tobe(0x917a57edL), tobe(0x4083efdeL), tobe(0x0fd487cfL), +tobe(0x72fa0e25L), tobe(0x3dad6634L), tobe(0xec54de07L), tobe(0xa303b616L), +tobe(0x4b66b3d6L), tobe(0x0431dbc7L), tobe(0xd5c863f4L), tobe(0x9a9f0be5L), +tobe(0x01c375c3L), tobe(0x4e941dd2L), tobe(0x9f6da5e1L), tobe(0xd03acdf0L), +tobe(0x385fc830L), tobe(0x7708a021L), tobe(0xa6f11812L), tobe(0xe9a67003L), +tobe(0x5cac0bc6L), tobe(0x13fb63d7L), tobe(0xc202dbe4L), tobe(0x8d55b3f5L), +tobe(0x6530b635L), tobe(0x2a67de24L), tobe(0xfb9e6617L), tobe(0xb4c90e06L), +tobe(0x2f957020L), tobe(0x60c21831L), tobe(0xb13ba002L), tobe(0xfe6cc813L), +tobe(0x1609cdd3L), tobe(0x595ea5c2L), tobe(0x88a71df1L), tobe(0xc7f075e0L), +tobe(0xbadefc0aL), tobe(0xf589941bL), tobe(0x24702c28L), tobe(0x6b274439L), +tobe(0x834241f9L), tobe(0xcc1529e8L), tobe(0x1dec91dbL), tobe(0x52bbf9caL), +tobe(0xc9e787ecL), tobe(0x86b0effdL), tobe(0x574957ceL), tobe(0x181e3fdfL), +tobe(0xf07b3a1fL), tobe(0xbf2c520eL), tobe(0x6ed5ea3dL), tobe(0x2182822cL), +tobe(0x2dd0ee65L), tobe(0x62878674L), tobe(0xb37e3e47L), tobe(0xfc295656L), +tobe(0x144c5396L), tobe(0x5b1b3b87L), tobe(0x8ae283b4L), tobe(0xc5b5eba5L), +tobe(0x5ee99583L), tobe(0x11befd92L), tobe(0xc04745a1L), tobe(0x8f102db0L), +tobe(0x67752870L), tobe(0x28224061L), tobe(0xf9dbf852L), tobe(0xb68c9043L), +tobe(0xcba219a9L), tobe(0x84f571b8L), tobe(0x550cc98bL), tobe(0x1a5ba19aL), +tobe(0xf23ea45aL), tobe(0xbd69cc4bL), tobe(0x6c907478L), tobe(0x23c71c69L), +tobe(0xb89b624fL), tobe(0xf7cc0a5eL), tobe(0x2635b26dL), tobe(0x6962da7cL), +tobe(0x8107dfbcL), tobe(0xce50b7adL), tobe(0x1fa90f9eL), tobe(0x50fe678fL), +tobe(0xe5f41c4aL), tobe(0xaaa3745bL), tobe(0x7b5acc68L), tobe(0x340da479L), +tobe(0xdc68a1b9L), tobe(0x933fc9a8L), tobe(0x42c6719bL), tobe(0x0d91198aL), +tobe(0x96cd67acL), tobe(0xd99a0fbdL), tobe(0x0863b78eL), tobe(0x4734df9fL), +tobe(0xaf51da5fL), tobe(0xe006b24eL), tobe(0x31ff0a7dL), tobe(0x7ea8626cL), +tobe(0x0386eb86L), tobe(0x4cd18397L), tobe(0x9d283ba4L), tobe(0xd27f53b5L), +tobe(0x3a1a5675L), tobe(0x754d3e64L), tobe(0xa4b48657L), tobe(0xebe3ee46L), +tobe(0x70bf9060L), tobe(0x3fe8f871L), tobe(0xee114042L), tobe(0xa1462853L), +tobe(0x49232d93L), tobe(0x06744582L), tobe(0xd78dfdb1L), tobe(0x98da95a0L), +tobe(0xb958178cL), tobe(0xf60f7f9dL), tobe(0x27f6c7aeL), tobe(0x68a1afbfL), +tobe(0x80c4aa7fL), tobe(0xcf93c26eL), tobe(0x1e6a7a5dL), tobe(0x513d124cL), +tobe(0xca616c6aL), tobe(0x8536047bL), tobe(0x54cfbc48L), tobe(0x1b98d459L), +tobe(0xf3fdd199L), tobe(0xbcaab988L), tobe(0x6d5301bbL), tobe(0x220469aaL), +tobe(0x5f2ae040L), tobe(0x107d8851L), tobe(0xc1843062L), tobe(0x8ed35873L), +tobe(0x66b65db3L), tobe(0x29e135a2L), tobe(0xf8188d91L), tobe(0xb74fe580L), +tobe(0x2c139ba6L), tobe(0x6344f3b7L), tobe(0xb2bd4b84L), tobe(0xfdea2395L), +tobe(0x158f2655L), tobe(0x5ad84e44L), tobe(0x8b21f677L), tobe(0xc4769e66L), +tobe(0x717ce5a3L), tobe(0x3e2b8db2L), tobe(0xefd23581L), tobe(0xa0855d90L), +tobe(0x48e05850L), tobe(0x07b73041L), tobe(0xd64e8872L), tobe(0x9919e063L), +tobe(0x02459e45L), tobe(0x4d12f654L), tobe(0x9ceb4e67L), tobe(0xd3bc2676L), +tobe(0x3bd923b6L), tobe(0x748e4ba7L), tobe(0xa577f394L), tobe(0xea209b85L), +tobe(0x970e126fL), tobe(0xd8597a7eL), tobe(0x09a0c24dL), tobe(0x46f7aa5cL), +tobe(0xae92af9cL), tobe(0xe1c5c78dL), tobe(0x303c7fbeL), tobe(0x7f6b17afL), +tobe(0xe4376989L), tobe(0xab600198L), tobe(0x7a99b9abL), tobe(0x35ced1baL), +tobe(0xddabd47aL), tobe(0x92fcbc6bL), tobe(0x43050458L), tobe(0x0c526c49L)}, +{ +tobe(0x00000000L), tobe(0x5ba1dccaL), tobe(0xb743b994L), tobe(0xece2655eL), +tobe(0x6a466e9fL), tobe(0x31e7b255L), tobe(0xdd05d70bL), tobe(0x86a40bc1L), +tobe(0xd48cdd3eL), tobe(0x8f2d01f4L), tobe(0x63cf64aaL), tobe(0x386eb860L), +tobe(0xbecab3a1L), tobe(0xe56b6f6bL), tobe(0x09890a35L), tobe(0x5228d6ffL), +tobe(0xadd8a7cbL), tobe(0xf6797b01L), tobe(0x1a9b1e5fL), tobe(0x413ac295L), +tobe(0xc79ec954L), tobe(0x9c3f159eL), tobe(0x70dd70c0L), tobe(0x2b7cac0aL), +tobe(0x79547af5L), tobe(0x22f5a63fL), tobe(0xce17c361L), tobe(0x95b61fabL), +tobe(0x1312146aL), tobe(0x48b3c8a0L), tobe(0xa451adfeL), tobe(0xfff07134L), +tobe(0x5f705221L), tobe(0x04d18eebL), tobe(0xe833ebb5L), tobe(0xb392377fL), +tobe(0x35363cbeL), tobe(0x6e97e074L), tobe(0x8275852aL), tobe(0xd9d459e0L), +tobe(0x8bfc8f1fL), tobe(0xd05d53d5L), tobe(0x3cbf368bL), tobe(0x671eea41L), +tobe(0xe1bae180L), tobe(0xba1b3d4aL), tobe(0x56f95814L), tobe(0x0d5884deL), +tobe(0xf2a8f5eaL), tobe(0xa9092920L), tobe(0x45eb4c7eL), tobe(0x1e4a90b4L), +tobe(0x98ee9b75L), tobe(0xc34f47bfL), tobe(0x2fad22e1L), tobe(0x740cfe2bL), +tobe(0x262428d4L), tobe(0x7d85f41eL), tobe(0x91679140L), tobe(0xcac64d8aL), +tobe(0x4c62464bL), tobe(0x17c39a81L), tobe(0xfb21ffdfL), tobe(0xa0802315L), +tobe(0xbee0a442L), tobe(0xe5417888L), tobe(0x09a31dd6L), tobe(0x5202c11cL), +tobe(0xd4a6caddL), tobe(0x8f071617L), tobe(0x63e57349L), tobe(0x3844af83L), +tobe(0x6a6c797cL), tobe(0x31cda5b6L), tobe(0xdd2fc0e8L), tobe(0x868e1c22L), +tobe(0x002a17e3L), tobe(0x5b8bcb29L), tobe(0xb769ae77L), tobe(0xecc872bdL), +tobe(0x13380389L), tobe(0x4899df43L), tobe(0xa47bba1dL), tobe(0xffda66d7L), +tobe(0x797e6d16L), tobe(0x22dfb1dcL), tobe(0xce3dd482L), tobe(0x959c0848L), +tobe(0xc7b4deb7L), tobe(0x9c15027dL), tobe(0x70f76723L), tobe(0x2b56bbe9L), +tobe(0xadf2b028L), tobe(0xf6536ce2L), tobe(0x1ab109bcL), tobe(0x4110d576L), +tobe(0xe190f663L), tobe(0xba312aa9L), tobe(0x56d34ff7L), tobe(0x0d72933dL), +tobe(0x8bd698fcL), tobe(0xd0774436L), tobe(0x3c952168L), tobe(0x6734fda2L), +tobe(0x351c2b5dL), tobe(0x6ebdf797L), tobe(0x825f92c9L), tobe(0xd9fe4e03L), +tobe(0x5f5a45c2L), tobe(0x04fb9908L), tobe(0xe819fc56L), tobe(0xb3b8209cL), +tobe(0x4c4851a8L), tobe(0x17e98d62L), tobe(0xfb0be83cL), tobe(0xa0aa34f6L), +tobe(0x260e3f37L), tobe(0x7dafe3fdL), tobe(0x914d86a3L), tobe(0xcaec5a69L), +tobe(0x98c48c96L), tobe(0xc365505cL), tobe(0x2f873502L), tobe(0x7426e9c8L), +tobe(0xf282e209L), tobe(0xa9233ec3L), tobe(0x45c15b9dL), tobe(0x1e608757L), +tobe(0x79005533L), tobe(0x22a189f9L), tobe(0xce43eca7L), tobe(0x95e2306dL), +tobe(0x13463bacL), tobe(0x48e7e766L), tobe(0xa4058238L), tobe(0xffa45ef2L), +tobe(0xad8c880dL), tobe(0xf62d54c7L), tobe(0x1acf3199L), tobe(0x416eed53L), +tobe(0xc7cae692L), tobe(0x9c6b3a58L), tobe(0x70895f06L), tobe(0x2b2883ccL), +tobe(0xd4d8f2f8L), tobe(0x8f792e32L), tobe(0x639b4b6cL), tobe(0x383a97a6L), +tobe(0xbe9e9c67L), tobe(0xe53f40adL), tobe(0x09dd25f3L), tobe(0x527cf939L), +tobe(0x00542fc6L), tobe(0x5bf5f30cL), tobe(0xb7179652L), tobe(0xecb64a98L), +tobe(0x6a124159L), tobe(0x31b39d93L), tobe(0xdd51f8cdL), tobe(0x86f02407L), +tobe(0x26700712L), tobe(0x7dd1dbd8L), tobe(0x9133be86L), tobe(0xca92624cL), +tobe(0x4c36698dL), tobe(0x1797b547L), tobe(0xfb75d019L), tobe(0xa0d40cd3L), +tobe(0xf2fcda2cL), tobe(0xa95d06e6L), tobe(0x45bf63b8L), tobe(0x1e1ebf72L), +tobe(0x98bab4b3L), tobe(0xc31b6879L), tobe(0x2ff90d27L), tobe(0x7458d1edL), +tobe(0x8ba8a0d9L), tobe(0xd0097c13L), tobe(0x3ceb194dL), tobe(0x674ac587L), +tobe(0xe1eece46L), tobe(0xba4f128cL), tobe(0x56ad77d2L), tobe(0x0d0cab18L), +tobe(0x5f247de7L), tobe(0x0485a12dL), tobe(0xe867c473L), tobe(0xb3c618b9L), +tobe(0x35621378L), tobe(0x6ec3cfb2L), tobe(0x8221aaecL), tobe(0xd9807626L), +tobe(0xc7e0f171L), tobe(0x9c412dbbL), tobe(0x70a348e5L), tobe(0x2b02942fL), +tobe(0xada69feeL), tobe(0xf6074324L), tobe(0x1ae5267aL), tobe(0x4144fab0L), +tobe(0x136c2c4fL), tobe(0x48cdf085L), tobe(0xa42f95dbL), tobe(0xff8e4911L), +tobe(0x792a42d0L), tobe(0x228b9e1aL), tobe(0xce69fb44L), tobe(0x95c8278eL), +tobe(0x6a3856baL), tobe(0x31998a70L), tobe(0xdd7bef2eL), tobe(0x86da33e4L), +tobe(0x007e3825L), tobe(0x5bdfe4efL), tobe(0xb73d81b1L), tobe(0xec9c5d7bL), +tobe(0xbeb48b84L), tobe(0xe515574eL), tobe(0x09f73210L), tobe(0x5256eedaL), +tobe(0xd4f2e51bL), tobe(0x8f5339d1L), tobe(0x63b15c8fL), tobe(0x38108045L), +tobe(0x9890a350L), tobe(0xc3317f9aL), tobe(0x2fd31ac4L), tobe(0x7472c60eL), +tobe(0xf2d6cdcfL), tobe(0xa9771105L), tobe(0x4595745bL), tobe(0x1e34a891L), +tobe(0x4c1c7e6eL), tobe(0x17bda2a4L), tobe(0xfb5fc7faL), tobe(0xa0fe1b30L), +tobe(0x265a10f1L), tobe(0x7dfbcc3bL), tobe(0x9119a965L), tobe(0xcab875afL), +tobe(0x3548049bL), tobe(0x6ee9d851L), tobe(0x820bbd0fL), tobe(0xd9aa61c5L), +tobe(0x5f0e6a04L), tobe(0x04afb6ceL), tobe(0xe84dd390L), tobe(0xb3ec0f5aL), +tobe(0xe1c4d9a5L), tobe(0xba65056fL), tobe(0x56876031L), tobe(0x0d26bcfbL), +tobe(0x8b82b73aL), tobe(0xd0236bf0L), tobe(0x3cc10eaeL), tobe(0x6760d264L)}, +}; +static const uint32_t crc32ctable_le[8][256] = {{ +tole(0x00000000L), tole(0xf26b8303L), tole(0xe13b70f7L), tole(0x1350f3f4L), +tole(0xc79a971fL), tole(0x35f1141cL), tole(0x26a1e7e8L), tole(0xd4ca64ebL), +tole(0x8ad958cfL), tole(0x78b2dbccL), tole(0x6be22838L), tole(0x9989ab3bL), +tole(0x4d43cfd0L), tole(0xbf284cd3L), tole(0xac78bf27L), tole(0x5e133c24L), +tole(0x105ec76fL), tole(0xe235446cL), tole(0xf165b798L), tole(0x030e349bL), +tole(0xd7c45070L), tole(0x25afd373L), tole(0x36ff2087L), tole(0xc494a384L), +tole(0x9a879fa0L), tole(0x68ec1ca3L), tole(0x7bbcef57L), tole(0x89d76c54L), +tole(0x5d1d08bfL), tole(0xaf768bbcL), tole(0xbc267848L), tole(0x4e4dfb4bL), +tole(0x20bd8edeL), tole(0xd2d60dddL), tole(0xc186fe29L), tole(0x33ed7d2aL), +tole(0xe72719c1L), tole(0x154c9ac2L), tole(0x061c6936L), tole(0xf477ea35L), +tole(0xaa64d611L), tole(0x580f5512L), tole(0x4b5fa6e6L), tole(0xb93425e5L), +tole(0x6dfe410eL), tole(0x9f95c20dL), tole(0x8cc531f9L), tole(0x7eaeb2faL), +tole(0x30e349b1L), tole(0xc288cab2L), tole(0xd1d83946L), tole(0x23b3ba45L), +tole(0xf779deaeL), tole(0x05125dadL), tole(0x1642ae59L), tole(0xe4292d5aL), +tole(0xba3a117eL), tole(0x4851927dL), tole(0x5b016189L), tole(0xa96ae28aL), +tole(0x7da08661L), tole(0x8fcb0562L), tole(0x9c9bf696L), tole(0x6ef07595L), +tole(0x417b1dbcL), tole(0xb3109ebfL), tole(0xa0406d4bL), tole(0x522bee48L), +tole(0x86e18aa3L), tole(0x748a09a0L), tole(0x67dafa54L), tole(0x95b17957L), +tole(0xcba24573L), tole(0x39c9c670L), tole(0x2a993584L), tole(0xd8f2b687L), +tole(0x0c38d26cL), tole(0xfe53516fL), tole(0xed03a29bL), tole(0x1f682198L), +tole(0x5125dad3L), tole(0xa34e59d0L), tole(0xb01eaa24L), tole(0x42752927L), +tole(0x96bf4dccL), tole(0x64d4cecfL), tole(0x77843d3bL), tole(0x85efbe38L), +tole(0xdbfc821cL), tole(0x2997011fL), tole(0x3ac7f2ebL), tole(0xc8ac71e8L), +tole(0x1c661503L), tole(0xee0d9600L), tole(0xfd5d65f4L), tole(0x0f36e6f7L), +tole(0x61c69362L), tole(0x93ad1061L), tole(0x80fde395L), tole(0x72966096L), +tole(0xa65c047dL), tole(0x5437877eL), tole(0x4767748aL), tole(0xb50cf789L), +tole(0xeb1fcbadL), tole(0x197448aeL), tole(0x0a24bb5aL), tole(0xf84f3859L), +tole(0x2c855cb2L), tole(0xdeeedfb1L), tole(0xcdbe2c45L), tole(0x3fd5af46L), +tole(0x7198540dL), tole(0x83f3d70eL), tole(0x90a324faL), tole(0x62c8a7f9L), +tole(0xb602c312L), tole(0x44694011L), tole(0x5739b3e5L), tole(0xa55230e6L), +tole(0xfb410cc2L), tole(0x092a8fc1L), tole(0x1a7a7c35L), tole(0xe811ff36L), +tole(0x3cdb9bddL), tole(0xceb018deL), tole(0xdde0eb2aL), tole(0x2f8b6829L), +tole(0x82f63b78L), tole(0x709db87bL), tole(0x63cd4b8fL), tole(0x91a6c88cL), +tole(0x456cac67L), tole(0xb7072f64L), tole(0xa457dc90L), tole(0x563c5f93L), +tole(0x082f63b7L), tole(0xfa44e0b4L), tole(0xe9141340L), tole(0x1b7f9043L), +tole(0xcfb5f4a8L), tole(0x3dde77abL), tole(0x2e8e845fL), tole(0xdce5075cL), +tole(0x92a8fc17L), tole(0x60c37f14L), tole(0x73938ce0L), tole(0x81f80fe3L), +tole(0x55326b08L), tole(0xa759e80bL), tole(0xb4091bffL), tole(0x466298fcL), +tole(0x1871a4d8L), tole(0xea1a27dbL), tole(0xf94ad42fL), tole(0x0b21572cL), +tole(0xdfeb33c7L), tole(0x2d80b0c4L), tole(0x3ed04330L), tole(0xccbbc033L), +tole(0xa24bb5a6L), tole(0x502036a5L), tole(0x4370c551L), tole(0xb11b4652L), +tole(0x65d122b9L), tole(0x97baa1baL), tole(0x84ea524eL), tole(0x7681d14dL), +tole(0x2892ed69L), tole(0xdaf96e6aL), tole(0xc9a99d9eL), tole(0x3bc21e9dL), +tole(0xef087a76L), tole(0x1d63f975L), tole(0x0e330a81L), tole(0xfc588982L), +tole(0xb21572c9L), tole(0x407ef1caL), tole(0x532e023eL), tole(0xa145813dL), +tole(0x758fe5d6L), tole(0x87e466d5L), tole(0x94b49521L), tole(0x66df1622L), +tole(0x38cc2a06L), tole(0xcaa7a905L), tole(0xd9f75af1L), tole(0x2b9cd9f2L), +tole(0xff56bd19L), tole(0x0d3d3e1aL), tole(0x1e6dcdeeL), tole(0xec064eedL), +tole(0xc38d26c4L), tole(0x31e6a5c7L), tole(0x22b65633L), tole(0xd0ddd530L), +tole(0x0417b1dbL), tole(0xf67c32d8L), tole(0xe52cc12cL), tole(0x1747422fL), +tole(0x49547e0bL), tole(0xbb3ffd08L), tole(0xa86f0efcL), tole(0x5a048dffL), +tole(0x8ecee914L), tole(0x7ca56a17L), tole(0x6ff599e3L), tole(0x9d9e1ae0L), +tole(0xd3d3e1abL), tole(0x21b862a8L), tole(0x32e8915cL), tole(0xc083125fL), +tole(0x144976b4L), tole(0xe622f5b7L), tole(0xf5720643L), tole(0x07198540L), +tole(0x590ab964L), tole(0xab613a67L), tole(0xb831c993L), tole(0x4a5a4a90L), +tole(0x9e902e7bL), tole(0x6cfbad78L), tole(0x7fab5e8cL), tole(0x8dc0dd8fL), +tole(0xe330a81aL), tole(0x115b2b19L), tole(0x020bd8edL), tole(0xf0605beeL), +tole(0x24aa3f05L), tole(0xd6c1bc06L), tole(0xc5914ff2L), tole(0x37faccf1L), +tole(0x69e9f0d5L), tole(0x9b8273d6L), tole(0x88d28022L), tole(0x7ab90321L), +tole(0xae7367caL), tole(0x5c18e4c9L), tole(0x4f48173dL), tole(0xbd23943eL), +tole(0xf36e6f75L), tole(0x0105ec76L), tole(0x12551f82L), tole(0xe03e9c81L), +tole(0x34f4f86aL), tole(0xc69f7b69L), tole(0xd5cf889dL), tole(0x27a40b9eL), +tole(0x79b737baL), tole(0x8bdcb4b9L), tole(0x988c474dL), tole(0x6ae7c44eL), +tole(0xbe2da0a5L), tole(0x4c4623a6L), tole(0x5f16d052L), tole(0xad7d5351L)}, +{ +tole(0x00000000L), tole(0x13a29877L), tole(0x274530eeL), tole(0x34e7a899L), +tole(0x4e8a61dcL), tole(0x5d28f9abL), tole(0x69cf5132L), tole(0x7a6dc945L), +tole(0x9d14c3b8L), tole(0x8eb65bcfL), tole(0xba51f356L), tole(0xa9f36b21L), +tole(0xd39ea264L), tole(0xc03c3a13L), tole(0xf4db928aL), tole(0xe7790afdL), +tole(0x3fc5f181L), tole(0x2c6769f6L), tole(0x1880c16fL), tole(0x0b225918L), +tole(0x714f905dL), tole(0x62ed082aL), tole(0x560aa0b3L), tole(0x45a838c4L), +tole(0xa2d13239L), tole(0xb173aa4eL), tole(0x859402d7L), tole(0x96369aa0L), +tole(0xec5b53e5L), tole(0xfff9cb92L), tole(0xcb1e630bL), tole(0xd8bcfb7cL), +tole(0x7f8be302L), tole(0x6c297b75L), tole(0x58ced3ecL), tole(0x4b6c4b9bL), +tole(0x310182deL), tole(0x22a31aa9L), tole(0x1644b230L), tole(0x05e62a47L), +tole(0xe29f20baL), tole(0xf13db8cdL), tole(0xc5da1054L), tole(0xd6788823L), +tole(0xac154166L), tole(0xbfb7d911L), tole(0x8b507188L), tole(0x98f2e9ffL), +tole(0x404e1283L), tole(0x53ec8af4L), tole(0x670b226dL), tole(0x74a9ba1aL), +tole(0x0ec4735fL), tole(0x1d66eb28L), tole(0x298143b1L), tole(0x3a23dbc6L), +tole(0xdd5ad13bL), tole(0xcef8494cL), tole(0xfa1fe1d5L), tole(0xe9bd79a2L), +tole(0x93d0b0e7L), tole(0x80722890L), tole(0xb4958009L), tole(0xa737187eL), +tole(0xff17c604L), tole(0xecb55e73L), tole(0xd852f6eaL), tole(0xcbf06e9dL), +tole(0xb19da7d8L), tole(0xa23f3fafL), tole(0x96d89736L), tole(0x857a0f41L), +tole(0x620305bcL), tole(0x71a19dcbL), tole(0x45463552L), tole(0x56e4ad25L), +tole(0x2c896460L), tole(0x3f2bfc17L), tole(0x0bcc548eL), tole(0x186eccf9L), +tole(0xc0d23785L), tole(0xd370aff2L), tole(0xe797076bL), tole(0xf4359f1cL), +tole(0x8e585659L), tole(0x9dface2eL), tole(0xa91d66b7L), tole(0xbabffec0L), +tole(0x5dc6f43dL), tole(0x4e646c4aL), tole(0x7a83c4d3L), tole(0x69215ca4L), +tole(0x134c95e1L), tole(0x00ee0d96L), tole(0x3409a50fL), tole(0x27ab3d78L), +tole(0x809c2506L), tole(0x933ebd71L), tole(0xa7d915e8L), tole(0xb47b8d9fL), +tole(0xce1644daL), tole(0xddb4dcadL), tole(0xe9537434L), tole(0xfaf1ec43L), +tole(0x1d88e6beL), tole(0x0e2a7ec9L), tole(0x3acdd650L), tole(0x296f4e27L), +tole(0x53028762L), tole(0x40a01f15L), tole(0x7447b78cL), tole(0x67e52ffbL), +tole(0xbf59d487L), tole(0xacfb4cf0L), tole(0x981ce469L), tole(0x8bbe7c1eL), +tole(0xf1d3b55bL), tole(0xe2712d2cL), tole(0xd69685b5L), tole(0xc5341dc2L), +tole(0x224d173fL), tole(0x31ef8f48L), tole(0x050827d1L), tole(0x16aabfa6L), +tole(0x6cc776e3L), tole(0x7f65ee94L), tole(0x4b82460dL), tole(0x5820de7aL), +tole(0xfbc3faf9L), tole(0xe861628eL), tole(0xdc86ca17L), tole(0xcf245260L), +tole(0xb5499b25L), tole(0xa6eb0352L), tole(0x920cabcbL), tole(0x81ae33bcL), +tole(0x66d73941L), tole(0x7575a136L), tole(0x419209afL), tole(0x523091d8L), +tole(0x285d589dL), tole(0x3bffc0eaL), tole(0x0f186873L), tole(0x1cbaf004L), +tole(0xc4060b78L), tole(0xd7a4930fL), tole(0xe3433b96L), tole(0xf0e1a3e1L), +tole(0x8a8c6aa4L), tole(0x992ef2d3L), tole(0xadc95a4aL), tole(0xbe6bc23dL), +tole(0x5912c8c0L), tole(0x4ab050b7L), tole(0x7e57f82eL), tole(0x6df56059L), +tole(0x1798a91cL), tole(0x043a316bL), tole(0x30dd99f2L), tole(0x237f0185L), +tole(0x844819fbL), tole(0x97ea818cL), tole(0xa30d2915L), tole(0xb0afb162L), +tole(0xcac27827L), tole(0xd960e050L), tole(0xed8748c9L), tole(0xfe25d0beL), +tole(0x195cda43L), tole(0x0afe4234L), tole(0x3e19eaadL), tole(0x2dbb72daL), +tole(0x57d6bb9fL), tole(0x447423e8L), tole(0x70938b71L), tole(0x63311306L), +tole(0xbb8de87aL), tole(0xa82f700dL), tole(0x9cc8d894L), tole(0x8f6a40e3L), +tole(0xf50789a6L), tole(0xe6a511d1L), tole(0xd242b948L), tole(0xc1e0213fL), +tole(0x26992bc2L), tole(0x353bb3b5L), tole(0x01dc1b2cL), tole(0x127e835bL), +tole(0x68134a1eL), tole(0x7bb1d269L), tole(0x4f567af0L), tole(0x5cf4e287L), +tole(0x04d43cfdL), tole(0x1776a48aL), tole(0x23910c13L), tole(0x30339464L), +tole(0x4a5e5d21L), tole(0x59fcc556L), tole(0x6d1b6dcfL), tole(0x7eb9f5b8L), +tole(0x99c0ff45L), tole(0x8a626732L), tole(0xbe85cfabL), tole(0xad2757dcL), +tole(0xd74a9e99L), tole(0xc4e806eeL), tole(0xf00fae77L), tole(0xe3ad3600L), +tole(0x3b11cd7cL), tole(0x28b3550bL), tole(0x1c54fd92L), tole(0x0ff665e5L), +tole(0x759baca0L), tole(0x663934d7L), tole(0x52de9c4eL), tole(0x417c0439L), +tole(0xa6050ec4L), tole(0xb5a796b3L), tole(0x81403e2aL), tole(0x92e2a65dL), +tole(0xe88f6f18L), tole(0xfb2df76fL), tole(0xcfca5ff6L), tole(0xdc68c781L), +tole(0x7b5fdfffL), tole(0x68fd4788L), tole(0x5c1aef11L), tole(0x4fb87766L), +tole(0x35d5be23L), tole(0x26772654L), tole(0x12908ecdL), tole(0x013216baL), +tole(0xe64b1c47L), tole(0xf5e98430L), tole(0xc10e2ca9L), tole(0xd2acb4deL), +tole(0xa8c17d9bL), tole(0xbb63e5ecL), tole(0x8f844d75L), tole(0x9c26d502L), +tole(0x449a2e7eL), tole(0x5738b609L), tole(0x63df1e90L), tole(0x707d86e7L), +tole(0x0a104fa2L), tole(0x19b2d7d5L), tole(0x2d557f4cL), tole(0x3ef7e73bL), +tole(0xd98eedc6L), tole(0xca2c75b1L), tole(0xfecbdd28L), tole(0xed69455fL), +tole(0x97048c1aL), tole(0x84a6146dL), tole(0xb041bcf4L), tole(0xa3e32483L)}, +{ +tole(0x00000000L), tole(0xa541927eL), tole(0x4f6f520dL), tole(0xea2ec073L), +tole(0x9edea41aL), tole(0x3b9f3664L), tole(0xd1b1f617L), tole(0x74f06469L), +tole(0x38513ec5L), tole(0x9d10acbbL), tole(0x773e6cc8L), tole(0xd27ffeb6L), +tole(0xa68f9adfL), tole(0x03ce08a1L), tole(0xe9e0c8d2L), tole(0x4ca15aacL), +tole(0x70a27d8aL), tole(0xd5e3eff4L), tole(0x3fcd2f87L), tole(0x9a8cbdf9L), +tole(0xee7cd990L), tole(0x4b3d4beeL), tole(0xa1138b9dL), tole(0x045219e3L), +tole(0x48f3434fL), tole(0xedb2d131L), tole(0x079c1142L), tole(0xa2dd833cL), +tole(0xd62de755L), tole(0x736c752bL), tole(0x9942b558L), tole(0x3c032726L), +tole(0xe144fb14L), tole(0x4405696aL), tole(0xae2ba919L), tole(0x0b6a3b67L), +tole(0x7f9a5f0eL), tole(0xdadbcd70L), tole(0x30f50d03L), tole(0x95b49f7dL), +tole(0xd915c5d1L), tole(0x7c5457afL), tole(0x967a97dcL), tole(0x333b05a2L), +tole(0x47cb61cbL), tole(0xe28af3b5L), tole(0x08a433c6L), tole(0xade5a1b8L), +tole(0x91e6869eL), tole(0x34a714e0L), tole(0xde89d493L), tole(0x7bc846edL), +tole(0x0f382284L), tole(0xaa79b0faL), tole(0x40577089L), tole(0xe516e2f7L), +tole(0xa9b7b85bL), tole(0x0cf62a25L), tole(0xe6d8ea56L), tole(0x43997828L), +tole(0x37691c41L), tole(0x92288e3fL), tole(0x78064e4cL), tole(0xdd47dc32L), +tole(0xc76580d9L), tole(0x622412a7L), tole(0x880ad2d4L), tole(0x2d4b40aaL), +tole(0x59bb24c3L), tole(0xfcfab6bdL), tole(0x16d476ceL), tole(0xb395e4b0L), +tole(0xff34be1cL), tole(0x5a752c62L), tole(0xb05bec11L), tole(0x151a7e6fL), +tole(0x61ea1a06L), tole(0xc4ab8878L), tole(0x2e85480bL), tole(0x8bc4da75L), +tole(0xb7c7fd53L), tole(0x12866f2dL), tole(0xf8a8af5eL), tole(0x5de93d20L), +tole(0x29195949L), tole(0x8c58cb37L), tole(0x66760b44L), tole(0xc337993aL), +tole(0x8f96c396L), tole(0x2ad751e8L), tole(0xc0f9919bL), tole(0x65b803e5L), +tole(0x1148678cL), tole(0xb409f5f2L), tole(0x5e273581L), tole(0xfb66a7ffL), +tole(0x26217bcdL), tole(0x8360e9b3L), tole(0x694e29c0L), tole(0xcc0fbbbeL), +tole(0xb8ffdfd7L), tole(0x1dbe4da9L), tole(0xf7908ddaL), tole(0x52d11fa4L), +tole(0x1e704508L), tole(0xbb31d776L), tole(0x511f1705L), tole(0xf45e857bL), +tole(0x80aee112L), tole(0x25ef736cL), tole(0xcfc1b31fL), tole(0x6a802161L), +tole(0x56830647L), tole(0xf3c29439L), tole(0x19ec544aL), tole(0xbcadc634L), +tole(0xc85da25dL), tole(0x6d1c3023L), tole(0x8732f050L), tole(0x2273622eL), +tole(0x6ed23882L), tole(0xcb93aafcL), tole(0x21bd6a8fL), tole(0x84fcf8f1L), +tole(0xf00c9c98L), tole(0x554d0ee6L), tole(0xbf63ce95L), tole(0x1a225cebL), +tole(0x8b277743L), tole(0x2e66e53dL), tole(0xc448254eL), tole(0x6109b730L), +tole(0x15f9d359L), tole(0xb0b84127L), tole(0x5a968154L), tole(0xffd7132aL), +tole(0xb3764986L), tole(0x1637dbf8L), tole(0xfc191b8bL), tole(0x595889f5L), +tole(0x2da8ed9cL), tole(0x88e97fe2L), tole(0x62c7bf91L), tole(0xc7862defL), +tole(0xfb850ac9L), tole(0x5ec498b7L), tole(0xb4ea58c4L), tole(0x11abcabaL), +tole(0x655baed3L), tole(0xc01a3cadL), tole(0x2a34fcdeL), tole(0x8f756ea0L), +tole(0xc3d4340cL), tole(0x6695a672L), tole(0x8cbb6601L), tole(0x29faf47fL), +tole(0x5d0a9016L), tole(0xf84b0268L), tole(0x1265c21bL), tole(0xb7245065L), +tole(0x6a638c57L), tole(0xcf221e29L), tole(0x250cde5aL), tole(0x804d4c24L), +tole(0xf4bd284dL), tole(0x51fcba33L), tole(0xbbd27a40L), tole(0x1e93e83eL), +tole(0x5232b292L), tole(0xf77320ecL), tole(0x1d5de09fL), tole(0xb81c72e1L), +tole(0xccec1688L), tole(0x69ad84f6L), tole(0x83834485L), tole(0x26c2d6fbL), +tole(0x1ac1f1ddL), tole(0xbf8063a3L), tole(0x55aea3d0L), tole(0xf0ef31aeL), +tole(0x841f55c7L), tole(0x215ec7b9L), tole(0xcb7007caL), tole(0x6e3195b4L), +tole(0x2290cf18L), tole(0x87d15d66L), tole(0x6dff9d15L), tole(0xc8be0f6bL), +tole(0xbc4e6b02L), tole(0x190ff97cL), tole(0xf321390fL), tole(0x5660ab71L), +tole(0x4c42f79aL), tole(0xe90365e4L), tole(0x032da597L), tole(0xa66c37e9L), +tole(0xd29c5380L), tole(0x77ddc1feL), tole(0x9df3018dL), tole(0x38b293f3L), +tole(0x7413c95fL), tole(0xd1525b21L), tole(0x3b7c9b52L), tole(0x9e3d092cL), +tole(0xeacd6d45L), tole(0x4f8cff3bL), tole(0xa5a23f48L), tole(0x00e3ad36L), +tole(0x3ce08a10L), tole(0x99a1186eL), tole(0x738fd81dL), tole(0xd6ce4a63L), +tole(0xa23e2e0aL), tole(0x077fbc74L), tole(0xed517c07L), tole(0x4810ee79L), +tole(0x04b1b4d5L), tole(0xa1f026abL), tole(0x4bdee6d8L), tole(0xee9f74a6L), +tole(0x9a6f10cfL), tole(0x3f2e82b1L), tole(0xd50042c2L), tole(0x7041d0bcL), +tole(0xad060c8eL), tole(0x08479ef0L), tole(0xe2695e83L), tole(0x4728ccfdL), +tole(0x33d8a894L), tole(0x96993aeaL), tole(0x7cb7fa99L), tole(0xd9f668e7L), +tole(0x9557324bL), tole(0x3016a035L), tole(0xda386046L), tole(0x7f79f238L), +tole(0x0b899651L), tole(0xaec8042fL), tole(0x44e6c45cL), tole(0xe1a75622L), +tole(0xdda47104L), tole(0x78e5e37aL), tole(0x92cb2309L), tole(0x378ab177L), +tole(0x437ad51eL), tole(0xe63b4760L), tole(0x0c158713L), tole(0xa954156dL), +tole(0xe5f54fc1L), tole(0x40b4ddbfL), tole(0xaa9a1dccL), tole(0x0fdb8fb2L), +tole(0x7b2bebdbL), tole(0xde6a79a5L), tole(0x3444b9d6L), tole(0x91052ba8L)}, +{ +tole(0x00000000L), tole(0xdd45aab8L), tole(0xbf672381L), tole(0x62228939L), +tole(0x7b2231f3L), tole(0xa6679b4bL), tole(0xc4451272L), tole(0x1900b8caL), +tole(0xf64463e6L), tole(0x2b01c95eL), tole(0x49234067L), tole(0x9466eadfL), +tole(0x8d665215L), tole(0x5023f8adL), tole(0x32017194L), tole(0xef44db2cL), +tole(0xe964b13dL), tole(0x34211b85L), tole(0x560392bcL), tole(0x8b463804L), +tole(0x924680ceL), tole(0x4f032a76L), tole(0x2d21a34fL), tole(0xf06409f7L), +tole(0x1f20d2dbL), tole(0xc2657863L), tole(0xa047f15aL), tole(0x7d025be2L), +tole(0x6402e328L), tole(0xb9474990L), tole(0xdb65c0a9L), tole(0x06206a11L), +tole(0xd725148bL), tole(0x0a60be33L), tole(0x6842370aL), tole(0xb5079db2L), +tole(0xac072578L), tole(0x71428fc0L), tole(0x136006f9L), tole(0xce25ac41L), +tole(0x2161776dL), tole(0xfc24ddd5L), tole(0x9e0654ecL), tole(0x4343fe54L), +tole(0x5a43469eL), tole(0x8706ec26L), tole(0xe524651fL), tole(0x3861cfa7L), +tole(0x3e41a5b6L), tole(0xe3040f0eL), tole(0x81268637L), tole(0x5c632c8fL), +tole(0x45639445L), tole(0x98263efdL), tole(0xfa04b7c4L), tole(0x27411d7cL), +tole(0xc805c650L), tole(0x15406ce8L), tole(0x7762e5d1L), tole(0xaa274f69L), +tole(0xb327f7a3L), tole(0x6e625d1bL), tole(0x0c40d422L), tole(0xd1057e9aL), +tole(0xaba65fe7L), tole(0x76e3f55fL), tole(0x14c17c66L), tole(0xc984d6deL), +tole(0xd0846e14L), tole(0x0dc1c4acL), tole(0x6fe34d95L), tole(0xb2a6e72dL), +tole(0x5de23c01L), tole(0x80a796b9L), tole(0xe2851f80L), tole(0x3fc0b538L), +tole(0x26c00df2L), tole(0xfb85a74aL), tole(0x99a72e73L), tole(0x44e284cbL), +tole(0x42c2eedaL), tole(0x9f874462L), tole(0xfda5cd5bL), tole(0x20e067e3L), +tole(0x39e0df29L), tole(0xe4a57591L), tole(0x8687fca8L), tole(0x5bc25610L), +tole(0xb4868d3cL), tole(0x69c32784L), tole(0x0be1aebdL), tole(0xd6a40405L), +tole(0xcfa4bccfL), tole(0x12e11677L), tole(0x70c39f4eL), tole(0xad8635f6L), +tole(0x7c834b6cL), tole(0xa1c6e1d4L), tole(0xc3e468edL), tole(0x1ea1c255L), +tole(0x07a17a9fL), tole(0xdae4d027L), tole(0xb8c6591eL), tole(0x6583f3a6L), +tole(0x8ac7288aL), tole(0x57828232L), tole(0x35a00b0bL), tole(0xe8e5a1b3L), +tole(0xf1e51979L), tole(0x2ca0b3c1L), tole(0x4e823af8L), tole(0x93c79040L), +tole(0x95e7fa51L), tole(0x48a250e9L), tole(0x2a80d9d0L), tole(0xf7c57368L), +tole(0xeec5cba2L), tole(0x3380611aL), tole(0x51a2e823L), tole(0x8ce7429bL), +tole(0x63a399b7L), tole(0xbee6330fL), tole(0xdcc4ba36L), tole(0x0181108eL), +tole(0x1881a844L), tole(0xc5c402fcL), tole(0xa7e68bc5L), tole(0x7aa3217dL), +tole(0x52a0c93fL), tole(0x8fe56387L), tole(0xedc7eabeL), tole(0x30824006L), +tole(0x2982f8ccL), tole(0xf4c75274L), tole(0x96e5db4dL), tole(0x4ba071f5L), +tole(0xa4e4aad9L), tole(0x79a10061L), tole(0x1b838958L), tole(0xc6c623e0L), +tole(0xdfc69b2aL), tole(0x02833192L), tole(0x60a1b8abL), tole(0xbde41213L), +tole(0xbbc47802L), tole(0x6681d2baL), tole(0x04a35b83L), tole(0xd9e6f13bL), +tole(0xc0e649f1L), tole(0x1da3e349L), tole(0x7f816a70L), tole(0xa2c4c0c8L), +tole(0x4d801be4L), tole(0x90c5b15cL), tole(0xf2e73865L), tole(0x2fa292ddL), +tole(0x36a22a17L), tole(0xebe780afL), tole(0x89c50996L), tole(0x5480a32eL), +tole(0x8585ddb4L), tole(0x58c0770cL), tole(0x3ae2fe35L), tole(0xe7a7548dL), +tole(0xfea7ec47L), tole(0x23e246ffL), tole(0x41c0cfc6L), tole(0x9c85657eL), +tole(0x73c1be52L), tole(0xae8414eaL), tole(0xcca69dd3L), tole(0x11e3376bL), +tole(0x08e38fa1L), tole(0xd5a62519L), tole(0xb784ac20L), tole(0x6ac10698L), +tole(0x6ce16c89L), tole(0xb1a4c631L), tole(0xd3864f08L), tole(0x0ec3e5b0L), +tole(0x17c35d7aL), tole(0xca86f7c2L), tole(0xa8a47efbL), tole(0x75e1d443L), +tole(0x9aa50f6fL), tole(0x47e0a5d7L), tole(0x25c22ceeL), tole(0xf8878656L), +tole(0xe1873e9cL), tole(0x3cc29424L), tole(0x5ee01d1dL), tole(0x83a5b7a5L), +tole(0xf90696d8L), tole(0x24433c60L), tole(0x4661b559L), tole(0x9b241fe1L), +tole(0x8224a72bL), tole(0x5f610d93L), tole(0x3d4384aaL), tole(0xe0062e12L), +tole(0x0f42f53eL), tole(0xd2075f86L), tole(0xb025d6bfL), tole(0x6d607c07L), +tole(0x7460c4cdL), tole(0xa9256e75L), tole(0xcb07e74cL), tole(0x16424df4L), +tole(0x106227e5L), tole(0xcd278d5dL), tole(0xaf050464L), tole(0x7240aedcL), +tole(0x6b401616L), tole(0xb605bcaeL), tole(0xd4273597L), tole(0x09629f2fL), +tole(0xe6264403L), tole(0x3b63eebbL), tole(0x59416782L), tole(0x8404cd3aL), +tole(0x9d0475f0L), tole(0x4041df48L), tole(0x22635671L), tole(0xff26fcc9L), +tole(0x2e238253L), tole(0xf36628ebL), tole(0x9144a1d2L), tole(0x4c010b6aL), +tole(0x5501b3a0L), tole(0x88441918L), tole(0xea669021L), tole(0x37233a99L), +tole(0xd867e1b5L), tole(0x05224b0dL), tole(0x6700c234L), tole(0xba45688cL), +tole(0xa345d046L), tole(0x7e007afeL), tole(0x1c22f3c7L), tole(0xc167597fL), +tole(0xc747336eL), tole(0x1a0299d6L), tole(0x782010efL), tole(0xa565ba57L), +tole(0xbc65029dL), tole(0x6120a825L), tole(0x0302211cL), tole(0xde478ba4L), +tole(0x31035088L), tole(0xec46fa30L), tole(0x8e647309L), tole(0x5321d9b1L), +tole(0x4a21617bL), tole(0x9764cbc3L), tole(0xf54642faL), tole(0x2803e842L)}, +{ +tole(0x00000000L), tole(0x38116facL), tole(0x7022df58L), tole(0x4833b0f4L), +tole(0xe045beb0L), tole(0xd854d11cL), tole(0x906761e8L), tole(0xa8760e44L), +tole(0xc5670b91L), tole(0xfd76643dL), tole(0xb545d4c9L), tole(0x8d54bb65L), +tole(0x2522b521L), tole(0x1d33da8dL), tole(0x55006a79L), tole(0x6d1105d5L), +tole(0x8f2261d3L), tole(0xb7330e7fL), tole(0xff00be8bL), tole(0xc711d127L), +tole(0x6f67df63L), tole(0x5776b0cfL), tole(0x1f45003bL), tole(0x27546f97L), +tole(0x4a456a42L), tole(0x725405eeL), tole(0x3a67b51aL), tole(0x0276dab6L), +tole(0xaa00d4f2L), tole(0x9211bb5eL), tole(0xda220baaL), tole(0xe2336406L), +tole(0x1ba8b557L), tole(0x23b9dafbL), tole(0x6b8a6a0fL), tole(0x539b05a3L), +tole(0xfbed0be7L), tole(0xc3fc644bL), tole(0x8bcfd4bfL), tole(0xb3debb13L), +tole(0xdecfbec6L), tole(0xe6ded16aL), tole(0xaeed619eL), tole(0x96fc0e32L), +tole(0x3e8a0076L), tole(0x069b6fdaL), tole(0x4ea8df2eL), tole(0x76b9b082L), +tole(0x948ad484L), tole(0xac9bbb28L), tole(0xe4a80bdcL), tole(0xdcb96470L), +tole(0x74cf6a34L), tole(0x4cde0598L), tole(0x04edb56cL), tole(0x3cfcdac0L), +tole(0x51eddf15L), tole(0x69fcb0b9L), tole(0x21cf004dL), tole(0x19de6fe1L), +tole(0xb1a861a5L), tole(0x89b90e09L), tole(0xc18abefdL), tole(0xf99bd151L), +tole(0x37516aaeL), tole(0x0f400502L), tole(0x4773b5f6L), tole(0x7f62da5aL), +tole(0xd714d41eL), tole(0xef05bbb2L), tole(0xa7360b46L), tole(0x9f2764eaL), +tole(0xf236613fL), tole(0xca270e93L), tole(0x8214be67L), tole(0xba05d1cbL), +tole(0x1273df8fL), tole(0x2a62b023L), tole(0x625100d7L), tole(0x5a406f7bL), +tole(0xb8730b7dL), tole(0x806264d1L), tole(0xc851d425L), tole(0xf040bb89L), +tole(0x5836b5cdL), tole(0x6027da61L), tole(0x28146a95L), tole(0x10050539L), +tole(0x7d1400ecL), tole(0x45056f40L), tole(0x0d36dfb4L), tole(0x3527b018L), +tole(0x9d51be5cL), tole(0xa540d1f0L), tole(0xed736104L), tole(0xd5620ea8L), +tole(0x2cf9dff9L), tole(0x14e8b055L), tole(0x5cdb00a1L), tole(0x64ca6f0dL), +tole(0xccbc6149L), tole(0xf4ad0ee5L), tole(0xbc9ebe11L), tole(0x848fd1bdL), +tole(0xe99ed468L), tole(0xd18fbbc4L), tole(0x99bc0b30L), tole(0xa1ad649cL), +tole(0x09db6ad8L), tole(0x31ca0574L), tole(0x79f9b580L), tole(0x41e8da2cL), +tole(0xa3dbbe2aL), tole(0x9bcad186L), tole(0xd3f96172L), tole(0xebe80edeL), +tole(0x439e009aL), tole(0x7b8f6f36L), tole(0x33bcdfc2L), tole(0x0badb06eL), +tole(0x66bcb5bbL), tole(0x5eadda17L), tole(0x169e6ae3L), tole(0x2e8f054fL), +tole(0x86f90b0bL), tole(0xbee864a7L), tole(0xf6dbd453L), tole(0xcecabbffL), +tole(0x6ea2d55cL), tole(0x56b3baf0L), tole(0x1e800a04L), tole(0x269165a8L), +tole(0x8ee76becL), tole(0xb6f60440L), tole(0xfec5b4b4L), tole(0xc6d4db18L), +tole(0xabc5decdL), tole(0x93d4b161L), tole(0xdbe70195L), tole(0xe3f66e39L), +tole(0x4b80607dL), tole(0x73910fd1L), tole(0x3ba2bf25L), tole(0x03b3d089L), +tole(0xe180b48fL), tole(0xd991db23L), tole(0x91a26bd7L), tole(0xa9b3047bL), +tole(0x01c50a3fL), tole(0x39d46593L), tole(0x71e7d567L), tole(0x49f6bacbL), +tole(0x24e7bf1eL), tole(0x1cf6d0b2L), tole(0x54c56046L), tole(0x6cd40feaL), +tole(0xc4a201aeL), tole(0xfcb36e02L), tole(0xb480def6L), tole(0x8c91b15aL), +tole(0x750a600bL), tole(0x4d1b0fa7L), tole(0x0528bf53L), tole(0x3d39d0ffL), +tole(0x954fdebbL), tole(0xad5eb117L), tole(0xe56d01e3L), tole(0xdd7c6e4fL), +tole(0xb06d6b9aL), tole(0x887c0436L), tole(0xc04fb4c2L), tole(0xf85edb6eL), +tole(0x5028d52aL), tole(0x6839ba86L), tole(0x200a0a72L), tole(0x181b65deL), +tole(0xfa2801d8L), tole(0xc2396e74L), tole(0x8a0ade80L), tole(0xb21bb12cL), +tole(0x1a6dbf68L), tole(0x227cd0c4L), tole(0x6a4f6030L), tole(0x525e0f9cL), +tole(0x3f4f0a49L), tole(0x075e65e5L), tole(0x4f6dd511L), tole(0x777cbabdL), +tole(0xdf0ab4f9L), tole(0xe71bdb55L), tole(0xaf286ba1L), tole(0x9739040dL), +tole(0x59f3bff2L), tole(0x61e2d05eL), tole(0x29d160aaL), tole(0x11c00f06L), +tole(0xb9b60142L), tole(0x81a76eeeL), tole(0xc994de1aL), tole(0xf185b1b6L), +tole(0x9c94b463L), tole(0xa485dbcfL), tole(0xecb66b3bL), tole(0xd4a70497L), +tole(0x7cd10ad3L), tole(0x44c0657fL), tole(0x0cf3d58bL), tole(0x34e2ba27L), +tole(0xd6d1de21L), tole(0xeec0b18dL), tole(0xa6f30179L), tole(0x9ee26ed5L), +tole(0x36946091L), tole(0x0e850f3dL), tole(0x46b6bfc9L), tole(0x7ea7d065L), +tole(0x13b6d5b0L), tole(0x2ba7ba1cL), tole(0x63940ae8L), tole(0x5b856544L), +tole(0xf3f36b00L), tole(0xcbe204acL), tole(0x83d1b458L), tole(0xbbc0dbf4L), +tole(0x425b0aa5L), tole(0x7a4a6509L), tole(0x3279d5fdL), tole(0x0a68ba51L), +tole(0xa21eb415L), tole(0x9a0fdbb9L), tole(0xd23c6b4dL), tole(0xea2d04e1L), +tole(0x873c0134L), tole(0xbf2d6e98L), tole(0xf71ede6cL), tole(0xcf0fb1c0L), +tole(0x6779bf84L), tole(0x5f68d028L), tole(0x175b60dcL), tole(0x2f4a0f70L), +tole(0xcd796b76L), tole(0xf56804daL), tole(0xbd5bb42eL), tole(0x854adb82L), +tole(0x2d3cd5c6L), tole(0x152dba6aL), tole(0x5d1e0a9eL), tole(0x650f6532L), +tole(0x081e60e7L), tole(0x300f0f4bL), tole(0x783cbfbfL), tole(0x402dd013L), +tole(0xe85bde57L), tole(0xd04ab1fbL), tole(0x9879010fL), tole(0xa0686ea3L)}, +{ +tole(0x00000000L), tole(0xef306b19L), tole(0xdb8ca0c3L), tole(0x34bccbdaL), +tole(0xb2f53777L), tole(0x5dc55c6eL), tole(0x697997b4L), tole(0x8649fcadL), +tole(0x6006181fL), tole(0x8f367306L), tole(0xbb8ab8dcL), tole(0x54bad3c5L), +tole(0xd2f32f68L), tole(0x3dc34471L), tole(0x097f8fabL), tole(0xe64fe4b2L), +tole(0xc00c303eL), tole(0x2f3c5b27L), tole(0x1b8090fdL), tole(0xf4b0fbe4L), +tole(0x72f90749L), tole(0x9dc96c50L), tole(0xa975a78aL), tole(0x4645cc93L), +tole(0xa00a2821L), tole(0x4f3a4338L), tole(0x7b8688e2L), tole(0x94b6e3fbL), +tole(0x12ff1f56L), tole(0xfdcf744fL), tole(0xc973bf95L), tole(0x2643d48cL), +tole(0x85f4168dL), tole(0x6ac47d94L), tole(0x5e78b64eL), tole(0xb148dd57L), +tole(0x370121faL), tole(0xd8314ae3L), tole(0xec8d8139L), tole(0x03bdea20L), +tole(0xe5f20e92L), tole(0x0ac2658bL), tole(0x3e7eae51L), tole(0xd14ec548L), +tole(0x570739e5L), tole(0xb83752fcL), tole(0x8c8b9926L), tole(0x63bbf23fL), +tole(0x45f826b3L), tole(0xaac84daaL), tole(0x9e748670L), tole(0x7144ed69L), +tole(0xf70d11c4L), tole(0x183d7addL), tole(0x2c81b107L), tole(0xc3b1da1eL), +tole(0x25fe3eacL), tole(0xcace55b5L), tole(0xfe729e6fL), tole(0x1142f576L), +tole(0x970b09dbL), tole(0x783b62c2L), tole(0x4c87a918L), tole(0xa3b7c201L), +tole(0x0e045bebL), tole(0xe13430f2L), tole(0xd588fb28L), tole(0x3ab89031L), +tole(0xbcf16c9cL), tole(0x53c10785L), tole(0x677dcc5fL), tole(0x884da746L), +tole(0x6e0243f4L), tole(0x813228edL), tole(0xb58ee337L), tole(0x5abe882eL), +tole(0xdcf77483L), tole(0x33c71f9aL), tole(0x077bd440L), tole(0xe84bbf59L), +tole(0xce086bd5L), tole(0x213800ccL), tole(0x1584cb16L), tole(0xfab4a00fL), +tole(0x7cfd5ca2L), tole(0x93cd37bbL), tole(0xa771fc61L), tole(0x48419778L), +tole(0xae0e73caL), tole(0x413e18d3L), tole(0x7582d309L), tole(0x9ab2b810L), +tole(0x1cfb44bdL), tole(0xf3cb2fa4L), tole(0xc777e47eL), tole(0x28478f67L), +tole(0x8bf04d66L), tole(0x64c0267fL), tole(0x507ceda5L), tole(0xbf4c86bcL), +tole(0x39057a11L), tole(0xd6351108L), tole(0xe289dad2L), tole(0x0db9b1cbL), +tole(0xebf65579L), tole(0x04c63e60L), tole(0x307af5baL), tole(0xdf4a9ea3L), +tole(0x5903620eL), tole(0xb6330917L), tole(0x828fc2cdL), tole(0x6dbfa9d4L), +tole(0x4bfc7d58L), tole(0xa4cc1641L), tole(0x9070dd9bL), tole(0x7f40b682L), +tole(0xf9094a2fL), tole(0x16392136L), tole(0x2285eaecL), tole(0xcdb581f5L), +tole(0x2bfa6547L), tole(0xc4ca0e5eL), tole(0xf076c584L), tole(0x1f46ae9dL), +tole(0x990f5230L), tole(0x763f3929L), tole(0x4283f2f3L), tole(0xadb399eaL), +tole(0x1c08b7d6L), tole(0xf338dccfL), tole(0xc7841715L), tole(0x28b47c0cL), +tole(0xaefd80a1L), tole(0x41cdebb8L), tole(0x75712062L), tole(0x9a414b7bL), +tole(0x7c0eafc9L), tole(0x933ec4d0L), tole(0xa7820f0aL), tole(0x48b26413L), +tole(0xcefb98beL), tole(0x21cbf3a7L), tole(0x1577387dL), tole(0xfa475364L), +tole(0xdc0487e8L), tole(0x3334ecf1L), tole(0x0788272bL), tole(0xe8b84c32L), +tole(0x6ef1b09fL), tole(0x81c1db86L), tole(0xb57d105cL), tole(0x5a4d7b45L), +tole(0xbc029ff7L), tole(0x5332f4eeL), tole(0x678e3f34L), tole(0x88be542dL), +tole(0x0ef7a880L), tole(0xe1c7c399L), tole(0xd57b0843L), tole(0x3a4b635aL), +tole(0x99fca15bL), tole(0x76ccca42L), tole(0x42700198L), tole(0xad406a81L), +tole(0x2b09962cL), tole(0xc439fd35L), tole(0xf08536efL), tole(0x1fb55df6L), +tole(0xf9fab944L), tole(0x16cad25dL), tole(0x22761987L), tole(0xcd46729eL), +tole(0x4b0f8e33L), tole(0xa43fe52aL), tole(0x90832ef0L), tole(0x7fb345e9L), +tole(0x59f09165L), tole(0xb6c0fa7cL), tole(0x827c31a6L), tole(0x6d4c5abfL), +tole(0xeb05a612L), tole(0x0435cd0bL), tole(0x308906d1L), tole(0xdfb96dc8L), +tole(0x39f6897aL), tole(0xd6c6e263L), tole(0xe27a29b9L), tole(0x0d4a42a0L), +tole(0x8b03be0dL), tole(0x6433d514L), tole(0x508f1eceL), tole(0xbfbf75d7L), +tole(0x120cec3dL), tole(0xfd3c8724L), tole(0xc9804cfeL), tole(0x26b027e7L), +tole(0xa0f9db4aL), tole(0x4fc9b053L), tole(0x7b757b89L), tole(0x94451090L), +tole(0x720af422L), tole(0x9d3a9f3bL), tole(0xa98654e1L), tole(0x46b63ff8L), +tole(0xc0ffc355L), tole(0x2fcfa84cL), tole(0x1b736396L), tole(0xf443088fL), +tole(0xd200dc03L), tole(0x3d30b71aL), tole(0x098c7cc0L), tole(0xe6bc17d9L), +tole(0x60f5eb74L), tole(0x8fc5806dL), tole(0xbb794bb7L), tole(0x544920aeL), +tole(0xb206c41cL), tole(0x5d36af05L), tole(0x698a64dfL), tole(0x86ba0fc6L), +tole(0x00f3f36bL), tole(0xefc39872L), tole(0xdb7f53a8L), tole(0x344f38b1L), +tole(0x97f8fab0L), tole(0x78c891a9L), tole(0x4c745a73L), tole(0xa344316aL), +tole(0x250dcdc7L), tole(0xca3da6deL), tole(0xfe816d04L), tole(0x11b1061dL), +tole(0xf7fee2afL), tole(0x18ce89b6L), tole(0x2c72426cL), tole(0xc3422975L), +tole(0x450bd5d8L), tole(0xaa3bbec1L), tole(0x9e87751bL), tole(0x71b71e02L), +tole(0x57f4ca8eL), tole(0xb8c4a197L), tole(0x8c786a4dL), tole(0x63480154L), +tole(0xe501fdf9L), tole(0x0a3196e0L), tole(0x3e8d5d3aL), tole(0xd1bd3623L), +tole(0x37f2d291L), tole(0xd8c2b988L), tole(0xec7e7252L), tole(0x034e194bL), +tole(0x8507e5e6L), tole(0x6a378effL), tole(0x5e8b4525L), tole(0xb1bb2e3cL)}, +{ +tole(0x00000000L), tole(0x68032cc8L), tole(0xd0065990L), tole(0xb8057558L), +tole(0xa5e0c5d1L), tole(0xcde3e919L), tole(0x75e69c41L), tole(0x1de5b089L), +tole(0x4e2dfd53L), tole(0x262ed19bL), tole(0x9e2ba4c3L), tole(0xf628880bL), +tole(0xebcd3882L), tole(0x83ce144aL), tole(0x3bcb6112L), tole(0x53c84ddaL), +tole(0x9c5bfaa6L), tole(0xf458d66eL), tole(0x4c5da336L), tole(0x245e8ffeL), +tole(0x39bb3f77L), tole(0x51b813bfL), tole(0xe9bd66e7L), tole(0x81be4a2fL), +tole(0xd27607f5L), tole(0xba752b3dL), tole(0x02705e65L), tole(0x6a7372adL), +tole(0x7796c224L), tole(0x1f95eeecL), tole(0xa7909bb4L), tole(0xcf93b77cL), +tole(0x3d5b83bdL), tole(0x5558af75L), tole(0xed5dda2dL), tole(0x855ef6e5L), +tole(0x98bb466cL), tole(0xf0b86aa4L), tole(0x48bd1ffcL), tole(0x20be3334L), +tole(0x73767eeeL), tole(0x1b755226L), tole(0xa370277eL), tole(0xcb730bb6L), +tole(0xd696bb3fL), tole(0xbe9597f7L), tole(0x0690e2afL), tole(0x6e93ce67L), +tole(0xa100791bL), tole(0xc90355d3L), tole(0x7106208bL), tole(0x19050c43L), +tole(0x04e0bccaL), tole(0x6ce39002L), tole(0xd4e6e55aL), tole(0xbce5c992L), +tole(0xef2d8448L), tole(0x872ea880L), tole(0x3f2bddd8L), tole(0x5728f110L), +tole(0x4acd4199L), tole(0x22ce6d51L), tole(0x9acb1809L), tole(0xf2c834c1L), +tole(0x7ab7077aL), tole(0x12b42bb2L), tole(0xaab15eeaL), tole(0xc2b27222L), +tole(0xdf57c2abL), tole(0xb754ee63L), tole(0x0f519b3bL), tole(0x6752b7f3L), +tole(0x349afa29L), tole(0x5c99d6e1L), tole(0xe49ca3b9L), tole(0x8c9f8f71L), +tole(0x917a3ff8L), tole(0xf9791330L), tole(0x417c6668L), tole(0x297f4aa0L), +tole(0xe6ecfddcL), tole(0x8eefd114L), tole(0x36eaa44cL), tole(0x5ee98884L), +tole(0x430c380dL), tole(0x2b0f14c5L), tole(0x930a619dL), tole(0xfb094d55L), +tole(0xa8c1008fL), tole(0xc0c22c47L), tole(0x78c7591fL), tole(0x10c475d7L), +tole(0x0d21c55eL), tole(0x6522e996L), tole(0xdd279cceL), tole(0xb524b006L), +tole(0x47ec84c7L), tole(0x2fefa80fL), tole(0x97eadd57L), tole(0xffe9f19fL), +tole(0xe20c4116L), tole(0x8a0f6ddeL), tole(0x320a1886L), tole(0x5a09344eL), +tole(0x09c17994L), tole(0x61c2555cL), tole(0xd9c72004L), tole(0xb1c40cccL), +tole(0xac21bc45L), tole(0xc422908dL), tole(0x7c27e5d5L), tole(0x1424c91dL), +tole(0xdbb77e61L), tole(0xb3b452a9L), tole(0x0bb127f1L), tole(0x63b20b39L), +tole(0x7e57bbb0L), tole(0x16549778L), tole(0xae51e220L), tole(0xc652cee8L), +tole(0x959a8332L), tole(0xfd99affaL), tole(0x459cdaa2L), tole(0x2d9ff66aL), +tole(0x307a46e3L), tole(0x58796a2bL), tole(0xe07c1f73L), tole(0x887f33bbL), +tole(0xf56e0ef4L), tole(0x9d6d223cL), tole(0x25685764L), tole(0x4d6b7bacL), +tole(0x508ecb25L), tole(0x388de7edL), tole(0x808892b5L), tole(0xe88bbe7dL), +tole(0xbb43f3a7L), tole(0xd340df6fL), tole(0x6b45aa37L), tole(0x034686ffL), +tole(0x1ea33676L), tole(0x76a01abeL), tole(0xcea56fe6L), tole(0xa6a6432eL), +tole(0x6935f452L), tole(0x0136d89aL), tole(0xb933adc2L), tole(0xd130810aL), +tole(0xccd53183L), tole(0xa4d61d4bL), tole(0x1cd36813L), tole(0x74d044dbL), +tole(0x27180901L), tole(0x4f1b25c9L), tole(0xf71e5091L), tole(0x9f1d7c59L), +tole(0x82f8ccd0L), tole(0xeafbe018L), tole(0x52fe9540L), tole(0x3afdb988L), +tole(0xc8358d49L), tole(0xa036a181L), tole(0x1833d4d9L), tole(0x7030f811L), +tole(0x6dd54898L), tole(0x05d66450L), tole(0xbdd31108L), tole(0xd5d03dc0L), +tole(0x8618701aL), tole(0xee1b5cd2L), tole(0x561e298aL), tole(0x3e1d0542L), +tole(0x23f8b5cbL), tole(0x4bfb9903L), tole(0xf3feec5bL), tole(0x9bfdc093L), +tole(0x546e77efL), tole(0x3c6d5b27L), tole(0x84682e7fL), tole(0xec6b02b7L), +tole(0xf18eb23eL), tole(0x998d9ef6L), tole(0x2188ebaeL), tole(0x498bc766L), +tole(0x1a438abcL), tole(0x7240a674L), tole(0xca45d32cL), tole(0xa246ffe4L), +tole(0xbfa34f6dL), tole(0xd7a063a5L), tole(0x6fa516fdL), tole(0x07a63a35L), +tole(0x8fd9098eL), tole(0xe7da2546L), tole(0x5fdf501eL), tole(0x37dc7cd6L), +tole(0x2a39cc5fL), tole(0x423ae097L), tole(0xfa3f95cfL), tole(0x923cb907L), +tole(0xc1f4f4ddL), tole(0xa9f7d815L), tole(0x11f2ad4dL), tole(0x79f18185L), +tole(0x6414310cL), tole(0x0c171dc4L), tole(0xb412689cL), tole(0xdc114454L), +tole(0x1382f328L), tole(0x7b81dfe0L), tole(0xc384aab8L), tole(0xab878670L), +tole(0xb66236f9L), tole(0xde611a31L), tole(0x66646f69L), tole(0x0e6743a1L), +tole(0x5daf0e7bL), tole(0x35ac22b3L), tole(0x8da957ebL), tole(0xe5aa7b23L), +tole(0xf84fcbaaL), tole(0x904ce762L), tole(0x2849923aL), tole(0x404abef2L), +tole(0xb2828a33L), tole(0xda81a6fbL), tole(0x6284d3a3L), tole(0x0a87ff6bL), +tole(0x17624fe2L), tole(0x7f61632aL), tole(0xc7641672L), tole(0xaf673abaL), +tole(0xfcaf7760L), tole(0x94ac5ba8L), tole(0x2ca92ef0L), tole(0x44aa0238L), +tole(0x594fb2b1L), tole(0x314c9e79L), tole(0x8949eb21L), tole(0xe14ac7e9L), +tole(0x2ed97095L), tole(0x46da5c5dL), tole(0xfedf2905L), tole(0x96dc05cdL), +tole(0x8b39b544L), tole(0xe33a998cL), tole(0x5b3fecd4L), tole(0x333cc01cL), +tole(0x60f48dc6L), tole(0x08f7a10eL), tole(0xb0f2d456L), tole(0xd8f1f89eL), +tole(0xc5144817L), tole(0xad1764dfL), tole(0x15121187L), tole(0x7d113d4fL)}, +{ +tole(0x00000000L), tole(0x493c7d27L), tole(0x9278fa4eL), tole(0xdb448769L), +tole(0x211d826dL), tole(0x6821ff4aL), tole(0xb3657823L), tole(0xfa590504L), +tole(0x423b04daL), tole(0x0b0779fdL), tole(0xd043fe94L), tole(0x997f83b3L), +tole(0x632686b7L), tole(0x2a1afb90L), tole(0xf15e7cf9L), tole(0xb86201deL), +tole(0x847609b4L), tole(0xcd4a7493L), tole(0x160ef3faL), tole(0x5f328eddL), +tole(0xa56b8bd9L), tole(0xec57f6feL), tole(0x37137197L), tole(0x7e2f0cb0L), +tole(0xc64d0d6eL), tole(0x8f717049L), tole(0x5435f720L), tole(0x1d098a07L), +tole(0xe7508f03L), tole(0xae6cf224L), tole(0x7528754dL), tole(0x3c14086aL), +tole(0x0d006599L), tole(0x443c18beL), tole(0x9f789fd7L), tole(0xd644e2f0L), +tole(0x2c1de7f4L), tole(0x65219ad3L), tole(0xbe651dbaL), tole(0xf759609dL), +tole(0x4f3b6143L), tole(0x06071c64L), tole(0xdd439b0dL), tole(0x947fe62aL), +tole(0x6e26e32eL), tole(0x271a9e09L), tole(0xfc5e1960L), tole(0xb5626447L), +tole(0x89766c2dL), tole(0xc04a110aL), tole(0x1b0e9663L), tole(0x5232eb44L), +tole(0xa86bee40L), tole(0xe1579367L), tole(0x3a13140eL), tole(0x732f6929L), +tole(0xcb4d68f7L), tole(0x827115d0L), tole(0x593592b9L), tole(0x1009ef9eL), +tole(0xea50ea9aL), tole(0xa36c97bdL), tole(0x782810d4L), tole(0x31146df3L), +tole(0x1a00cb32L), tole(0x533cb615L), tole(0x8878317cL), tole(0xc1444c5bL), +tole(0x3b1d495fL), tole(0x72213478L), tole(0xa965b311L), tole(0xe059ce36L), +tole(0x583bcfe8L), tole(0x1107b2cfL), tole(0xca4335a6L), tole(0x837f4881L), +tole(0x79264d85L), tole(0x301a30a2L), tole(0xeb5eb7cbL), tole(0xa262caecL), +tole(0x9e76c286L), tole(0xd74abfa1L), tole(0x0c0e38c8L), tole(0x453245efL), +tole(0xbf6b40ebL), tole(0xf6573dccL), tole(0x2d13baa5L), tole(0x642fc782L), +tole(0xdc4dc65cL), tole(0x9571bb7bL), tole(0x4e353c12L), tole(0x07094135L), +tole(0xfd504431L), tole(0xb46c3916L), tole(0x6f28be7fL), tole(0x2614c358L), +tole(0x1700aeabL), tole(0x5e3cd38cL), tole(0x857854e5L), tole(0xcc4429c2L), +tole(0x361d2cc6L), tole(0x7f2151e1L), tole(0xa465d688L), tole(0xed59abafL), +tole(0x553baa71L), tole(0x1c07d756L), tole(0xc743503fL), tole(0x8e7f2d18L), +tole(0x7426281cL), tole(0x3d1a553bL), tole(0xe65ed252L), tole(0xaf62af75L), +tole(0x9376a71fL), tole(0xda4ada38L), tole(0x010e5d51L), tole(0x48322076L), +tole(0xb26b2572L), tole(0xfb575855L), tole(0x2013df3cL), tole(0x692fa21bL), +tole(0xd14da3c5L), tole(0x9871dee2L), tole(0x4335598bL), tole(0x0a0924acL), +tole(0xf05021a8L), tole(0xb96c5c8fL), tole(0x6228dbe6L), tole(0x2b14a6c1L), +tole(0x34019664L), tole(0x7d3deb43L), tole(0xa6796c2aL), tole(0xef45110dL), +tole(0x151c1409L), tole(0x5c20692eL), tole(0x8764ee47L), tole(0xce589360L), +tole(0x763a92beL), tole(0x3f06ef99L), tole(0xe44268f0L), tole(0xad7e15d7L), +tole(0x572710d3L), tole(0x1e1b6df4L), tole(0xc55fea9dL), tole(0x8c6397baL), +tole(0xb0779fd0L), tole(0xf94be2f7L), tole(0x220f659eL), tole(0x6b3318b9L), +tole(0x916a1dbdL), tole(0xd856609aL), tole(0x0312e7f3L), tole(0x4a2e9ad4L), +tole(0xf24c9b0aL), tole(0xbb70e62dL), tole(0x60346144L), tole(0x29081c63L), +tole(0xd3511967L), tole(0x9a6d6440L), tole(0x4129e329L), tole(0x08159e0eL), +tole(0x3901f3fdL), tole(0x703d8edaL), tole(0xab7909b3L), tole(0xe2457494L), +tole(0x181c7190L), tole(0x51200cb7L), tole(0x8a648bdeL), tole(0xc358f6f9L), +tole(0x7b3af727L), tole(0x32068a00L), tole(0xe9420d69L), tole(0xa07e704eL), +tole(0x5a27754aL), tole(0x131b086dL), tole(0xc85f8f04L), tole(0x8163f223L), +tole(0xbd77fa49L), tole(0xf44b876eL), tole(0x2f0f0007L), tole(0x66337d20L), +tole(0x9c6a7824L), tole(0xd5560503L), tole(0x0e12826aL), tole(0x472eff4dL), +tole(0xff4cfe93L), tole(0xb67083b4L), tole(0x6d3404ddL), tole(0x240879faL), +tole(0xde517cfeL), tole(0x976d01d9L), tole(0x4c2986b0L), tole(0x0515fb97L), +tole(0x2e015d56L), tole(0x673d2071L), tole(0xbc79a718L), tole(0xf545da3fL), +tole(0x0f1cdf3bL), tole(0x4620a21cL), tole(0x9d642575L), tole(0xd4585852L), +tole(0x6c3a598cL), tole(0x250624abL), tole(0xfe42a3c2L), tole(0xb77edee5L), +tole(0x4d27dbe1L), tole(0x041ba6c6L), tole(0xdf5f21afL), tole(0x96635c88L), +tole(0xaa7754e2L), tole(0xe34b29c5L), tole(0x380faeacL), tole(0x7133d38bL), +tole(0x8b6ad68fL), tole(0xc256aba8L), tole(0x19122cc1L), tole(0x502e51e6L), +tole(0xe84c5038L), tole(0xa1702d1fL), tole(0x7a34aa76L), tole(0x3308d751L), +tole(0xc951d255L), tole(0x806daf72L), tole(0x5b29281bL), tole(0x1215553cL), +tole(0x230138cfL), tole(0x6a3d45e8L), tole(0xb179c281L), tole(0xf845bfa6L), +tole(0x021cbaa2L), tole(0x4b20c785L), tole(0x906440ecL), tole(0xd9583dcbL), +tole(0x613a3c15L), tole(0x28064132L), tole(0xf342c65bL), tole(0xba7ebb7cL), +tole(0x4027be78L), tole(0x091bc35fL), tole(0xd25f4436L), tole(0x9b633911L), +tole(0xa777317bL), tole(0xee4b4c5cL), tole(0x350fcb35L), tole(0x7c33b612L), +tole(0x866ab316L), tole(0xcf56ce31L), tole(0x14124958L), tole(0x5d2e347fL), +tole(0xe54c35a1L), tole(0xac704886L), tole(0x7734cfefL), tole(0x3e08b2c8L), +tole(0xc451b7ccL), tole(0x8d6dcaebL), tole(0x56294d82L), tole(0x1f1530a5L)}, +}; diff --git a/include/e2fsprogs/ext2fs/dosio.h b/include/e2fsprogs/ext2fs/dosio.h new file mode 100755 index 0000000..d2a8f03 --- /dev/null +++ b/include/e2fsprogs/ext2fs/dosio.h @@ -0,0 +1,157 @@ +/* + * v1.0 + * + * Disk I/O include file for the ext2fs/DOS library. + * + * Copyright (c) 1997 Mark Habersack + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef __diskio_h +#define __diskio_h +#ifdef __TURBOC__ +#ifndef __LARGE__ +# error "ext2fs/DOS library requires LARGE model!" +#endif +#endif + +#ifdef __TURBOC__ +#include "msdos.h" +#endif + +/* + * A helper structure used in LBA => CHS conversion + */ +typedef struct +{ + unsigned short cyl; /* Cylinder (or track) */ + unsigned short head; + unsigned short sector; + unsigned short offset; /* Offset of byte within the sector */ +} CHS; + +/* + * All partition data we need is here + */ +typedef struct +{ + char *dev; /* _Linux_ device name (like "/dev/hda1") */ + unsigned char phys; /* Physical DOS drive number */ + unsigned long start; /* LBA address of partition start */ + unsigned long len; /* length of partition in sectors */ + unsigned char pno; /* Partition number (read from *dev) */ + + /* This partition's drive geometry */ + unsigned short cyls; + unsigned short heads; + unsigned short sects; +} PARTITION; + +/* + * PC partition table entry format + */ +#ifdef __DJGPP__ +#pragma pack(1) +#endif +typedef struct +{ + unsigned char active; + unsigned char start_head; + unsigned char start_sec; + unsigned char start_cyl; + unsigned char type; + unsigned char end_head; + unsigned char end_sec; + unsigned char end_cyl; + unsigned long first_sec_rel; + unsigned long size; +} PTABLE_ENTRY; +#ifdef __DJGPP__ +#pragma pack() +#endif + +/* + * INT 0x13 operation codes + */ +#define DISK_READ 0x02 +#define DISK_WRITE 0x03 +#define DISK_GET_GEOMETRY 0x08 +#define DISK_READY 0x10 + +/* + * Errors to put in _dio_error + */ +#define ERR_BADDEV 0x00000001L +#define ERR_HARDWARE 0x00000002L +#define ERR_NOTSUPP 0x00000003L +#define ERR_NOTEXT2FS 0x00000004L +#define ERR_EMPTYPART 0x00000005L +#define ERR_LINUXSWAP 0x00000006L + +/* + * Functions in diskio.c + */ + +/* + * Variable contains last module's error + */ +extern unsigned long _dio_error; + +/* + * This one contains last hardware error (if _dio_error == ERR_HARDWARE) + */ +extern unsigned long _dio_hw_error; + +/* + * Macros to check for disk hardware errors + */ +#define HW_OK() ((unsigned char)_dio_hw_error == 0x00) +#define HW_BAD_CMD() ((unsigned char)_dio_hw_error == 0x01) +#define HW_NO_ADDR_MARK() ((unsigned char)_dio_hw_error == 0x02) +#define HW_WRITE_PROT() ((unsigned char)_dio_hw_error == 0x03) +#define HW_NO_SECTOR() ((unsigned char)_dio_hw_error == 0x04) +#define HW_RESET_FAIL() ((unsigned char)_dio_hw_error == 0x05) +#define HW_DISK_CHANGED() ((unsigned char)_dio_hw_error == 0x06) +#define HW_DRIVE_FAIL() ((unsigned char)_dio_hw_error == 0x07) +#define HW_DMA_OVERRUN() ((unsigned char)_dio_hw_error == 0x08) +#define HW_DMA_BOUNDARY() ((unsigned char)_dio_hw_error == 0x09) +#define HW_BAD_SECTOR() ((unsigned char)_dio_hw_error == 0x0A) +#define HW_BAD_TRACK() ((unsigned char)_dio_hw_error == 0x0B) +#define HW_UNSUPP_TRACK() ((unsigned char)_dio_hw_error == 0x0C) +#define HW_BAD_CRC_ECC() ((unsigned char)_dio_hw_error == 0x10) +#define HW_CRC_ECC_CORR() ((unsigned char)_dio_hw_error == 0x11) +#define HW_CONTR_FAIL() ((unsigned char)_dio_hw_error == 0x20) +#define HW_SEEK_FAIL() ((unsigned char)_dio_hw_error == 0x40) +#define HW_ATTACH_FAIL() ((unsigned char)_dio_hw_error == 0x80) +#define HW_DRIVE_NREADY() ((unsigned char)_dio_hw_error == 0xAA) +#define HW_UNDEF_ERROR() ((unsigned char)_dio_hw_error == 0xBB) +#define HW_WRITE_FAULT() ((unsigned char)_dio_hw_error == 0xCC) +#define HW_STATUS_ERROR() ((unsigned char)_dio_hw_error == 0xE0) +#define HW_SENSE_FAIL() ((unsigned char)_dio_hw_error == 0xFF) + + +/* + * Open the specified partition. + * String 'dev' must have a format: + * + * /dev/{sd|hd|fd}[X] + * + * where, + * + * only one of the option in curly braces can be used and X is an optional + * partition number for the given device. If X is not specified, function + * scans the drive's partition table in search for the first Linux ext2fs + * partition (signature 0x83). Along the way it dives into every extended + * partition encountered. + * Scan ends if either (a) there are no more used partition entries, or + * (b) there is no Xth partition. + * + * Routine returns 0 on success and !=0 otherwise. + */ +int open_partition(char *dev); + +#endif /* __diskio_h */ diff --git a/include/e2fsprogs/ext2fs/e2image.h b/include/e2fsprogs/ext2fs/e2image.h new file mode 100755 index 0000000..53b20cc --- /dev/null +++ b/include/e2fsprogs/ext2fs/e2image.h @@ -0,0 +1,37 @@ +/* + * e2image.h --- header file describing the ext2 image format + * + * Copyright (C) 2000 Theodore Ts'o. + * + * Note: this uses the POSIX IO interfaces, unlike most of the other + * functions in this library. So sue me. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +struct ext2_image_hdr { + __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */ + char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */ + char fs_hostname[64];/* Hostname of machine of image */ + char fs_netaddr[32]; /* Network address */ + __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */ + __u32 fs_device; /* Device number of image */ + char fs_device_name[64]; /* Device name */ + char fs_uuid[16]; /* UUID of filesystem */ + __u32 fs_blocksize; /* Block size of the filesystem */ + __u32 fs_reserved[8]; + + __u32 image_device; /* Device number of image file */ + __u32 image_inode; /* Inode number of image file */ + __u32 image_time; /* Time of image creation */ + __u32 image_reserved[8]; + + __u32 offset_super; /* Byte offset of the sb and descriptors */ + __u32 offset_inode; /* Byte offset of the inode table */ + __u32 offset_inodemap; /* Byte offset of the inode bitmaps */ + __u32 offset_blockmap; /* Byte offset of the inode bitmaps */ + __u32 offset_reserved[8]; +}; diff --git a/include/e2fsprogs/ext2fs/ext2_err.h b/include/e2fsprogs/ext2fs/ext2_err.h new file mode 100755 index 0000000..3575af0 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2_err.h @@ -0,0 +1,201 @@ +/* + * ext2_err.h: + * This file is automatically generated; please do not edit it. + */ + +#include + +#define EXT2_ET_BASE (2133571328L) +#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L) +#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L) +#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L) +#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L) +#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L) +#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L) +#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L) +#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L) +#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L) +#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L) +#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L) +#define EXT2_ET_MAGIC_DBLIST (2133571340L) +#define EXT2_ET_MAGIC_ICOUNT (2133571341L) +#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L) +#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L) +#define EXT2_ET_MAGIC_E2IMAGE (2133571344L) +#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L) +#define EXT2_ET_MAGIC_EXTENT_HANDLE (2133571346L) +#define EXT2_ET_BAD_MAGIC (2133571347L) +#define EXT2_ET_REV_TOO_HIGH (2133571348L) +#define EXT2_ET_RO_FILSYS (2133571349L) +#define EXT2_ET_GDESC_READ (2133571350L) +#define EXT2_ET_GDESC_WRITE (2133571351L) +#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L) +#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L) +#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L) +#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L) +#define EXT2_ET_INODE_BITMAP_READ (2133571356L) +#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L) +#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L) +#define EXT2_ET_INODE_TABLE_WRITE (2133571359L) +#define EXT2_ET_INODE_TABLE_READ (2133571360L) +#define EXT2_ET_NEXT_INODE_READ (2133571361L) +#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L) +#define EXT2_ET_DIR_CORRUPTED (2133571363L) +#define EXT2_ET_SHORT_READ (2133571364L) +#define EXT2_ET_SHORT_WRITE (2133571365L) +#define EXT2_ET_DIR_NO_SPACE (2133571366L) +#define EXT2_ET_NO_INODE_BITMAP (2133571367L) +#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L) +#define EXT2_ET_BAD_INODE_NUM (2133571369L) +#define EXT2_ET_BAD_BLOCK_NUM (2133571370L) +#define EXT2_ET_EXPAND_DIR_ERR (2133571371L) +#define EXT2_ET_TOOSMALL (2133571372L) +#define EXT2_ET_BAD_BLOCK_MARK (2133571373L) +#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L) +#define EXT2_ET_BAD_BLOCK_TEST (2133571375L) +#define EXT2_ET_BAD_INODE_MARK (2133571376L) +#define EXT2_ET_BAD_INODE_UNMARK (2133571377L) +#define EXT2_ET_BAD_INODE_TEST (2133571378L) +#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L) +#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L) +#define EXT2_ET_BAD_IND_BLOCK (2133571381L) +#define EXT2_ET_BAD_DIND_BLOCK (2133571382L) +#define EXT2_ET_BAD_TIND_BLOCK (2133571383L) +#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L) +#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L) +#define EXT2_ET_BAD_DEVICE_NAME (2133571386L) +#define EXT2_ET_MISSING_INODE_TABLE (2133571387L) +#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L) +#define EXT2_ET_BAD_GENERIC_MARK (2133571389L) +#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L) +#define EXT2_ET_BAD_GENERIC_TEST (2133571391L) +#define EXT2_ET_SYMLINK_LOOP (2133571392L) +#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L) +#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L) +#define EXT2_ET_UNSUPP_FEATURE (2133571395L) +#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L) +#define EXT2_ET_LLSEEK_FAILED (2133571397L) +#define EXT2_ET_NO_MEMORY (2133571398L) +#define EXT2_ET_INVALID_ARGUMENT (2133571399L) +#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L) +#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L) +#define EXT2_ET_NO_DIRECTORY (2133571402L) +#define EXT2_ET_TOO_MANY_REFS (2133571403L) +#define EXT2_ET_FILE_NOT_FOUND (2133571404L) +#define EXT2_ET_FILE_RO (2133571405L) +#define EXT2_ET_DB_NOT_FOUND (2133571406L) +#define EXT2_ET_DIR_EXISTS (2133571407L) +#define EXT2_ET_UNIMPLEMENTED (2133571408L) +#define EXT2_ET_CANCEL_REQUESTED (2133571409L) +#define EXT2_ET_FILE_TOO_BIG (2133571410L) +#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L) +#define EXT2_ET_NO_JOURNAL_SB (2133571412L) +#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L) +#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L) +#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L) +#define EXT2_ET_NO_JOURNAL (2133571416L) +#define EXT2_ET_DIRHASH_UNSUPP (2133571417L) +#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L) +#define EXT2_ET_TOO_MANY_INODES (2133571419L) +#define EXT2_ET_NOT_IMAGE_FILE (2133571420L) +#define EXT2_ET_RES_GDT_BLOCKS (2133571421L) +#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L) +#define EXT2_ET_SET_BMAP_NO_IND (2133571423L) +#define EXT2_ET_TDB_SUCCESS (2133571424L) +#define EXT2_ET_TDB_ERR_CORRUPT (2133571425L) +#define EXT2_ET_TDB_ERR_IO (2133571426L) +#define EXT2_ET_TDB_ERR_LOCK (2133571427L) +#define EXT2_ET_TDB_ERR_OOM (2133571428L) +#define EXT2_ET_TDB_ERR_EXISTS (2133571429L) +#define EXT2_ET_TDB_ERR_NOLOCK (2133571430L) +#define EXT2_ET_TDB_ERR_EINVAL (2133571431L) +#define EXT2_ET_TDB_ERR_NOEXIST (2133571432L) +#define EXT2_ET_TDB_ERR_RDONLY (2133571433L) +#define EXT2_ET_DBLIST_EMPTY (2133571434L) +#define EXT2_ET_RO_BLOCK_ITERATE (2133571435L) +#define EXT2_ET_MAGIC_EXTENT_PATH (2133571436L) +#define EXT2_ET_MAGIC_GENERIC_BITMAP64 (2133571437L) +#define EXT2_ET_MAGIC_BLOCK_BITMAP64 (2133571438L) +#define EXT2_ET_MAGIC_INODE_BITMAP64 (2133571439L) +#define EXT2_ET_MAGIC_RESERVED_13 (2133571440L) +#define EXT2_ET_MAGIC_RESERVED_14 (2133571441L) +#define EXT2_ET_MAGIC_RESERVED_15 (2133571442L) +#define EXT2_ET_MAGIC_RESERVED_16 (2133571443L) +#define EXT2_ET_MAGIC_RESERVED_17 (2133571444L) +#define EXT2_ET_MAGIC_RESERVED_18 (2133571445L) +#define EXT2_ET_MAGIC_RESERVED_19 (2133571446L) +#define EXT2_ET_EXTENT_HEADER_BAD (2133571447L) +#define EXT2_ET_EXTENT_INDEX_BAD (2133571448L) +#define EXT2_ET_EXTENT_LEAF_BAD (2133571449L) +#define EXT2_ET_EXTENT_NO_SPACE (2133571450L) +#define EXT2_ET_INODE_NOT_EXTENT (2133571451L) +#define EXT2_ET_EXTENT_NO_NEXT (2133571452L) +#define EXT2_ET_EXTENT_NO_PREV (2133571453L) +#define EXT2_ET_EXTENT_NO_UP (2133571454L) +#define EXT2_ET_EXTENT_NO_DOWN (2133571455L) +#define EXT2_ET_NO_CURRENT_NODE (2133571456L) +#define EXT2_ET_OP_NOT_SUPPORTED (2133571457L) +#define EXT2_ET_CANT_INSERT_EXTENT (2133571458L) +#define EXT2_ET_CANT_SPLIT_EXTENT (2133571459L) +#define EXT2_ET_EXTENT_NOT_FOUND (2133571460L) +#define EXT2_ET_EXTENT_NOT_SUPPORTED (2133571461L) +#define EXT2_ET_EXTENT_INVALID_LENGTH (2133571462L) +#define EXT2_ET_IO_CHANNEL_NO_SUPPORT_64 (2133571463L) +#define EXT2_ET_NO_MTAB_FILE (2133571464L) +#define EXT2_ET_CANT_USE_LEGACY_BITMAPS (2133571465L) +#define EXT2_ET_MMP_MAGIC_INVALID (2133571466L) +#define EXT2_ET_MMP_FAILED (2133571467L) +#define EXT2_ET_MMP_FSCK_ON (2133571468L) +#define EXT2_ET_MMP_BAD_BLOCK (2133571469L) +#define EXT2_ET_MMP_UNKNOWN_SEQ (2133571470L) +#define EXT2_ET_MMP_CHANGE_ABORT (2133571471L) +#define EXT2_ET_MMP_OPEN_DIRECT (2133571472L) +#define EXT2_ET_BAD_DESC_SIZE (2133571473L) +#define EXT2_ET_INODE_CSUM_INVALID (2133571474L) +#define EXT2_ET_INODE_BITMAP_CSUM_INVALID (2133571475L) +#define EXT2_ET_EXTENT_CSUM_INVALID (2133571476L) +#define EXT2_ET_DIR_NO_SPACE_FOR_CSUM (2133571477L) +#define EXT2_ET_DIR_CSUM_INVALID (2133571478L) +#define EXT2_ET_EXT_ATTR_CSUM_INVALID (2133571479L) +#define EXT2_ET_SB_CSUM_INVALID (2133571480L) +#define EXT2_ET_UNKNOWN_CSUM (2133571481L) +#define EXT2_ET_MMP_CSUM_INVALID (2133571482L) +#define EXT2_ET_FILE_EXISTS (2133571483L) +#define EXT2_ET_BLOCK_BITMAP_CSUM_INVALID (2133571484L) +#define EXT2_ET_INLINE_DATA_CANT_ITERATE (2133571485L) +#define EXT2_ET_EA_BAD_NAME_LEN (2133571486L) +#define EXT2_ET_EA_BAD_VALUE_SIZE (2133571487L) +#define EXT2_ET_BAD_EA_HASH (2133571488L) +#define EXT2_ET_BAD_EA_HEADER (2133571489L) +#define EXT2_ET_EA_KEY_NOT_FOUND (2133571490L) +#define EXT2_ET_EA_NO_SPACE (2133571491L) +#define EXT2_ET_MISSING_EA_FEATURE (2133571492L) +#define EXT2_ET_NO_INLINE_DATA (2133571493L) +#define EXT2_ET_INLINE_DATA_NO_BLOCK (2133571494L) +#define EXT2_ET_INLINE_DATA_NO_SPACE (2133571495L) +#define EXT2_ET_MAGIC_EA_HANDLE (2133571496L) +#define EXT2_ET_INODE_IS_GARBAGE (2133571497L) +#define EXT2_ET_EA_BAD_VALUE_OFFSET (2133571498L) +#define EXT2_ET_JOURNAL_FLAGS_WRONG (2133571499L) +#define EXT2_ET_UNDO_FILE_CORRUPT (2133571500L) +#define EXT2_ET_UNDO_FILE_WRONG (2133571501L) +#define EXT2_ET_FILESYSTEM_CORRUPTED (2133571502L) +#define EXT2_ET_BAD_CRC (2133571503L) +#define EXT2_ET_CORRUPT_JOURNAL_SB (2133571504L) +#define EXT2_ET_INODE_CORRUPTED (2133571505L) +#define EXT2_ET_EA_INODE_CORRUPTED (2133571506L) +#define EXT2_ET_NO_GDESC (2133571507L) +#define EXT2_FILSYS_CORRUPTED (2133571508L) +#define EXT2_ET_EXTENT_CYCLE (2133571509L) +#define EXT2_ET_EXTERNAL_JOURNAL_NOSUPP (2133571510L) +extern const struct error_table et_ext2_error_table; +extern void initialize_ext2_error_table(void); + +/* For compatibility with Heimdal */ +extern void initialize_ext2_error_table_r(struct et_list **list); + +#define ERROR_TABLE_BASE_ext2 (2133571328L) + +/* for compatibility with older versions... */ +#define init_ext2_err_tbl initialize_ext2_error_table +#define ext2_err_base ERROR_TABLE_BASE_ext2 diff --git a/include/e2fsprogs/ext2fs/ext2_ext_attr.h b/include/e2fsprogs/ext2fs/ext2_ext_attr.h new file mode 100755 index 0000000..f2042ed --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2_ext_attr.h @@ -0,0 +1,73 @@ +/* + File: linux/ext2_ext_attr.h + + On-disk format of extended attributes for the ext2 filesystem. + + (C) 2000 Andreas Gruenbacher, +*/ + +#ifndef _EXT2_EXT_ATTR_H +#define _EXT2_EXT_ATTR_H +/* Magic value in attribute blocks */ +#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000 +#define EXT2_EXT_ATTR_MAGIC 0xEA020000 + +/* Maximum number of references to one attribute block */ +#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024 + +struct ext2_ext_attr_header { + __u32 h_magic; /* magic number for identification */ + __u32 h_refcount; /* reference count */ + __u32 h_blocks; /* number of disk blocks used */ + __u32 h_hash; /* hash value of all attributes */ + __u32 h_checksum; /* crc32c(uuid+id+xattrs) */ + /* id = inum if refcount = 1, else blknum */ + __u32 h_reserved[3]; /* zero right now */ +}; + +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_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 0 + char e_name[0]; /* attribute name */ +#endif +}; + +#define EXT2_EXT_ATTR_PAD_BITS 2 +#define EXT2_EXT_ATTR_PAD ((unsigned) 1<e_name_len)) ) +#define EXT2_EXT_ATTR_SIZE(size) \ + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) +#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL) +#define EXT2_EXT_ATTR_NAME(entry) \ + (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry)) +#define EXT2_XATTR_LEN(name_len) \ + (((name_len) + EXT2_EXT_ATTR_ROUND + \ + sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND) +#define EXT2_XATTR_SIZE(size) \ + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) + +#ifdef __KERNEL__ +# ifdef CONFIG_EXT2_FS_EXT_ATTR +extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int); +extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int); +extern void ext2_ext_attr_free_inode(struct inode *inode); +extern void ext2_ext_attr_put_super(struct super_block *sb); +extern int ext2_ext_attr_init(void); +extern void ext2_ext_attr_done(void); +# else +# define ext2_get_ext_attr NULL +# define ext2_set_ext_attr NULL +# endif +#endif /* __KERNEL__ */ +#endif /* _EXT2_EXT_ATTR_H */ diff --git a/include/e2fsprogs/ext2fs/ext2_fs.h b/include/e2fsprogs/ext2fs/ext2_fs.h new file mode 100755 index 0000000..01d2573 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2_fs.h @@ -0,0 +1,1189 @@ +/* + * linux/include/linux/ext2_fs.h + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/include/linux/minix_fs.h + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#ifndef _LINUX_EXT2_FS_H +#define _LINUX_EXT2_FS_H + +#include /* Changed from linux/types.h */ + +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GNUC_PREREQ(maj, min) 0 +#endif +#endif + +#ifndef __nonstring +#ifdef __has_attribute +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif /* __has_attribute(__nonstring__) */ +#else +# define __nonstring +#endif /* __has_attribute */ +#endif /* __nonstring */ + +/* + * The second extended filesystem constants/structures + */ + +/* + * Define EXT2FS_DEBUG to produce debug messages + */ +#undef EXT2FS_DEBUG + +/* + * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files + */ +#define EXT2_PREALLOCATE +#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 + +/* + * The second extended file system version + */ +#define EXT2FS_DATE "95/08/09" +#define EXT2FS_VERSION "0.5b" + +/* + * Special inode numbers + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT4_USR_QUOTA_INO 3 /* User quota inode */ +#define EXT4_GRP_QUOTA_INO 4 /* Group quota inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ +#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ +#define EXT2_JOURNAL_INO 8 /* Journal inode */ +#define EXT2_EXCLUDE_INO 9 /* The "exclude" inode, for snapshots */ +#define EXT4_REPLICA_INO 10 /* Used by non-upstream feature */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11 + +/* + * The second extended file system magic number + */ +#define EXT2_SUPER_MAGIC 0xEF53 + +#ifdef __KERNEL__ +#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) +#else +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) +#endif + +/* + * Maximal count of links to a file + */ +#define EXT2_LINK_MAX 65000 + +/* + * Macro-instructions used to manage several block sizes + */ +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) +#ifdef __KERNEL__ +#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits) +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) +#else +#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) +#endif +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32)) + +/* + * Macro-instructions used to manage allocation clusters + */ +#define EXT2_MIN_CLUSTER_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE +#define EXT2_MAX_CLUSTER_LOG_SIZE 29 /* 512MB */ +#define EXT2_MIN_CLUSTER_SIZE EXT2_MIN_BLOCK_SIZE +#define EXT2_MAX_CLUSTER_SIZE (1 << EXT2_MAX_CLUSTER_LOG_SIZE) +#define EXT2_CLUSTER_SIZE(s) (EXT2_MIN_BLOCK_SIZE << \ + (s)->s_log_cluster_size) +#define EXT2_CLUSTER_SIZE_BITS(s) ((s)->s_log_cluster_size + 10) + +/* + * Macro-instructions used to manage fragments + * + * Note: for backwards compatibility only, for the dump program. + * Ext2/3/4 will never support fragments.... + */ +#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE +#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE +#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE +#define EXT2_FRAG_SIZE(s) EXT2_BLOCK_SIZE(s) +#define EXT2_FRAGS_PER_BLOCK(s) 1 + +/* + * ACL structures + */ +struct ext2_acl_header /* Header of Access Control Lists */ +{ + __u32 aclh_size; + __u32 aclh_file_count; + __u32 aclh_acle_count; + __u32 aclh_first_acle; +}; + +struct ext2_acl_entry /* Access Control List Entry */ +{ + __u32 acle_size; + __u16 acle_perms; /* Access permissions */ + __u16 acle_type; /* Type of entry */ + __u16 acle_tag; /* User or group identity */ + __u16 acle_pad1; + __u32 acle_next; /* Pointer on next entry for the */ + /* same inode or on next free entry */ +}; + +/* + * Structure of a blocks group descriptor + */ +struct ext2_group_desc +{ + __u32 bg_block_bitmap; /* Blocks bitmap block */ + __u32 bg_inode_bitmap; /* Inodes bitmap block */ + __u32 bg_inode_table; /* Inodes table block */ + __u16 bg_free_blocks_count; /* Free blocks count */ + __u16 bg_free_inodes_count; /* Free inodes count */ + __u16 bg_used_dirs_count; /* Directories count */ + __u16 bg_flags; + __u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */ + __u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */ + __u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */ + __u16 bg_itable_unused; /* Unused inodes count */ + __u16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/ +}; + +/* + * Structure of a blocks group descriptor + */ +struct ext4_group_desc +{ + __u32 bg_block_bitmap; /* Blocks bitmap block */ + __u32 bg_inode_bitmap; /* Inodes bitmap block */ + __u32 bg_inode_table; /* Inodes table block */ + __u16 bg_free_blocks_count; /* Free blocks count */ + __u16 bg_free_inodes_count; /* Free inodes count */ + __u16 bg_used_dirs_count; /* Directories count */ + __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ + __u32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */ + __u16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */ + __u16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */ + __u16 bg_itable_unused; /* Unused inodes count */ + __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */ + __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ + __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ + __u32 bg_inode_table_hi; /* Inodes table block MSB */ + __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */ + __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */ + __u16 bg_used_dirs_count_hi; /* Directories count MSB */ + __u16 bg_itable_unused_hi; /* Unused inodes count MSB */ + __u32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */ + __u16 bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */ + __u16 bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bitmap) MSB */ + __u32 bg_reserved; +}; + +#define EXT4_BG_INODE_BITMAP_CSUM_HI_END \ + (offsetof(struct ext4_group_desc, bg_inode_bitmap_csum_hi) + \ + sizeof(__u16)) +#define EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION \ + (offsetof(struct ext4_group_desc, bg_block_bitmap_csum_hi) + \ + sizeof(__u16)) + +#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */ +#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */ +#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */ + +/* + * Data structures used by the directory indexing feature + * + * Note: all of the multibyte integer fields are little endian. + */ + +/* + * Note: dx_root_info is laid out so that if it should somehow get + * overlaid by a dirent the two low bits of the hash version will be + * zero. Therefore, the hash version mod 4 should never be 0. + * Sincerely, the paranoia department. + */ +struct ext2_dx_root_info { + __u32 reserved_zero; + __u8 hash_version; /* 0 now, 1 at release */ + __u8 info_length; /* 8 */ + __u8 indirect_levels; + __u8 unused_flags; +}; + +#define EXT2_HASH_LEGACY 0 +#define EXT2_HASH_HALF_MD4 1 +#define EXT2_HASH_TEA 2 +#define EXT2_HASH_LEGACY_UNSIGNED 3 /* reserved for userspace lib */ +#define EXT2_HASH_HALF_MD4_UNSIGNED 4 /* reserved for userspace lib */ +#define EXT2_HASH_TEA_UNSIGNED 5 /* reserved for userspace lib */ +#define EXT2_HASH_SIPHASH 6 + +#define EXT2_HASH_FLAG_INCOMPAT 0x1 + +#define EXT4_DX_BLOCK_MASK 0x0fffffff + +struct ext2_dx_entry { + __le32 hash; + __le32 block; +}; + +struct ext2_dx_countlimit { + __le16 limit; + __le16 count; +}; + +/* + * This goes at the end of each htree block. + */ +struct ext2_dx_tail { + __le32 dt_reserved; + __le32 dt_checksum; /* crc32c(uuid+inum+dxblock) */ +}; + +/* + * Macro-instructions used to manage group descriptors + */ +#define EXT2_MIN_DESC_SIZE 32 +#define EXT2_MIN_DESC_SIZE_64BIT 64 +#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE +#define EXT2_DESC_SIZE(s) \ + (ext2fs_has_feature_64bit(s) ? (s)->s_desc_size : EXT2_MIN_DESC_SIZE) + +#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) +#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group) +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) +/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ +#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((((unsigned) 1 << 16) - 8) * \ + (EXT2_CLUSTER_SIZE(s) / \ + EXT2_BLOCK_SIZE(s))) +#define EXT2_MAX_CLUSTERS_PER_GROUP(s) (((unsigned) 1 << 16) - 8) +#define EXT2_MAX_INODES_PER_GROUP(s) (((unsigned) 1 << 16) - \ + EXT2_INODES_PER_BLOCK(s)) +#ifdef __KERNEL__ +#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) +#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) +#else +#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s)) +#endif + +#define EXT2_GROUPS_TO_BLOCKS(s, g) ((blk64_t) EXT2_BLOCKS_PER_GROUP(s) * \ + (g)) +#define EXT2_GROUPS_TO_CLUSTERS(s, g) ((blk64_t) EXT2_CLUSTERS_PER_GROUP(s) * \ + (g)) + +/* + * Constants relative to the data blocks + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + +/* + * Inode flags + */ +#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ +#define EXT2_UNRM_FL 0x00000002 /* Undelete */ +#define EXT2_COMPR_FL 0x00000004 /* Compress file */ +#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ +#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ +#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ +/* Reserved for compression usage... */ +#define EXT2_DIRTY_FL 0x00000100 +#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ +#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ + /* nb: was previously EXT2_ECOMPR_FL */ +#define EXT4_ENCRYPT_FL 0x00000800 /* encrypted inode */ +/* End compression flags --- maybe not all used */ +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ +#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ +#define EXT2_IMAGIC_FL 0x00002000 +#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ +#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ +#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ +#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ +#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT4_VERITY_FL 0x00100000 /* Verity protected inode */ +#define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ +/* EXT4_EOFBLOCKS_FL 0x00400000 was here */ +#define FS_NOCOW_FL 0x00800000 /* Do not cow file */ +#define EXT4_SNAPFILE_FL 0x01000000 /* Inode is a snapshot */ +#define FS_DAX_FL 0x02000000 /* Inode is DAX */ +#define EXT4_SNAPFILE_DELETED_FL 0x04000000 /* Snapshot is being deleted */ +#define EXT4_SNAPFILE_SHRUNK_FL 0x08000000 /* Snapshot shrink has completed */ +#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data */ +#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ +#define EXT4_CASEFOLD_FL 0x40000000 /* Casefolded file */ +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ + +#define EXT2_FL_USER_VISIBLE 0x604BDFFF /* User visible flags */ +#define EXT2_FL_USER_MODIFIABLE 0x604B80FF /* User modifiable flags */ + +/* + * ioctl commands + */ + +/* Used for online resize */ +struct ext2_new_group_input { + __u32 group; /* Group number for this data */ + __u32 block_bitmap; /* Absolute block number of block bitmap */ + __u32 inode_bitmap; /* Absolute block number of inode bitmap */ + __u32 inode_table; /* Absolute block number of inode table start */ + __u32 blocks_count; /* Total number of blocks in this group */ + __u16 reserved_blocks; /* Number of reserved blocks in this group */ + __u16 unused; /* Number of reserved GDT blocks in group */ +}; + +struct ext4_new_group_input { + __u32 group; /* Group number for this data */ + __u64 block_bitmap; /* Absolute block number of block bitmap */ + __u64 inode_bitmap; /* Absolute block number of inode bitmap */ + __u64 inode_table; /* Absolute block number of inode table start */ + __u32 blocks_count; /* Total number of blocks in this group */ + __u16 reserved_blocks; /* Number of reserved blocks in this group */ + __u16 unused; +}; + +#ifdef __GNU__ /* Needed for the Hurd */ +#define _IOT_ext2_new_group_input _IOT (_IOTS(__u32), 5, _IOTS(__u16), 2, 0, 0) +#endif + +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) +#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) +#define EXT2_IOC_GETVERSION _IOR('v', 1, long) +#define EXT2_IOC_SETVERSION _IOW('v', 2, long) +#define EXT2_IOC_GETVERSION_NEW _IOR('f', 3, long) +#define EXT2_IOC_SETVERSION_NEW _IOW('f', 4, long) +#define EXT2_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long) +#define EXT2_IOC_GROUP_ADD _IOW('f', 8,struct ext2_new_group_input) +#define EXT4_IOC_GROUP_ADD _IOW('f', 8,struct ext4_new_group_input) +#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) + +/* + * Structure of an inode on the disk + */ +struct ext2_inode { +/*00*/ __u16 i_mode; /* File mode */ + __u16 i_uid; /* Low 16 bits of Owner Uid */ + __u32 i_size; /* Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Inode change time */ +/*10*/ __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u16 i_gid; /* Low 16 bits of Group Id */ + __u16 i_links_count; /* Links count */ + __u32 i_blocks; /* Blocks count */ +/*20*/ __u32 i_flags; /* File flags */ + union { + struct { + __u32 l_i_version; /* was l_i_reserved1 */ + } linux1; + struct { + __u32 h_i_translator; + } hurd1; + } osd1; /* OS dependent 1 */ +/*28*/ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ +/*64*/ __u32 i_generation; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_size_high; +/*70*/ __u32 i_faddr; /* Fragment address */ + union { + struct { + __u16 l_i_blocks_hi; + __u16 l_i_file_acl_high; + __u16 l_i_uid_high; /* these 2 fields */ + __u16 l_i_gid_high; /* were reserved2[0] */ + __u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */ + __u16 l_i_reserved; + } linux2; + struct { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } hurd2; + } osd2; /* OS dependent 2 */ +}; + +/* + * Permanent part of an large inode on the disk + */ +struct ext2_inode_large { +/*00*/ __u16 i_mode; /* File mode */ + __u16 i_uid; /* Low 16 bits of Owner Uid */ + __u32 i_size; /* Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Inode Change time */ +/*10*/ __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u16 i_gid; /* Low 16 bits of Group Id */ + __u16 i_links_count; /* Links count */ + __u32 i_blocks; /* Blocks count */ +/*20*/ __u32 i_flags; /* File flags */ + union { + struct { + __u32 l_i_version; /* was l_i_reserved1 */ + } linux1; + struct { + __u32 h_i_translator; + } hurd1; + } osd1; /* OS dependent 1 */ +/*28*/ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ +/*64*/ __u32 i_generation; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_size_high; +/*70*/ __u32 i_faddr; /* Fragment address */ + union { + struct { + __u16 l_i_blocks_hi; + __u16 l_i_file_acl_high; + __u16 l_i_uid_high; /* these 2 fields */ + __u16 l_i_gid_high; /* were reserved2[0] */ + __u16 l_i_checksum_lo; /* crc32c(uuid+inum+inode) */ + __u16 l_i_reserved; + } linux2; + struct { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } hurd2; + } osd2; /* OS dependent 2 */ +/*80*/ __u16 i_extra_isize; + __u16 i_checksum_hi; /* crc32c(uuid+inum+inode) */ + __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ + __u32 i_mtime_extra; /* extra Modification time (nsec << 2 | epoch) */ + __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ +/*90*/ __u32 i_crtime; /* File creation time */ + __u32 i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/ + __u32 i_version_hi; /* high 32 bits for 64-bit version */ +/*9c*/ __u32 i_projid; /* Project ID */ +}; + +#define EXT4_INODE_CSUM_HI_EXTRA_END \ + (offsetof(struct ext2_inode_large, i_checksum_hi) + sizeof(__u16) - \ + EXT2_GOOD_OLD_INODE_SIZE) + +#define EXT4_EPOCH_BITS 2 +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) + +#define i_checksum_lo osd2.linux2.l_i_checksum_lo + +#define inode_includes(size, field) \ + (size >= (sizeof(((struct ext2_inode_large *)0)->field) + \ + offsetof(struct ext2_inode_large, field))) + +#if defined(__KERNEL__) || defined(__linux__) +#define i_reserved1 osd1.linux1.l_i_reserved1 +#define i_frag osd2.linux2.l_i_frag +#define i_fsize osd2.linux2.l_i_fsize +#define i_uid_low i_uid +#define i_gid_low i_gid +#define i_uid_high osd2.linux2.l_i_uid_high +#define i_gid_high osd2.linux2.l_i_gid_high +#else +#if defined(__GNU__) + +#define i_translator osd1.hurd1.h_i_translator +#define i_frag osd2.hurd2.h_i_frag; +#define i_fsize osd2.hurd2.h_i_fsize; +#define i_uid_high osd2.hurd2.h_i_uid_high +#define i_gid_high osd2.hurd2.h_i_gid_high +#define i_author osd2.hurd2.h_i_author + +#endif /* __GNU__ */ +#endif /* defined(__KERNEL__) || defined(__linux__) */ + +#define inode_uid(inode) ((inode).i_uid | (unsigned)(inode).osd2.linux2.l_i_uid_high << 16) +#define inode_gid(inode) ((inode).i_gid | (unsigned)(inode).osd2.linux2.l_i_gid_high << 16) +#define inode_projid(inode) ((inode).i_projid) +#define ext2fs_set_i_uid_high(inode,x) ((inode).osd2.linux2.l_i_uid_high = (x)) +#define ext2fs_set_i_gid_high(inode,x) ((inode).osd2.linux2.l_i_gid_high = (x)) + +static inline +struct ext2_inode *EXT2_INODE(struct ext2_inode_large *large_inode) +{ + return (struct ext2_inode *) large_inode; +} + +/* + * File system states + */ +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ +#define EXT2_ERROR_FS 0x0002 /* Errors detected */ +#define EXT3_ORPHAN_FS 0x0004 /* Orphans being recovered */ +#define EXT4_FC_REPLAY 0x0020 /* Ext4 fast commit replay ongoing */ + +/* + * Misc. filesystem flags + */ +#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */ +#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */ +#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* OK for use on development code */ +#define EXT2_FLAGS_IS_SNAPSHOT 0x0010 /* This is a snapshot image */ +#define EXT2_FLAGS_FIX_SNAPSHOT 0x0020 /* Snapshot inodes corrupted */ +#define EXT2_FLAGS_FIX_EXCLUDE 0x0040 /* Exclude bitmaps corrupted */ + +/* + * Mount flags + */ +#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ +#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ +#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ +#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ +#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ +#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ +#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ + +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ + EXT2_MOUNT_##opt) +/* + * Maximal mount counts between two filesystem checks + */ +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ + +/* + * Behaviour when detecting errors + */ +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ +#define EXT2_ERRORS_PANIC 3 /* Panic */ +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE + +#if (__GNUC__ >= 4) +#define ext4_offsetof(TYPE,MEMBER) __builtin_offsetof(TYPE,MEMBER) +#else +#define ext4_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* Metadata checksum algorithms */ +#define EXT2_CRC32C_CHKSUM 1 + +/* Encryption algorithms, key size and key reference len */ +#define EXT4_ENCRYPTION_MODE_INVALID 0 +#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 +#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2 +#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3 +#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 + +#define EXT4_AES_256_XTS_KEY_SIZE 64 +#define EXT4_AES_256_GCM_KEY_SIZE 32 +#define EXT4_AES_256_CBC_KEY_SIZE 32 +#define EXT4_AES_256_CTS_KEY_SIZE 32 +#define EXT4_MAX_KEY_SIZE 64 + +#define EXT4_KEY_DESCRIPTOR_SIZE 8 +#define EXT4_CRYPTO_BLOCK_SIZE 16 + +/* Password derivation constants */ +#define EXT4_MAX_PASSPHRASE_SIZE 1024 +#define EXT4_MAX_SALT_SIZE 256 +#define EXT4_PBKDF2_ITERATIONS 0xFFFF + +#define EXT2_LABEL_LEN 16 + +/* + * Policy provided via an ioctl on the topmost directory. This + * structure is also in the kernel. + */ +struct ext4_encryption_policy { + char version; + char contents_encryption_mode; + char filenames_encryption_mode; + char flags; + char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; +} __attribute__((__packed__)); + +struct ext4_encryption_key { + __u32 mode; + char raw[EXT4_MAX_KEY_SIZE]; + __u32 size; +} __attribute__((__packed__)); + +/* + * Structure of the super block + */ +struct ext2_super_block { +/*000*/ __u32 s_inodes_count; /* Inodes count */ + __u32 s_blocks_count; /* Blocks count */ + __u32 s_r_blocks_count; /* Reserved blocks count */ + __u32 s_free_blocks_count; /* Free blocks count */ +/*010*/ __u32 s_free_inodes_count; /* Free inodes count */ + __u32 s_first_data_block; /* First Data Block */ + __u32 s_log_block_size; /* Block size */ + __u32 s_log_cluster_size; /* Allocation cluster size */ +/*020*/ __u32 s_blocks_per_group; /* # Blocks per group */ + __u32 s_clusters_per_group; /* # Fragments per group */ + __u32 s_inodes_per_group; /* # Inodes per group */ + __u32 s_mtime; /* Mount time */ +/*030*/ __u32 s_wtime; /* Write time */ + __u16 s_mnt_count; /* Mount count */ + __s16 s_max_mnt_count; /* Maximal mount count */ + __u16 s_magic; /* Magic signature */ + __u16 s_state; /* File system state */ + __u16 s_errors; /* Behaviour when detecting errors */ + __u16 s_minor_rev_level; /* minor revision level */ +/*040*/ __u32 s_lastcheck; /* time of last check */ + __u32 s_checkinterval; /* max. time between checks */ + __u32 s_creator_os; /* OS */ + __u32 s_rev_level; /* Revision level */ +/*050*/ __u16 s_def_resuid; /* Default uid for reserved blocks */ + __u16 s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __u32 s_first_ino; /* First non-reserved inode */ + __u16 s_inode_size; /* size of inode structure */ + __u16 s_block_group_nr; /* block group # of this superblock */ + __u32 s_feature_compat; /* compatible feature set */ +/*060*/ __u32 s_feature_incompat; /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ +/*068*/ __u8 s_uuid[16] __nonstring; /* 128-bit uuid for volume */ +/*078*/ __u8 s_volume_name[EXT2_LABEL_LEN] __nonstring; /* volume name, no NUL? */ +/*088*/ __u8 s_last_mounted[64] __nonstring; /* directory last mounted on, no NUL? */ +/*0c8*/ __u32 s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_reserved_gdt_blocks; /* Per group table for online growth */ + /* + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. + */ +/*0d0*/ __u8 s_journal_uuid[16] __nonstring; /* uuid of journal superblock */ +/*0e0*/ __u32 s_journal_inum; /* inode number of journal file */ + __u32 s_journal_dev; /* device number of journal file */ + __u32 s_last_orphan; /* start of list of inodes to delete */ +/*0ec*/ __u32 s_hash_seed[4]; /* HTREE hash seed */ +/*0fc*/ __u8 s_def_hash_version; /* Default hash version to use */ + __u8 s_jnl_backup_type; /* Default type of journal backup */ + __u16 s_desc_size; /* Group desc. size: INCOMPAT_64BIT */ +/*100*/ __u32 s_default_mount_opts; /* default EXT2_MOUNT_* flags used */ + __u32 s_first_meta_bg; /* First metablock group */ + __u32 s_mkfs_time; /* When the filesystem was created */ +/*10c*/ __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ +/*150*/ __u32 s_blocks_count_hi; /* Blocks count high 32bits */ + __u32 s_r_blocks_count_hi; /* Reserved blocks count high 32 bits*/ + __u32 s_free_blocks_hi; /* Free blocks count */ + __u16 s_min_extra_isize; /* All inodes have at least # bytes */ + __u16 s_want_extra_isize; /* New inodes should reserve # bytes */ +/*160*/ __u32 s_flags; /* Miscellaneous flags */ + __u16 s_raid_stride; /* RAID stride in blocks */ + __u16 s_mmp_update_interval; /* # seconds to wait in MMP checking */ + __u64 s_mmp_block; /* Block for multi-mount protection */ +/*170*/ __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ + __u8 s_log_groups_per_flex; /* FLEX_BG group size */ + __u8 s_checksum_type; /* metadata checksum algorithm */ + __u8 s_encryption_level; /* versioning level for encryption */ + __u8 s_reserved_pad; /* Padding to next 32bits */ + __u64 s_kbytes_written; /* nr of lifetime kilobytes written */ +/*180*/ __u32 s_snapshot_inum; /* Inode number of active snapshot */ + __u32 s_snapshot_id; /* sequential ID of active snapshot */ + __u64 s_snapshot_r_blocks_count; /* active snapshot reserved blocks */ +/*190*/ __u32 s_snapshot_list; /* inode number of disk snapshot list */ +#define EXT4_S_ERR_START ext4_offsetof(struct ext2_super_block, s_error_count) + __u32 s_error_count; /* number of fs errors */ + __u32 s_first_error_time; /* first time an error happened */ + __u32 s_first_error_ino; /* inode involved in first error */ +/*1a0*/ __u64 s_first_error_block; /* block involved in first error */ + __u8 s_first_error_func[32] __nonstring; /* function where error hit, no NUL? */ +/*1c8*/ __u32 s_first_error_line; /* line number where error happened */ + __u32 s_last_error_time; /* most recent time of an error */ +/*1d0*/ __u32 s_last_error_ino; /* inode involved in last error */ + __u32 s_last_error_line; /* line number where error happened */ + __u64 s_last_error_block; /* block involved of last error */ +/*1e0*/ __u8 s_last_error_func[32] __nonstring; /* function where error hit, no NUL? */ +#define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts) +/*200*/ __u8 s_mount_opts[64] __nonstring; /* default mount options, no NUL? */ +/*240*/ __u32 s_usr_quota_inum; /* inode number of user quota file */ + __u32 s_grp_quota_inum; /* inode number of group quota file */ + __u32 s_overhead_clusters; /* overhead blocks/clusters in fs */ +/*24c*/ __u32 s_backup_bgs[2]; /* If sparse_super2 enabled */ +/*254*/ __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */ +/*258*/ __u8 s_encrypt_pw_salt[16]; /* Salt used for string2key algorithm */ +/*268*/ __le32 s_lpf_ino; /* Location of the lost+found inode */ + __le32 s_prj_quota_inum; /* inode for tracking project quota */ +/*270*/ __le32 s_checksum_seed; /* crc32c(orig_uuid) if csum_seed set */ +/*274*/ __u8 s_wtime_hi; + __u8 s_mtime_hi; + __u8 s_mkfs_time_hi; + __u8 s_lastcheck_hi; + __u8 s_first_error_time_hi; + __u8 s_last_error_time_hi; + __u8 s_first_error_errcode; + __u8 s_last_error_errcode; +/*27c*/ __le16 s_encoding; /* Filename charset encoding */ + __le16 s_encoding_flags; /* Filename charset encoding flags */ + __le32 s_reserved[95]; /* Padding to the end of the block */ +/*3fc*/ __u32 s_checksum; /* crc32c(superblock) */ +}; + +#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) +#define EXT2_LEN_STR(buf) (int)sizeof(buf), (char *)buf + +/* + * Codes for operating systems + */ +#define EXT2_OS_LINUX 0 +#define EXT2_OS_HURD 1 +#define EXT2_OBSO_OS_MASIX 2 +#define EXT2_OS_FREEBSD 3 +#define EXT2_OS_LITES 4 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV + +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +/* + * Journal inode backup types + */ +#define EXT3_JNL_BACKUP_BLOCKS 1 + +/* + * Feature set definitions + */ + +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_compat & (mask) ) +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_incompat & (mask) ) + +#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 +#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 +#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 +#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 +#define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040 +/* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE 0x0080 not used, legacy */ +#define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP 0x0100 +#define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200 +#define EXT4_FEATURE_COMPAT_FAST_COMMIT 0x0400 +#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800 + + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 +#define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT 0x0080 +#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 +#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200 +/* + * METADATA_CSUM implies GDT_CSUM. When METADATA_CSUM is set, group + * descriptor checksums use the same algorithm as all other data + * structures' checksums. + */ +#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 +#define EXT4_FEATURE_RO_COMPAT_REPLICA 0x0800 +#define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000 +#define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000 /* Project quota */ +#define EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS 0x4000 +#define EXT4_FEATURE_RO_COMPAT_VERITY 0x8000 + +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 +#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 EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 +#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 +#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ +#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ +#define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 +#define EXT4_FEATURE_INCOMPAT_CASEFOLD 0x20000 + +#define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \ +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \ +{ \ + return ((EXT2_SB(sb)->s_feature_compat & \ + EXT##ver##_FEATURE_COMPAT_##flagname) != 0); \ +} \ +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_compat |= \ + EXT##ver##_FEATURE_COMPAT_##flagname; \ +} \ +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_compat &= \ + ~EXT##ver##_FEATURE_COMPAT_##flagname; \ +} + +#define EXT4_FEATURE_RO_COMPAT_FUNCS(name, ver, flagname) \ +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \ +{ \ + return ((EXT2_SB(sb)->s_feature_ro_compat & \ + EXT##ver##_FEATURE_RO_COMPAT_##flagname) != 0); \ +} \ +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_ro_compat |= \ + EXT##ver##_FEATURE_RO_COMPAT_##flagname; \ +} \ +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_ro_compat &= \ + ~EXT##ver##_FEATURE_RO_COMPAT_##flagname; \ +} + +#define EXT4_FEATURE_INCOMPAT_FUNCS(name, ver, flagname) \ +static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \ +{ \ + return ((EXT2_SB(sb)->s_feature_incompat & \ + EXT##ver##_FEATURE_INCOMPAT_##flagname) != 0); \ +} \ +static inline void ext2fs_set_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_incompat |= \ + EXT##ver##_FEATURE_INCOMPAT_##flagname; \ +} \ +static inline void ext2fs_clear_feature_##name(struct ext2_super_block *sb) \ +{ \ + EXT2_SB(sb)->s_feature_incompat &= \ + ~EXT##ver##_FEATURE_INCOMPAT_##flagname; \ +} + +EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc, 2, DIR_PREALLOC) +EXT4_FEATURE_COMPAT_FUNCS(imagic_inodes, 2, IMAGIC_INODES) +EXT4_FEATURE_COMPAT_FUNCS(journal, 3, HAS_JOURNAL) +EXT4_FEATURE_COMPAT_FUNCS(xattr, 2, EXT_ATTR) +EXT4_FEATURE_COMPAT_FUNCS(resize_inode, 2, RESIZE_INODE) +EXT4_FEATURE_COMPAT_FUNCS(dir_index, 2, DIR_INDEX) +EXT4_FEATURE_COMPAT_FUNCS(lazy_bg, 2, LAZY_BG) +EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap, 2, EXCLUDE_BITMAP) +EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, 4, SPARSE_SUPER2) +EXT4_FEATURE_COMPAT_FUNCS(fast_commit, 4, FAST_COMMIT) +EXT4_FEATURE_COMPAT_FUNCS(stable_inodes, 4, STABLE_INODES) + +EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, 2, SPARSE_SUPER) +EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, 2, LARGE_FILE) +EXT4_FEATURE_RO_COMPAT_FUNCS(huge_file, 4, HUGE_FILE) +EXT4_FEATURE_RO_COMPAT_FUNCS(gdt_csum, 4, GDT_CSUM) +EXT4_FEATURE_RO_COMPAT_FUNCS(dir_nlink, 4, DIR_NLINK) +EXT4_FEATURE_RO_COMPAT_FUNCS(extra_isize, 4, EXTRA_ISIZE) +EXT4_FEATURE_RO_COMPAT_FUNCS(has_snapshot, 4, HAS_SNAPSHOT) +EXT4_FEATURE_RO_COMPAT_FUNCS(quota, 4, QUOTA) +EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc, 4, BIGALLOC) +EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum, 4, METADATA_CSUM) +EXT4_FEATURE_RO_COMPAT_FUNCS(replica, 4, REPLICA) +EXT4_FEATURE_RO_COMPAT_FUNCS(readonly, 4, READONLY) +EXT4_FEATURE_RO_COMPAT_FUNCS(project, 4, PROJECT) +EXT4_FEATURE_RO_COMPAT_FUNCS(shared_blocks, 4, SHARED_BLOCKS) +EXT4_FEATURE_RO_COMPAT_FUNCS(verity, 4, VERITY) + +EXT4_FEATURE_INCOMPAT_FUNCS(compression, 2, COMPRESSION) +EXT4_FEATURE_INCOMPAT_FUNCS(filetype, 2, FILETYPE) +EXT4_FEATURE_INCOMPAT_FUNCS(journal_needs_recovery, 3, RECOVER) +EXT4_FEATURE_INCOMPAT_FUNCS(journal_dev, 3, JOURNAL_DEV) +EXT4_FEATURE_INCOMPAT_FUNCS(meta_bg, 2, META_BG) +EXT4_FEATURE_INCOMPAT_FUNCS(extents, 3, EXTENTS) +EXT4_FEATURE_INCOMPAT_FUNCS(64bit, 4, 64BIT) +EXT4_FEATURE_INCOMPAT_FUNCS(mmp, 4, MMP) +EXT4_FEATURE_INCOMPAT_FUNCS(flex_bg, 4, FLEX_BG) +EXT4_FEATURE_INCOMPAT_FUNCS(ea_inode, 4, EA_INODE) +EXT4_FEATURE_INCOMPAT_FUNCS(dirdata, 4, DIRDATA) +EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed, 4, CSUM_SEED) +EXT4_FEATURE_INCOMPAT_FUNCS(largedir, 4, LARGEDIR) +EXT4_FEATURE_INCOMPAT_FUNCS(inline_data, 4, INLINE_DATA) +EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, 4, ENCRYPT) +EXT4_FEATURE_INCOMPAT_FUNCS(casefold, 4, CASEFOLD) + +#define EXT2_FEATURE_COMPAT_SUPP 0 +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT4_FEATURE_INCOMPAT_MMP| \ + EXT4_FEATURE_INCOMPAT_LARGEDIR| \ + 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| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR| \ + EXT4_FEATURE_RO_COMPAT_VERITY) + +/* + * Default values for user and/or group using reserved blocks + */ +#define EXT2_DEF_RESUID 0 +#define EXT2_DEF_RESGID 0 + +/* + * Default mount options + */ +#define EXT2_DEFM_DEBUG 0x0001 +#define EXT2_DEFM_BSDGROUPS 0x0002 +#define EXT2_DEFM_XATTR_USER 0x0004 +#define EXT2_DEFM_ACL 0x0008 +#define EXT2_DEFM_UID16 0x0010 +#define EXT3_DEFM_JMODE 0x0060 +#define EXT3_DEFM_JMODE_DATA 0x0020 +#define EXT3_DEFM_JMODE_ORDERED 0x0040 +#define EXT3_DEFM_JMODE_WBACK 0x0060 +#define EXT4_DEFM_NOBARRIER 0x0100 +#define EXT4_DEFM_BLOCK_VALIDITY 0x0200 +#define EXT4_DEFM_DISCARD 0x0400 +#define EXT4_DEFM_NODELALLOC 0x0800 + +static inline int ext4_hash_in_dirent(const struct ext2_inode *inode) +{ + return (inode->i_flags & EXT4_ENCRYPT_FL) && + (inode->i_flags & EXT4_CASEFOLD_FL); +} + +/* + * Structure of a directory entry + */ +#define EXT2_NAME_LEN 255 + +struct ext2_dir_entry { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u16 name_len; /* Name length */ + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * The new version of the directory entry. Since EXT2 structures are + * stored in intel byte order, and the name_len field could never be + * bigger than 255 chars, it's safe to reclaim the extra byte for the + * file_type field. + * + * This structure is deprecated due to endian issues. Please use struct + * ext2_dir_entry and accessor functions + * ext2fs_dirent_name_len + * ext2fs_dirent_set_name_len + * ext2fs_dirent_file_type + * ext2fs_dirent_set_file_type + * to get and set name_len and file_type fields. + */ +struct ext2_dir_entry_2 { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u8 name_len; /* Name length */ + __u8 file_type; + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * Hashes for ext4_dir_entry for casefolded and ecrypted directories. + * This is located at the first 4 bit aligned location after the name. + */ + +struct ext2_dir_entry_hash { + __le32 hash; + __le32 minor_hash; +}; + +#define EXT2_DIRENT_HASHES(entry) \ + ((struct ext2_dir_entry_hash *) &entry->name[\ + (ext2fs_dirent_name_len(entry) + \ + EXT2_DIR_ROUND) & ~EXT2_DIR_ROUND]) +#define EXT2_DIRENT_HASH(entry) \ + ext2fs_le32_to_cpu(EXT2_DIRENT_HASHES(entry)->hash) +#define EXT2_DIRENT_MINOR_HASH(entry) \ + ext2fs_le32_to_cpu(EXT2_DIRENT_HASHES(entry)->minor_hash) + +/* + * This is a bogus directory entry at the end of each leaf block that + * records checksums. + */ +struct ext2_dir_entry_tail { + __u32 det_reserved_zero1; /* Pretend to be unused */ + __u16 det_rec_len; /* 12 */ + __u16 det_reserved_name_len; /* 0xDE00, fake namelen/filetype */ + __u32 det_checksum; /* crc32c(uuid+inode+dirent) */ +}; + +/* + * Ext2 directory file types. Only the low 3 bits are used. The + * other bits are reserved for now. + */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +#define EXT2_FT_MAX 8 + +/* + * Annoyingly, e2fsprogs always swab16s ext2_dir_entry.name_len, so we + * have to build ext2_dir_entry_tail with that assumption too. This + * constant helps to build the dir_entry_tail to look like it has an + * "invalid" file type. + */ +#define EXT2_DIR_NAME_LEN_CSUM 0xDE00 + +/* + * EXT2_DIR_PAD defines the directory entries boundaries + * + * NOTE: It must be a multiple of 4 + */ +#define EXT2_DIR_ENTRY_HEADER_LEN 8 +#define EXT2_DIR_ENTRY_HASH_LEN 8 +#define EXT2_DIR_PAD 4 +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +#define EXT2_DIR_REC_LEN(name_len) ext2fs_dir_rec_len(name_len, 0) + +static inline unsigned int ext2fs_dir_rec_len(__u8 name_len, + int extended) +{ + int rec_len = (name_len + EXT2_DIR_ENTRY_HEADER_LEN + EXT2_DIR_ROUND); + + rec_len &= ~EXT2_DIR_ROUND; + if (extended) + rec_len += EXT2_DIR_ENTRY_HASH_LEN; + return rec_len; +} + +/* + * Constants for ext4's extended time encoding + */ +#define EXT4_EPOCH_BITS 2 +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) +#define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS) + +/* + * This structure is used for multiple mount protection. It is 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 (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. + * + * The timestamp in the MMP structure will be updated by e2fsck at some + * arbitrary intervals (start of passes, after every few groups of 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. + * + * Note: Only the mmp_seq value is used to determine whether the MMP block + * is being updated. The mmp_time, mmp_nodename, and mmp_bdevname + * fields are only for informational purposes for the administrator, + * due to clock skew between nodes and hostname HA service takeover. + */ +#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */ +#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */ +#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */ +#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */ + +/* Not endian-annotated; it's swapped at read/write time */ +struct mmp_struct { + __u32 mmp_magic; /* Magic number for MMP */ + __u32 mmp_seq; /* Sequence no. updated periodically */ + __u64 mmp_time; /* Time last updated (seconds) */ + __u8 mmp_nodename[64] __nonstring; /* Node updating MMP block, no NUL? */ + __u8 mmp_bdevname[32] __nonstring; /* Bdev updating MMP block, no NUL? */ + __u16 mmp_check_interval; /* Changed mmp_check_interval */ + __u16 mmp_pad1; + __u32 mmp_pad2[226]; + __u32 mmp_checksum; /* crc32c(uuid+mmp_block) */ +}; + +/* + * Default interval for MMP update in seconds. + */ +#define EXT4_MMP_UPDATE_INTERVAL 5 + +/* + * Maximum interval for MMP update in seconds. + */ +#define EXT4_MMP_MAX_UPDATE_INTERVAL 300 + +/* + * Minimum interval for MMP checking in seconds. + */ +#define EXT4_MMP_MIN_CHECK_INTERVAL 5 + +/* + * Minimum size of inline data. + */ +#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__u32) * EXT2_N_BLOCKS)) + +/* + * Size of a parent inode in inline data directory. + */ +#define EXT4_INLINE_DATA_DOTDOT_SIZE (4) + +#define EXT4_ENC_UTF8_12_1 1 + +#define EXT4_ENC_STRICT_MODE_FL (1 << 0) /* Reject invalid sequences */ + +#endif /* _LINUX_EXT2_FS_H */ diff --git a/include/e2fsprogs/ext2fs/ext2_io.h b/include/e2fsprogs/ext2fs/ext2_io.h new file mode 100755 index 0000000..679184e --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2_io.h @@ -0,0 +1,179 @@ +/* + * io.h --- the I/O manager abstraction + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _EXT2FS_EXT2_IO_H +#define _EXT2FS_EXT2_IO_H + +#include + +/* + * ext2_loff_t is defined here since unix_io.c needs it. + */ +#if defined(__GNUC__) || defined(HAS_LONG_LONG) +typedef long long ext2_loff_t; +#else +typedef long ext2_loff_t; +#endif + +/* llseek.c */ +ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); + +typedef struct struct_io_manager *io_manager; +typedef struct struct_io_channel *io_channel; +typedef struct struct_io_stats *io_stats; + +#define CHANNEL_FLAGS_WRITETHROUGH 0x01 +#define CHANNEL_FLAGS_DISCARD_ZEROES 0x02 +#define CHANNEL_FLAGS_BLOCK_DEVICE 0x04 +#define CHANNEL_FLAGS_THREADS 0x08 + +#define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES) + +struct struct_io_channel { + errcode_t magic; + io_manager manager; + char *name; + int block_size; + errcode_t (*read_error)(io_channel channel, + unsigned long block, + int count, + void *data, + size_t size, + int actual_bytes_read, + errcode_t error); + errcode_t (*write_error)(io_channel channel, + unsigned long block, + int count, + const void *data, + size_t size, + int actual_bytes_written, + errcode_t error); + int refcount; + int flags; + long reserved[14]; + void *private_data; + void *app_data; + int align; +}; + +struct struct_io_stats { + int num_fields; + int reserved; + unsigned long long bytes_read; + unsigned long long bytes_written; +}; + +struct struct_io_manager { + errcode_t magic; + const char *name; + errcode_t (*open)(const char *name, int flags, io_channel *channel); + errcode_t (*close)(io_channel channel); + errcode_t (*set_blksize)(io_channel channel, int blksize); + errcode_t (*read_blk)(io_channel channel, unsigned long block, + int count, void *data); + errcode_t (*write_blk)(io_channel channel, unsigned long block, + int count, const void *data); + errcode_t (*flush)(io_channel channel); + errcode_t (*write_byte)(io_channel channel, unsigned long offset, + int count, const void *data); + errcode_t (*set_option)(io_channel channel, const char *option, + const char *arg); + errcode_t (*get_stats)(io_channel channel, io_stats *io_stats); + errcode_t (*read_blk64)(io_channel channel, unsigned long long block, + int count, void *data); + errcode_t (*write_blk64)(io_channel channel, unsigned long long block, + int count, const void *data); + errcode_t (*discard)(io_channel channel, unsigned long long block, + unsigned long long count); + errcode_t (*cache_readahead)(io_channel channel, + unsigned long long block, + unsigned long long count); + errcode_t (*zeroout)(io_channel channel, unsigned long long block, + unsigned long long count); + long reserved[14]; +}; + +#define IO_FLAG_RW 0x0001 +#define IO_FLAG_EXCLUSIVE 0x0002 +#define IO_FLAG_DIRECT_IO 0x0004 +#define IO_FLAG_FORCE_BOUNCE 0x0008 +#define IO_FLAG_THREADS 0x0010 +#define IO_FLAG_NOCACHE 0x0020 + +/* + * Convenience functions.... + */ +#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_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++) + +/* io_manager.c */ +extern errcode_t io_channel_set_options(io_channel channel, + const char *options); +extern errcode_t io_channel_write_byte(io_channel channel, + unsigned long offset, + int count, const void *data); +extern errcode_t io_channel_read_blk64(io_channel channel, + unsigned long long block, + int count, void *data); +extern errcode_t io_channel_write_blk64(io_channel channel, + unsigned long long block, + int count, const void *data); +extern errcode_t io_channel_discard(io_channel channel, + unsigned long long block, + unsigned long long count); +extern errcode_t io_channel_zeroout(io_channel channel, + unsigned long long block, + unsigned long long count); +extern errcode_t io_channel_alloc_buf(io_channel channel, + int count, void *ptr); +extern errcode_t io_channel_cache_readahead(io_channel io, + unsigned long long block, + unsigned long long count); + +#ifdef _WIN32 +/* windows_io.c */ +extern io_manager windows_io_manager; +#define default_io_manager windows_io_manager +#else +/* unix_io.c */ +extern io_manager unix_io_manager; +extern io_manager unixfd_io_manager; +#define default_io_manager unix_io_manager +#endif + +/* sparse_io.c */ +extern io_manager sparse_io_manager; +extern io_manager sparsefd_io_manager; + +/* undo_io.c */ +extern io_manager undo_io_manager; +extern errcode_t set_undo_io_backing_manager(io_manager manager); +extern errcode_t set_undo_io_backup_file(char *file_name); + +/* test_io.c */ +extern io_manager test_io_manager, test_io_backing_manager; +extern void (*test_io_cb_read_blk) + (unsigned long block, int count, errcode_t err); +extern void (*test_io_cb_write_blk) + (unsigned long block, int count, errcode_t err); +extern void (*test_io_cb_read_blk64) + (unsigned long long block, int count, errcode_t err); +extern void (*test_io_cb_write_blk64) + (unsigned long long block, int count, errcode_t err); +extern void (*test_io_cb_set_blksize) + (int blksize, errcode_t err); + +#endif /* _EXT2FS_EXT2_IO_H */ + diff --git a/include/e2fsprogs/ext2fs/ext2_types.h b/include/e2fsprogs/ext2fs/ext2_types.h new file mode 100755 index 0000000..0e5ebe6 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2_types.h @@ -0,0 +1,45 @@ +/* + * If linux/types.h is already been included, assume it has defined + * everything we need. (cross fingers) Other header files may have + * also defined the types that we need. + */ +#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \ + !defined(_EXT2_TYPES_H) && !defined(_UUID_TYPES_H)) +#define _EXT2_TYPES_H + +typedef unsigned char __u8; +typedef __signed__ char __s8; +typedef unsigned short __u16; +typedef __signed__ short __s16; +typedef unsigned int __u32; +typedef __signed__ int __s32; +typedef unsigned long long __u64; +typedef __signed__ long long __s64; +#endif + +#include //uintptr_t + +/* endian checking stuff */ +#ifndef EXT2_ENDIAN_H_ +#define EXT2_ENDIAN_H_ + +#ifdef __CHECKER__ +#ifndef __bitwise +#define __bitwise __attribute__((bitwise)) +#endif +#define __force __attribute__((force)) +#else +#ifndef __bitwise +#define __bitwise +#endif +#define __force +#endif + +typedef __u16 __bitwise __le16; +typedef __u32 __bitwise __le32; +typedef __u64 __bitwise __le64; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __be64; + +#endif /* EXT2_ENDIAN_H_ */ diff --git a/include/e2fsprogs/ext2fs/ext2fs.h b/include/e2fsprogs/ext2fs/ext2fs.h new file mode 100755 index 0000000..b5477c1 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2fs.h @@ -0,0 +1,2191 @@ +/* + * ext2fs.h --- ext2fs + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _EXT2FS_EXT2FS_H +#define _EXT2FS_EXT2FS_H + +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + +#ifndef __nonstring +#ifdef __has_attribute +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif /* __has_attribute(__nonstring__) */ +#else +# define __nonstring +#endif /* __has_attribute */ +#endif /* __nonstring */ + +#ifdef CONFIG_TDB +#define EXT2FS_NO_TDB_UNUSED +#else +#define EXT2FS_NO_TDB_UNUSED EXT2FS_ATTR((unused)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Non-GNU C compilers won't necessarily understand inline + */ +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) +#define NO_INLINE_FUNCS +#endif + +/* + * Where the master copy of the superblock is located, and how big + * superblocks are supposed to be. We define SUPERBLOCK_SIZE because + * the size of the superblock structure is not necessarily trustworthy + * (some versions have the padding set up so that the superblock is + * 1032 bytes long). + */ +#define SUPERBLOCK_OFFSET 1024 +#define SUPERBLOCK_SIZE 1024 + +#define UUID_STR_SIZE 37 + +/* + * The last ext2fs revision level that this version of the library is + * able to support. + */ +#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include +#include +#include +#include +#include + +#if EXT2_FLAT_INCLUDES +#include "e2_types.h" +#include "ext2_fs.h" +#include "ext3_extents.h" +#else +#include +#include +#include +#endif /* EXT2_FLAT_INCLUDES */ + +typedef __u32 __bitwise ext2_ino_t; +typedef __u32 __bitwise blk_t; +typedef __u64 __bitwise blk64_t; +typedef __u32 __bitwise dgrp_t; +typedef __s32 __bitwise ext2_off_t; +typedef __s64 __bitwise ext2_off64_t; +typedef __s64 __bitwise e2_blkcnt_t; +typedef __u32 __bitwise ext2_dirhash_t; + +#if EXT2_FLAT_INCLUDES +#include "com_err.h" +#include "ext2_io.h" +#include "ext2_err.h" +#include "ext2_ext_attr.h" +#else +#include +#include +#include +#include +#endif + +#include "hashmap.h" + +/* + * Portability help for Microsoft Visual C++ + */ +#ifdef _MSC_VER +#define EXT2_QSORT_TYPE int __cdecl +#else +#define EXT2_QSORT_TYPE int +#endif + +typedef struct struct_ext2_filsys *ext2_filsys; + +#define EXT2FS_MARK_ERROR 0 +#define EXT2FS_UNMARK_ERROR 1 +#define EXT2FS_TEST_ERROR 2 + +struct ext2fs_struct_generic_bitmap_base { + errcode_t magic; + ext2_filsys fs; +}; + +typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_generic_bitmap; +typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_inode_bitmap; +typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_block_bitmap; + +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s) + + +/* + * Badblocks list definitions + */ + +typedef struct ext2_struct_u32_list *ext2_badblocks_list; +typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; + +typedef struct ext2_struct_u32_list *ext2_u32_list; +typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; + +/* old */ +typedef struct ext2_struct_u32_list *badblocks_list; +typedef struct ext2_struct_u32_iterate *badblocks_iterate; + +#define BADBLOCKS_FLAG_DIRTY 1 + +/* + * ext2_dblist structure and abstractions (see dblist.c) + */ +struct ext2_db_entry2 { + ext2_ino_t ino; + blk64_t blk; + e2_blkcnt_t blockcnt; +}; + +/* Ye Olde 32-bit version */ +struct ext2_db_entry { + ext2_ino_t ino; + blk_t blk; + int blockcnt; +}; + +typedef struct ext2_struct_dblist *ext2_dblist; + +#define DBLIST_ABORT 1 + +/* + * ext2_fileio definitions + */ + +#define EXT2_FILE_WRITE 0x0001 +#define EXT2_FILE_CREATE 0x0002 + +#define EXT2_FILE_MASK 0x00FF + +#define EXT2_FILE_BUF_DIRTY 0x4000 +#define EXT2_FILE_BUF_VALID 0x2000 + +typedef struct ext2_file *ext2_file_t; + +#define EXT2_SEEK_SET 0 +#define EXT2_SEEK_CUR 1 +#define EXT2_SEEK_END 2 + +/* + * Flags for the ext2_filsys structure and for ext2fs_open() + */ +#define EXT2_FLAG_RW 0x01 +#define EXT2_FLAG_CHANGED 0x02 +#define EXT2_FLAG_DIRTY 0x04 +#define EXT2_FLAG_VALID 0x08 +#define EXT2_FLAG_IB_DIRTY 0x10 +#define EXT2_FLAG_BB_DIRTY 0x20 +#define EXT2_FLAG_SWAP_BYTES 0x40 +#define EXT2_FLAG_SWAP_BYTES_READ 0x80 +#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100 +#define EXT2_FLAG_MASTER_SB_ONLY 0x200 +#define EXT2_FLAG_FORCE 0x400 +#define EXT2_FLAG_SUPER_ONLY 0x800 +#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000 +#define EXT2_FLAG_IMAGE_FILE 0x2000 +#define EXT2_FLAG_EXCLUSIVE 0x4000 +#define EXT2_FLAG_SOFTSUPP_FEATURES 0x8000 +#define EXT2_FLAG_NOFREE_ON_ERROR 0x10000 +#define EXT2_FLAG_64BITS 0x20000 +#define EXT2_FLAG_PRINT_PROGRESS 0x40000 +#define EXT2_FLAG_DIRECT_IO 0x80000 +#define EXT2_FLAG_SKIP_MMP 0x100000 +#define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000 +#define EXT2_FLAG_SHARE_DUP 0x400000 +#define EXT2_FLAG_IGNORE_SB_ERRORS 0x800000 +#define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000 +#define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000 +#define EXT2_FLAG_THREADS 0x4000000 +#define EXT2_FLAG_IGNORE_SWAP_DIRENT 0x8000000 + +/* + * Special flag in the ext2 inode i_flag field that means that this is + * a new inode. (So that ext2_write_inode() can clear extra fields.) + */ +#define EXT2_NEW_INODE_FL 0x80000000 + +/* + * Flags for mkjournal + */ +#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 /* create V1 superblock (deprecated) */ +#define EXT2_MKJOURNAL_LAZYINIT 0x0000002 /* don't zero journal inode before use*/ +#define EXT2_MKJOURNAL_NO_MNT_CHECK 0x0000004 /* don't check mount status */ + +/* + * Normal journal area size to fast commit area size ratio. This is used to + * set default size of fast commit area. + */ +#define EXT2_JOURNAL_TO_FC_BLKS_RATIO 64 + +struct blk_alloc_ctx; +struct opaque_ext2_group_desc; + +struct struct_ext2_filsys { + errcode_t magic; + io_channel io; + int flags; + char * device_name; + struct ext2_super_block * super; + unsigned int blocksize; + int fragsize; + dgrp_t group_desc_count; + unsigned long desc_blocks; + struct opaque_ext2_group_desc * group_desc; + unsigned int inode_blocks_per_group; + ext2fs_inode_bitmap inode_map; + ext2fs_block_bitmap block_map; + /* XXX FIXME-64: not 64-bit safe, but not used? */ + errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); + errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino); + errcode_t (*write_bitmaps)(ext2_filsys fs); + errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode); + errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode); + ext2_badblocks_list badblocks; + ext2_dblist dblist; + __u32 stride; /* for mke2fs */ + struct ext2_super_block * orig_super; + struct ext2_image_hdr * image_header; + __u32 umask; + time_t now; + int cluster_ratio_bits; + __u16 default_bitmap_type; + __u16 pad; + /* + * Reserved for future expansion + */ + __u32 reserved[5]; + + /* + * Reserved for the use of the calling application. + */ + void * priv_data; + + /* + * Inode cache + */ + struct ext2_inode_cache *icache; + io_channel image_io; + + /* + * More callback functions + */ + errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal, + blk64_t *ret); + errcode_t (*get_alloc_block2)(ext2_filsys fs, blk64_t goal, + blk64_t *ret, struct blk_alloc_ctx *ctx); + void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse); + + /* + * Buffers for Multiple mount protection(MMP) block. + */ + void *mmp_buf; + void *mmp_cmp; + int mmp_fd; + + /* + * Time at which e2fsck last updated the MMP block. + */ + long mmp_last_written; + + /* progress operation functions */ + struct ext2fs_progress_ops *progress_ops; + + /* Precomputed FS UUID checksum for seeding other checksums */ + __u32 csum_seed; + + io_channel journal_io; + char *journal_name; + + /* New block range allocation hooks */ + errcode_t (*new_range)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen); + void (*block_alloc_stats_range)(ext2_filsys fs, blk64_t blk, blk_t num, + int inuse); + + /* hashmap for SHA of data blocks */ + struct ext2fs_hashmap* block_sha_map; + + const struct ext2fs_nls_table *encoding; +}; + +#if EXT2_FLAT_INCLUDES +#include "e2_bitops.h" +#else +#include +#endif + +/* + * 64-bit bitmap backend types + */ +#define EXT2FS_BMAP64_BITARRAY 1 +#define EXT2FS_BMAP64_RBTREE 2 +#define EXT2FS_BMAP64_AUTODIR 3 + +/* + * Return flags for the block iterator functions + */ +#define BLOCK_CHANGED 1 +#define BLOCK_ABORT 2 +#define BLOCK_ERROR 4 +#define BLOCK_INLINE_DATA_CHANGED 8 + +/* + * Block iterate flags + * + * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the iterator + * function should be called on blocks where the block number is zero. + * This is used by ext2fs_expand_dir() to be able to add a new block + * to an inode. It can also be used for programs that want to be able + * to deal with files that contain "holes". + * + * BLOCK_FLAG_DEPTH_TRAVERSE indicates that the iterator function for + * the indirect, doubly indirect, etc. blocks should be called after + * all of the blocks contained in the indirect blocks are processed. + * This is useful if you are going to be deallocating blocks from an + * inode. + * + * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be + * called for data blocks only. + * + * BLOCK_FLAG_READ_ONLY is a promise by the caller that it will not + * modify returned block number. + * + * BLOCK_FLAG_NO_LARGE is for internal use only. It informs + * ext2fs_block_iterate2 that large files won't be accepted. + */ +#define BLOCK_FLAG_APPEND 1 +#define BLOCK_FLAG_HOLE 1 +#define BLOCK_FLAG_DEPTH_TRAVERSE 2 +#define BLOCK_FLAG_DATA_ONLY 4 +#define BLOCK_FLAG_READ_ONLY 8 + +#define BLOCK_FLAG_NO_LARGE 0x1000 + +/* + * Magic "block count" return values for the block iterator function. + */ +#define BLOCK_COUNT_IND (-1) +#define BLOCK_COUNT_DIND (-2) +#define BLOCK_COUNT_TIND (-3) +#define BLOCK_COUNT_TRANSLATOR (-4) + +#define BLOCK_ALLOC_UNKNOWN 0 +#define BLOCK_ALLOC_DATA 1 +#define BLOCK_ALLOC_METADATA 2 + +struct blk_alloc_ctx { + ext2_ino_t ino; + struct ext2_inode *inode; + blk64_t lblk; + int flags; +}; + +#if 0 +/* + * Flags for ext2fs_move_blocks + */ +#define EXT2_BMOVE_GET_DBLIST 0x0001 +#define EXT2_BMOVE_DEBUG 0x0002 +#endif + +/* + * Generic (non-filesystem layout specific) extents structure + */ + +#define EXT2_EXTENT_FLAGS_LEAF 0x0001 +#define EXT2_EXTENT_FLAGS_UNINIT 0x0002 +#define EXT2_EXTENT_FLAGS_SECOND_VISIT 0x0004 + +struct ext2fs_extent { + blk64_t e_pblk; /* first physical block */ + blk64_t e_lblk; /* first logical block extent covers */ + __u32 e_len; /* number of blocks covered by extent */ + __u32 e_flags; /* extent flags */ +}; + +typedef struct ext2_extent_handle *ext2_extent_handle_t; +typedef struct ext2_extent_path *ext2_extent_path_t; + +/* + * Flags used by ext2fs_extent_get() + */ +#define EXT2_EXTENT_CURRENT 0x0000 +#define EXT2_EXTENT_MOVE_MASK 0x000F +#define EXT2_EXTENT_ROOT 0x0001 +#define EXT2_EXTENT_LAST_LEAF 0x0002 +#define EXT2_EXTENT_FIRST_SIB 0x0003 +#define EXT2_EXTENT_LAST_SIB 0x0004 +#define EXT2_EXTENT_NEXT_SIB 0x0005 +#define EXT2_EXTENT_PREV_SIB 0x0006 +#define EXT2_EXTENT_NEXT_LEAF 0x0007 +#define EXT2_EXTENT_PREV_LEAF 0x0008 +#define EXT2_EXTENT_NEXT 0x0009 +#define EXT2_EXTENT_PREV 0x000A +#define EXT2_EXTENT_UP 0x000B +#define EXT2_EXTENT_DOWN 0x000C +#define EXT2_EXTENT_DOWN_AND_LAST 0x000D + +/* + * Flags used by ext2fs_extent_insert() + */ +#define EXT2_EXTENT_INSERT_AFTER 0x0001 /* insert after handle loc'n */ +#define EXT2_EXTENT_INSERT_NOSPLIT 0x0002 /* insert may not cause split */ + +/* + * Flags used by ext2fs_extent_delete() + */ +#define EXT2_EXTENT_DELETE_KEEP_EMPTY 0x001 /* keep node if last extent gone */ + +/* + * Flags used by ext2fs_extent_set_bmap() + */ +#define EXT2_EXTENT_SET_BMAP_UNINIT 0x0001 + +/* + * Data structure returned by ext2fs_extent_get_info() + */ +struct ext2_extent_info { + int curr_entry; + int curr_level; + int num_entries; + int max_entries; + int max_depth; + int bytes_avail; + blk64_t max_lblk; + blk64_t max_pblk; + __u32 max_len; + __u32 max_uninit_len; +}; + +/* + * Flags for directory block reading and writing functions + */ +#define EXT2_DIRBLOCK_V2_STRUCT 0x0001 + +/* + * Return flags for the directory iterator functions + */ +#define DIRENT_CHANGED 1 +#define DIRENT_ABORT 2 +#define DIRENT_ERROR 3 + +/* + * Directory iterator flags + */ + +#define DIRENT_FLAG_INCLUDE_EMPTY 1 +#define DIRENT_FLAG_INCLUDE_REMOVED 2 +#define DIRENT_FLAG_INCLUDE_CSUM 4 +#define DIRENT_FLAG_INCLUDE_INLINE_DATA 8 + +#define DIRENT_DOT_FILE 1 +#define DIRENT_DOT_DOT_FILE 2 +#define DIRENT_OTHER_FILE 3 +#define DIRENT_DELETED_FILE 4 +#define DIRENT_CHECKSUM 5 + +/* + * Inode scan definitions + */ +typedef struct ext2_struct_inode_scan *ext2_inode_scan; + +/* + * ext2fs_scan flags + */ +#define EXT2_SF_CHK_BADBLOCKS 0x0001 +#define EXT2_SF_BAD_INODE_BLK 0x0002 +#define EXT2_SF_BAD_EXTRA_BYTES 0x0004 +#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008 +#define EXT2_SF_DO_LAZY 0x0010 +#define EXT2_SF_WARN_GARBAGE_INODES 0x0020 + +/* + * ext2fs_check_if_mounted flags + */ +#define EXT2_MF_MOUNTED 1 +#define EXT2_MF_ISROOT 2 +#define EXT2_MF_READONLY 4 +#define EXT2_MF_SWAP 8 +#define EXT2_MF_BUSY 16 + +/* + * Ext2/linux mode flags. We define them here so that we don't need + * to depend on the OS's sys/stat.h, since we may be compiling on a + * non-Linux system. + */ +#define LINUX_S_IFMT 00170000 +#define LINUX_S_IFSOCK 0140000 +#define LINUX_S_IFLNK 0120000 +#define LINUX_S_IFREG 0100000 +#define LINUX_S_IFBLK 0060000 +#define LINUX_S_IFDIR 0040000 +#define LINUX_S_IFCHR 0020000 +#define LINUX_S_IFIFO 0010000 +#define LINUX_S_ISUID 0004000 +#define LINUX_S_ISGID 0002000 +#define LINUX_S_ISVTX 0001000 + +#define LINUX_S_IRWXU 00700 +#define LINUX_S_IRUSR 00400 +#define LINUX_S_IWUSR 00200 +#define LINUX_S_IXUSR 00100 + +#define LINUX_S_IRWXG 00070 +#define LINUX_S_IRGRP 00040 +#define LINUX_S_IWGRP 00020 +#define LINUX_S_IXGRP 00010 + +#define LINUX_S_IRWXO 00007 +#define LINUX_S_IROTH 00004 +#define LINUX_S_IWOTH 00002 +#define LINUX_S_IXOTH 00001 + +#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK) +#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG) +#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR) +#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR) +#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK) +#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO) +#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK) + +/* + * ext2 size of an inode + */ +#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32)) + +/* + * ext2_icount_t abstraction + */ +#define EXT2_ICOUNT_OPT_INCREMENT 0x01 +#define EXT2_ICOUNT_OPT_FULLMAP 0x02 + +typedef struct ext2_icount *ext2_icount_t; + +/* + * Flags for ext2fs_bmap + */ +#define BMAP_ALLOC 0x0001 +#define BMAP_SET 0x0002 +#define BMAP_UNINIT 0x0004 +#define BMAP_ZERO 0x0008 + +/* + * Returned flags from ext2fs_bmap + */ +#define BMAP_RET_UNINIT 0x0001 + +/* + * Flags for ext2fs_read_inode2 + */ +#define READ_INODE_NOCSUM 0x0001 + +/* + * Flags for ext2fs_write_inode2 + */ +#define WRITE_INODE_NOCSUM 0x0001 + +/* + * Flags for imager.c functions + */ +#define IMAGER_FLAG_INODEMAP 1 +#define IMAGER_FLAG_SPARSEWRITE 2 + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +/* + * Features supported by this version of the library + */ +#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\ + EXT2_FEATURE_COMPAT_IMAGIC_INODES|\ + EXT3_FEATURE_COMPAT_HAS_JOURNAL|\ + EXT2_FEATURE_COMPAT_RESIZE_INODE|\ + EXT2_FEATURE_COMPAT_DIR_INDEX|\ + EXT2_FEATURE_COMPAT_EXT_ATTR|\ + EXT4_FEATURE_COMPAT_SPARSE_SUPER2|\ + EXT4_FEATURE_COMPAT_FAST_COMMIT|\ + EXT4_FEATURE_COMPAT_STABLE_INODES) + +#ifdef CONFIG_MMP +#define EXT4_LIB_INCOMPAT_MMP EXT4_FEATURE_INCOMPAT_MMP +#else +#define EXT4_LIB_INCOMPAT_MMP (0) +#endif + +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ + EXT2_FEATURE_INCOMPAT_META_BG|\ + EXT3_FEATURE_INCOMPAT_RECOVER|\ + EXT3_FEATURE_INCOMPAT_EXTENTS|\ + EXT4_FEATURE_INCOMPAT_FLEX_BG|\ + EXT4_FEATURE_INCOMPAT_EA_INODE|\ + EXT4_LIB_INCOMPAT_MMP|\ + EXT4_FEATURE_INCOMPAT_64BIT|\ + EXT4_FEATURE_INCOMPAT_INLINE_DATA|\ + EXT4_FEATURE_INCOMPAT_ENCRYPT|\ + EXT4_FEATURE_INCOMPAT_CASEFOLD|\ + EXT4_FEATURE_INCOMPAT_CSUM_SEED|\ + EXT4_FEATURE_INCOMPAT_LARGEDIR) + +#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ + EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\ + EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\ + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\ + EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\ + EXT4_FEATURE_RO_COMPAT_BIGALLOC|\ + EXT4_FEATURE_RO_COMPAT_QUOTA|\ + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ + EXT4_FEATURE_RO_COMPAT_READONLY |\ + EXT4_FEATURE_RO_COMPAT_PROJECT |\ + EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS |\ + EXT4_FEATURE_RO_COMPAT_VERITY) + +/* + * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed + * to ext2fs_openfs() + */ +#define EXT2_LIB_SOFTSUPP_INCOMPAT (0) +#define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_REPLICA) + + +/* Translate a block number to a cluster number */ +#define EXT2FS_CLUSTER_RATIO(fs) (1 << (fs)->cluster_ratio_bits) +#define EXT2FS_CLUSTER_MASK(fs) (EXT2FS_CLUSTER_RATIO(fs) - 1) +#define EXT2FS_B2C(fs, blk) ((blk) >> (fs)->cluster_ratio_bits) +/* Translate a cluster number to a block number */ +#define EXT2FS_C2B(fs, cluster) ((cluster) << (fs)->cluster_ratio_bits) +/* Translate # of blks to # of clusters */ +#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \ + (fs)->cluster_ratio_bits) + +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) +typedef struct stat64 ext2fs_struct_stat; +#else +typedef struct stat ext2fs_struct_stat; +#endif + +/* + * For ext2fs_close2() and ext2fs_flush2(), this flag allows you to + * avoid the fsync call. + */ +#define EXT2_FLAG_FLUSH_NO_SYNC 1 + +/* + * Modify and iterate extended attributes + */ +struct ext2_xattr_handle; +#define XATTR_ABORT 1 +#define XATTR_CHANGED 2 + +/* + * flags for ext2fs_rw_bitmaps() + */ +#define EXT2FS_BITMAPS_WRITE 0x0001 +#define EXT2FS_BITMAPS_BLOCK 0x0002 +#define EXT2FS_BITMAPS_INODE 0x0004 +#define EXT2FS_BITMAPS_VALID_FLAGS 0x0007 + +/* + * function prototypes + */ +static inline int ext2fs_has_group_desc_csum(ext2_filsys fs) +{ + return ext2fs_has_feature_metadata_csum(fs->super) || + ext2fs_has_feature_gdt_csum(fs->super); +} + +/* The LARGE_FILE feature should be set if we have stored files 2GB+ in size */ +static inline int ext2fs_needs_large_file_feature(unsigned long long file_size) +{ + return file_size >= 0x80000000ULL; +} + +/* alloc.c */ +extern void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group); +extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, + ext2fs_inode_bitmap map, ext2_ino_t *ret); +extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, + ext2fs_block_bitmap map, blk_t *ret); +extern errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal, + ext2fs_block_bitmap map, blk64_t *ret); +extern errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal, + ext2fs_block_bitmap map, blk64_t *ret, + struct blk_alloc_ctx *ctx); +extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, + blk_t finish, int num, + ext2fs_block_bitmap map, + blk_t *ret); +extern errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, + blk64_t finish, int num, + ext2fs_block_bitmap map, + blk64_t *ret); +extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, + char *block_buf, blk_t *ret); +extern errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal, + char *block_buf, blk64_t *ret); +extern errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal, + char *block_buf, blk64_t *ret, + struct blk_alloc_ctx *ctx); + +extern void ext2fs_set_alloc_block_callback(ext2_filsys fs, + errcode_t (*func)(ext2_filsys fs, + blk64_t goal, + blk64_t *ret), + errcode_t (**old)(ext2_filsys fs, + blk64_t goal, + blk64_t *ret)); +blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t lblk); +extern void ext2fs_set_new_range_callback(ext2_filsys fs, + errcode_t (*func)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen), + errcode_t (**old)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen)); +extern void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs, + void (*func)(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse), + void (**old)(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse)); +#define EXT2_NEWRANGE_FIXED_GOAL (0x1) +#define EXT2_NEWRANGE_MIN_LENGTH (0x2) +#define EXT2_NEWRANGE_ALL_FLAGS (0x3) +errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk, + blk64_t *plen); +#define EXT2_ALLOCRANGE_FIXED_GOAL (0x1) +#define EXT2_ALLOCRANGE_ZERO_BLOCKS (0x2) +#define EXT2_ALLOCRANGE_ALL_FLAGS (0x3) +errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal, + blk_t len, blk64_t *ret); + +/* alloc_sb.c */ +extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap); +extern void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs, + void (*func)(ext2_filsys fs, + blk64_t blk, + int inuse), + void (**old)(ext2_filsys fs, + blk64_t blk, + int inuse)); + +/* alloc_stats.c */ +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse); +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, + int inuse, int isdir); +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse); +void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse); +void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse); + +/* alloc_tables.c */ +extern errcode_t ext2fs_allocate_tables(ext2_filsys fs); +extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap); + +/* badblocks.c */ +extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size); +extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk); +extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk); +extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk); +extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, + ext2_u32_iterate *ret); +extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk); +extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter); +extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest); +extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2); + +extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, + int size); +extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, + blk_t blk); +extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb, + blk_t blk); +extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk); +extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk); +extern errcode_t + ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, + ext2_badblocks_iterate *ret); +extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, + blk_t *blk); +extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter); +extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, + ext2_badblocks_list *dest); +extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1, + ext2_badblocks_list bb2); +extern int ext2fs_u32_list_count(ext2_u32_list bb); + +/* bb_compat */ +extern errcode_t badblocks_list_create(badblocks_list *ret, int size); +extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk); +extern int badblocks_list_test(badblocks_list bb, blk_t blk); +extern errcode_t badblocks_list_iterate_begin(badblocks_list bb, + badblocks_iterate *ret); +extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk); +extern void badblocks_list_iterate_end(badblocks_iterate iter); +extern void badblocks_list_free(badblocks_list bb); + +/* bb_inode.c */ +extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs, + ext2_badblocks_list bb_list); + +/* bitmaps.c */ +extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap); +extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap); +extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest); +extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret); +extern errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret); +extern int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap); +extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_inode_bitmap *ret); +extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, + ext2_ino_t end, ext2_ino_t *oend); +extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, + blk_t end, blk_t *oend); +extern errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap, + blk64_t end, blk64_t *oend); +extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap); +extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap); +extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_inode_bitmap bmap); +extern errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, + __u64 new_real_end, + ext2fs_inode_bitmap bmap); +extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_block_bitmap bmap); +extern errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, + __u64 new_real_end, + ext2fs_block_bitmap bmap); +extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, + ext2fs_block_bitmap bm2); +extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, + ext2fs_inode_bitmap bm2); +extern errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap, + ext2_ino_t start, unsigned int num, + void *in); +extern errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap, + __u64 start, size_t num, + void *in); +extern errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap, + ext2_ino_t start, unsigned int num, + void *out); +extern errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap, + __u64 start, size_t num, + void *out); +extern errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap, + blk_t start, unsigned int num, + void *in); +extern errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap, + blk64_t start, size_t num, + void *in); +extern errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap, + blk_t start, unsigned int num, + void *out); +extern errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap, + blk64_t start, size_t num, + void *out); + +/* blknum.c */ +extern __u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group); +extern __u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group); +extern dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t); +extern blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group); +extern blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group); +extern int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group); +extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, + struct ext2_inode *inode); +extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, + struct ext2_inode *inode); +extern blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs, + struct ext2_inode *inode); +extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super); +extern void ext2fs_blocks_count_set(struct ext2_super_block *super, + blk64_t blk); +extern void ext2fs_blocks_count_add(struct ext2_super_block *super, + blk64_t blk); +extern blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super); +extern void ext2fs_r_blocks_count_set(struct ext2_super_block *super, + blk64_t blk); +extern void ext2fs_r_blocks_count_add(struct ext2_super_block *super, + blk64_t blk); +extern blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super); +extern void ext2fs_free_blocks_count_set(struct ext2_super_block *super, + blk64_t blk); +extern void ext2fs_free_blocks_count_add(struct ext2_super_block *super, + blk64_t blk); +/* Block group descriptor accessor functions */ +extern struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, + struct opaque_ext2_group_desc *gdp, + dgrp_t group); +extern blk64_t ext2fs_block_bitmap_csum(ext2_filsys fs, dgrp_t group); +extern blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group); +extern void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, + blk64_t blk); +extern __u32 ext2fs_inode_bitmap_csum(ext2_filsys fs, dgrp_t group); +extern blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group); +extern void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, + blk64_t blk); +extern blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group); +extern void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, + blk64_t blk); +extern __u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, + __u32 n); +extern __u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, + __u32 n); +extern __u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, + __u32 n); +extern __u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, + __u32 n); +extern __u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group); +extern int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag); +extern void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags); +extern void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags); +extern __u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group); +extern void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum); +extern blk64_t ext2fs_file_acl_block(ext2_filsys fs, + const struct ext2_inode *inode); +extern void ext2fs_file_acl_block_set(ext2_filsys fs, + struct ext2_inode *inode, blk64_t blk); +extern errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode, + ext2_off64_t size); + +/* block.c */ +extern errcode_t ext2fs_block_iterate(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int blockcnt, + void *priv_data), + void *priv_data); +errcode_t ext2fs_block_iterate2(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data); +errcode_t ext2fs_block_iterate3(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data); + +/* bmap.c */ +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, int bmap_flags, + blk_t block, blk_t *phys_blk); +extern errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, int bmap_flags, blk64_t block, + int *ret_flags, blk64_t *phys_blk); +errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t lblk, + blk64_t *pblk); + +#if 0 +/* bmove.c */ +extern errcode_t ext2fs_move_blocks(ext2_filsys fs, + ext2fs_block_bitmap reserve, + ext2fs_block_bitmap alloc_map, + int flags); +#endif + +/* check_desc.c */ +extern errcode_t ext2fs_check_desc(ext2_filsys fs); + +/* closefs.c */ +extern errcode_t ext2fs_close(ext2_filsys fs); +extern errcode_t ext2fs_close2(ext2_filsys fs, int flags); +extern errcode_t ext2fs_close_free(ext2_filsys *fs); +extern errcode_t ext2fs_flush(ext2_filsys fs); +extern errcode_t ext2fs_flush2(ext2_filsys fs, int flags); +extern int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group_block); +extern errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs, + dgrp_t group, + blk64_t *ret_super_blk, + blk64_t *ret_old_desc_blk, + blk64_t *ret_new_desc_blk, + blk_t *ret_used_blks); +extern int ext2fs_super_and_bgd_loc(ext2_filsys fs, + dgrp_t group, + blk_t *ret_super_blk, + blk_t *ret_old_desc_blk, + blk_t *ret_new_desc_blk, + int *ret_meta_bg); +extern void ext2fs_update_dynamic_rev(ext2_filsys fs); + +/* crc32c.c */ +extern __u32 ext2fs_crc32_be(__u32 crc, unsigned char const *p, size_t len); +extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len); + +/* csum.c */ +extern void ext2fs_init_csum_seed(ext2_filsys fs); +extern errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp); +extern int ext2fs_mmp_csum_verify(ext2_filsys, struct mmp_struct *mmp); +extern int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb); +extern errcode_t ext2fs_superblock_csum_set(ext2_filsys fs, + struct ext2_super_block *sb); +extern int ext2fs_superblock_csum_verify(ext2_filsys fs, + struct ext2_super_block *sb); +extern errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, + ext2_ino_t inum, blk64_t block, + struct ext2_ext_attr_header *hdr); +extern int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, + blk64_t block, + struct ext2_ext_attr_header *hdr); +#define EXT2_DIRENT_TAIL(block, blocksize) \ + ((struct ext2_dir_entry_tail *)(((char *)(block)) + \ + (blocksize) - sizeof(struct ext2_dir_entry_tail))) + +extern void ext2fs_initialize_dirent_tail(ext2_filsys fs, + struct ext2_dir_entry_tail *t); +extern int ext2fs_dirent_has_tail(ext2_filsys fs, + struct ext2_dir_entry *dirent); +extern int ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent); +extern int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent); +extern errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent); +extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset); +extern errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent, + __u32 *crc, struct ext2_dx_tail **ret_t); +extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, + ext2_ino_t inum, + struct ext3_extent_header *eh); +extern int ext2fs_extent_block_csum_verify(ext2_filsys fs, + ext2_ino_t inum, + struct ext3_extent_header *eh); +extern errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group, + char *bitmap, int size); +extern int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, + char *bitmap, int size); +extern errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group, + char *bitmap, int size); +extern int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, + char *bitmap, int size); +extern errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_inode_large *inode); +extern int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_inode_large *inode); +extern void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group); +extern int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group); +extern errcode_t ext2fs_set_gdt_csum(ext2_filsys fs); +extern __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group); + +/* dblist.c */ +extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist); +extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, + blk_t blk, int blockcnt); +extern errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino, + blk64_t blk, e2_blkcnt_t blockcnt); +extern void ext2fs_dblist_sort(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)); +extern void ext2fs_dblist_sort2(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)); +extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, + int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info, + void *priv_data), + void *priv_data); +extern errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist, + int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info, + void *priv_data), + void *priv_data); +extern errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist, + int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info, + void *priv_data), + unsigned long long start, + unsigned long long count, + void *priv_data); +extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, + blk_t blk, int blockcnt); +extern errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino, + blk64_t blk, e2_blkcnt_t blockcnt); +extern errcode_t ext2fs_copy_dblist(ext2_dblist src, + ext2_dblist *dest); +extern int ext2fs_dblist_count(ext2_dblist dblist); +extern blk64_t ext2fs_dblist_count2(ext2_dblist dblist); +extern errcode_t ext2fs_dblist_get_last(ext2_dblist dblist, + struct ext2_db_entry **entry); +extern errcode_t ext2fs_dblist_get_last2(ext2_dblist dblist, + struct ext2_db_entry2 **entry); +extern errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist); + +/* dblist_dir.c */ +extern errcode_t + ext2fs_dblist_dir_iterate(ext2_dblist dblist, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); + +#if 0 +/* digest_encode.c */ +#define EXT2FS_DIGEST_SIZE EXT2FS_SHA256_LENGTH +extern int ext2fs_digest_encode(const char *src, int len, char *dst); +extern int ext2fs_digest_decode(const char *src, int len, char *dst); +#endif + +/* dirblock.c */ +extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags); +extern errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block, + void *buf, int flags); +extern errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block, + void *buf, int flags, ext2_ino_t ino); +extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags); +extern errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block, + void *buf, int flags); +extern errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block, + void *buf, int flags, ext2_ino_t ino); + +/* dirhash.c */ +extern errcode_t ext2fs_dirhash(int version, const char *name, int len, + const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash); + +extern errcode_t ext2fs_dirhash2(int version, const char *name, int len, + const struct ext2fs_nls_table *charset, + int hash_flags, + const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash); + +/* dir_iterate.c */ +extern errcode_t ext2fs_get_rec_len(ext2_filsys fs, + struct ext2_dir_entry *dirent, + unsigned int *rec_len); +extern errcode_t ext2fs_set_rec_len(ext2_filsys fs, + unsigned int len, + struct ext2_dir_entry *dirent); +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); +extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); + +/* dupfs.c */ +extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest); + +/* expanddir.c */ +extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); + +/* ext_attr.c */ +extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, + void *data); +extern __u32 ext2fs_ext_attr_hash_entry_signed(struct ext2_ext_attr_entry *entry, + void *data); +extern errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash); +extern errcode_t ext2fs_ext_attr_hash_entry3(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash, + __u32 *signed_hash); +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); +extern errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, + void *buf, ext2_ino_t inum); +extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, + void *buf); +extern errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, + void *buf, ext2_ino_t inum); +extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, + int adjust, __u32 *newcount); +extern errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk, + char *block_buf, + int adjust, __u32 *newcount); +extern errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk, + char *block_buf, + int adjust, __u32 *newcount, + ext2_ino_t inum); +errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle); +errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle); +errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h, + int (*func)(char *name, char *value, + size_t value_len, void *data), + void *data); +errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key, + void **value, size_t *value_len); +errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *handle, + const char *key, + const void *value, + size_t value_len); +errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle, + const char *key); +errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino, + struct ext2_xattr_handle **handle); +errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle); +errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode_large *inode); +errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count); +errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino, + size_t *size); +#define XATTR_HANDLE_FLAG_RAW 0x0001 +errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle, + unsigned int *new_flags, unsigned int *old_flags); +extern void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header, + struct ext2_ext_attr_entry *end); +extern __u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode); +extern void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash); +extern __u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode); +extern void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count); + +/* extent.c */ +extern errcode_t ext2fs_extent_header_verify(void *ptr, int size); +extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino, + ext2_extent_handle_t *handle); +extern errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t *ret_handle); +extern void ext2fs_extent_free(ext2_extent_handle_t handle); +extern errcode_t ext2fs_extent_get(ext2_extent_handle_t handle, + int flags, struct ext2fs_extent *extent); +extern errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle); +extern errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags, + struct ext2fs_extent *extent); +extern errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags, + struct ext2fs_extent *extent); +extern errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, + blk64_t logical, blk64_t physical, + int flags); +extern errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags); +extern errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle, + struct ext2_extent_info *info); +extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle, + blk64_t blk); +extern errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle, + int leaf_level, blk64_t blk); +extern errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle); +extern size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle); +extern errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode); +extern errcode_t ext2fs_count_blocks(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t *ret_count); +extern errcode_t ext2fs_decode_extent(struct ext2fs_extent *to, void *from, + int len); + +/* fallocate.c */ +#define EXT2_FALLOCATE_ZERO_BLOCKS (0x1) +#define EXT2_FALLOCATE_FORCE_INIT (0x2) +#define EXT2_FALLOCATE_FORCE_UNINIT (0x4) +#define EXT2_FALLOCATE_INIT_BEYOND_EOF (0x8) +#define EXT2_FALLOCATE_ALL_FLAGS (0xF) +errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t goal, + blk64_t start, blk64_t len); + +/* fileio.c */ +extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + int flags, ext2_file_t *ret); +extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, + int flags, ext2_file_t *ret); +extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file); +struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file); +extern ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file); +extern errcode_t ext2fs_file_close(ext2_file_t file); +extern errcode_t ext2fs_file_flush(ext2_file_t file); +extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf, + unsigned int wanted, unsigned int *got); +extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, + unsigned int nbytes, unsigned int *written); +extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, + int whence, __u64 *ret_pos); +extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, + int whence, ext2_off_t *ret_pos); +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size); +extern ext2_off_t ext2fs_file_get_size(ext2_file_t file); +extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size); +extern errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size); + +/* finddev.c */ +extern char *ext2fs_find_block_device(dev_t device); + +/* flushb.c */ +extern errcode_t ext2fs_sync_device(int fd, int flushb); + +/* freefs.c */ +extern void ext2fs_free(ext2_filsys fs); +extern void ext2fs_free_dblist(ext2_dblist dblist); +extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb); +extern void ext2fs_u32_list_free(ext2_u32_list bb); + +/* gen_bitmap.c */ +extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap); +extern errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs, + __u32 start, __u32 end, + __u32 real_end, + const char *descr, char *init_map, + ext2fs_generic_bitmap *ret); +extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start, + __u32 end, + __u32 real_end, + const char *descr, + ext2fs_generic_bitmap *ret); +extern errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest); +extern void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap); +extern errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap, + errcode_t magic, + errcode_t neq, + ext2_ino_t end, + ext2_ino_t *oend); +extern void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map); +extern errcode_t ext2fs_resize_generic_bitmap(errcode_t magic, + __u32 new_end, + __u32 new_real_end, + ext2fs_generic_bitmap bmap); +extern errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq, + ext2fs_generic_bitmap bm1, + ext2fs_generic_bitmap bm2); +extern errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap, + errcode_t magic, + __u32 start, __u32 num, + void *out); +extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap, + errcode_t magic, + __u32 start, __u32 num, + void *in); +extern errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 start, __u32 end, + __u32 *out); +extern errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 start, __u32 end, + __u32 *out); + +/* gen_bitmap64.c */ +void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap); +errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic, + int type, __u64 start, __u64 end, + __u64 real_end, + const char *descr, + ext2fs_generic_bitmap *ret); +errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest); +void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap); +errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap, + errcode_t neq, + __u64 end, __u64 *oend); +void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap); +errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap, + __u64 new_end, + __u64 new_real_end); +errcode_t ext2fs_compare_generic_bmap(errcode_t neq, + ext2fs_generic_bitmap bm1, + ext2fs_generic_bitmap bm2); +errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap, + __u64 start, unsigned int num, + void *out); +errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap, + __u64 start, unsigned int num, + void *in); +errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, + ext2fs_block_bitmap *bitmap); +errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, + blk64_t end, blk64_t *out); + +/* get_num_dirs.c */ +extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); + +/* getsize.c */ +extern errcode_t ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks); +extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize, + blk64_t *retblocks); + +/* getsectsize.c */ +extern int ext2fs_get_dio_alignment(int fd); +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize); +errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize); + +/* i_block.c */ +errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode, + blk64_t num_blocks); +errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode, + blk64_t num_blocks); +errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b); + +/* imager.c */ +extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags); + +/* ind_block.c */ +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf); +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf); + +/* initialize.c */ +extern errcode_t ext2fs_initialize(const char *name, int flags, + struct ext2_super_block *param, + io_manager manager, ext2_filsys *ret_fs); +extern errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs, int super_only); + +/* icount.c */ +extern void ext2fs_free_icount(ext2_icount_t icount); +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, + unsigned int size, + ext2_icount_t hint, ext2_icount_t *ret); +extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, + unsigned int size, + ext2_icount_t *ret); +extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, + __u16 count); +extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); + +/* inline.c */ + +extern errcode_t ext2fs_get_memalign(unsigned long size, + unsigned long align, void *ptr); + +/* inline_data.c */ +extern errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino); +extern errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, + size_t *size); +extern errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t *size); +extern errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t size); + +/* inode.c */ +extern errcode_t ext2fs_create_inode_cache(ext2_filsys fs, + unsigned int cache_size); +extern void ext2fs_free_inode_cache(struct ext2_inode_cache *icache); +extern errcode_t ext2fs_flush_icache(ext2_filsys fs); +extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, + ext2_ino_t *ino, + struct ext2_inode *inode, + int bufsize); +#define EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS 8 +extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, + ext2_inode_scan *ret_scan); +extern void ext2fs_close_inode_scan(ext2_inode_scan scan); +extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode); +extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, + int group); +extern void ext2fs_set_inode_callback + (ext2_inode_scan scan, + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data), + void *done_group_data); +extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, + int clear_flags); +extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); +extern errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize, int flags); +extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); +extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize, int flags); +extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); +extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino); + +/* inode_io.c */ +extern io_manager inode_io_manager; +extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, + char **name); +extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char **name); + +/* ismounted.c */ +extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); +extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, + char *mtpt, int mtlen); + +/* punch.c */ +/* + * NOTE: This function removes from an inode the blocks "start", "end", and + * every block in between. + */ +extern errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, blk64_t start, + blk64_t end); + +/* namei.c */ +extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, + int namelen, char *buf, ext2_ino_t *inode); +extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode); +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode); +extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t inode, ext2_ino_t *res_inode); + +/* native.c */ +int ext2fs_native_flag(void); + +/* newdir.c */ +extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, + ext2_ino_t parent_ino, char **block); +extern errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino, + ext2_ino_t parent_ino, __u32 *iblock); + +/* nls_utf8.c */ +extern const struct ext2fs_nls_table *ext2fs_load_nls_table(int encoding); +extern int ext2fs_check_encoded_name(const struct ext2fs_nls_table *table, + char *s, size_t len, char **pos); +extern int ext2fs_casefold_cmp(const struct ext2fs_nls_table *table, + const unsigned char *str1, size_t len1, + const unsigned char *str2, size_t len2); + +/* mkdir.c */ +extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, + const char *name); + +/* mkjournal.c */ +struct ext2fs_journal_params { + blk_t num_journal_blocks; + blk_t num_fc_blocks; +}; +extern errcode_t ext2fs_get_journal_params( + struct ext2fs_journal_params *params, ext2_filsys fs); +extern errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num, + blk_t *ret_blk, int *ret_count); +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 num_blocks, int flags, + char **ret_jsb); +extern errcode_t ext2fs_create_journal_superblock2(ext2_filsys fs, + struct ext2fs_journal_params *params, + 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 num_blocks, + int flags); +extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks, + blk64_t goal, int flags); +extern errcode_t ext2fs_add_journal_inode3(ext2_filsys fs, + struct ext2fs_journal_params *params, + blk64_t goal, int flags); +extern int ext2fs_default_journal_size(__u64 num_blocks); +extern int ext2fs_journal_sb_start(int blocksize); + +/* openfs.c */ +extern errcode_t ext2fs_open(const char *name, int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs); +extern errcode_t ext2fs_open2(const char *name, const char *io_options, + int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs); +/* + * The dgrp_t argument to these two functions is not actually a group number + * but a block number offset within a group table! Convert with the formula + * (group_number / groups_per_block). + */ +extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, + blk64_t group_block, dgrp_t i); +extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, + dgrp_t i); +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io); +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io); +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io); + +/* get_pathname.c */ +extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, + char **name); + +/* link.c */ +#define EXT2FS_UNLINK_FORCE 0x1 /* Forcefully unlink even if + * the inode number doesn't + * match the dirent + */ +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags); +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags); + +/* symlink.c */ +errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, + const char *name, const char *target); +int ext2fs_is_fast_symlink(struct ext2_inode *inode); + +/* mmp.c */ +errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf); +errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_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_update2(ext2_filsys fs, int immediately); +errcode_t ext2fs_mmp_stop(ext2_filsys fs); +unsigned ext2fs_mmp_new_seq(void); + +/* read_bb.c */ +extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, + ext2_badblocks_list *bb_list); + +/* read_bb_file.c */ +extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void *priv_data, + void (*invalid)(ext2_filsys fs, + blk_t blk, + char *badstr, + void *priv_data)); +extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void (*invalid)(ext2_filsys fs, + blk_t blk)); + +/* res_gdt.c */ +extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs); + +/* rw_bitmaps.c */ +extern errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads); +extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs); +extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs); +extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs); +extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs); +extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs); +extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs); + +/*sha256.c */ +#define EXT2FS_SHA256_LENGTH 32 +#if 0 +extern void ext2fs_sha256(const unsigned char *in, unsigned long in_size, + unsigned char out[EXT2FS_SHA256_LENGTH]); +#endif + +/* sha512.c */ +#define EXT2FS_SHA512_LENGTH 64 +extern void ext2fs_sha512(const unsigned char *in, unsigned long in_size, + unsigned char out[EXT2FS_SHA512_LENGTH]); + +/* swapfs.c */ +extern errcode_t ext2fs_dirent_swab_in2(ext2_filsys fs, char *buf, size_t size, + int flags); +extern errcode_t ext2fs_dirent_swab_in(ext2_filsys fs, char *buf, int flags); +extern errcode_t ext2fs_dirent_swab_out2(ext2_filsys fs, char *buf, size_t size, + int flags); +extern errcode_t ext2fs_dirent_swab_out(ext2_filsys fs, char *buf, int flags); +extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, + int has_header); +extern void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header, + struct ext2_ext_attr_header *from_hdr); +extern void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry, + struct ext2_ext_attr_entry *from_entry); +extern void ext2fs_swap_super(struct ext2_super_block * super); +extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp); +extern void ext2fs_swap_group_desc2(ext2_filsys, struct ext2_group_desc *gdp); +extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + 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); + +/* unix_io.c */ +extern int ext2fs_open_file(const char *pathname, int flags, mode_t mode); +extern int ext2fs_stat(const char *path, ext2fs_struct_stat *buf); +extern int ext2fs_fstat(int fd, ext2fs_struct_stat *buf); + +/* valid_blk.c */ +extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); +extern int ext2fs_inode_has_valid_blocks2(ext2_filsys fs, + struct ext2_inode *inode); + +/* version.c */ +extern int ext2fs_parse_version_string(const char *ver_string); +extern int ext2fs_get_library_version(const char **ver_string, + const char **date_string); + +/* write_bb_file.c */ +extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, + unsigned int flags, + FILE *f); + + +/* inline functions */ +#ifdef NO_INLINE_FUNCS +extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr); +extern errcode_t ext2fs_get_memzero(unsigned long size, void *ptr); +extern errcode_t ext2fs_get_array(unsigned long count, + unsigned long size, void *ptr); +extern errcode_t ext2fs_get_arrayzero(unsigned long count, + unsigned long size, void *ptr); +extern errcode_t ext2fs_free_mem(void *ptr); +extern errcode_t ext2fs_resize_mem(unsigned long old_size, + unsigned long size, void *ptr); +extern errcode_t ext2fs_resize_array(unsigned long old_count, unsigned long count, + unsigned long size, void *ptr); +extern void ext2fs_mark_super_dirty(ext2_filsys fs); +extern void ext2fs_mark_changed(ext2_filsys fs); +extern int ext2fs_test_changed(ext2_filsys fs); +extern void ext2fs_mark_valid(ext2_filsys fs); +extern void ext2fs_unmark_valid(ext2_filsys fs); +extern int ext2fs_test_valid(ext2_filsys fs); +extern void ext2fs_mark_ib_dirty(ext2_filsys fs); +extern void ext2fs_mark_bb_dirty(ext2_filsys fs); +extern int ext2fs_test_ib_dirty(ext2_filsys fs); +extern int ext2fs_test_bb_dirty(ext2_filsys fs); +extern dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); +extern dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); +extern blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group); +extern blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group); +extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode); +extern int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks); +extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b); +extern __u64 ext2fs_div64_ceil(__u64 a, __u64 b); +extern int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry); +extern void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len); +extern int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry); +extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type); +extern struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode); +extern const struct ext2_inode *ext2fs_const_inode(const struct ext2_inode_large * large_inode); + +#endif + +/* + * The actual inlined functions definitions themselves... + * + * If NO_INLINE_FUNCS is defined, then we won't try to do inline + * functions at all! + */ +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +#ifdef INCLUDE_INLINE_FUNCS +#define _INLINE_ extern +#else +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ inline +#else +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif /* __GNUC__ */ +#endif /* __STDC_VERSION__ >= 199901L */ +#endif + +#ifndef EXT2_CUSTOM_MEMORY_ROUTINES +#include +/* + * Allocate memory. The 'ptr' arg must point to a pointer. + */ +_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr) +{ + void *pp; + + pp = malloc(size); + if (!pp) + return EXT2_ET_NO_MEMORY; + memcpy(ptr, &pp, sizeof (pp)); + return 0; +} + +_INLINE_ errcode_t ext2fs_get_memzero(unsigned long size, void *ptr) +{ + void *pp; + + pp = malloc(size); + if (!pp) + return EXT2_ET_NO_MEMORY; + memset(pp, 0, size); + memcpy(ptr, &pp, sizeof(pp)); + return 0; +} + +_INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, + void *ptr) +{ + if (count && (~0UL)/count < size) + return EXT2_ET_NO_MEMORY; + return ext2fs_get_mem(count*size, ptr); +} + +_INLINE_ errcode_t ext2fs_get_arrayzero(unsigned long count, + unsigned long size, void *ptr) +{ + if (count && (~0UL)/count < size) + return EXT2_ET_NO_MEMORY; + + return ext2fs_get_memzero((size_t)count * size, ptr); +} + +/* + * Free memory. The 'ptr' arg must point to a pointer. + */ +_INLINE_ errcode_t ext2fs_free_mem(void *ptr) +{ + void *p; + + memcpy(&p, ptr, sizeof(p)); + free(p); + p = 0; + memcpy(ptr, &p, sizeof(p)); + return 0; +} + +/* + * Resize memory. The 'ptr' arg must point to a pointer. + */ +_INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size, + unsigned long size, void *ptr) +{ + void *p; + + /* Use "memcpy" for pointer assignments here to avoid problems + * with C99 strict type aliasing rules. */ + memcpy(&p, ptr, sizeof(p)); + p = realloc(p, size); + if (!p) + return EXT2_ET_NO_MEMORY; + memcpy(ptr, &p, sizeof(p)); + return 0; +} + +/* + * Resize array. The 'ptr' arg must point to a pointer. + */ +_INLINE_ errcode_t ext2fs_resize_array(unsigned long size, + unsigned long old_count, + unsigned long count, void *ptr) +{ + unsigned long old_size; + errcode_t retval; + + if (count && (~0UL)/count < size) + return EXT2_ET_NO_MEMORY; + + size *= count; + old_size = size * old_count; + retval = ext2fs_resize_mem(old_size, size, ptr); + if (retval) + return retval; + + if (size > old_size) { + void *p; + + memcpy(&p, ptr, sizeof(p)); + memset((char *)p + old_size, 0, size - old_size); + memcpy(ptr, &p, sizeof(p)); + } + + return 0; +} +#endif /* Custom memory routines */ + +/* + * Mark a filesystem superblock as dirty + */ +_INLINE_ void ext2fs_mark_super_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Mark a filesystem as changed + */ +_INLINE_ void ext2fs_mark_changed(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_CHANGED; +} + +/* + * Check to see if a filesystem has changed + */ +_INLINE_ int ext2fs_test_changed(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_CHANGED); +} + +/* + * Mark a filesystem as valid + */ +_INLINE_ void ext2fs_mark_valid(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_VALID; +} + +/* + * Mark a filesystem as NOT valid + */ +_INLINE_ void ext2fs_unmark_valid(ext2_filsys fs) +{ + fs->flags &= ~EXT2_FLAG_VALID; +} + +/* + * Check to see if a filesystem is valid + */ +_INLINE_ int ext2fs_test_valid(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_VALID); +} + +/* + * Mark the inode bitmap as dirty + */ +_INLINE_ void ext2fs_mark_ib_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Mark the block bitmap as dirty + */ +_INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Check to see if a filesystem's inode bitmap is dirty + */ +_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_IB_DIRTY); +} + +/* + * Check to see if a filesystem's block bitmap is dirty + */ +_INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_BB_DIRTY); +} + +/* + * Return the group # of a block + */ +_INLINE_ dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk) +{ + return ext2fs_group_of_blk2(fs, blk); +} +/* + * Return the group # of an inode number + */ +_INLINE_ dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) +{ + return (ino - 1) / fs->super->s_inodes_per_group; +} + +/* + * Return the first block (inclusive) in a group + */ +_INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group) +{ + return (blk_t) ext2fs_group_first_block2(fs, group); +} + +/* + * Return the last block (inclusive) in a group + */ +_INLINE_ blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group) +{ + return (blk_t) ext2fs_group_last_block2(fs, group); +} + +_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode) +{ + return (blk_t) ext2fs_inode_data_blocks2(fs, inode); +} + +_INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks) +{ + int csum_size = 0; + + if ((EXT2_SB(fs->super)->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) != 0) + csum_size = sizeof(struct ext2_dx_tail); + return blocks * ((fs->blocksize - (8 + csum_size)) / + sizeof(struct ext2_dx_entry)); +} + +/* + * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b) + */ +_INLINE_ unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b) +{ + if (!a) + return 0; + return ((a - 1) / b) + 1; +} + +_INLINE_ __u64 ext2fs_div64_ceil(__u64 a, __u64 b) +{ + if (!a) + return 0; + return ((a - 1) / b) + 1; +} + +_INLINE_ int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry) +{ + return entry->name_len & 0xff; +} + +_INLINE_ void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len) +{ + entry->name_len = (entry->name_len & 0xff00) | (len & 0xff); +} + +_INLINE_ int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry) +{ + return entry->name_len >> 8; +} + +_INLINE_ void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type) +{ + entry->name_len = (entry->name_len & 0xff) | (type << 8); +} + +_INLINE_ struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode) +{ + /* It is always safe to convert large inode to a small inode */ + return (struct ext2_inode *) large_inode; +} + +_INLINE_ const struct ext2_inode * +ext2fs_const_inode(const struct ext2_inode_large * large_inode) +{ + /* It is always safe to convert large inode to a small inode */ + return (const struct ext2_inode *) large_inode; +} + +#undef _INLINE_ +#endif + +/* htree levels for ext4 */ +#define EXT4_HTREE_LEVEL_COMPAT 2 +#define EXT4_HTREE_LEVEL 3 + +static inline unsigned int ext2_dir_htree_level(ext2_filsys fs) +{ + if (ext2fs_has_feature_largedir(fs->super)) + return EXT4_HTREE_LEVEL; + + return EXT4_HTREE_LEVEL_COMPAT; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT2FS_EXT2FS_H */ diff --git a/include/e2fsprogs/ext2fs/ext2fsP.h b/include/e2fsprogs/ext2fs/ext2fsP.h new file mode 100755 index 0000000..0687384 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext2fsP.h @@ -0,0 +1,210 @@ +/* + * ext2fsP.h --- private header file for ext2 library + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#if HAVE_SYS_STAT_H +#include +#endif + +#include "ext2fs.h" + +#define EXT2FS_MAX_NESTED_LINKS 8 + +static inline int ext2fsP_is_disk_device(mode_t mode) +{ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + return S_ISBLK(mode) || S_ISCHR(mode); +#else + return S_ISBLK(mode); +#endif +} + +/* + * Badblocks list + */ +struct ext2_struct_u32_list { + int magic; + int num; + int size; + __u32 *list; + int badblocks_flags; +}; + +struct ext2_struct_u32_iterate { + int magic; + ext2_u32_list bb; + int ptr; +}; + + +/* + * Directory block iterator definition + */ +struct ext2_struct_dblist { + int magic; + ext2_filsys fs; + unsigned long long size; + unsigned long long count; + int sorted; + struct ext2_db_entry2 * list; +}; + +/* + * For directory iterators + */ +struct dir_context { + ext2_ino_t dir; + int flags; + char *buf; + unsigned int buflen; + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data); + void *priv_data; + errcode_t errcode; +}; + +/* + * Inode cache structure + */ +struct ext2_inode_cache { + void * buffer; + blk64_t buffer_blk; + int cache_last; + unsigned int cache_size; + int refcount; + struct ext2_inode_cache_ent *cache; +}; + +struct ext2_inode_cache_ent { + ext2_ino_t ino; + struct ext2_inode *inode; +}; + +/* + * NLS definitions + */ +struct ext2fs_nls_table { + int version; + const struct ext2fs_nls_ops *ops; +}; + +struct ext2fs_nls_ops { + int (*casefold)(const struct ext2fs_nls_table *charset, + const unsigned char *str, size_t len, + unsigned char *dest, size_t dlen); + int (*validate)(const struct ext2fs_nls_table *table, + char *s, size_t len, char **pos); + int (*casefold_cmp)(const struct ext2fs_nls_table *table, + const unsigned char *str1, size_t len1, + const unsigned char *str2, size_t len2); +}; + +/* Function prototypes */ + +extern int ext2fs_process_dir_block(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_block, + int ref_offset, + void *priv_data); + +extern errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino); +extern errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino); +extern int ext2fs_inline_data_dir_iterate(ext2_filsys fs, + ext2_ino_t ino, + void *priv_data); + +/* Generic numeric progress meter */ + +struct ext2fs_numeric_progress_struct { + __u64 max; + int log_max; + int skip_progress; +}; + +/* + * progress callback functions + */ +struct ext2fs_progress_ops { + void (*init)(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *label, __u64 max); + void (*update)(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + __u64 val); + void (*close)(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *message); +}; + +extern struct ext2fs_progress_ops ext2fs_numeric_progress_ops; + +extern void ext2fs_numeric_progress_init(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *label, __u64 max); +extern void ext2fs_numeric_progress_update(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + __u64 val); +extern void ext2fs_numeric_progress_close(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *message); + +/* + * 64-bit bitmap support + */ + +extern errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic, + int type, __u64 start, __u64 end, + __u64 real_end, + const char * description, + ext2fs_generic_bitmap *bmap); + +extern void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap); + +extern errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest); + +extern errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap, + __u64 new_end, + __u64 new_real_end); +extern errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap, + errcode_t neq, + __u64 end, __u64 *oend); +extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 arg); +extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 arg); +extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 arg); +extern errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bitmap, + __u64 start, unsigned int num, + void *in); +extern errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bitmap, + __u64 start, unsigned int num, + void *out); +extern void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap,const char *func); + +extern int ext2fs_mem_is_zero(const char *mem, size_t len); + +extern int ext2fs_file_block_offset_too_big(ext2_filsys fs, + struct ext2_inode *inode, + blk64_t offset); + +/* atexit support */ +typedef void (*ext2_exit_fn)(void *); +errcode_t ext2fs_add_exit_fn(ext2_exit_fn fn, void *data); +errcode_t ext2fs_remove_exit_fn(ext2_exit_fn fn, void *data); + +#define EXT2FS_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2*!!(cond)])) diff --git a/include/e2fsprogs/ext2fs/ext3_extents.h b/include/e2fsprogs/ext2fs/ext3_extents.h new file mode 100755 index 0000000..309fbc8 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext3_extents.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2003,2004 Cluster File Systems, Inc, info@clusterfs.com + * Written by Alex Tomas + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LINUX_EXT3_EXTENTS +#define _LINUX_EXT3_EXTENTS + +/* + * ext3_inode has i_block array (total 60 bytes) + * first 4 bytes are used to store: + * - tree depth (0 mean there is no tree yet. all extents in the inode) + * - number of alive extents in the inode + */ + +/* + * This is extent tail on-disk structure. + * All other extent structures are 12 bytes long. It turns out that + * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which + * covers all valid ext4 block sizes. Therefore, this tail structure can be + * crammed into the end of the block without having to rebalance the tree. + */ +struct ext3_extent_tail { + __le32 et_checksum; /* crc32c(uuid+inum+extent_block) */ +}; + +/* + * this is extent on-disk structure + * it's used at the bottom of the tree + */ +struct ext3_extent { + __le32 ee_block; /* first logical block extent covers */ + __le16 ee_len; /* number of blocks covered by extent */ + __le16 ee_start_hi; /* high 16 bits of physical block */ + __le32 ee_start; /* low 32 bigs of physical block */ +}; + +/* + * this is index on-disk structure + * it's used at all the levels, but the bottom + */ +struct ext3_extent_idx { + __le32 ei_block; /* index covers logical blocks from 'block' */ + __le32 ei_leaf; /* pointer to the physical block of the next * + * level. leaf or next index could bet here */ + __le16 ei_leaf_hi; /* high 16 bits of physical block */ + __le16 ei_unused; +}; + +/* + * each block (leaves and indexes), even inode-stored has header + */ +struct ext3_extent_header { + __le16 eh_magic; /* probably will support different formats */ + __le16 eh_entries; /* number of valid entries */ + __le16 eh_max; /* capacity of store in entries */ + __le16 eh_depth; /* has tree real underlying blocks? */ + __le32 eh_generation; /* generation of the tree */ +}; + +#define EXT3_EXT_MAGIC 0xf30a + +/* + * array of ext3_ext_path contains path to some extent + * creation/lookup routines use it for traversal/splitting/etc + * truncate uses it to simulate recursive walking + */ +struct ext3_ext_path { + __u32 p_block; + __u16 p_depth; + struct ext3_extent *p_ext; + struct ext3_extent_idx *p_idx; + struct ext3_extent_header *p_hdr; + struct buffer_head *p_bh; +}; + +/* + * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an + * initialized extent. This is 2^15 and not (2^16 - 1), since we use the + * MSB of ee_len field in the extent datastructure to signify if this + * particular extent is an initialized extent or an uninitialized (i.e. + * preallocated). + * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an + * uninitialized extent. + * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an + * uninitialized one. In other words, if MSB of ee_len is set, it is an + * uninitialized extent with only one special scenario when ee_len = 0x8000. + * In this case we can not have an uninitialized extent of zero length and + * thus we make it as a special case of initialized extent with 0x8000 length. + * This way we get better extent-to-group alignment for initialized extents. + * Hence, the maximum number of blocks we can have in an *initialized* + * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767). + */ +#define EXT_INIT_MAX_LEN (1UL << 15) +#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1) +#define EXT_MAX_EXTENT_LBLK (((__u64) 1 << 32) - 1) +#define EXT_MAX_EXTENT_PBLK (((__u64) 1 << 48) - 1) + +#define EXT_FIRST_EXTENT(__hdr__) \ + ((struct ext3_extent *) (((char *) (__hdr__)) + \ + sizeof(struct ext3_extent_header))) +#define EXT_FIRST_INDEX(__hdr__) \ + ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \ + sizeof(struct ext3_extent_header))) +#define EXT_HAS_FREE_INDEX(__path__) \ + (ext2fs_le16_to_cpu((__path__)->p_hdr->eh_entries) < \ + ext2fs_le16_to_cpu((__path__)->p_hdr->eh_max)) +#define EXT_LAST_EXTENT(__hdr__) \ + (EXT_FIRST_EXTENT((__hdr__)) + \ + ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1) +#define EXT_LAST_INDEX(__hdr__) \ + (EXT_FIRST_INDEX((__hdr__)) + \ + ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1) +#define EXT_MAX_EXTENT(__hdr__) \ + (EXT_FIRST_EXTENT((__hdr__)) + \ + ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1) +#define EXT_MAX_INDEX(__hdr__) \ + (EXT_FIRST_INDEX((__hdr__)) + \ + ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1) + +#endif /* _LINUX_EXT3_EXTENTS */ + diff --git a/include/e2fsprogs/ext2fs/ext4_acl.h b/include/e2fsprogs/ext2fs/ext4_acl.h new file mode 100755 index 0000000..8d4d974 --- /dev/null +++ b/include/e2fsprogs/ext2fs/ext4_acl.h @@ -0,0 +1,62 @@ +/* + * Ext4's on-disk acl format. From linux/fs/ext4/acl.h + */ + +#define EXT4_ACL_VERSION 0x0001 + +/* 23.2.5 acl_tag_t values */ + +#define ACL_UNDEFINED_TAG (0x00) +#define ACL_USER_OBJ (0x01) +#define ACL_USER (0x02) +#define ACL_GROUP_OBJ (0x04) +#define ACL_GROUP (0x08) +#define ACL_MASK (0x10) +#define ACL_OTHER (0x20) + +/* 23.3.6 acl_type_t values */ + +#define ACL_TYPE_ACCESS (0x8000) +#define ACL_TYPE_DEFAULT (0x4000) + +/* 23.2.7 ACL qualifier constants */ + +#define ACL_UNDEFINED_ID ((id_t)-1) + +typedef struct { + __le16 e_tag; + __le16 e_perm; + __le32 e_id; + } ext4_acl_entry; + +typedef struct { + __le16 e_tag; + __le16 e_perm; +} ext4_acl_entry_short; + +typedef struct { + __le32 a_version; +} ext4_acl_header; + + +/* Supported ACL a_version fields */ + #define POSIX_ACL_XATTR_VERSION 0x0002 + +typedef struct { + __le16 e_tag; + __le16 e_perm; + __le32 e_id; +} posix_acl_xattr_entry; + +typedef struct { + __le32 a_version; +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + posix_acl_xattr_entry a_entries[0]; +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic pop +#endif +} posix_acl_xattr_header; + diff --git a/include/e2fsprogs/ext2fs/fast_commit.h b/include/e2fsprogs/ext2fs/fast_commit.h new file mode 100755 index 0000000..4ad38f1 --- /dev/null +++ b/include/e2fsprogs/ext2fs/fast_commit.h @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __FAST_COMMIT_H__ +#define __FAST_COMMIT_H__ + +#include "jfs_compat.h" + +/* + * Note this file is present in e2fsprogs/lib/ext2fs/fast_commit.h and + * linux/fs/ext4/fast_commit.h. These file should always be byte identical. + */ + +/* Fast commit tags */ +#define EXT4_FC_TAG_ADD_RANGE 0x0001 +#define EXT4_FC_TAG_DEL_RANGE 0x0002 +#define EXT4_FC_TAG_CREAT 0x0003 +#define EXT4_FC_TAG_LINK 0x0004 +#define EXT4_FC_TAG_UNLINK 0x0005 +#define EXT4_FC_TAG_INODE 0x0006 +#define EXT4_FC_TAG_PAD 0x0007 +#define EXT4_FC_TAG_TAIL 0x0008 +#define EXT4_FC_TAG_HEAD 0x0009 + +#define EXT4_FC_SUPPORTED_FEATURES 0x0 + +/* On disk fast commit tlv value structures */ + +/* Fast commit on disk tag length structure */ +struct ext4_fc_tl { + __le16 fc_tag; + __le16 fc_len; +}; + +/* Value structure for tag EXT4_FC_TAG_HEAD. */ +struct ext4_fc_head { + __le32 fc_features; + __le32 fc_tid; +}; + +/* Value structure for EXT4_FC_TAG_ADD_RANGE. */ +struct ext4_fc_add_range { + __le32 fc_ino; + __u8 fc_ex[12]; +}; + +/* Value structure for tag EXT4_FC_TAG_DEL_RANGE. */ +struct ext4_fc_del_range { + __le32 fc_ino; + __le32 fc_lblk; + __le32 fc_len; +}; + +/* + * This is the value structure for tags EXT4_FC_TAG_CREAT, EXT4_FC_TAG_LINK + * and EXT4_FC_TAG_UNLINK. + */ +struct ext4_fc_dentry_info { + __le32 fc_parent_ino; + __le32 fc_ino; + __u8 fc_dname[0]; +}; + +/* Value structure for EXT4_FC_TAG_INODE and EXT4_FC_TAG_INODE_PARTIAL. */ +struct ext4_fc_inode { + __le32 fc_ino; + __u8 fc_raw_inode[0]; +}; + +/* Value structure for tag EXT4_FC_TAG_TAIL. */ +struct ext4_fc_tail { + __le32 fc_tid; + __le32 fc_crc; +}; + +/* + * Fast commit reason codes + */ +enum { + /* + * Commit status codes: + */ + EXT4_FC_REASON_OK = 0, + EXT4_FC_REASON_INELIGIBLE, + EXT4_FC_REASON_ALREADY_COMMITTED, + EXT4_FC_REASON_FC_START_FAILED, + EXT4_FC_REASON_FC_FAILED, + + /* + * Fast commit ineligiblity reasons: + */ + EXT4_FC_REASON_XATTR = 0, + EXT4_FC_REASON_CROSS_RENAME, + EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, + EXT4_FC_REASON_NOMEM, + EXT4_FC_REASON_SWAP_BOOT, + EXT4_FC_REASON_RESIZE, + EXT4_FC_REASON_RENAME_DIR, + EXT4_FC_REASON_FALLOC_RANGE, + EXT4_FC_REASON_INODE_JOURNAL_DATA, + EXT4_FC_COMMIT_FAILED, + EXT4_FC_REASON_MAX +}; + +#ifdef __KERNEL__ +/* + * In memory list of dentry updates that are performed on the file + * system used by fast commit code. + */ +struct ext4_fc_dentry_update { + int fcd_op; /* Type of update create / unlink / link */ + int fcd_parent; /* Parent inode number */ + int fcd_ino; /* Inode number */ + struct qstr fcd_name; /* Dirent name */ + unsigned char fcd_iname[DNAME_INLINE_LEN]; /* Dirent name string */ + struct list_head fcd_list; +}; + +struct ext4_fc_stats { + unsigned int fc_ineligible_reason_count[EXT4_FC_REASON_MAX]; + unsigned long fc_num_commits; + unsigned long fc_ineligible_commits; + unsigned long fc_numblks; +}; + +#define EXT4_FC_REPLAY_REALLOC_INCREMENT 4 + +/* + * Physical block regions added to different inodes due to fast commit + * recovery. These are set during the SCAN phase. During the replay phase, + * our allocator excludes these from its allocation. This ensures that + * we don't accidentally allocating a block that is going to be used by + * another inode. + */ +struct ext4_fc_alloc_region { + ext4_lblk_t lblk; + ext4_fsblk_t pblk; + int ino, len; +}; + +/* + * Fast commit replay state. + */ +struct ext4_fc_replay_state { + int fc_replay_num_tags; + int fc_replay_expected_off; + int fc_current_pass; + int fc_cur_tag; + int fc_crc; + struct ext4_fc_alloc_region *fc_regions; + int fc_regions_size, fc_regions_used, fc_regions_valid; + int *fc_modified_inodes; + int fc_modified_inodes_used, fc_modified_inodes_size; +}; + +#define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1) +#endif + +static inline const char *tag2str(__u16 tag) +{ + switch (tag) { + case EXT4_FC_TAG_LINK: + return "ADD_ENTRY"; + case EXT4_FC_TAG_UNLINK: + return "DEL_ENTRY"; + case EXT4_FC_TAG_ADD_RANGE: + return "ADD_RANGE"; + case EXT4_FC_TAG_CREAT: + return "CREAT_DENTRY"; + case EXT4_FC_TAG_DEL_RANGE: + return "DEL_RANGE"; + case EXT4_FC_TAG_INODE: + return "INODE"; + case EXT4_FC_TAG_PAD: + return "PAD"; + case EXT4_FC_TAG_TAIL: + return "TAIL"; + case EXT4_FC_TAG_HEAD: + return "HEAD"; + default: + return "ERROR"; + } +} + +/* Get length of a particular tlv */ +static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl) +{ + return le16_to_cpu(tl->fc_len); +} + +#endif /* __FAST_COMMIT_H__ */ diff --git a/include/e2fsprogs/ext2fs/fiemap.h b/include/e2fsprogs/ext2fs/fiemap.h new file mode 100755 index 0000000..33ab8fb --- /dev/null +++ b/include/e2fsprogs/ext2fs/fiemap.h @@ -0,0 +1,93 @@ +/* + * FS_IOC_FIEMAP ioctl infrastructure. + * + * Some portions copyright (C) 2007 Cluster File Systems, Inc + * + * Authors: Mark Fasheh + * Kalpak Shah + * Andreas Dilger + */ + +#ifndef _LINUX_FIEMAP_H +#define _LINUX_FIEMAP_H + +struct fiemap_extent { + __u64 fe_logical; /* logical offset in bytes for the start of + * the extent from the beginning of the file */ + __u64 fe_physical; /* physical offset in bytes for the start + * of the extent from the beginning of the disk */ + __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]; +}; + +struct fiemap { + __u64 fm_start; /* logical offset (inclusive) at + * which to start mapping (in) */ + __u64 fm_length; /* logical length of mapping which + * userspace wants (in) */ + __u32 fm_flags; /* FIEMAP_FLAG_* flags for request (in/out) */ + __u32 fm_mapped_extents;/* number of extents that were mapped (out) */ + __u32 fm_extent_count; /* size of fm_extents array (in) */ + __u32 fm_reserved; +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + struct fiemap_extent fm_extents[0]; /* array of mapped extents (out) */ +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic pop +#endif +}; + +#if defined(__linux__) && !defined(FS_IOC_FIEMAP) +#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) +#endif + +#if defined(__linux__) && !defined(FS_IOC_GETSTATE) +#define EXT4_IOC_GETSTATE _IOW('f', 41, __u32) +#endif + +#if defined(__linux__) && !defined(EXT4_IOC_GET_ES_CACHE) +#define EXT4_IOC_GET_ES_CACHE _IOWR('f', 42, struct fiemap) +#endif + +#if defined(__linux__) && !defined(EXT4_STATE_FLAG_EXT_PRECACHED) +#define EXT4_STATE_FLAG_EXT_PRECACHED 0x00000001 +#endif + +#define FIEMAP_MAX_OFFSET (~0ULL) + +#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */ +#define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute tree */ +#define FIEMAP_FLAG_CACHE 0x00000004 /* request caching of the extents */ + +#define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR) + +#define FIEMAP_EXTENT_LAST 0x00000001 /* Last extent in file. */ +#define FIEMAP_EXTENT_UNKNOWN 0x00000002 /* Data location unknown. */ +#define FIEMAP_EXTENT_DELALLOC 0x00000004 /* Location still pending. + * Sets EXTENT_UNKNOWN. */ +#define FIEMAP_EXTENT_ENCODED 0x00000008 /* Data can not be read + * while fs is unmounted */ +#define FIEMAP_EXTENT_DATA_ENCRYPTED 0x00000080 /* Data is encrypted by fs. + * Sets EXTENT_NO_BYPASS. */ +#define FIEMAP_EXTENT_NOT_ALIGNED 0x00000100 /* Extent offsets may not be + * block aligned. */ +#define FIEMAP_EXTENT_DATA_INLINE 0x00000200 /* Data mixed with metadata. + * Sets EXTENT_NOT_ALIGNED.*/ +#define FIEMAP_EXTENT_DATA_TAIL 0x00000400 /* Multiple files in block. + * Sets EXTENT_NOT_ALIGNED.*/ +#define FIEMAP_EXTENT_UNWRITTEN 0x00000800 /* Space allocated, but + * no data (i.e. zero). */ +#define FIEMAP_EXTENT_MERGED 0x00001000 /* File does not natively + * support extents. Result + * merged for efficiency. */ +#define FIEMAP_EXTENT_SHARED 0x00002000 /* Space shared with other + * files. */ + +#define EXT4_FIEMAP_EXTENT_HOLE 0x08000000 /* Entry in extent status + cache for a hole*/ + +#endif /* _LINUX_FIEMAP_H */ diff --git a/include/e2fsprogs/ext2fs/hashmap.h b/include/e2fsprogs/ext2fs/hashmap.h new file mode 100755 index 0000000..0c09d2b --- /dev/null +++ b/include/e2fsprogs/ext2fs/hashmap.h @@ -0,0 +1,42 @@ +#ifndef HASHMAP_H +# define HASHMAP_H + +# include +# include + +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GNUC_PREREQ(maj, min) 0 +#endif +#endif + +struct ext2fs_hashmap; + +struct ext2fs_hashmap_entry { + void *data; + const void *key; + size_t key_len; + struct ext2fs_hashmap_entry *next; + struct ext2fs_hashmap_entry *list_next; + struct ext2fs_hashmap_entry *list_prev; +}; + +struct ext2fs_hashmap *ext2fs_hashmap_create( + uint32_t(*hash_fct)(const void*, size_t), + void(*free_fct)(void*), size_t size); +int ext2fs_hashmap_add(struct ext2fs_hashmap *h, + void *data, const void *key,size_t key_len); +void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key, + size_t key_len); +void *ext2fs_hashmap_iter_in_order(struct ext2fs_hashmap *h, + struct ext2fs_hashmap_entry **it); +void ext2fs_hashmap_del(struct ext2fs_hashmap *h, + struct ext2fs_hashmap_entry *e); +void ext2fs_hashmap_free(struct ext2fs_hashmap *h); + +uint32_t ext2fs_djb2_hash(const void *str, size_t size); + +#endif /* !HASHMAP_H */ diff --git a/include/e2fsprogs/ext2fs/irel.h b/include/e2fsprogs/ext2fs/irel.h new file mode 100755 index 0000000..23741ba --- /dev/null +++ b/include/e2fsprogs/ext2fs/irel.h @@ -0,0 +1,114 @@ +/* + * irel.h + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +struct ext2_inode_reference { + blk64_t block; + __u16 offset; +}; + +struct ext2_inode_relocate_entry { + ext2_ino_t new; + ext2_ino_t orig; + __u16 flags; + __u16 max_refs; +}; + +typedef struct ext2_inode_relocation_table *ext2_irel; + +struct ext2_inode_relocation_table { + __u32 magic; + char *name; + ext2_ino_t current; + void *priv_data; + + /* + * Add an inode relocation entry. + */ + errcode_t (*put)(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); + /* + * Get an inode relocation entry. + */ + errcode_t (*get)(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); + + /* + * Get an inode relocation entry by its original inode number + */ + errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); + + /* + * Initialize for iterating over the inode relocation entries. + */ + errcode_t (*start_iter)(ext2_irel irel); + + /* + * The iterator function for the inode relocation entries. + * Returns an inode number of 0 when out of entries. + */ + errcode_t (*next)(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); + + /* + * Add an inode reference (i.e., note the fact that a + * particular block/offset contains a reference to an inode) + */ + errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref); + + /* + * Initialize for iterating over the inode references for a + * particular inode. + */ + errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino); + + /* + * The iterator function for the inode references for an + * inode. The references for only one inode can be iterator + * over at a time, as the iterator state is stored in ext2_irel. + */ + errcode_t (*next_ref)(ext2_irel irel, + struct ext2_inode_reference *ref); + + /* + * Move the inode relocation table from one inode number to + * another. Note that the inode references also must move. + */ + errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); + + /* + * Remove an inode relocation entry, along with all of the + * inode references. + */ + errcode_t (*delete)(ext2_irel irel, ext2_ino_t old); + + /* + * Free the inode relocation table. + */ + errcode_t (*free)(ext2_irel irel); +}; + +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, + ext2_irel *irel); + +#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent)) +#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent)) +#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \ + ((irel)->get_by_orig((irel), orig, old, ent)) +#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel))) +#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent)) +#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref)) +#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino)) +#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref)) +#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new)) +#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old)) +#define ext2fs_irel_free(irel) ((irel)->free((irel))) diff --git a/include/e2fsprogs/ext2fs/jfs_compat.h b/include/e2fsprogs/ext2fs/jfs_compat.h new file mode 100755 index 0000000..0e96b56 --- /dev/null +++ b/include/e2fsprogs/ext2fs/jfs_compat.h @@ -0,0 +1,113 @@ + +#ifndef _JFS_COMPAT_H +#define _JFS_COMPAT_H + +#include "kernel-list.h" +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +#include + +#define printk printf +#define KERN_ERR "" +#define KERN_DEBUG "" + +#define REQ_OP_READ 0 +#define REQ_OP_WRITE 1 + +#define cpu_to_le16(x) ext2fs_cpu_to_le16(x) +#define cpu_to_be16(x) ext2fs_cpu_to_be16(x) +#define cpu_to_le32(x) ext2fs_cpu_to_le32(x) +#define cpu_to_be32(x) ext2fs_cpu_to_be32(x) +#define cpu_to_le64(x) ext2fs_cpu_to_le64(x) +#define cpu_to_be64(x) ext2fs_cpu_to_be64(x) + +#define le16_to_cpu(x) ext2fs_le16_to_cpu(x) +#define be16_to_cpu(x) ext2fs_be16_to_cpu(x) +#define le32_to_cpu(x) ext2fs_le32_to_cpu(x) +#define be32_to_cpu(x) ext2fs_be32_to_cpu(x) +#define le64_to_cpu(x) ext2fs_le64_to_cpu(x) +#define be64_to_cpu(x) ext2fs_be64_to_cpu(x) + +typedef unsigned int tid_t; +typedef struct journal_s journal_t; +typedef struct kdev_s *kdev_t; + +struct buffer_head; +struct inode; + +typedef unsigned int gfp_t; +#define GFP_KERNEL 0 +#define GFP_NOFS 0 +#define __GFP_NOFAIL 0 +#define JBD2_TAG_SIZE32 JBD_TAG_SIZE32 +#define JBD2_BARRIER 0 +typedef __u64 u64; +#define put_bh(x) brelse(x) + +#define crc32_be(x, y, z) ext2fs_crc32_be((x), (y), (z)) +#define spin_lock_init(x) +#define spin_lock(x) +#define spin_unlock(x) +#define SLAB_HWCACHE_ALIGN 0 +#define SLAB_TEMPORARY 0 +#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\ + sizeof(struct __struct), __alignof__(struct __struct),\ + (__flags), NULL) + +#define blkdev_issue_flush(kdev) sync_blockdev(kdev) +#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) +#define pr_emerg(fmt) +#define pr_err(...) + +enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY}; + +#define JBD2_FC_REPLAY_STOP 0 +#define JBD2_FC_REPLAY_CONTINUE 1 + +struct journal_s +{ + unsigned long j_flags; + int j_errno; + struct buffer_head * j_sb_buffer; + struct journal_superblock_s *j_superblock; + int j_format_version; + unsigned long j_head; + unsigned long j_tail; + unsigned long j_fc_first; + unsigned long j_fc_off; + unsigned long j_fc_last; + unsigned long j_free; + unsigned long j_first, j_last; + kdev_t j_dev; + kdev_t j_fs_dev; + int j_blocksize; + unsigned int j_blk_offset; + unsigned int j_total_len; + struct inode * j_inode; + tid_t j_tail_sequence; + tid_t j_transaction_sequence; + __u8 j_uuid[16]; + struct jbd2_revoke_table_s *j_revoke; + struct jbd2_revoke_table_s *j_revoke_table[2]; + tid_t j_failed_commit; + __u32 j_csum_seed; + int (*j_fc_replay_callback)(struct journal_s *journal, + struct buffer_head *bh, + enum passtype pass, int off, + tid_t expected_tid); + +}; + +#define is_journal_abort(x) 0 + +#define BUFFER_TRACE(bh, info) do {} while (0) + +/* Need this so we can compile with configure --enable-gcc-wall */ +#ifdef NO_INLINE_FUNCS +#define inline +#endif + +#endif /* _JFS_COMPAT_H */ diff --git a/include/e2fsprogs/ext2fs/kernel-jbd.h b/include/e2fsprogs/ext2fs/kernel-jbd.h new file mode 100755 index 0000000..e569500 --- /dev/null +++ b/include/e2fsprogs/ext2fs/kernel-jbd.h @@ -0,0 +1,456 @@ +/* + * linux/include/linux/jbd.h + * + * Written by Stephen C. Tweedie + * + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * Definitions for transaction data structures for the buffer cache + * filesystem journaling support. + */ + +#ifndef _LINUX_JBD_H +#define _LINUX_JBD_H + +#include "jfs_compat.h" +#define JFS_DEBUG +#define jfs_debug jbd_debug + +#ifndef __GNUC__ +#define __FUNCTION__ "" +#endif + +#define journal_oom_retry 0 + +#ifdef CONFIG_JBD_DEBUG +/* + * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal + * consistency checks. By default we don't do this unless + * CONFIG_JBD_DEBUG is on. + */ +#define JBD_EXPENSIVE_CHECKING +extern int journal_enable_debug; +#else +#define journal_enable_debug (-1) +#endif /* !CONFIG_JBD_DEBUG */ + +#ifdef __STDC__ +#define jbd_debug(n, f, a...) \ + do { \ + if ((n) <= journal_enable_debug) { \ + printk (KERN_DEBUG "(%s, %d): %s: ", \ + __FILE__, __LINE__, __FUNCTION__); \ + printk (f, ## a); \ + } \ + } while (0) +#else +#define jbd_debug(x) /* AIX doesn't do STDC */ +#endif /* !__STDC__ */ + +extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); +#define jbd_kmalloc(size, flags) \ + __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) +#define jbd_rep_kmalloc(size, flags) \ + __jbd_kmalloc(__FUNCTION__, (size), (flags), 1) + +#define JBD2_MIN_JOURNAL_BLOCKS 1024 +#define JBD2_DEFAULT_FAST_COMMIT_BLOCKS 256 + +/* + * Internal structures used by the logging mechanism: + */ + +#define JBD2_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ + +/* + * On-disk structures + */ + +/* + * Descriptor block types: + */ + +#define JBD2_DESCRIPTOR_BLOCK 1 +#define JBD2_COMMIT_BLOCK 2 +#define JBD2_SUPERBLOCK_V1 3 +#define JBD2_SUPERBLOCK_V2 4 +#define JBD2_REVOKE_BLOCK 5 +#define JBD2_FC_BLOCK 6 + +/* + * Standard header for all descriptor blocks: + */ +typedef struct journal_header_s +{ + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; +} journal_header_t; + +/* + * Checksum types. + */ +#define JBD2_CRC32_CHKSUM 1 +#define JBD2_MD5_CHKSUM 2 +#define JBD2_SHA1_CHKSUM 3 +#define JBD2_CRC32C_CHKSUM 4 + +#define JBD2_CRC32_CHKSUM_SIZE 4 + +#define JBD2_CHECKSUM_BYTES (32 / sizeof(__u32)) +/* + * Commit block header for storing transactional checksums: + * + * NOTE: If FEATURE_COMPAT_CHECKSUM (checksum v1) is set, the h_chksum* + * fields are used to store a checksum of the descriptor and data blocks. + * + * If FEATURE_INCOMPAT_CSUM_V2 (checksum v2) is set, then the h_chksum + * field is used to store crc32c(uuid+commit_block). Each journal metadata + * block gets its own checksum, and data block checksums are stored in + * journal_block_tag (in the descriptor). The other h_chksum* fields are + * not used. + * + * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses + * journal_block_tag3_t to store a full 32-bit checksum. Everything else + * is the same as v2. + * + * Checksum v1, v2, and v3 are mutually exclusive features. + */ +struct commit_header { + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; + unsigned char h_chksum_type; + unsigned char h_chksum_size; + unsigned char h_padding[2]; + __be32 h_chksum[JBD2_CHECKSUM_BYTES]; + __be64 h_commit_sec; + __be32 h_commit_nsec; +}; + +/* + * The block tag: used to describe a single buffer in the journal + */ +typedef struct journal_block_tag3_s +{ + __be32 t_blocknr; /* The on-disk block number */ + __be32 t_flags; /* See below */ + __be32 t_blocknr_high; /* most-significant high 32bits. */ + __be32 t_checksum; /* crc32c(uuid+seq+block) */ +} journal_block_tag3_t; + +typedef struct journal_block_tag_s +{ + __be32 t_blocknr; /* The on-disk block number */ + __be16 t_checksum; /* truncated crc32c(uuid+seq+block) */ + __be16 t_flags; /* See below */ + __be32 t_blocknr_high; /* most-significant high 32bits. */ +} journal_block_tag_t; + +/* Tail of descriptor or revoke block, for checksumming */ +struct jbd2_journal_block_tail { + __be32 t_checksum; +}; + +/* + * The revoke descriptor: used on disk to describe a series of blocks to + * be revoked from the log + */ +typedef struct journal_revoke_header_s +{ + journal_header_t r_header; + __be32 r_count; /* Count of bytes used in the block */ +} jbd2_journal_revoke_header_t; + +/* Definitions for the journal tag flags word: */ +#define JBD2_FLAG_ESCAPE 1 /* on-disk block is escaped */ +#define JBD2_FLAG_SAME_UUID 2 /* block has same uuid as previous */ +#define JBD2_FLAG_DELETED 4 /* block deleted by this transaction */ +#define JBD2_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ + + +#define UUID_SIZE 16 +#define JBD2_USERS_MAX 48 +#define JBD2_USERS_SIZE (UUID_SIZE * JBD2_USERS_MAX) +/* + * The journal superblock. All fields are in big-endian byte order. + */ +typedef struct journal_superblock_s +{ +/* 0x0000 */ + journal_header_t s_header; + +/* 0x000C */ + /* Static information describing the journal */ + __be32 s_blocksize; /* journal device blocksize */ + __be32 s_maxlen; /* total blocks in journal file */ + __be32 s_first; /* first block of log information */ + +/* 0x0018 */ + /* Dynamic information describing the current state of the log */ + __be32 s_sequence; /* first commit ID expected in log */ + __be32 s_start; /* blocknr of start of log */ + +/* 0x0020 */ + /* Error value, as set by journal_abort(). */ + __s32 s_errno; + +/* 0x0024 */ + /* Remaining fields are only valid in a version-2 superblock */ + __be32 s_feature_compat; /* compatible feature set */ + __be32 s_feature_incompat; /* incompatible feature set */ + __be32 s_feature_ro_compat; /* readonly-compatible feature set */ +/* 0x0030 */ + __u8 s_uuid[16]; /* 128-bit uuid for journal */ + +/* 0x0040 */ + __be32 s_nr_users; /* Nr of filesystems sharing log */ + + __be32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ + +/* 0x0048 */ + __be32 s_max_transaction; /* Limit of journal blocks per trans.*/ + __be32 s_max_trans_data; /* Limit of data blocks per trans. */ + +/* 0x0050 */ + __u8 s_checksum_type; /* checksum type */ + __u8 s_padding2[3]; +/* 0x0054 */ + __be32 s_num_fc_blks; /* Number of fast commit blocks */ +/* 0x0058 */ + __be32 s_padding[41]; + __be32 s_checksum; /* crc32c(superblock) */ + +/* 0x0100 */ + __u8 s_users[JBD2_USERS_SIZE]; /* ids of all fs'es sharing the log */ + +/* 0x0400 */ +} journal_superblock_t; + +#define JBD2_HAS_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask)))) +#define JBD2_HAS_RO_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask)))) +#define JBD2_HAS_INCOMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask)))) + +#define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 + +#define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 +#define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 +#define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 +#define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 +#define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 +#define JBD2_FEATURE_INCOMPAT_FAST_COMMIT 0x00000020 + +/* Features known to this kernel version: */ +#define JBD2_KNOWN_COMPAT_FEATURES 0 +#define JBD2_KNOWN_ROCOMPAT_FEATURES 0 +#define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE|\ + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT| \ + JBD2_FEATURE_INCOMPAT_64BIT|\ + JBD2_FEATURE_INCOMPAT_CSUM_V2| \ + JBD2_FEATURE_INCOMPAT_CSUM_V3 | \ + JBD2_FEATURE_INCOMPAT_FAST_COMMIT) + +#ifdef NO_INLINE_FUNCS +extern size_t journal_tag_bytes(journal_t *journal); +extern int jbd2_journal_has_csum_v2or3(journal_t *journal); +extern int jbd2_journal_get_num_fc_blks(journal_superblock_t *jsb); +extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused)); +extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); +#endif + +#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +#ifdef E2FSCK_INCLUDE_INLINE_FUNCS +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ extern inline +#else +#define _INLINE_ inline +#endif +#else /* !E2FSCK_INCLUDE_INLINE FUNCS */ +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ inline +#else /* not C99 */ +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif /* __GNUC__ */ +#endif /* __STDC_VERSION__ >= 199901L */ +#endif /* INCLUDE_INLINE_FUNCS */ + +/* journal feature predicate functions */ +#define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j); \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & \ + ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname)) != 0); \ +} \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_compat |= \ + ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ +} \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_compat &= \ + ~ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ +} + +#define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j); \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & \ + ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname)) != 0); \ +} \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_ro_compat |= \ + ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ +} \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_ro_compat &= \ + ~ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ +} + +#define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j); \ +_INLINE_ int jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & \ + ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname)) != 0); \ +} \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_incompat |= \ + ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ +} \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ +_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_incompat &= \ + ~ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ +} + +#else +#define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ +extern int jbd2_has_feature_##name(journal_t *j); \ +extern void jbd2_set_feature_##name(journal_t *j); \ +extern void jbd2_clear_feature_##name(journal_t *j); + +#define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ +extern int jbd2_has_feature_##name(journal_t *j); \ +extern void jbd2_set_feature_##name(journal_t *j); \ +extern void jbd2_clear_feature_##name(journal_t *j); + +#define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ +extern int jbd2_has_feature_##name(journal_t *j); \ +extern void jbd2_set_feature_##name(journal_t *j); \ +extern void jbd2_clear_feature_##name(journal_t *j); + +#endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ + +JBD2_FEATURE_COMPAT_FUNCS(checksum, CHECKSUM) + +JBD2_FEATURE_INCOMPAT_FUNCS(revoke, REVOKE) +JBD2_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT) +JBD2_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT) +JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2) +JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) +JBD2_FEATURE_INCOMPAT_FUNCS(fast_commit, FAST_COMMIT) + +#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +/* + * helper functions to deal with 32 or 64bit block numbers. + */ +_INLINE_ size_t journal_tag_bytes(journal_t *journal) +{ + size_t sz; + + if (jbd2_has_feature_csum3(journal)) + return sizeof(journal_block_tag3_t); + + sz = sizeof(journal_block_tag_t); + + if (jbd2_has_feature_csum2(journal)) + sz += sizeof(__u16); + + if (jbd2_has_feature_64bit(journal)) + return sz; + + return sz - sizeof(__u32); +} + +_INLINE_ int jbd2_journal_has_csum_v2or3(journal_t *journal) +{ + if (jbd2_has_feature_csum2(journal) || jbd2_has_feature_csum3(journal)) + return 1; + + return 0; +} + +_INLINE_ int jbd2_journal_get_num_fc_blks(journal_superblock_t *jsb) +{ + int num_fc_blocks = be32_to_cpu(jsb->s_num_fc_blks); + + return num_fc_blocks ? num_fc_blocks : JBD2_DEFAULT_FAST_COMMIT_BLOCKS; +} + +/* Comparison functions for transaction IDs: perform comparisons using + * modulo arithmetic so that they work over sequence number wraps. */ + +_INLINE_ int tid_gt(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference > 0); +} + +_INLINE_ int tid_geq(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference >= 0); +} +#endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ + +#undef _INLINE_ + +extern int journal_blocks_per_page(struct inode *inode); + +/* + * Definitions which augment the buffer_head layer + */ + +/* journaling buffer types */ +#define BJ_None 0 /* Not journaled */ +#define BJ_SyncData 1 /* Normal data: flush before commit */ +#define BJ_AsyncData 2 /* writepage data: wait on it before commit */ +#define BJ_Metadata 3 /* Normal journaled metadata */ +#define BJ_Forget 4 /* Buffer superseded by this transaction */ +#define BJ_IO 5 /* Buffer is for temporary IO use */ +#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ +#define BJ_LogCtl 7 /* Buffer contains log descriptors */ +#define BJ_Reserved 8 /* Buffer is reserved for access by journal */ +#define BJ_Types 9 + +extern int jbd_blocks_per_page(struct inode *inode); + +#endif /* _LINUX_JBD_H */ diff --git a/include/e2fsprogs/ext2fs/kernel-list.h b/include/e2fsprogs/ext2fs/kernel-list.h new file mode 100755 index 0000000..dd7b8e0 --- /dev/null +++ b/include/e2fsprogs/ext2fs/kernel-list.h @@ -0,0 +1,111 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include "compiler.h" + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) +#define __inline__ +#endif + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/* + * Insert a new entry after the specified head.. + */ +static __inline__ void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/* + * Insert a new entry at the tail + */ +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +static __inline__ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static __inline__ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/* + * Splice in "list" into "head" + */ +static __inline__ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#endif diff --git a/include/e2fsprogs/ext2fs/qcow2.h b/include/e2fsprogs/ext2fs/qcow2.h new file mode 100755 index 0000000..b649c9c --- /dev/null +++ b/include/e2fsprogs/ext2fs/qcow2.h @@ -0,0 +1,114 @@ +/* + * qcow2.h --- structures and function prototypes for qcow2.c to generate + * qcow2 formatted disk images. This format is used originally by QEMU + * for virtual machines, and stores the filesystem data on disk in a + * packed format to avoid creating sparse image files that need lots of + * seeking to read and write. + * + * The qcow2 format supports zlib compression, but that is not yet + * implemented. + * + * It is possible to directly mount a qcow2 image using qemu-nbd: + * + * [root]# modprobe nbd max_part=63 + * [root]# qemu-nbd -c /dev/nbd0 image.img + * [root]# mount /dev/nbd0p1 /mnt/qemu + * + * Format details at http://people.gnome.org/~markmc/qcow-image-format.html + * + * Copyright (C) 2010 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* Number of l2 tables in memory before writeback */ +#define L2_CACHE_PREALLOC 512 + + +#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) +#define QCOW_VERSION 2 +#define QCOW_OFLAG_COPIED (1ULL << 63) +#define QCOW_OFLAG_COMPRESSED (1ULL << 62) + +#define QCOW_COMPRESSED 1 +#define QCOW_ENCRYPTED 2 +#define QCOW_CORRUPTED 3 + +struct ext2_qcow2_hdr { + __u32 magic; + __u32 version; + + __u64 backing_file_offset; + __u32 backing_file_size; + + __u32 cluster_bits; + __u64 size; + __u32 crypt_method; + + __u32 l1_size; + __u64 l1_table_offset; + + __u64 refcount_table_offset; + __u32 refcount_table_clusters; + + __u32 nb_snapshots; + __u64 snapshots_offset; +}; + +typedef struct ext2_qcow2_l2_table L2_CACHE_HEAD; + +struct ext2_qcow2_l2_table { + __u32 l1_index; + __u64 offset; + __u64 *data; + L2_CACHE_HEAD *next; +}; + +struct ext2_qcow2_l2_cache { + L2_CACHE_HEAD *used_head; + L2_CACHE_HEAD *used_tail; + L2_CACHE_HEAD *free_head; + __u32 free; + __u32 count; + __u64 next_offset; +}; + +struct ext2_qcow2_refcount { + __u64 *refcount_table; + __u64 refcount_table_offset; + __u64 refcount_block_offset; + + __u32 refcount_table_clusters; + __u32 refcount_table_index; + __u32 refcount_block_index; + + __u16 *refcount_block; +}; + +struct ext2_qcow2_image { + int fd; + struct ext2_qcow2_hdr *hdr; + struct ext2_qcow2_l2_cache *l2_cache; + struct ext2_qcow2_refcount refcount; + __u32 cluster_size; + __u32 cluster_bits; + __u32 l1_size; + __u32 l2_size; + + __u64 *l1_table; + __u64 l2_offset; + __u64 l1_offset; + __u64 image_size; +}; + +/* Function prototypes */ + +/* qcow2.c */ + +/* Functions for converting qcow2 image into raw image */ +struct ext2_qcow2_hdr *qcow2_read_header(int); +int qcow2_write_raw_image(int, int, struct ext2_qcow2_hdr *); + diff --git a/include/e2fsprogs/ext2fs/rbtree.h b/include/e2fsprogs/ext2fs/rbtree.h new file mode 100755 index 0000000..790f5c1 --- /dev/null +++ b/include/e2fsprogs/ext2fs/rbtree.h @@ -0,0 +1,183 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop dramatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + Some example of insert and search follows here. The search is a plain + normal search over an ordered tree. The insert instead must be implemented + in two steps: First, the code must insert the element in order as a red leaf + in the tree, and then the support library function rb_insert_color() must + be called. Such function will do the not trivial work to rebalance the + rbtree, if necessary. + +----------------------------------------------------------------------- +static inline struct page * rb_search_page_cache(struct inode * inode, + unsigned long offset) +{ + struct rb_node * n = inode->i_rb_page_cache.rb_node; + struct page * page; + + while (n) + { + page = rb_entry(n, struct page, rb_page_cache); + + if (offset < page->offset) + n = n->rb_left; + else if (offset > page->offset) + n = n->rb_right; + else + return page; + } + return NULL; +} + +static inline struct page * __rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct rb_node ** p = &inode->i_rb_page_cache.rb_node; + struct rb_node * parent = NULL; + struct page * page; + + while (*p) + { + parent = *p; + page = rb_entry(parent, struct page, rb_page_cache); + + if (offset < page->offset) + p = &(*p)->rb_left; + else if (offset > page->offset) + p = &(*p)->rb_right; + else + return page; + } + + rb_link_node(node, parent, p); + + return NULL; +} + +static inline struct page * rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct page * ret; + if ((ret = __rb_insert_page_cache(inode, offset, node))) + goto out; + rb_insert_color(node, &inode->i_rb_page_cache); + out: + return ret; +} +----------------------------------------------------------------------- +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +#include +#include +#include "compiler.h" + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +struct rb_node +{ + uintptr_t rb_parent_color; +#define RB_RED 0 +#define RB_BLACK 1 + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + struct rb_node *rb_node; +}; + + +#define ext2fs_rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define ext2fs_rb_color(r) ((r)->rb_parent_color & 1) +#define ext2fs_rb_is_red(r) (!ext2fs_rb_color(r)) +#define ext2fs_rb_is_black(r) ext2fs_rb_color(r) +#define ext2fs_rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define ext2fs_rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) + +static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p; +} +static inline void ext2fs_rb_set_color(struct rb_node *rb, int color) +{ + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; +} + +#define RB_ROOT (struct rb_root) { NULL, } +#define ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member) + +static inline int ext2fs_rb_empty_root(struct rb_root *root) +{ + return root->rb_node == NULL; +} + +static inline int ext2fs_rb_empty_node(struct rb_node *node) +{ + return ext2fs_rb_parent(node) == node; +} + +static inline void ext2fs_rb_clear_node(struct rb_node *node) +{ + ext2fs_rb_set_parent(node, node); +} + +extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *); +extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *ext2fs_rb_next(struct rb_node *); +extern struct rb_node *ext2fs_rb_prev(struct rb_node *); +extern struct rb_node *ext2fs_rb_first(const struct rb_root *); +extern struct rb_node *ext2fs_rb_last(const struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void ext2fs_rb_link_node(struct rb_node * node, + struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent_color = (uintptr_t)parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +#endif /* _LINUX_RBTREE_H */ diff --git a/include/e2fsprogs/ext2fs/tdb.h b/include/e2fsprogs/ext2fs/tdb.h new file mode 100755 index 0000000..de7aa33 --- /dev/null +++ b/include/e2fsprogs/ext2fs/tdb.h @@ -0,0 +1,215 @@ +#ifndef __TDB_H__ +#define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* flags to tdb_store() */ +#define TDB_REPLACE 1 +#define TDB_INSERT 2 +#define TDB_MODIFY 3 + +/* flags for tdb_open() */ +#define TDB_DEFAULT 0 /* just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 +#define TDB_INTERNAL 2 /* don't store on disk */ +#define TDB_NOLOCK 4 /* don't do any locking */ +#define TDB_NOMMAP 8 /* don't use mmap */ +#define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /* don't use synchronous transactions */ +#define TDB_SEQNUM 128 /* maintain a sequence number */ + +#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) + +/* error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY}; + +/* debugging uses one of the following levels */ +enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, + TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; + +typedef struct TDB_DATA { + unsigned char *dptr; + size_t dsize; +} TDB_DATA; + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* ext2fs tdb renames */ +#define tdb_open ext2fs_tdb_open +#define tdb_open_ex ext2fs_tdb_open_ex +#define tdb_set_max_dead ext2fs_tdb_set_max_dead +#define tdb_reopen ext2fs_tdb_reopen +#define tdb_reopen_all ext2fs_tdb_reopen_all +#define tdb_set_logging_function ext2fs_tdb_set_logging_function +#define tdb_error ext2fs_tdb_error +#define tdb_errorstr ext2fs_tdb_errorstr +#define tdb_fetch ext2fs_tdb_fetch +#define tdb_parse_record ext2fs_tdb_parse_record +#define tdb_delete ext2fs_tdb_delete +#define tdb_store ext2fs_tdb_store +#define tdb_append ext2fs_tdb_append +#define tdb_close ext2fs_tdb_close +#define tdb_firstkey ext2fs_tdb_firstkey +#define tdb_nextkey ext2fs_tdb_nextkey +#define tdb_traverse ext2fs_tdb_traverse +#define tdb_traverse_read ext2fs_tdb_traverse_read +#define tdb_exists ext2fs_tdb_exists +#define tdb_lockall ext2fs_tdb_lockall +#define tdb_unlockall ext2fs_tdb_unlockall +#define tdb_lockall_read ext2fs_tdb_lockall_read +#define tdb_unlockall_read ext2fs_tdb_unlockall_read +#define tdb_name ext2fs_tdb_name +#define tdb_fd ext2fs_tdb_fd +#define tdb_log_fn ext2fs_tdb_log_fn +#define tdb_get_logging_private ext2fs_tdb_get_logging_private +#define tdb_transaction_start ext2fs_tdb_transaction_start +#define tdb_transaction_commit ext2fs_tdb_transaction_commit +#define tdb_transaction_cancel ext2fs_tdb_transaction_cancel +#define tdb_transaction_recover ext2fs_tdb_transaction_recover +#define tdb_get_seqnum ext2fs_tdb_get_seqnum +#define tdb_hash_size ext2fs_tdb_hash_size +#define tdb_map_size ext2fs_tdb_map_size +#define tdb_get_flags ext2fs_tdb_get_flags +#define tdb_chainlock ext2fs_tdb_chainlock +#define tdb_chainunlock ext2fs_tdb_chainunlock +#define tdb_chainlock_read ext2fs_tdb_chainlock_read +#define tdb_chainunlock_read ext2fs_tdb_chainunlock_read +#define tdb_dump_all ext2fs_tdb_dump_all +#define tdb_printfreelist ext2fs_tdb_printfreelist +#define tdb_validate_freelist ext2fs_tdb_validate_freelist +#define tdb_chainlock_mark ext2fs_tdb_chainlock_mark +#define tdb_chainlock_nonblock ext2fs_tdb_chainlock_nonblock +#define tdb_chainlock_unmark ext2fs_tdb_chainlock_unmark +#define tdb_enable_seqnum ext2fs_tdb_enable_seqnum +#define tdb_increment_seqnum_nonblock ext2fs_tdb_increment_seqnum_nonblock +#define tdb_lock_nonblock ext2fs_tdb_lock_nonblock +#define tdb_lockall_mark ext2fs_tdb_lockall_mark +#define tdb_lockall_nonblock ext2fs_tdb_lockall_nonblock +#define tdb_lockall_read_nonblock ext2fs_tdb_lockall_read_nonblock +#define tdb_lockall_unmark ext2fs_tdb_lockall_unmark +#define tdb_flush ext2fs_tdb_flush + +/* this is the context structure that is returned from a db open */ +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_logging_context { + tdb_log_func log_fn; + void *log_private; +}; + +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn); +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead); + +int tdb_reopen(struct tdb_context *tdb); +int tdb_reopen_all(int parent_longlived); +void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx); +enum TDB_ERROR tdb_error(struct tdb_context *tdb); +const char *tdb_errorstr(struct tdb_context *tdb); +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(struct tdb_context *tdb); +TDB_DATA tdb_firstkey(struct tdb_context *tdb); +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key); +int tdb_lockall(struct tdb_context *tdb); +int tdb_lockall_nonblock(struct tdb_context *tdb); +int tdb_unlockall(struct tdb_context *tdb); +int tdb_lockall_read(struct tdb_context *tdb); +int tdb_lockall_read_nonblock(struct tdb_context *tdb); +int tdb_unlockall_read(struct tdb_context *tdb); +int tdb_lockall_mark(struct tdb_context *tdb); +int tdb_lockall_unmark(struct tdb_context *tdb); +const char *tdb_name(struct tdb_context *tdb); +int tdb_fd(struct tdb_context *tdb); +tdb_log_func tdb_log_fn(struct tdb_context *tdb); +void *tdb_get_logging_private(struct tdb_context *tdb); +int tdb_transaction_start(struct tdb_context *tdb); +int tdb_transaction_commit(struct tdb_context *tdb); +int tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_transaction_recover(struct tdb_context *tdb); +int tdb_get_seqnum(struct tdb_context *tdb); +int tdb_hash_size(struct tdb_context *tdb); +size_t tdb_map_size(struct tdb_context *tdb); +int tdb_get_flags(struct tdb_context *tdb); +void tdb_enable_seqnum(struct tdb_context *tdb); +void tdb_increment_seqnum_nonblock(struct tdb_context *tdb); +int tdb_flush(struct tdb_context *tdb); + +/* Low level locking functions: use with care */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(struct tdb_context *tdb); +int tdb_printfreelist(struct tdb_context *tdb); +int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries); + +#ifdef __cplusplus +} +#endif + +#endif /* tdb.h */ diff --git a/include/e2fsprogs/ext2fs/utf8data.h b/include/e2fsprogs/ext2fs/utf8data.h new file mode 100755 index 0000000..76e4f0e --- /dev/null +++ b/include/e2fsprogs/ext2fs/utf8data.h @@ -0,0 +1,4109 @@ +/* This file is generated code, do not edit. */ +#ifndef __INCLUDED_FROM_UTF8NORM_C__ +#error Only nls_utf8-norm.c should include this file. +#endif + +static const unsigned int utf8vers = 0xc0100; + +static const unsigned int utf8agetab[] = { + 0, + 0x10100, + 0x20000, + 0x20100, + 0x30000, + 0x30100, + 0x30200, + 0x40000, + 0x40100, + 0x50000, + 0x50100, + 0x50200, + 0x60000, + 0x60100, + 0x60200, + 0x60300, + 0x70000, + 0x80000, + 0x90000, + 0xa0000, + 0xb0000, + 0xc0000, + 0xc0100 +}; + +static const struct utf8data utf8nfdicfdata[] = { + { 0, 0 }, + { 0x10100, 0 }, + { 0x20000, 0 }, + { 0x20100, 0 }, + { 0x30000, 0 }, + { 0x30100, 0 }, + { 0x30200, 1792 }, + { 0x40000, 3200 }, + { 0x40100, 3200 }, + { 0x50000, 3200 }, + { 0x50100, 3200 }, + { 0x50200, 3200 }, + { 0x60000, 3200 }, + { 0x60100, 3200 }, + { 0x60200, 3200 }, + { 0x60300, 3200 }, + { 0x70000, 3200 }, + { 0x80000, 3200 }, + { 0x90000, 3200 }, + { 0xa0000, 3200 }, + { 0xb0000, 3200 }, + { 0xc0000, 3200 }, + { 0xc0100, 3200 } +}; + +static const struct utf8data utf8nfdidata[] = { + { 0, 896 }, + { 0x10100, 896 }, + { 0x20000, 896 }, + { 0x20100, 896 }, + { 0x30000, 896 }, + { 0x30100, 896 }, + { 0x30200, 2496 }, + { 0x40000, 20736 }, + { 0x40100, 20736 }, + { 0x50000, 20736 }, + { 0x50100, 20736 }, + { 0x50200, 20736 }, + { 0x60000, 20736 }, + { 0x60100, 20736 }, + { 0x60200, 20736 }, + { 0x60300, 20736 }, + { 0x70000, 20736 }, + { 0x80000, 20736 }, + { 0x90000, 20736 }, + { 0xa0000, 20736 }, + { 0xb0000, 20736 }, + { 0xc0000, 20736 }, + { 0xc0100, 20736 } +}; + +static const unsigned char utf8data[64256] = { + /* nfdicf_30100 */ + 0xd7,0x07,0x66,0x84,0x0c,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x99,0x1a,0xe3,0x63,0x15, + 0xe2,0x4c,0x0e,0xc1,0xe0,0x4e,0x0d,0xcf,0x86,0x65,0x2d,0x0d,0x01,0x00,0xd4,0xb8, + 0xd3,0x27,0xe2,0x89,0xa3,0xe1,0xce,0x35,0xe0,0x2c,0x22,0xcf,0x86,0xc5,0xe4,0x15, + 0x6d,0xe3,0x60,0x68,0xe2,0xf6,0x65,0xe1,0x29,0x65,0xe0,0xee,0x64,0xcf,0x86,0xe5, + 0xb3,0x64,0x64,0x96,0x64,0x0b,0x00,0xd2,0x0e,0xe1,0xb5,0x3c,0xe0,0xba,0xa3,0xcf, + 0x86,0xcf,0x06,0x01,0x00,0xd1,0x0c,0xe0,0x1e,0xa9,0xcf,0x86,0xcf,0x06,0x02,0xff, + 0xff,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01, + 0x00,0xe4,0xe1,0x45,0xe3,0x3b,0x45,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x87,0xad, + 0xd0,0x21,0xcf,0x86,0xe5,0x81,0xaa,0xe4,0x00,0xaa,0xe3,0xbf,0xa9,0xe2,0x9e,0xa9, + 0xe1,0x8d,0xa9,0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4, + 0x00,0xcf,0x86,0xe5,0x63,0xac,0xd4,0x19,0xe3,0xa2,0xab,0xe2,0x81,0xab,0xe1,0x70, + 0xab,0x10,0x08,0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3, + 0x09,0xac,0xe2,0xe8,0xab,0xe1,0xd7,0xab,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00, + 0x01,0xff,0xe9,0x9b,0xbb,0x00,0x83,0xe2,0x19,0xfa,0xe1,0xf2,0xf6,0xe0,0x6f,0xf5, + 0xcf,0x86,0xd5,0x31,0xc4,0xe3,0x54,0x4e,0xe2,0xf5,0x4c,0xe1,0xa4,0xcc,0xe0,0x9c, + 0x4b,0xcf,0x86,0xe5,0x8e,0x49,0xe4,0xaf,0x46,0xe3,0x11,0xbd,0xe2,0x68,0xbc,0xe1, + 0x43,0xbc,0xe0,0x1c,0xbc,0xcf,0x86,0xe5,0xe9,0xbb,0x94,0x07,0x63,0xd4,0xbb,0x07, + 0x00,0x07,0x00,0xe4,0xdb,0xf4,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b, + 0xe1,0xea,0xe1,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0xd9,0xe2,0xcf,0x86, + 0xe5,0x9e,0xe2,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xd9,0xe2,0xcf,0x06, + 0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x74,0xf4,0xe3,0x5d,0xf3, + 0xd2,0xa0,0xe1,0x13,0xe7,0xd0,0x21,0xcf,0x86,0xe5,0x14,0xe4,0xe4,0x90,0xe3,0xe3, + 0x4e,0xe3,0xe2,0x2d,0xe3,0xe1,0x1b,0xe3,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00, + 0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0x70,0xe5,0xe3,0x2f,0xe5, + 0xe2,0x0e,0xe5,0xe1,0xfd,0xe4,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff, + 0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0xf7,0xe5,0xe1,0xe6,0xe5,0x10,0x09, + 0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x17, + 0xe6,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac, + 0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0x5d,0xe6,0xd2,0x14,0xe1,0x2c,0xe6, + 0x10,0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1, + 0x38,0xe6,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00, + 0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x8d,0xeb,0xd4,0x19,0xe3,0xc6,0xea,0xe2,0xa4, + 0xea,0xe1,0x93,0xea,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5, + 0xb7,0x00,0xd3,0x18,0xe2,0x10,0xeb,0xe1,0xff,0xea,0x10,0x09,0x05,0xff,0xf0,0xa3, + 0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x28,0xeb,0x10, + 0x08,0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10, + 0x08,0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08, + 0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0x2a, + 0xed,0xd4,0x1a,0xe3,0x62,0xec,0xe2,0x48,0xec,0xe1,0x35,0xec,0x10,0x08,0x05,0xff, + 0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0xaa,0xec, + 0xe1,0x98,0xec,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3, + 0x00,0xd2,0x13,0xe1,0xc6,0xec,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff, + 0xe7,0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05, + 0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05, + 0xff,0xe7,0xaa,0xae,0x00,0xe0,0xdc,0xef,0xcf,0x86,0xd5,0x1d,0xe4,0x51,0xee,0xe3, + 0x0d,0xee,0xe2,0xeb,0xed,0xe1,0xda,0xed,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f, + 0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0xf8,0xee,0xe2,0xd4,0xee,0xe1, + 0xc3,0xee,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00, + 0xd3,0x18,0xe2,0x43,0xef,0xe1,0x32,0xef,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1, + 0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x5b,0xef,0x10,0x08,0x05, + 0xff,0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8, + 0x9e,0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* nfdi_30100 */ + 0x57,0x04,0x01,0x00,0xc6,0xd5,0x16,0xe4,0xc2,0x59,0xe3,0xfb,0x54,0xe2,0x74,0x4f, + 0xc1,0xe0,0xa0,0x4d,0xcf,0x86,0x65,0x84,0x4d,0x01,0x00,0xd4,0xb8,0xd3,0x27,0xe2, + 0x0c,0xa0,0xe1,0xdf,0x8d,0xe0,0x39,0x71,0xcf,0x86,0xc5,0xe4,0x98,0x69,0xe3,0xe3, + 0x64,0xe2,0x79,0x62,0xe1,0xac,0x61,0xe0,0x71,0x61,0xcf,0x86,0xe5,0x36,0x61,0x64, + 0x19,0x61,0x0b,0x00,0xd2,0x0e,0xe1,0xc2,0xa0,0xe0,0x3d,0xa0,0xcf,0x86,0xcf,0x06, + 0x01,0x00,0xd1,0x0c,0xe0,0xa1,0xa5,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xd0,0x08, + 0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xe4,0x9e, + 0xb6,0xe3,0x18,0xae,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x0a,0xaa,0xd0,0x21,0xcf, + 0x86,0xe5,0x04,0xa7,0xe4,0x83,0xa6,0xe3,0x42,0xa6,0xe2,0x21,0xa6,0xe1,0x10,0xa6, + 0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0xcf,0x86, + 0xe5,0xe6,0xa8,0xd4,0x19,0xe3,0x25,0xa8,0xe2,0x04,0xa8,0xe1,0xf3,0xa7,0x10,0x08, + 0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3,0x8c,0xa8,0xe2, + 0x6b,0xa8,0xe1,0x5a,0xa8,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,0x01,0xff,0xe9, + 0x9b,0xbb,0x00,0x83,0xe2,0x9c,0xf6,0xe1,0x75,0xf3,0xe0,0xf2,0xf1,0xcf,0x86,0xd5, + 0x31,0xc4,0xe3,0x6d,0xcc,0xe2,0x46,0xca,0xe1,0x27,0xc9,0xe0,0xb7,0xbf,0xcf,0x86, + 0xe5,0xaa,0xbb,0xe4,0xa3,0xba,0xe3,0x94,0xb9,0xe2,0xeb,0xb8,0xe1,0xc6,0xb8,0xe0, + 0x9f,0xb8,0xcf,0x86,0xe5,0x6c,0xb8,0x94,0x07,0x63,0x57,0xb8,0x07,0x00,0x07,0x00, + 0xe4,0x5e,0xf1,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1,0x6d,0xde, + 0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x5c,0xdf,0xcf,0x86,0xe5,0x21,0xdf, + 0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x5c,0xdf,0xcf,0x06,0x13,0x00,0xcf, + 0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0xf7,0xf0,0xe3,0xe0,0xef,0xd2,0xa0,0xe1, + 0x96,0xe3,0xd0,0x21,0xcf,0x86,0xe5,0x97,0xe0,0xe4,0x13,0xe0,0xe3,0xd1,0xdf,0xe2, + 0xb0,0xdf,0xe1,0x9e,0xdf,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,0xff,0xe4, + 0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xf3,0xe1,0xe3,0xb2,0xe1,0xe2,0x91,0xe1, + 0xe1,0x80,0xe1,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,0x93,0xb6, + 0x00,0xd4,0x34,0xd3,0x18,0xe2,0x7a,0xe2,0xe1,0x69,0xe2,0x10,0x09,0x05,0xff,0xf0, + 0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x9a,0xe2,0x91,0x11, + 0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88,0x00,0x05, + 0xff,0xe5,0xac,0xbe,0x00,0xe3,0xe0,0xe2,0xd2,0x14,0xe1,0xaf,0xe2,0x10,0x08,0x05, + 0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0xbb,0xe2,0x10, + 0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1,0xd5,0xd0, + 0x6a,0xcf,0x86,0xe5,0x10,0xe8,0xd4,0x19,0xe3,0x49,0xe7,0xe2,0x27,0xe7,0xe1,0x16, + 0xe7,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7,0x00,0xd3, + 0x18,0xe2,0x93,0xe7,0xe1,0x82,0xe7,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,0x9e,0x00, + 0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xab,0xe7,0x10,0x08,0x05,0xff, + 0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08,0x05,0xff, + 0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,0xff,0xe7, + 0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0xad,0xe9,0xd4,0x1a, + 0xe3,0xe5,0xe8,0xe2,0xcb,0xe8,0xe1,0xb8,0xe8,0x10,0x08,0x05,0xff,0xe7,0x9b,0xb4, + 0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x2d,0xe9,0xe1,0x1b,0xe9, + 0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,0xd2,0x13, + 0xe1,0x49,0xe9,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7,0xa9,0x80, + 0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff,0xf0,0xa5, + 0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff,0xe7,0xaa, + 0xae,0x00,0xe0,0x5f,0xec,0xcf,0x86,0xd5,0x1d,0xe4,0xd4,0xea,0xe3,0x90,0xea,0xe2, + 0x6e,0xea,0xe1,0x5d,0xea,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,0x05,0xff, + 0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0x7b,0xeb,0xe2,0x57,0xeb,0xe1,0x46,0xeb,0x10, + 0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3,0x18,0xe2, + 0xc6,0xeb,0xe1,0xb5,0xeb,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00,0x05,0xff, + 0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0xde,0xeb,0x10,0x08,0x05,0xff,0xe8,0x9a, + 0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9c, + 0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,0x86,0x00, + 0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* nfdicf_30200 */ + 0xd7,0x07,0x66,0x84,0x05,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x99,0x13,0xe3,0x63,0x0e, + 0xe2,0x4c,0x07,0xc1,0xe0,0x4e,0x06,0xcf,0x86,0x65,0x2d,0x06,0x01,0x00,0xd4,0x2a, + 0xe3,0xd0,0x35,0xe2,0x88,0x9c,0xe1,0xcd,0x2e,0xe0,0x2b,0x1b,0xcf,0x86,0xc5,0xe4, + 0x14,0x66,0xe3,0x5f,0x61,0xe2,0xf5,0x5e,0xe1,0x28,0x5e,0xe0,0xed,0x5d,0xcf,0x86, + 0xe5,0xb2,0x5d,0x64,0x95,0x5d,0x0b,0x00,0x83,0xe2,0xa7,0xf3,0xe1,0x80,0xf0,0xe0, + 0xfd,0xee,0xcf,0x86,0xd5,0x31,0xc4,0xe3,0xe2,0x47,0xe2,0x83,0x46,0xe1,0x32,0xc6, + 0xe0,0x2a,0x45,0xcf,0x86,0xe5,0x1c,0x43,0xe4,0x3d,0x40,0xe3,0x9f,0xb6,0xe2,0xf6, + 0xb5,0xe1,0xd1,0xb5,0xe0,0xaa,0xb5,0xcf,0x86,0xe5,0x77,0xb5,0x94,0x07,0x63,0x62, + 0xb5,0x07,0x00,0x07,0x00,0xe4,0x69,0xee,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00, + 0xd2,0x0b,0xe1,0x78,0xdb,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x67,0xdc, + 0xcf,0x86,0xe5,0x2c,0xdc,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x67,0xdc, + 0xcf,0x06,0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x02,0xee,0xe3, + 0xeb,0xec,0xd2,0xa0,0xe1,0xa1,0xe0,0xd0,0x21,0xcf,0x86,0xe5,0xa2,0xdd,0xe4,0x1e, + 0xdd,0xe3,0xdc,0xdc,0xe2,0xbb,0xdc,0xe1,0xa9,0xdc,0x10,0x08,0x05,0xff,0xe4,0xb8, + 0xbd,0x00,0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xfe,0xde,0xe3, + 0xbd,0xde,0xe2,0x9c,0xde,0xe1,0x8b,0xde,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00, + 0x05,0xff,0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0x85,0xdf,0xe1,0x74,0xdf, + 0x10,0x09,0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00, + 0xe2,0xa5,0xdf,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff, + 0xe5,0xac,0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0xeb,0xdf,0xd2,0x14,0xe1, + 0xba,0xdf,0x10,0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98, + 0x00,0xe1,0xc6,0xdf,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0, + 0xa2,0x00,0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x1b,0xe5,0xd4,0x19,0xe3,0x54,0xe4, + 0xe2,0x32,0xe4,0xe1,0x21,0xe4,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff, + 0xe6,0xb5,0xb7,0x00,0xd3,0x18,0xe2,0x9e,0xe4,0xe1,0x8d,0xe4,0x10,0x09,0x05,0xff, + 0xf0,0xa3,0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xb6, + 0xe4,0x10,0x08,0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1, + 0x11,0x10,0x08,0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00, + 0x10,0x08,0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86, + 0xe5,0xb8,0xe6,0xd4,0x1a,0xe3,0xf0,0xe5,0xe2,0xd6,0xe5,0xe1,0xc3,0xe5,0x10,0x08, + 0x05,0xff,0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2, + 0x38,0xe6,0xe1,0x26,0xe6,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4, + 0x83,0xa3,0x00,0xd2,0x13,0xe1,0x54,0xe6,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00, + 0x05,0xff,0xe7,0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc, + 0x00,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7, + 0x00,0x05,0xff,0xe7,0xaa,0xae,0x00,0xe0,0x6a,0xe9,0xcf,0x86,0xd5,0x1d,0xe4,0xdf, + 0xe7,0xe3,0x9b,0xe7,0xe2,0x79,0xe7,0xe1,0x68,0xe7,0x10,0x09,0x05,0xff,0xf0,0xa3, + 0x8d,0x9f,0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0x86,0xe8,0xe2,0x62, + 0xe8,0xe1,0x51,0xe8,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f, + 0x8a,0x00,0xd3,0x18,0xe2,0xd1,0xe8,0xe1,0xc0,0xe8,0x10,0x09,0x05,0xff,0xf0,0xa6, + 0xbe,0xb1,0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0xe9,0xe8,0x10, + 0x08,0x05,0xff,0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05, + 0xff,0xe8,0x9e,0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00, + /* nfdi_30200 */ + 0x57,0x04,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x82,0x53,0xe3,0xbb,0x4e,0xe2,0x34,0x49, + 0xc1,0xe0,0x60,0x47,0xcf,0x86,0x65,0x44,0x47,0x01,0x00,0xd4,0x2a,0xe3,0x1c,0x9a, + 0xe2,0xcb,0x99,0xe1,0x9e,0x87,0xe0,0xf8,0x6a,0xcf,0x86,0xc5,0xe4,0x57,0x63,0xe3, + 0xa2,0x5e,0xe2,0x38,0x5c,0xe1,0x6b,0x5b,0xe0,0x30,0x5b,0xcf,0x86,0xe5,0xf5,0x5a, + 0x64,0xd8,0x5a,0x0b,0x00,0x83,0xe2,0xea,0xf0,0xe1,0xc3,0xed,0xe0,0x40,0xec,0xcf, + 0x86,0xd5,0x31,0xc4,0xe3,0xbb,0xc6,0xe2,0x94,0xc4,0xe1,0x75,0xc3,0xe0,0x05,0xba, + 0xcf,0x86,0xe5,0xf8,0xb5,0xe4,0xf1,0xb4,0xe3,0xe2,0xb3,0xe2,0x39,0xb3,0xe1,0x14, + 0xb3,0xe0,0xed,0xb2,0xcf,0x86,0xe5,0xba,0xb2,0x94,0x07,0x63,0xa5,0xb2,0x07,0x00, + 0x07,0x00,0xe4,0xac,0xeb,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1, + 0xbb,0xd8,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0xaa,0xd9,0xcf,0x86,0xe5, + 0x6f,0xd9,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xaa,0xd9,0xcf,0x06,0x13, + 0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x45,0xeb,0xe3,0x2e,0xea,0xd2, + 0xa0,0xe1,0xe4,0xdd,0xd0,0x21,0xcf,0x86,0xe5,0xe5,0xda,0xe4,0x61,0xda,0xe3,0x1f, + 0xda,0xe2,0xfe,0xd9,0xe1,0xec,0xd9,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05, + 0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0x41,0xdc,0xe3,0x00,0xdc,0xe2, + 0xdf,0xdb,0xe1,0xce,0xdb,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5, + 0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0xc8,0xdc,0xe1,0xb7,0xdc,0x10,0x09,0x05, + 0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0xe8,0xdc, + 0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88, + 0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0x2e,0xdd,0xd2,0x14,0xe1,0xfd,0xdc,0x10, + 0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0x09, + 0xdd,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1, + 0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x5e,0xe2,0xd4,0x19,0xe3,0x97,0xe1,0xe2,0x75,0xe1, + 0xe1,0x64,0xe1,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7, + 0x00,0xd3,0x18,0xe2,0xe1,0xe1,0xe1,0xd0,0xe1,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd, + 0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xf9,0xe1,0x10,0x08, + 0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08, + 0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05, + 0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0xfb,0xe3, + 0xd4,0x1a,0xe3,0x33,0xe3,0xe2,0x19,0xe3,0xe1,0x06,0xe3,0x10,0x08,0x05,0xff,0xe7, + 0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x7b,0xe3,0xe1, + 0x69,0xe3,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00, + 0xd2,0x13,0xe1,0x97,0xe3,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7, + 0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff, + 0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff, + 0xe7,0xaa,0xae,0x00,0xe0,0xad,0xe6,0xcf,0x86,0xd5,0x1d,0xe4,0x22,0xe5,0xe3,0xde, + 0xe4,0xe2,0xbc,0xe4,0xe1,0xab,0xe4,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00, + 0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0xc9,0xe5,0xe2,0xa5,0xe5,0xe1,0x94, + 0xe5,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3, + 0x18,0xe2,0x14,0xe6,0xe1,0x03,0xe6,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00, + 0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x2c,0xe6,0x10,0x08,0x05,0xff, + 0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff, + 0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e, + 0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* nfdicf_c0100 */ + 0xd7,0xb0,0x56,0x04,0x01,0x00,0x95,0xa8,0xd4,0x5e,0xd3,0x2e,0xd2,0x16,0xd1,0x0a, + 0x10,0x04,0x01,0x00,0x01,0xff,0x61,0x00,0x10,0x06,0x01,0xff,0x62,0x00,0x01,0xff, + 0x63,0x00,0xd1,0x0c,0x10,0x06,0x01,0xff,0x64,0x00,0x01,0xff,0x65,0x00,0x10,0x06, + 0x01,0xff,0x66,0x00,0x01,0xff,0x67,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x06,0x01,0xff, + 0x68,0x00,0x01,0xff,0x69,0x00,0x10,0x06,0x01,0xff,0x6a,0x00,0x01,0xff,0x6b,0x00, + 0xd1,0x0c,0x10,0x06,0x01,0xff,0x6c,0x00,0x01,0xff,0x6d,0x00,0x10,0x06,0x01,0xff, + 0x6e,0x00,0x01,0xff,0x6f,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x06,0x01,0xff, + 0x70,0x00,0x01,0xff,0x71,0x00,0x10,0x06,0x01,0xff,0x72,0x00,0x01,0xff,0x73,0x00, + 0xd1,0x0c,0x10,0x06,0x01,0xff,0x74,0x00,0x01,0xff,0x75,0x00,0x10,0x06,0x01,0xff, + 0x76,0x00,0x01,0xff,0x77,0x00,0x92,0x16,0xd1,0x0c,0x10,0x06,0x01,0xff,0x78,0x00, + 0x01,0xff,0x79,0x00,0x10,0x06,0x01,0xff,0x7a,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0xc6,0xe5,0xf9,0x14,0xe4,0x6f,0x0d,0xe3,0x39,0x08,0xe2,0x22,0x01,0xc1,0xd0,0x24, + 0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x07,0x63,0xd8,0x43,0x01,0x00,0x93,0x13,0x52, + 0x04,0x01,0x00,0x91,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xce,0xbc,0x00,0x01,0x00, + 0x01,0x00,0xcf,0x86,0xe5,0xb3,0x44,0xd4,0x7f,0xd3,0x3f,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x61,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x81,0x00,0x10,0x08,0x01, + 0xff,0x61,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x61,0xcc,0x88,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x10,0x07,0x01,0xff,0xc3, + 0xa6,0x00,0x01,0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x65,0xcc,0x80,0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x65,0xcc, + 0x82,0x00,0x01,0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc, + 0x80,0x00,0x01,0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x82,0x00, + 0x01,0xff,0x69,0xcc,0x88,0x00,0xd3,0x3b,0xd2,0x1f,0xd1,0x0f,0x10,0x07,0x01,0xff, + 0xc3,0xb0,0x00,0x01,0xff,0x6e,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x80, + 0x00,0x01,0xff,0x6f,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x82, + 0x00,0x01,0xff,0x6f,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,0x01, + 0x00,0xd2,0x1f,0xd1,0x0f,0x10,0x07,0x01,0xff,0xc3,0xb8,0x00,0x01,0xff,0x75,0xcc, + 0x80,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x82,0x00, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x88,0x00,0x01,0xff,0x79,0xcc,0x81,0x00, + 0x10,0x07,0x01,0xff,0xc3,0xbe,0x00,0x01,0xff,0x73,0x73,0x00,0xe1,0xd4,0x03,0xe0, + 0xeb,0x01,0xcf,0x86,0xd5,0xfb,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0x61,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x84,0x00,0x10,0x08,0x01,0xff, + 0x61,0xcc,0x86,0x00,0x01,0xff,0x61,0xcc,0x86,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x61,0xcc,0xa8,0x00,0x01,0xff,0x61,0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x63,0xcc, + 0x81,0x00,0x01,0xff,0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x63,0xcc,0x82,0x00,0x01,0xff,0x63,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x63,0xcc, + 0x87,0x00,0x01,0xff,0x63,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x63,0xcc, + 0x8c,0x00,0x01,0xff,0x63,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x8c,0x00, + 0x01,0xff,0x64,0xcc,0x8c,0x00,0xd3,0x3b,0xd2,0x1b,0xd1,0x0b,0x10,0x07,0x01,0xff, + 0xc4,0x91,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x84,0x00,0x01,0xff,0x65, + 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x86,0x00,0x01,0xff,0x65, + 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x87,0x00,0x01,0xff,0x65,0xcc,0x87, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0xa8,0x00,0x01,0xff,0x65, + 0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x8c,0x00,0x01,0xff,0x65,0xcc,0x8c, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x82,0x00,0x01,0xff,0x67,0xcc,0x82, + 0x00,0x10,0x08,0x01,0xff,0x67,0xcc,0x86,0x00,0x01,0xff,0x67,0xcc,0x86,0x00,0xd4, + 0x7b,0xd3,0x3b,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x87,0x00,0x01, + 0xff,0x67,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x67,0xcc,0xa7,0x00,0x01,0xff,0x67, + 0xcc,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x68,0xcc,0x82,0x00,0x01,0xff,0x68, + 0xcc,0x82,0x00,0x10,0x07,0x01,0xff,0xc4,0xa7,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0x69,0xcc,0x83,0x00,0x01,0xff,0x69,0xcc,0x83,0x00,0x10,0x08, + 0x01,0xff,0x69,0xcc,0x84,0x00,0x01,0xff,0x69,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0x69,0xcc,0x86,0x00,0x01,0xff,0x69,0xcc,0x86,0x00,0x10,0x08,0x01,0xff, + 0x69,0xcc,0xa8,0x00,0x01,0xff,0x69,0xcc,0xa8,0x00,0xd3,0x37,0xd2,0x17,0xd1,0x0c, + 0x10,0x08,0x01,0xff,0x69,0xcc,0x87,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc4,0xb3, + 0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6a,0xcc,0x82,0x00,0x01,0xff,0x6a, + 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x6b,0xcc,0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7, + 0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x6c,0xcc,0x81,0x00,0x10, + 0x08,0x01,0xff,0x6c,0xcc,0x81,0x00,0x01,0xff,0x6c,0xcc,0xa7,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x6c,0xcc,0xa7,0x00,0x01,0xff,0x6c,0xcc,0x8c,0x00,0x10,0x08,0x01, + 0xff,0x6c,0xcc,0x8c,0x00,0x01,0xff,0xc5,0x80,0x00,0xcf,0x86,0xd5,0xed,0xd4,0x72, + 0xd3,0x37,0xd2,0x17,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc5,0x82,0x00,0x10, + 0x04,0x01,0x00,0x01,0xff,0x6e,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e, + 0xcc,0x81,0x00,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa7, + 0x00,0x01,0xff,0x6e,0xcc,0x8c,0x00,0xd2,0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e, + 0xcc,0x8c,0x00,0x01,0xff,0xca,0xbc,0x6e,0x00,0x10,0x07,0x01,0xff,0xc5,0x8b,0x00, + 0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc, + 0x84,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,0x86,0x00, + 0xd3,0x3b,0xd2,0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01,0xff, + 0x6f,0xcc,0x8b,0x00,0x10,0x07,0x01,0xff,0xc5,0x93,0x00,0x01,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x72,0xcc,0x81,0x00,0x01,0xff,0x72,0xcc,0x81,0x00,0x10,0x08,0x01, + 0xff,0x72,0xcc,0xa7,0x00,0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x72,0xcc,0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c,0x00,0x10,0x08,0x01, + 0xff,0x73,0xcc,0x81,0x00,0x01,0xff,0x73,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x73,0xcc,0x82,0x00,0x01,0xff,0x73,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x73, + 0xcc,0xa7,0x00,0x01,0xff,0x73,0xcc,0xa7,0x00,0xd4,0x7b,0xd3,0x3b,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x73,0xcc,0x8c,0x00,0x01,0xff,0x73,0xcc,0x8c,0x00,0x10, + 0x08,0x01,0xff,0x74,0xcc,0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x74,0xcc,0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c,0x00,0x10,0x07,0x01, + 0xff,0xc5,0xa7,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc, + 0x83,0x00,0x01,0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x84,0x00, + 0x01,0xff,0x75,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x86,0x00, + 0x01,0xff,0x75,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x8a,0x00,0x01,0xff, + 0x75,0xcc,0x8a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc, + 0x8b,0x00,0x01,0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa8,0x00, + 0x01,0xff,0x75,0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x82,0x00, + 0x01,0xff,0x77,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x82,0x00,0x01,0xff, + 0x79,0xcc,0x82,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x79,0xcc,0x88,0x00, + 0x01,0xff,0x7a,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x81,0x00,0x01,0xff, + 0x7a,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x87,0x00,0x01,0xff, + 0x7a,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,0x01,0xff,0x73,0x00, + 0xe0,0x65,0x01,0xcf,0x86,0xd5,0xb4,0xd4,0x5a,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10, + 0x04,0x01,0x00,0x01,0xff,0xc9,0x93,0x00,0x10,0x07,0x01,0xff,0xc6,0x83,0x00,0x01, + 0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc6,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff, + 0xc9,0x94,0x00,0x01,0xff,0xc6,0x88,0x00,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x01,0x00, + 0x01,0xff,0xc9,0x96,0x00,0x10,0x07,0x01,0xff,0xc9,0x97,0x00,0x01,0xff,0xc6,0x8c, + 0x00,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xc7,0x9d,0x00,0x01,0xff,0xc9,0x99, + 0x00,0xd3,0x32,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,0xff,0xc9,0x9b,0x00,0x01,0xff, + 0xc6,0x92,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xc9,0xa0,0x00,0xd1,0x0b,0x10,0x07, + 0x01,0xff,0xc9,0xa3,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc9,0xa9,0x00,0x01,0xff, + 0xc9,0xa8,0x00,0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0x99,0x00,0x01,0x00, + 0x01,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xc9,0xaf,0x00,0x01,0xff,0xc9,0xb2,0x00, + 0x10,0x04,0x01,0x00,0x01,0xff,0xc9,0xb5,0x00,0xd4,0x5d,0xd3,0x34,0xd2,0x1b,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x10, + 0x07,0x01,0xff,0xc6,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc6,0xa5, + 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xca,0x80,0x00,0x01,0xff,0xc6,0xa8,0x00,0xd2, + 0x0f,0x91,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xca,0x83,0x00,0x01,0x00,0xd1,0x0b, + 0x10,0x07,0x01,0xff,0xc6,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xca,0x88,0x00, + 0x01,0xff,0x75,0xcc,0x9b,0x00,0xd3,0x33,0xd2,0x1d,0xd1,0x0f,0x10,0x08,0x01,0xff, + 0x75,0xcc,0x9b,0x00,0x01,0xff,0xca,0x8a,0x00,0x10,0x07,0x01,0xff,0xca,0x8b,0x00, + 0x01,0xff,0xc6,0xb4,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc6,0xb6,0x00, + 0x10,0x04,0x01,0x00,0x01,0xff,0xca,0x92,0x00,0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01, + 0xff,0xc6,0xb9,0x00,0x01,0x00,0x01,0x00,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0xbd, + 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd4,0xd4,0x44,0xd3,0x16,0x52,0x04,0x01, + 0x00,0x51,0x07,0x01,0xff,0xc7,0x86,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xc7,0x89, + 0x00,0xd2,0x12,0x91,0x0b,0x10,0x07,0x01,0xff,0xc7,0x89,0x00,0x01,0x00,0x01,0xff, + 0xc7,0x8c,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x61,0xcc,0x8c,0x00,0x10, + 0x08,0x01,0xff,0x61,0xcc,0x8c,0x00,0x01,0xff,0x69,0xcc,0x8c,0x00,0xd3,0x46,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8c,0x00,0x01,0xff,0x6f,0xcc,0x8c, + 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x8c,0x00,0xd1, + 0x12,0x10,0x08,0x01,0xff,0x75,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84, + 0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x75,0xcc,0x88, + 0xcc,0x81,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81, + 0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x8c,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88, + 0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01, + 0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x88, + 0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,0xd4,0x87,0xd3,0x41,0xd2, + 0x26,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x87,0xcc,0x84,0x00,0x01,0xff,0x61, + 0xcc,0x87,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc3,0xa6,0xcc,0x84,0x00,0x01,0xff, + 0xc3,0xa6,0xcc,0x84,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc7,0xa5,0x00,0x01,0x00, + 0x10,0x08,0x01,0xff,0x67,0xcc,0x8c,0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00, + 0x10,0x08,0x01,0xff,0x6f,0xcc,0xa8,0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14, + 0x10,0x0a,0x01,0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc, + 0x84,0x00,0x10,0x09,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc, + 0x8c,0x00,0xd3,0x38,0xd2,0x1a,0xd1,0x0f,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00, + 0x01,0xff,0xc7,0xb3,0x00,0x10,0x07,0x01,0xff,0xc7,0xb3,0x00,0x01,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0x67,0xcc,0x81,0x00,0x01,0xff,0x67,0xcc,0x81,0x00,0x10,0x07, + 0x04,0xff,0xc6,0x95,0x00,0x04,0xff,0xc6,0xbf,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08, + 0x04,0xff,0x6e,0xcc,0x80,0x00,0x04,0xff,0x6e,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff, + 0x61,0xcc,0x8a,0xcc,0x81,0x00,0x01,0xff,0x61,0xcc,0x8a,0xcc,0x81,0x00,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00, + 0x10,0x09,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00, + 0xe2,0x31,0x02,0xe1,0xc3,0x44,0xe0,0xc8,0x01,0xcf,0x86,0xd5,0xfb,0xd4,0x80,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0x8f,0x00,0x01,0xff,0x61, + 0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x91,0x00,0x01,0xff,0x61,0xcc,0x91, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x8f,0x00,0x01,0xff,0x65,0xcc,0x8f, + 0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x91,0x00,0x01,0xff,0x65,0xcc,0x91,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8f,0x00,0x01,0xff,0x69,0xcc,0x8f, + 0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x91,0x00,0x01,0xff,0x69,0xcc,0x91,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x10, + 0x08,0x01,0xff,0x6f,0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc,0x91,0x00,0xd3,0x40,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x72,0xcc,0x8f,0x00,0x01,0xff,0x72,0xcc,0x8f, + 0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0x91,0x00,0x01,0xff,0x72,0xcc,0x91,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x8f,0x00,0x01,0xff,0x75,0xcc,0x8f,0x00,0x10, + 0x08,0x01,0xff,0x75,0xcc,0x91,0x00,0x01,0xff,0x75,0xcc,0x91,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x04,0xff,0x73,0xcc,0xa6,0x00,0x04,0xff,0x73,0xcc,0xa6,0x00,0x10, + 0x08,0x04,0xff,0x74,0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc,0xa6,0x00,0xd1,0x0b,0x10, + 0x07,0x04,0xff,0xc8,0x9d,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x68,0xcc,0x8c,0x00, + 0x04,0xff,0x68,0xcc,0x8c,0x00,0xd4,0x79,0xd3,0x31,0xd2,0x16,0xd1,0x0b,0x10,0x07, + 0x06,0xff,0xc6,0x9e,0x00,0x07,0x00,0x10,0x07,0x04,0xff,0xc8,0xa3,0x00,0x04,0x00, + 0xd1,0x0b,0x10,0x07,0x04,0xff,0xc8,0xa5,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x61, + 0xcc,0x87,0x00,0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04, + 0xff,0x65,0xcc,0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,0x0a,0x04,0xff,0x6f, + 0xcc,0x88,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,0x00,0xd1,0x14,0x10, + 0x0a,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84, + 0x00,0x10,0x08,0x04,0xff,0x6f,0xcc,0x87,0x00,0x04,0xff,0x6f,0xcc,0x87,0x00,0xd3, + 0x27,0xe2,0x21,0x43,0xd1,0x14,0x10,0x0a,0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00, + 0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x79,0xcc,0x84,0x00, + 0x04,0xff,0x79,0xcc,0x84,0x00,0xd2,0x13,0x51,0x04,0x08,0x00,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0xa5,0x00,0x08,0xff,0xc8,0xbc,0x00,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08, + 0xff,0xc6,0x9a,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0xa6,0x00,0x08,0x00,0xcf,0x86, + 0x95,0x5f,0x94,0x5b,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,0xff, + 0xc9,0x82,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xc6,0x80,0x00,0xd1,0x0e,0x10,0x07, + 0x09,0xff,0xca,0x89,0x00,0x09,0xff,0xca,0x8c,0x00,0x10,0x07,0x09,0xff,0xc9,0x87, + 0x00,0x09,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9,0x89,0x00,0x09,0x00, + 0x10,0x07,0x09,0xff,0xc9,0x8b,0x00,0x09,0x00,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9, + 0x8d,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xc9,0x8f,0x00,0x09,0x00,0x01,0x00,0x01, + 0x00,0xd1,0x8b,0xd0,0x0c,0xcf,0x86,0xe5,0x10,0x43,0x64,0xef,0x42,0x01,0xe6,0xcf, + 0x86,0xd5,0x2a,0xe4,0x99,0x43,0xe3,0x7f,0x43,0xd2,0x11,0xe1,0x5e,0x43,0x10,0x07, + 0x01,0xff,0xcc,0x80,0x00,0x01,0xff,0xcc,0x81,0x00,0xe1,0x65,0x43,0x10,0x09,0x01, + 0xff,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0x00,0xd4,0x0f,0x93,0x0b,0x92, + 0x07,0x61,0xab,0x43,0x01,0xea,0x06,0xe6,0x06,0xe6,0xd3,0x2c,0xd2,0x16,0xd1,0x0b, + 0x10,0x07,0x0a,0xff,0xcd,0xb1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xcd,0xb3,0x00, + 0x0a,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x10,0x07,0x0a, + 0xff,0xcd,0xb7,0x00,0x0a,0x00,0xd2,0x07,0x61,0x97,0x43,0x00,0x00,0x51,0x04,0x09, + 0x00,0x10,0x06,0x01,0xff,0x3b,0x00,0x10,0xff,0xcf,0xb3,0x00,0xe0,0x31,0x01,0xcf, + 0x86,0xd5,0xd3,0xd4,0x5f,0xd3,0x21,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x01, + 0x00,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x81, + 0x00,0x01,0xff,0xc2,0xb7,0x00,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5, + 0xcc,0x81,0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9, + 0xcc,0x81,0x00,0x00,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00, + 0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x01,0xff,0xcf,0x89,0xcc, + 0x81,0x00,0xd3,0x3c,0xd2,0x20,0xd1,0x12,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x88, + 0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0x00,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01, + 0xff,0xce,0xb3,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xb4,0x00,0x01,0xff,0xce, + 0xb5,0x00,0x10,0x07,0x01,0xff,0xce,0xb6,0x00,0x01,0xff,0xce,0xb7,0x00,0xd2,0x1c, + 0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xb8,0x00,0x01,0xff,0xce,0xb9,0x00,0x10,0x07, + 0x01,0xff,0xce,0xba,0x00,0x01,0xff,0xce,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff, + 0xce,0xbc,0x00,0x01,0xff,0xce,0xbd,0x00,0x10,0x07,0x01,0xff,0xce,0xbe,0x00,0x01, + 0xff,0xce,0xbf,0x00,0xe4,0x85,0x43,0xd3,0x35,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01, + 0xff,0xcf,0x80,0x00,0x01,0xff,0xcf,0x81,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf, + 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xcf,0x84,0x00,0x01,0xff,0xcf,0x85,0x00, + 0x10,0x07,0x01,0xff,0xcf,0x86,0x00,0x01,0xff,0xcf,0x87,0x00,0xe2,0x2b,0x43,0xd1, + 0x0e,0x10,0x07,0x01,0xff,0xcf,0x88,0x00,0x01,0xff,0xcf,0x89,0x00,0x10,0x09,0x01, + 0xff,0xce,0xb9,0xcc,0x88,0x00,0x01,0xff,0xcf,0x85,0xcc,0x88,0x00,0xcf,0x86,0xd5, + 0x94,0xd4,0x3c,0xd3,0x13,0x92,0x0f,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xcf, + 0x83,0x00,0x01,0x00,0x01,0x00,0xd2,0x07,0x61,0x3a,0x43,0x01,0x00,0xd1,0x12,0x10, + 0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x10, + 0x09,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x0a,0xff,0xcf,0x97,0x00,0xd3,0x2c,0xd2, + 0x11,0xe1,0x46,0x43,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01,0xff,0xce,0xb8,0x00, + 0xd1,0x10,0x10,0x09,0x01,0xff,0xcf,0x92,0xcc,0x88,0x00,0x01,0xff,0xcf,0x86,0x00, + 0x10,0x07,0x01,0xff,0xcf,0x80,0x00,0x04,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06, + 0xff,0xcf,0x99,0x00,0x06,0x00,0x10,0x07,0x01,0xff,0xcf,0x9b,0x00,0x04,0x00,0xd1, + 0x0b,0x10,0x07,0x01,0xff,0xcf,0x9d,0x00,0x04,0x00,0x10,0x07,0x01,0xff,0xcf,0x9f, + 0x00,0x04,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf, + 0xa1,0x00,0x04,0x00,0x10,0x07,0x01,0xff,0xcf,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10, + 0x07,0x01,0xff,0xcf,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0xa7,0x00,0x01, + 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xa9,0x00,0x01,0x00,0x10,0x07, + 0x01,0xff,0xcf,0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xad,0x00, + 0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0xaf,0x00,0x01,0x00,0xd3,0x2b,0xd2,0x12,0x91, + 0x0e,0x10,0x07,0x01,0xff,0xce,0xba,0x00,0x01,0xff,0xcf,0x81,0x00,0x01,0x00,0xd1, + 0x0e,0x10,0x07,0x05,0xff,0xce,0xb8,0x00,0x05,0xff,0xce,0xb5,0x00,0x10,0x04,0x06, + 0x00,0x07,0xff,0xcf,0xb8,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x07,0x00,0x07,0xff, + 0xcf,0xb2,0x00,0x10,0x07,0x07,0xff,0xcf,0xbb,0x00,0x07,0x00,0xd1,0x0b,0x10,0x04, + 0x08,0x00,0x08,0xff,0xcd,0xbb,0x00,0x10,0x07,0x08,0xff,0xcd,0xbc,0x00,0x08,0xff, + 0xcd,0xbd,0x00,0xe3,0xed,0x46,0xe2,0x3d,0x05,0xe1,0x27,0x02,0xe0,0x66,0x01,0xcf, + 0x86,0xd5,0xf0,0xd4,0x7e,0xd3,0x40,0xd2,0x22,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0, + 0xb5,0xcc,0x80,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,0x00,0x10,0x07,0x01,0xff,0xd1, + 0x92,0x00,0x01,0xff,0xd0,0xb3,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1, + 0x94,0x00,0x01,0xff,0xd1,0x95,0x00,0x10,0x07,0x01,0xff,0xd1,0x96,0x00,0x01,0xff, + 0xd1,0x96,0xcc,0x88,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x98,0x00, + 0x01,0xff,0xd1,0x99,0x00,0x10,0x07,0x01,0xff,0xd1,0x9a,0x00,0x01,0xff,0xd1,0x9b, + 0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8, + 0xcc,0x80,0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x86,0x00,0x01,0xff,0xd1,0x9f, + 0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xb0,0x00,0x01,0xff, + 0xd0,0xb1,0x00,0x10,0x07,0x01,0xff,0xd0,0xb2,0x00,0x01,0xff,0xd0,0xb3,0x00,0xd1, + 0x0e,0x10,0x07,0x01,0xff,0xd0,0xb4,0x00,0x01,0xff,0xd0,0xb5,0x00,0x10,0x07,0x01, + 0xff,0xd0,0xb6,0x00,0x01,0xff,0xd0,0xb7,0x00,0xd2,0x1e,0xd1,0x10,0x10,0x07,0x01, + 0xff,0xd0,0xb8,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x10,0x07,0x01,0xff,0xd0, + 0xba,0x00,0x01,0xff,0xd0,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xbc,0x00, + 0x01,0xff,0xd0,0xbd,0x00,0x10,0x07,0x01,0xff,0xd0,0xbe,0x00,0x01,0xff,0xd0,0xbf, + 0x00,0xe4,0x25,0x42,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x80, + 0x00,0x01,0xff,0xd1,0x81,0x00,0x10,0x07,0x01,0xff,0xd1,0x82,0x00,0x01,0xff,0xd1, + 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x84,0x00,0x01,0xff,0xd1,0x85,0x00, + 0x10,0x07,0x01,0xff,0xd1,0x86,0x00,0x01,0xff,0xd1,0x87,0x00,0xd2,0x1c,0xd1,0x0e, + 0x10,0x07,0x01,0xff,0xd1,0x88,0x00,0x01,0xff,0xd1,0x89,0x00,0x10,0x07,0x01,0xff, + 0xd1,0x8a,0x00,0x01,0xff,0xd1,0x8b,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x8c, + 0x00,0x01,0xff,0xd1,0x8d,0x00,0x10,0x07,0x01,0xff,0xd1,0x8e,0x00,0x01,0xff,0xd1, + 0x8f,0x00,0xcf,0x86,0xd5,0x07,0x64,0xcf,0x41,0x01,0x00,0xd4,0x58,0xd3,0x2c,0xd2, + 0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa1,0x00,0x01,0x00,0x10,0x07,0x01,0xff, + 0xd1,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa5,0x00,0x01,0x00, + 0x10,0x07,0x01,0xff,0xd1,0xa7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01, + 0xff,0xd1,0xa9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xab,0x00,0x01,0x00,0xd1, + 0x0b,0x10,0x07,0x01,0xff,0xd1,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xaf, + 0x00,0x01,0x00,0xd3,0x33,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb1,0x00, + 0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xb3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01, + 0xff,0xd1,0xb5,0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb5,0xcc,0x8f,0x00,0x01, + 0xff,0xd1,0xb5,0xcc,0x8f,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb9, + 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07, + 0x01,0xff,0xd1,0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xbf,0x00,0x01,0x00, + 0xe0,0x41,0x01,0xcf,0x86,0xd5,0x8e,0xd4,0x36,0xd3,0x11,0xe2,0x91,0x41,0xe1,0x88, + 0x41,0x10,0x07,0x01,0xff,0xd2,0x81,0x00,0x01,0x00,0xd2,0x0f,0x51,0x04,0x04,0x00, + 0x10,0x07,0x06,0xff,0xd2,0x8b,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x04,0xff,0xd2, + 0x8d,0x00,0x04,0x00,0x10,0x07,0x04,0xff,0xd2,0x8f,0x00,0x04,0x00,0xd3,0x2c,0xd2, + 0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x91,0x00,0x01,0x00,0x10,0x07,0x01,0xff, + 0xd2,0x93,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x95,0x00,0x01,0x00, + 0x10,0x07,0x01,0xff,0xd2,0x97,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01, + 0xff,0xd2,0x99,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9b,0x00,0x01,0x00,0xd1, + 0x0b,0x10,0x07,0x01,0xff,0xd2,0x9d,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9f, + 0x00,0x01,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2, + 0xa1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10, + 0x07,0x01,0xff,0xd2,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xa7,0x00,0x01, + 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xa9,0x00,0x01,0x00,0x10,0x07, + 0x01,0xff,0xd2,0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xad,0x00, + 0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xaf,0x00,0x01,0x00,0xd3,0x2c,0xd2,0x16,0xd1, + 0x0b,0x10,0x07,0x01,0xff,0xd2,0xb1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xb3, + 0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xb5,0x00,0x01,0x00,0x10,0x07, + 0x01,0xff,0xd2,0xb7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2, + 0xb9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10, + 0x07,0x01,0xff,0xd2,0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xbf,0x00,0x01, + 0x00,0xcf,0x86,0xd5,0xdc,0xd4,0x5a,0xd3,0x36,0xd2,0x20,0xd1,0x10,0x10,0x07,0x01, + 0xff,0xd3,0x8f,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0, + 0xb6,0xcc,0x86,0x00,0x01,0xff,0xd3,0x84,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x06, + 0xff,0xd3,0x86,0x00,0x10,0x04,0x06,0x00,0x01,0xff,0xd3,0x88,0x00,0xd2,0x16,0xd1, + 0x0b,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x8a,0x00,0x10,0x04,0x06,0x00,0x01,0xff, + 0xd3,0x8c,0x00,0xe1,0x69,0x40,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x8e,0x00,0xd3, + 0x41,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x01,0xff, + 0xd0,0xb0,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x01,0xff, + 0xd0,0xb0,0xcc,0x88,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0x95,0x00,0x01,0x00, + 0x10,0x09,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00, + 0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0x99,0x00,0x01,0x00,0x10,0x09,0x01, + 0xff,0xd3,0x99,0xcc,0x88,0x00,0x01,0xff,0xd3,0x99,0xcc,0x88,0x00,0xd1,0x12,0x10, + 0x09,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x10, + 0x09,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0xd4, + 0x82,0xd3,0x41,0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa1,0x00,0x01,0x00, + 0x10,0x09,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb8,0xcc, + 0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00,0x01,0xff,0xd0,0xbe,0xcc, + 0x88,0x00,0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa9,0x00,0x01,0x00,0x10, + 0x09,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1, + 0x12,0x10,0x09,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88, + 0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0x01,0xff,0xd1,0x83,0xcc,0x84, + 0x00,0xd3,0x41,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x88,0x00, + 0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00, + 0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x87,0xcc, + 0x88,0x00,0x01,0xff,0xd1,0x87,0xcc,0x88,0x00,0x10,0x07,0x08,0xff,0xd3,0xb7,0x00, + 0x08,0x00,0xd2,0x1d,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x8b,0xcc,0x88,0x00,0x01, + 0xff,0xd1,0x8b,0xcc,0x88,0x00,0x10,0x07,0x09,0xff,0xd3,0xbb,0x00,0x09,0x00,0xd1, + 0x0b,0x10,0x07,0x09,0xff,0xd3,0xbd,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xd3,0xbf, + 0x00,0x09,0x00,0xe1,0x26,0x02,0xe0,0x78,0x01,0xcf,0x86,0xd5,0xb0,0xd4,0x58,0xd3, + 0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x81,0x00,0x06,0x00,0x10,0x07, + 0x06,0xff,0xd4,0x83,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x85,0x00, + 0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x87,0x00,0x06,0x00,0xd2,0x16,0xd1,0x0b,0x10, + 0x07,0x06,0xff,0xd4,0x89,0x00,0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x8b,0x00,0x06, + 0x00,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x8d,0x00,0x06,0x00,0x10,0x07,0x06,0xff, + 0xd4,0x8f,0x00,0x06,0x00,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xd4, + 0x91,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xd4,0x93,0x00,0x09,0x00,0xd1,0x0b,0x10, + 0x07,0x0a,0xff,0xd4,0x95,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0x97,0x00,0x0a, + 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x99,0x00,0x0a,0x00,0x10,0x07, + 0x0a,0xff,0xd4,0x9b,0x00,0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x9d,0x00, + 0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0x9f,0x00,0x0a,0x00,0xd4,0x58,0xd3,0x2c,0xd2, + 0x16,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0xa1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff, + 0xd4,0xa3,0x00,0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xd4,0xa5,0x00,0x0b,0x00, + 0x10,0x07,0x0c,0xff,0xd4,0xa7,0x00,0x0c,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x10, + 0xff,0xd4,0xa9,0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xab,0x00,0x10,0x00,0xd1, + 0x0b,0x10,0x07,0x10,0xff,0xd4,0xad,0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xaf, + 0x00,0x10,0x00,0xd3,0x35,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x00,0x00,0x01,0xff,0xd5, + 0xa1,0x00,0x10,0x07,0x01,0xff,0xd5,0xa2,0x00,0x01,0xff,0xd5,0xa3,0x00,0xd1,0x0e, + 0x10,0x07,0x01,0xff,0xd5,0xa4,0x00,0x01,0xff,0xd5,0xa5,0x00,0x10,0x07,0x01,0xff, + 0xd5,0xa6,0x00,0x01,0xff,0xd5,0xa7,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff, + 0xd5,0xa8,0x00,0x01,0xff,0xd5,0xa9,0x00,0x10,0x07,0x01,0xff,0xd5,0xaa,0x00,0x01, + 0xff,0xd5,0xab,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xac,0x00,0x01,0xff,0xd5, + 0xad,0x00,0x10,0x07,0x01,0xff,0xd5,0xae,0x00,0x01,0xff,0xd5,0xaf,0x00,0xcf,0x86, + 0xe5,0x08,0x3f,0xd4,0x70,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5, + 0xb0,0x00,0x01,0xff,0xd5,0xb1,0x00,0x10,0x07,0x01,0xff,0xd5,0xb2,0x00,0x01,0xff, + 0xd5,0xb3,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xb4,0x00,0x01,0xff,0xd5,0xb5, + 0x00,0x10,0x07,0x01,0xff,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb7,0x00,0xd2,0x1c,0xd1, + 0x0e,0x10,0x07,0x01,0xff,0xd5,0xb8,0x00,0x01,0xff,0xd5,0xb9,0x00,0x10,0x07,0x01, + 0xff,0xd5,0xba,0x00,0x01,0xff,0xd5,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5, + 0xbc,0x00,0x01,0xff,0xd5,0xbd,0x00,0x10,0x07,0x01,0xff,0xd5,0xbe,0x00,0x01,0xff, + 0xd5,0xbf,0x00,0xe3,0x87,0x3e,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd6,0x80, + 0x00,0x01,0xff,0xd6,0x81,0x00,0x10,0x07,0x01,0xff,0xd6,0x82,0x00,0x01,0xff,0xd6, + 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd6,0x84,0x00,0x01,0xff,0xd6,0x85,0x00, + 0x10,0x07,0x01,0xff,0xd6,0x86,0x00,0x00,0x00,0xe0,0x2f,0x3f,0xcf,0x86,0xe5,0xc0, + 0x3e,0xe4,0x97,0x3e,0xe3,0x76,0x3e,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x01,0xff,0xd5,0xa5,0xd6,0x82,0x00,0xe4,0x3e,0x25,0xe3,0xc3,0x1a, + 0xe2,0x7b,0x81,0xe1,0xc0,0x13,0xd0,0x1e,0xcf,0x86,0xc5,0xe4,0x08,0x4b,0xe3,0x53, + 0x46,0xe2,0xe9,0x43,0xe1,0x1c,0x43,0xe0,0xe1,0x42,0xcf,0x86,0xe5,0xa6,0x42,0x64, + 0x89,0x42,0x0b,0x00,0xcf,0x86,0xe5,0xfa,0x01,0xe4,0x03,0x56,0xe3,0x76,0x01,0xe2, + 0x8e,0x53,0xd1,0x0c,0xe0,0xef,0x52,0xcf,0x86,0x65,0x8d,0x52,0x04,0x00,0xe0,0x0d, + 0x01,0xcf,0x86,0xd5,0x0a,0xe4,0x10,0x53,0x63,0xff,0x52,0x0a,0x00,0xd4,0x80,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x80,0x00,0x01,0xff,0xe2, + 0xb4,0x81,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x82,0x00,0x01,0xff,0xe2,0xb4,0x83, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x84,0x00,0x01,0xff,0xe2,0xb4,0x85, + 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x86,0x00,0x01,0xff,0xe2,0xb4,0x87,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x88,0x00,0x01,0xff,0xe2,0xb4,0x89, + 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x8a,0x00,0x01,0xff,0xe2,0xb4,0x8b,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x8c,0x00,0x01,0xff,0xe2,0xb4,0x8d,0x00,0x10, + 0x08,0x01,0xff,0xe2,0xb4,0x8e,0x00,0x01,0xff,0xe2,0xb4,0x8f,0x00,0xd3,0x40,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x90,0x00,0x01,0xff,0xe2,0xb4,0x91, + 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x92,0x00,0x01,0xff,0xe2,0xb4,0x93,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x94,0x00,0x01,0xff,0xe2,0xb4,0x95,0x00,0x10, + 0x08,0x01,0xff,0xe2,0xb4,0x96,0x00,0x01,0xff,0xe2,0xb4,0x97,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x98,0x00,0x01,0xff,0xe2,0xb4,0x99,0x00,0x10, + 0x08,0x01,0xff,0xe2,0xb4,0x9a,0x00,0x01,0xff,0xe2,0xb4,0x9b,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe2,0xb4,0x9c,0x00,0x01,0xff,0xe2,0xb4,0x9d,0x00,0x10,0x08,0x01, + 0xff,0xe2,0xb4,0x9e,0x00,0x01,0xff,0xe2,0xb4,0x9f,0x00,0xcf,0x86,0xe5,0x42,0x52, + 0x94,0x50,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa0,0x00, + 0x01,0xff,0xe2,0xb4,0xa1,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa2,0x00,0x01,0xff, + 0xe2,0xb4,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa4,0x00,0x01,0xff, + 0xe2,0xb4,0xa5,0x00,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xa7,0x00,0x52,0x04, + 0x00,0x00,0x91,0x0c,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xad,0x00,0x00,0x00, + 0x01,0x00,0xd2,0x1b,0xe1,0xfc,0x52,0xe0,0xad,0x52,0xcf,0x86,0x95,0x0f,0x94,0x0b, + 0x93,0x07,0x62,0x92,0x52,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xd1,0x13,0xe0, + 0xd3,0x53,0xcf,0x86,0x95,0x0a,0xe4,0xa8,0x53,0x63,0x97,0x53,0x04,0x00,0x04,0x00, + 0xd0,0x0d,0xcf,0x86,0x95,0x07,0x64,0x22,0x54,0x08,0x00,0x04,0x00,0xcf,0x86,0x55, + 0x04,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x07,0x62,0x2f,0x54,0x04,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0xb0,0x00,0x11,0xff,0xe1,0x8f,0xb1,0x00, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0xb2,0x00,0x11,0xff,0xe1,0x8f,0xb3,0x00,0x91,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0xb4,0x00,0x11,0xff,0xe1,0x8f,0xb5,0x00,0x00,0x00, + 0xd4,0x1c,0xe3,0xe0,0x56,0xe2,0x17,0x56,0xe1,0xda,0x55,0xe0,0xbb,0x55,0xcf,0x86, + 0x95,0x0a,0xe4,0xa4,0x55,0x63,0x88,0x55,0x04,0x00,0x04,0x00,0xe3,0xd2,0x01,0xe2, + 0x2b,0x5a,0xd1,0x0c,0xe0,0x4c,0x59,0xcf,0x86,0x65,0x25,0x59,0x0a,0x00,0xe0,0x9c, + 0x59,0xcf,0x86,0xd5,0xc5,0xd4,0x45,0xd3,0x31,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x12, + 0xff,0xd0,0xb2,0x00,0x12,0xff,0xd0,0xb4,0x00,0x10,0x07,0x12,0xff,0xd0,0xbe,0x00, + 0x12,0xff,0xd1,0x81,0x00,0x51,0x07,0x12,0xff,0xd1,0x82,0x00,0x10,0x07,0x12,0xff, + 0xd1,0x8a,0x00,0x12,0xff,0xd1,0xa3,0x00,0x92,0x10,0x91,0x0c,0x10,0x08,0x12,0xff, + 0xea,0x99,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x14,0xff,0xe1,0x83,0x90,0x00,0x14,0xff,0xe1,0x83,0x91,0x00,0x10,0x08, + 0x14,0xff,0xe1,0x83,0x92,0x00,0x14,0xff,0xe1,0x83,0x93,0x00,0xd1,0x10,0x10,0x08, + 0x14,0xff,0xe1,0x83,0x94,0x00,0x14,0xff,0xe1,0x83,0x95,0x00,0x10,0x08,0x14,0xff, + 0xe1,0x83,0x96,0x00,0x14,0xff,0xe1,0x83,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x14,0xff,0xe1,0x83,0x98,0x00,0x14,0xff,0xe1,0x83,0x99,0x00,0x10,0x08,0x14,0xff, + 0xe1,0x83,0x9a,0x00,0x14,0xff,0xe1,0x83,0x9b,0x00,0xd1,0x10,0x10,0x08,0x14,0xff, + 0xe1,0x83,0x9c,0x00,0x14,0xff,0xe1,0x83,0x9d,0x00,0x10,0x08,0x14,0xff,0xe1,0x83, + 0x9e,0x00,0x14,0xff,0xe1,0x83,0x9f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x14,0xff,0xe1,0x83,0xa0,0x00,0x14,0xff,0xe1,0x83,0xa1,0x00,0x10,0x08, + 0x14,0xff,0xe1,0x83,0xa2,0x00,0x14,0xff,0xe1,0x83,0xa3,0x00,0xd1,0x10,0x10,0x08, + 0x14,0xff,0xe1,0x83,0xa4,0x00,0x14,0xff,0xe1,0x83,0xa5,0x00,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xa6,0x00,0x14,0xff,0xe1,0x83,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x14,0xff,0xe1,0x83,0xa8,0x00,0x14,0xff,0xe1,0x83,0xa9,0x00,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xaa,0x00,0x14,0xff,0xe1,0x83,0xab,0x00,0xd1,0x10,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xac,0x00,0x14,0xff,0xe1,0x83,0xad,0x00,0x10,0x08,0x14,0xff,0xe1,0x83, + 0xae,0x00,0x14,0xff,0xe1,0x83,0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x14,0xff,0xe1,0x83,0xb0,0x00,0x14,0xff,0xe1,0x83,0xb1,0x00,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xb2,0x00,0x14,0xff,0xe1,0x83,0xb3,0x00,0xd1,0x10,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xb4,0x00,0x14,0xff,0xe1,0x83,0xb5,0x00,0x10,0x08,0x14,0xff,0xe1,0x83, + 0xb6,0x00,0x14,0xff,0xe1,0x83,0xb7,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x14,0xff, + 0xe1,0x83,0xb8,0x00,0x14,0xff,0xe1,0x83,0xb9,0x00,0x10,0x08,0x14,0xff,0xe1,0x83, + 0xba,0x00,0x00,0x00,0xd1,0x0c,0x10,0x04,0x00,0x00,0x14,0xff,0xe1,0x83,0xbd,0x00, + 0x10,0x08,0x14,0xff,0xe1,0x83,0xbe,0x00,0x14,0xff,0xe1,0x83,0xbf,0x00,0xe2,0x9d, + 0x08,0xe1,0x48,0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa5,0x00,0x01,0xff,0x61,0xcc, + 0xa5,0x00,0x10,0x08,0x01,0xff,0x62,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc,0x87,0x00, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x62,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc,0xa3,0x00, + 0x10,0x08,0x01,0xff,0x62,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00,0xd2,0x24, + 0xd1,0x14,0x10,0x0a,0x01,0xff,0x63,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff,0x63,0xcc, + 0xa7,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x87,0x00,0x01,0xff,0x64,0xcc, + 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa3,0x00,0x01,0xff,0x64,0xcc, + 0xa3,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc,0xb1,0x00, + 0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa7,0x00,0x01,0xff, + 0x64,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0xad,0x00,0x01,0xff,0x64,0xcc, + 0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff, + 0x65,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00, + 0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x65,0xcc,0xad,0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x65,0xcc, + 0xb0,0x00,0x01,0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc, + 0xa7,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08,0x01,0xff, + 0x66,0xcc,0x87,0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc,0x84,0x00, + 0x10,0x08,0x01,0xff,0x68,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0x68,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00,0x10,0x08, + 0x01,0xff,0x68,0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0x68,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00,0x10,0x08, + 0x01,0xff,0x68,0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0x69,0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a,0x01,0xff, + 0x69,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0x81,0x00,0x01,0xff,0x6b,0xcc, + 0x81,0x00,0x10,0x08,0x01,0xff,0x6b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc,0xa3,0x00, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc,0xb1,0x00, + 0x10,0x08,0x01,0xff,0x6c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00,0xd2,0x24, + 0xd1,0x14,0x10,0x0a,0x01,0xff,0x6c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,0x6c,0xcc, + 0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,0xb1,0x00,0x01,0xff,0x6c,0xcc, + 0xb1,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6c,0xcc,0xad,0x00,0x01,0xff,0x6c,0xcc, + 0xad,0x00,0x10,0x08,0x01,0xff,0x6d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc,0x81,0x00, + 0xcf,0x86,0xe5,0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x6d,0xcc,0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6d, + 0xcc,0xa3,0x00,0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e, + 0xcc,0x87,0x00,0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa3, + 0x00,0x01,0xff,0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e, + 0xcc,0xb1,0x00,0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xad, + 0x00,0x01,0xff,0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x83, + 0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f, + 0xcc,0x83,0xcc,0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3,0x48,0xd2, + 0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,0x6f, + 0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0x01, + 0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x70,0xcc,0x81, + 0x00,0x01,0xff,0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x70,0xcc,0x87,0x00,0x01, + 0xff,0x70,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x72,0xcc,0x87, + 0x00,0x01,0xff,0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xa3,0x00,0x01, + 0xff,0x72,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84, + 0x00,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xb1, + 0x00,0x01,0xff,0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x73,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10,0x08,0x01, + 0xff,0x73,0xcc,0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01, + 0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,0x10, + 0x0a,0x01,0xff,0x73,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c,0xcc,0x87, + 0x00,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x01, + 0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0x87,0x00,0x01, + 0xff,0x74,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xa3,0x00,0x01, + 0xff,0x74,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0xb1,0x00,0x01,0xff,0x74, + 0xcc,0xb1,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xad, + 0x00,0x01,0xff,0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa4,0x00,0x01, + 0xff,0x75,0xcc,0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0xb0,0x00,0x01, + 0xff,0x75,0xcc,0xb0,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xad,0x00,0x01,0xff,0x75, + 0xcc,0xad,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81, + 0x00,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x84, + 0xcc,0x88,0x00,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x76,0xcc,0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x76, + 0xcc,0xa3,0x00,0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x11,0x02,0xcf,0x86,0xd5,0xe2, + 0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x80,0x00, + 0x01,0xff,0x77,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x81,0x00,0x01,0xff, + 0x77,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x88,0x00,0x01,0xff, + 0x77,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x87,0x00,0x01,0xff,0x77,0xcc, + 0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0xa3,0x00,0x01,0xff, + 0x77,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x78,0xcc,0x87,0x00,0x01,0xff,0x78,0xcc, + 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x78,0xcc,0x88,0x00,0x01,0xff,0x78,0xcc, + 0x88,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc,0x87,0x00, + 0xd3,0x33,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x82,0x00,0x01,0xff, + 0x7a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0xa3,0x00,0x01,0xff,0x7a,0xcc, + 0xa3,0x00,0xe1,0x12,0x59,0x10,0x08,0x01,0xff,0x7a,0xcc,0xb1,0x00,0x01,0xff,0x7a, + 0xcc,0xb1,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01, + 0xff,0x79,0xcc,0x8a,0x00,0x10,0x08,0x01,0xff,0x61,0xca,0xbe,0x00,0x02,0xff,0x73, + 0xcc,0x87,0x00,0x51,0x04,0x0a,0x00,0x10,0x07,0x0a,0xff,0x73,0x73,0x00,0x0a,0x00, + 0xd4,0x98,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa3,0x00, + 0x01,0xff,0x61,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x89,0x00,0x01,0xff, + 0x61,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00, + 0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc, + 0x80,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a, + 0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00, + 0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc, + 0x83,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff, + 0x61,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00, + 0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a, + 0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00, + 0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc, + 0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x83,0x00,0x01,0xff, + 0x61,0xcc,0x86,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00, + 0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x65,0xcc,0xa3,0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x65,0xcc, + 0x89,0x00,0x01,0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc, + 0x83,0x00,0x01,0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc, + 0x81,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0xcf,0x86,0xe5,0x31,0x01,0xd4, + 0x90,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80, + 0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82, + 0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01, + 0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x10, + 0x0a,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x89,0x00,0x01,0xff,0x69, + 0xcc,0x89,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc,0xa3, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc,0xa3, + 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00,0xd3, + 0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x01, + 0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80, + 0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f, + 0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a,0x01, + 0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0xd2, + 0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x6f, + 0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0x01, + 0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b, + 0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x6f, + 0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x89,0x00,0xd4,0x98,0xd3, + 0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x01, + 0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3, + 0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75, + 0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x89, + 0x00,0x01,0xff,0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75, + 0xcc,0x9b,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x81,0x00,0x10,0x0a,0x01, + 0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0xd1, + 0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc,0x9b, + 0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,0x75, + 0xcc,0x9b,0xcc,0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75, + 0xcc,0x9b,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0xa3,0x00,0x10,0x08,0x01, + 0xff,0x79,0xcc,0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x79,0xcc,0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x79, + 0xcc,0x89,0x00,0x01,0xff,0x79,0xcc,0x89,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x79,0xcc,0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x10,0x08,0x0a,0xff,0xe1, + 0xbb,0xbb,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbd,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbf,0x00,0x0a,0x00,0xe1,0xbf,0x02,0xe0,0xa1, + 0x01,0xcf,0x86,0xd5,0xc6,0xd4,0x6c,0xd3,0x18,0xe2,0x0e,0x59,0xe1,0xf7,0x58,0x10, + 0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0x00,0xd2, + 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1, + 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff, + 0xce,0xb1,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc, + 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01, + 0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82, + 0x00,0xd3,0x18,0xe2,0x4a,0x59,0xe1,0x33,0x59,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc, + 0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01, + 0xff,0xce,0xb5,0xcc,0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01, + 0xff,0xce,0xb5,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80, + 0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff, + 0xce,0xb5,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd4,0x6c,0xd3,0x18,0xe2,0x74,0x59, + 0xe1,0x5d,0x59,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7, + 0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00, + 0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc, + 0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01, + 0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81, + 0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb7, + 0xcc,0x94,0xcd,0x82,0x00,0xd3,0x18,0xe2,0xb0,0x59,0xe1,0x99,0x59,0x10,0x09,0x01, + 0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0x00,0xd2,0x28,0xd1, + 0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94, + 0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9, + 0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc, + 0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce, + 0xb9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82,0x00,0xcf, + 0x86,0xd5,0xac,0xd4,0x5a,0xd3,0x18,0xe2,0xed,0x59,0xe1,0xd6,0x59,0x10,0x09,0x01, + 0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,0xd2,0x28,0xd1, + 0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94, + 0x00,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf, + 0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc, + 0x81,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x18,0xe2, + 0x17,0x5a,0xe1,0x00,0x5a,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff, + 0xcf,0x85,0xcc,0x94,0x00,0xd2,0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xcf, + 0x85,0xcc,0x94,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x80, + 0x00,0xd1,0x0f,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00, + 0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00,0xe4,0xd3,0x5a, + 0xd3,0x18,0xe2,0x52,0x5a,0xe1,0x3b,0x5a,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x93, + 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff, + 0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff, + 0xcf,0x89,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0x00, + 0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xcf, + 0x89,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82, + 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xe0,0xd9,0x02,0xcf,0x86,0xe5, + 0x91,0x01,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1, + 0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d, + 0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc, + 0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93, + 0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00, + 0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce, + 0xb1,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff, + 0xce,0xb1,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00, + 0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce, + 0xb1,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1, + 0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce, + 0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01, + 0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd3,0x64,0xd2,0x30,0xd1,0x16, + 0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc, + 0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0xce,0xb9, + 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d, + 0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc, + 0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82, + 0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30, + 0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce, + 0xb7,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80, + 0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a, + 0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce, + 0xb7,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93, + 0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00, + 0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93, + 0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff, + 0xcf,0x89,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc, + 0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81, + 0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d, + 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc, + 0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89, + 0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d, + 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc, + 0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93, + 0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00, + 0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf, + 0x89,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd3,0x49,0xd2,0x26,0xd1,0x12,0x10,0x09, + 0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,0xb1,0xcc,0x84,0x00,0x10,0x0b, + 0x01,0xff,0xce,0xb1,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xce,0xb9,0x00, + 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10, + 0x09,0x01,0xff,0xce,0xb1,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcd,0x82,0xce,0xb9, + 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff, + 0xce,0xb1,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01,0xff, + 0xce,0xb1,0xcc,0x81,0x00,0xe1,0xf3,0x5a,0x10,0x09,0x01,0xff,0xce,0xb1,0xce,0xb9, + 0x00,0x01,0x00,0xcf,0x86,0xd5,0xbd,0xd4,0x7e,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10, + 0x04,0x01,0x00,0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7, + 0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0xd1,0x0f,0x10,0x0b, + 0x01,0xff,0xce,0xb7,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce, + 0xb7,0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,0xd1, + 0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81, + 0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x81, + 0x00,0xe1,0x02,0x5b,0x10,0x09,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0x01,0xff,0xe1, + 0xbe,0xbf,0xcc,0x80,0x00,0xd3,0x18,0xe2,0x28,0x5b,0xe1,0x11,0x5b,0x10,0x09,0x01, + 0xff,0xce,0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0xe2,0x4c,0x5b, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc, + 0x84,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc, + 0x81,0x00,0xd4,0x51,0xd3,0x18,0xe2,0x6f,0x5b,0xe1,0x58,0x5b,0x10,0x09,0x01,0xff, + 0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00,0xd2,0x24,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00, + 0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00, + 0xe1,0x8f,0x5b,0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8, + 0xcc,0x80,0x00,0xd3,0x3b,0xd2,0x18,0x51,0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf, + 0x89,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0xd1,0x0f,0x10, + 0x0b,0x01,0xff,0xcf,0x89,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff, + 0xcf,0x89,0xcd,0x82,0x00,0x01,0xff,0xcf,0x89,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc, + 0x81,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc, + 0x81,0x00,0xe1,0x99,0x5b,0x10,0x09,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0x01,0xff, + 0xc2,0xb4,0x00,0xe0,0x0c,0x68,0xcf,0x86,0xe5,0x23,0x02,0xe4,0x25,0x01,0xe3,0x85, + 0x5e,0xd2,0x2a,0xe1,0x5f,0x5c,0xe0,0xdd,0x5b,0xcf,0x86,0xe5,0xbb,0x5b,0x94,0x1b, + 0xe3,0xa4,0x5b,0x92,0x14,0x91,0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01, + 0xff,0xe2,0x80,0x83,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd1,0xd6,0xd0,0x46,0xcf, + 0x86,0x55,0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,0x00,0x51,0x04,0x01, + 0x00,0x10,0x07,0x01,0xff,0xcf,0x89,0x00,0x01,0x00,0x92,0x12,0x51,0x04,0x01,0x00, + 0x10,0x06,0x01,0xff,0x6b,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x01,0x00,0xe3,0x25, + 0x5d,0x92,0x10,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0x8e,0x00,0x01, + 0x00,0x01,0x00,0xcf,0x86,0xd5,0x0a,0xe4,0x42,0x5d,0x63,0x2d,0x5d,0x06,0x00,0x94, + 0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb0,0x00,0x01, + 0xff,0xe2,0x85,0xb1,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb2,0x00,0x01,0xff,0xe2, + 0x85,0xb3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb4,0x00,0x01,0xff,0xe2, + 0x85,0xb5,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb6,0x00,0x01,0xff,0xe2,0x85,0xb7, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb8,0x00,0x01,0xff,0xe2, + 0x85,0xb9,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xba,0x00,0x01,0xff,0xe2,0x85,0xbb, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xbc,0x00,0x01,0xff,0xe2,0x85,0xbd, + 0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xbe,0x00,0x01,0xff,0xe2,0x85,0xbf,0x00,0x01, + 0x00,0xe0,0x34,0x5d,0xcf,0x86,0xe5,0x13,0x5d,0xe4,0xf2,0x5c,0xe3,0xe1,0x5c,0xe2, + 0xd4,0x5c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0xff,0xe2,0x86,0x84,0x00, + 0xe3,0x23,0x61,0xe2,0xf0,0x60,0xd1,0x0c,0xe0,0x9d,0x60,0xcf,0x86,0x65,0x7e,0x60, + 0x01,0x00,0xd0,0x62,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x18, + 0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x90,0x00, + 0x01,0xff,0xe2,0x93,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93, + 0x92,0x00,0x01,0xff,0xe2,0x93,0x93,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x94,0x00, + 0x01,0xff,0xe2,0x93,0x95,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x96,0x00, + 0x01,0xff,0xe2,0x93,0x97,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x98,0x00,0x01,0xff, + 0xe2,0x93,0x99,0x00,0xcf,0x86,0xe5,0x57,0x60,0x94,0x80,0xd3,0x40,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x9a,0x00,0x01,0xff,0xe2,0x93,0x9b,0x00,0x10, + 0x08,0x01,0xff,0xe2,0x93,0x9c,0x00,0x01,0xff,0xe2,0x93,0x9d,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe2,0x93,0x9e,0x00,0x01,0xff,0xe2,0x93,0x9f,0x00,0x10,0x08,0x01, + 0xff,0xe2,0x93,0xa0,0x00,0x01,0xff,0xe2,0x93,0xa1,0x00,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe2,0x93,0xa2,0x00,0x01,0xff,0xe2,0x93,0xa3,0x00,0x10,0x08,0x01, + 0xff,0xe2,0x93,0xa4,0x00,0x01,0xff,0xe2,0x93,0xa5,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe2,0x93,0xa6,0x00,0x01,0xff,0xe2,0x93,0xa7,0x00,0x10,0x08,0x01,0xff,0xe2, + 0x93,0xa8,0x00,0x01,0xff,0xe2,0x93,0xa9,0x00,0x01,0x00,0xd4,0x0c,0xe3,0x33,0x62, + 0xe2,0x2c,0x62,0xcf,0x06,0x04,0x00,0xe3,0x0c,0x65,0xe2,0xff,0x63,0xe1,0x2e,0x02, + 0xe0,0x84,0x01,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x08,0xff,0xe2,0xb0,0xb0,0x00,0x08,0xff,0xe2,0xb0,0xb1,0x00,0x10,0x08, + 0x08,0xff,0xe2,0xb0,0xb2,0x00,0x08,0xff,0xe2,0xb0,0xb3,0x00,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe2,0xb0,0xb4,0x00,0x08,0xff,0xe2,0xb0,0xb5,0x00,0x10,0x08,0x08,0xff, + 0xe2,0xb0,0xb6,0x00,0x08,0xff,0xe2,0xb0,0xb7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe2,0xb0,0xb8,0x00,0x08,0xff,0xe2,0xb0,0xb9,0x00,0x10,0x08,0x08,0xff, + 0xe2,0xb0,0xba,0x00,0x08,0xff,0xe2,0xb0,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe2,0xb0,0xbc,0x00,0x08,0xff,0xe2,0xb0,0xbd,0x00,0x10,0x08,0x08,0xff,0xe2,0xb0, + 0xbe,0x00,0x08,0xff,0xe2,0xb0,0xbf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe2,0xb1,0x80,0x00,0x08,0xff,0xe2,0xb1,0x81,0x00,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x82,0x00,0x08,0xff,0xe2,0xb1,0x83,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x84,0x00,0x08,0xff,0xe2,0xb1,0x85,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x86,0x00,0x08,0xff,0xe2,0xb1,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x88,0x00,0x08,0xff,0xe2,0xb1,0x89,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x8a,0x00,0x08,0xff,0xe2,0xb1,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x8c,0x00,0x08,0xff,0xe2,0xb1,0x8d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x8e,0x00, + 0x08,0xff,0xe2,0xb1,0x8f,0x00,0x94,0x7c,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe2,0xb1,0x90,0x00,0x08,0xff,0xe2,0xb1,0x91,0x00,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x92,0x00,0x08,0xff,0xe2,0xb1,0x93,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x94,0x00,0x08,0xff,0xe2,0xb1,0x95,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x96,0x00,0x08,0xff,0xe2,0xb1,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe2,0xb1,0x98,0x00,0x08,0xff,0xe2,0xb1,0x99,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x9a,0x00,0x08,0xff,0xe2,0xb1,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1, + 0x9c,0x00,0x08,0xff,0xe2,0xb1,0x9d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x9e,0x00, + 0x00,0x00,0x08,0x00,0xcf,0x86,0xd5,0x07,0x64,0xef,0x61,0x08,0x00,0xd4,0x63,0xd3, + 0x32,0xd2,0x1b,0xd1,0x0c,0x10,0x08,0x09,0xff,0xe2,0xb1,0xa1,0x00,0x09,0x00,0x10, + 0x07,0x09,0xff,0xc9,0xab,0x00,0x09,0xff,0xe1,0xb5,0xbd,0x00,0xd1,0x0b,0x10,0x07, + 0x09,0xff,0xc9,0xbd,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xa8, + 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xaa,0x00,0x10, + 0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xac,0x00,0xd1,0x0b,0x10,0x04,0x09,0x00,0x0a, + 0xff,0xc9,0x91,0x00,0x10,0x07,0x0a,0xff,0xc9,0xb1,0x00,0x0a,0xff,0xc9,0x90,0x00, + 0xd3,0x27,0xd2,0x17,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xc9,0x92,0x00,0x0a,0x00,0x10, + 0x08,0x0a,0xff,0xe2,0xb1,0xb3,0x00,0x0a,0x00,0x91,0x0c,0x10,0x04,0x09,0x00,0x09, + 0xff,0xe2,0xb1,0xb6,0x00,0x09,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10, + 0x07,0x0b,0xff,0xc8,0xbf,0x00,0x0b,0xff,0xc9,0x80,0x00,0xe0,0x83,0x01,0xcf,0x86, + 0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2, + 0x81,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x83,0x00,0x08,0x00,0xd1,0x0c, + 0x10,0x08,0x08,0xff,0xe2,0xb2,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2, + 0x87,0x00,0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x89,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08, + 0x08,0xff,0xe2,0xb2,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x8f,0x00, + 0x08,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x91,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08, + 0x08,0xff,0xe2,0xb2,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x97,0x00, + 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x99,0x00,0x08,0x00, + 0x10,0x08,0x08,0xff,0xe2,0xb2,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff, + 0xe2,0xb2,0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x9f,0x00,0x08,0x00, + 0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa1,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08, + 0x08,0xff,0xe2,0xb2,0xa5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa7,0x00, + 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa9,0x00,0x08,0x00, + 0x10,0x08,0x08,0xff,0xe2,0xb2,0xab,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff, + 0xe2,0xb2,0xad,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xaf,0x00,0x08,0x00, + 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb1,0x00,0x08,0x00, + 0x10,0x08,0x08,0xff,0xe2,0xb2,0xb3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff, + 0xe2,0xb2,0xb5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb7,0x00,0x08,0x00, + 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb9,0x00,0x08,0x00,0x10,0x08, + 0x08,0xff,0xe2,0xb2,0xbb,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2, + 0xbd,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xbf,0x00,0x08,0x00,0xcf,0x86, + 0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3, + 0x81,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x83,0x00,0x08,0x00,0xd1,0x0c, + 0x10,0x08,0x08,0xff,0xe2,0xb3,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3, + 0x87,0x00,0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x89,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08, + 0x08,0xff,0xe2,0xb3,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x8f,0x00, + 0x08,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x91,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08, + 0x08,0xff,0xe2,0xb3,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x97,0x00, + 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x99,0x00,0x08,0x00, + 0x10,0x08,0x08,0xff,0xe2,0xb3,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff, + 0xe2,0xb3,0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x9f,0x00,0x08,0x00, + 0xd4,0x3b,0xd3,0x1c,0x92,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0xa1,0x00, + 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0xa3,0x00,0x08,0x00,0x08,0x00,0xd2,0x10, + 0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x0b,0xff,0xe2,0xb3,0xac,0x00,0xe1,0x3b, + 0x5f,0x10,0x04,0x0b,0x00,0x0b,0xff,0xe2,0xb3,0xae,0x00,0xe3,0x40,0x5f,0x92,0x10, + 0x51,0x04,0x0b,0xe6,0x10,0x08,0x0d,0xff,0xe2,0xb3,0xb3,0x00,0x0d,0x00,0x00,0x00, + 0xe2,0x98,0x08,0xd1,0x0b,0xe0,0x11,0x67,0xcf,0x86,0xcf,0x06,0x01,0x00,0xe0,0x65, + 0x6c,0xcf,0x86,0xe5,0xa7,0x05,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x0c,0xe2,0xf8, + 0x67,0xe1,0x8f,0x67,0xcf,0x06,0x04,0x00,0xe2,0xdb,0x01,0xe1,0x26,0x01,0xd0,0x09, + 0xcf,0x86,0x65,0xf4,0x67,0x0a,0x00,0xcf,0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2, + 0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a, + 0xff,0xea,0x99,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x85, + 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1, + 0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea, + 0x99,0x8b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x8d,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1, + 0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea, + 0x99,0x93,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x95,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x97,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10, + 0x08,0x0a,0xff,0xea,0x99,0x99,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x9b, + 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x9d,0x00,0x0a,0x00,0x10, + 0x08,0x0a,0xff,0xea,0x99,0x9f,0x00,0x0a,0x00,0xe4,0x5d,0x67,0xd3,0x30,0xd2,0x18, + 0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x99,0xa1,0x00,0x0c,0x00,0x10,0x08,0x0a,0xff, + 0xea,0x99,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0xa5,0x00, + 0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c, + 0x10,0x08,0x0a,0xff,0xea,0x99,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99, + 0xab,0x00,0x0a,0x00,0xe1,0x0c,0x67,0x10,0x08,0x0a,0xff,0xea,0x99,0xad,0x00,0x0a, + 0x00,0xe0,0x35,0x67,0xcf,0x86,0x95,0xab,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c, + 0x10,0x08,0x0a,0xff,0xea,0x9a,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a, + 0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x85,0x00,0x0a,0x00, + 0x10,0x08,0x0a,0xff,0xea,0x9a,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08, + 0x0a,0xff,0xea,0x9a,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8b,0x00, + 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8d,0x00,0x0a,0x00,0x10,0x08, + 0x0a,0xff,0xea,0x9a,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08, + 0x0a,0xff,0xea,0x9a,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x93,0x00, + 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x95,0x00,0x0a,0x00,0x10,0x08, + 0x0a,0xff,0xea,0x9a,0x97,0x00,0x0a,0x00,0xe2,0x92,0x66,0xd1,0x0c,0x10,0x08,0x10, + 0xff,0xea,0x9a,0x99,0x00,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9a,0x9b,0x00,0x10, + 0x00,0x0b,0x00,0xe1,0x10,0x02,0xd0,0xb9,0xcf,0x86,0xd5,0x07,0x64,0x9e,0x66,0x08, + 0x00,0xd4,0x58,0xd3,0x28,0xd2,0x10,0x51,0x04,0x09,0x00,0x10,0x08,0x0a,0xff,0xea, + 0x9c,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa5,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10, + 0x08,0x0a,0xff,0xea,0x9c,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xab, + 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xad,0x00,0x0a,0x00,0x10, + 0x08,0x0a,0xff,0xea,0x9c,0xaf,0x00,0x0a,0x00,0xd3,0x28,0xd2,0x10,0x51,0x04,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a, + 0xff,0xea,0x9c,0xb5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb7,0x00,0x0a, + 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb9,0x00,0x0a,0x00,0x10, + 0x08,0x0a,0xff,0xea,0x9c,0xbb,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea, + 0x9c,0xbd,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xbf,0x00,0x0a,0x00,0xcf, + 0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea, + 0x9d,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x83,0x00,0x0a,0x00,0xd1, + 0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x85,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea, + 0x9d,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x89, + 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8b,0x00,0x0a,0x00,0xd1,0x0c,0x10, + 0x08,0x0a,0xff,0xea,0x9d,0x8d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8f, + 0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x91, + 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x93,0x00,0x0a,0x00,0xd1,0x0c,0x10, + 0x08,0x0a,0xff,0xea,0x9d,0x95,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x97, + 0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x99,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x9b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a, + 0xff,0xea,0x9d,0x9d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x9f,0x00,0x0a, + 0x00,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa1, + 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10, + 0x08,0x0a,0xff,0xea,0x9d,0xa5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa7, + 0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa9,0x00,0x0a, + 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xab,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a, + 0xff,0xea,0x9d,0xad,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xaf,0x00,0x0a, + 0x00,0x53,0x04,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea, + 0x9d,0xba,0x00,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9d,0xbc,0x00,0xd1,0x0c,0x10, + 0x04,0x0a,0x00,0x0a,0xff,0xe1,0xb5,0xb9,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xbf, + 0x00,0x0a,0x00,0xe0,0x71,0x01,0xcf,0x86,0xd5,0xa6,0xd4,0x4e,0xd3,0x30,0xd2,0x18, + 0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9e,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff, + 0xea,0x9e,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9e,0x85,0x00, + 0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9e,0x87,0x00,0x0a,0x00,0xd2,0x10,0x51,0x04, + 0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9e,0x8c,0x00,0xe1,0x9a,0x64,0x10, + 0x04,0x0a,0x00,0x0c,0xff,0xc9,0xa5,0x00,0xd3,0x28,0xd2,0x18,0xd1,0x0c,0x10,0x08, + 0x0c,0xff,0xea,0x9e,0x91,0x00,0x0c,0x00,0x10,0x08,0x0d,0xff,0xea,0x9e,0x93,0x00, + 0x0d,0x00,0x51,0x04,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x97,0x00,0x10,0x00, + 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e,0x99,0x00,0x10,0x00,0x10,0x08, + 0x10,0xff,0xea,0x9e,0x9b,0x00,0x10,0x00,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e, + 0x9d,0x00,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x9f,0x00,0x10,0x00,0xd4,0x63, + 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa1,0x00,0x0c,0x00, + 0x10,0x08,0x0c,0xff,0xea,0x9e,0xa3,0x00,0x0c,0x00,0xd1,0x0c,0x10,0x08,0x0c,0xff, + 0xea,0x9e,0xa5,0x00,0x0c,0x00,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa7,0x00,0x0c,0x00, + 0xd2,0x1a,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa9,0x00,0x0c,0x00,0x10,0x07, + 0x0d,0xff,0xc9,0xa6,0x00,0x10,0xff,0xc9,0x9c,0x00,0xd1,0x0e,0x10,0x07,0x10,0xff, + 0xc9,0xa1,0x00,0x10,0xff,0xc9,0xac,0x00,0x10,0x07,0x12,0xff,0xc9,0xaa,0x00,0x14, + 0x00,0xd3,0x35,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x10,0xff,0xca,0x9e,0x00,0x10,0xff, + 0xca,0x87,0x00,0x10,0x07,0x11,0xff,0xca,0x9d,0x00,0x11,0xff,0xea,0xad,0x93,0x00, + 0xd1,0x0c,0x10,0x08,0x11,0xff,0xea,0x9e,0xb5,0x00,0x11,0x00,0x10,0x08,0x11,0xff, + 0xea,0x9e,0xb7,0x00,0x11,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x14,0xff,0xea,0x9e, + 0xb9,0x00,0x14,0x00,0x10,0x08,0x15,0xff,0xea,0x9e,0xbb,0x00,0x15,0x00,0xd1,0x0c, + 0x10,0x08,0x15,0xff,0xea,0x9e,0xbd,0x00,0x15,0x00,0x10,0x08,0x15,0xff,0xea,0x9e, + 0xbf,0x00,0x15,0x00,0xcf,0x86,0xe5,0xd4,0x63,0x94,0x2f,0x93,0x2b,0xd2,0x10,0x51, + 0x04,0x00,0x00,0x10,0x08,0x15,0xff,0xea,0x9f,0x83,0x00,0x15,0x00,0xd1,0x0f,0x10, + 0x08,0x15,0xff,0xea,0x9e,0x94,0x00,0x15,0xff,0xca,0x82,0x00,0x10,0x08,0x15,0xff, + 0xe1,0xb6,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0xb4,0x66,0xd3,0x1d,0xe2, + 0x5b,0x64,0xe1,0x0a,0x64,0xe0,0xf7,0x63,0xcf,0x86,0xe5,0xd8,0x63,0x94,0x0b,0x93, + 0x07,0x62,0xc3,0x63,0x08,0x00,0x08,0x00,0x08,0x00,0xd2,0x0f,0xe1,0x5a,0x65,0xe0, + 0x27,0x65,0xcf,0x86,0x65,0x0c,0x65,0x0a,0x00,0xd1,0xab,0xd0,0x1a,0xcf,0x86,0xe5, + 0x17,0x66,0xe4,0xfa,0x65,0xe3,0xe1,0x65,0xe2,0xd4,0x65,0x91,0x08,0x10,0x04,0x00, + 0x00,0x0c,0x00,0x0c,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x0b,0x93,0x07,0x62, + 0x27,0x66,0x11,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff, + 0xe1,0x8e,0xa0,0x00,0x11,0xff,0xe1,0x8e,0xa1,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e, + 0xa2,0x00,0x11,0xff,0xe1,0x8e,0xa3,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e, + 0xa4,0x00,0x11,0xff,0xe1,0x8e,0xa5,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa6,0x00, + 0x11,0xff,0xe1,0x8e,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e, + 0xa8,0x00,0x11,0xff,0xe1,0x8e,0xa9,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xaa,0x00, + 0x11,0xff,0xe1,0x8e,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xac,0x00, + 0x11,0xff,0xe1,0x8e,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xae,0x00,0x11,0xff, + 0xe1,0x8e,0xaf,0x00,0xe0,0xb2,0x65,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb0,0x00,0x11,0xff,0xe1,0x8e, + 0xb1,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb2,0x00,0x11,0xff,0xe1,0x8e,0xb3,0x00, + 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb4,0x00,0x11,0xff,0xe1,0x8e,0xb5,0x00, + 0x10,0x08,0x11,0xff,0xe1,0x8e,0xb6,0x00,0x11,0xff,0xe1,0x8e,0xb7,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb8,0x00,0x11,0xff,0xe1,0x8e,0xb9,0x00, + 0x10,0x08,0x11,0xff,0xe1,0x8e,0xba,0x00,0x11,0xff,0xe1,0x8e,0xbb,0x00,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8e,0xbc,0x00,0x11,0xff,0xe1,0x8e,0xbd,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8e,0xbe,0x00,0x11,0xff,0xe1,0x8e,0xbf,0x00,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0x80,0x00,0x11,0xff,0xe1,0x8f,0x81,0x00, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x82,0x00,0x11,0xff,0xe1,0x8f,0x83,0x00,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x84,0x00,0x11,0xff,0xe1,0x8f,0x85,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x86,0x00,0x11,0xff,0xe1,0x8f,0x87,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x88,0x00,0x11,0xff,0xe1,0x8f,0x89,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x8a,0x00,0x11,0xff,0xe1,0x8f,0x8b,0x00,0xd1,0x10,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x8c,0x00,0x11,0xff,0xe1,0x8f,0x8d,0x00,0x10,0x08,0x11,0xff, + 0xe1,0x8f,0x8e,0x00,0x11,0xff,0xe1,0x8f,0x8f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0x90,0x00,0x11,0xff,0xe1,0x8f,0x91,0x00, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x92,0x00,0x11,0xff,0xe1,0x8f,0x93,0x00,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x94,0x00,0x11,0xff,0xe1,0x8f,0x95,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x96,0x00,0x11,0xff,0xe1,0x8f,0x97,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0x98,0x00,0x11,0xff,0xe1,0x8f,0x99,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x9a,0x00,0x11,0xff,0xe1,0x8f,0x9b,0x00,0xd1,0x10,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0x9c,0x00,0x11,0xff,0xe1,0x8f,0x9d,0x00,0x10,0x08,0x11,0xff, + 0xe1,0x8f,0x9e,0x00,0x11,0xff,0xe1,0x8f,0x9f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x11,0xff,0xe1,0x8f,0xa0,0x00,0x11,0xff,0xe1,0x8f,0xa1,0x00,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0xa2,0x00,0x11,0xff,0xe1,0x8f,0xa3,0x00,0xd1,0x10,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0xa4,0x00,0x11,0xff,0xe1,0x8f,0xa5,0x00,0x10,0x08,0x11,0xff, + 0xe1,0x8f,0xa6,0x00,0x11,0xff,0xe1,0x8f,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x11,0xff,0xe1,0x8f,0xa8,0x00,0x11,0xff,0xe1,0x8f,0xa9,0x00,0x10,0x08,0x11,0xff, + 0xe1,0x8f,0xaa,0x00,0x11,0xff,0xe1,0x8f,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff, + 0xe1,0x8f,0xac,0x00,0x11,0xff,0xe1,0x8f,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f, + 0xae,0x00,0x11,0xff,0xe1,0x8f,0xaf,0x00,0xd1,0x0c,0xe0,0xeb,0x63,0xcf,0x86,0xcf, + 0x06,0x02,0xff,0xff,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06, + 0xcf,0x06,0x01,0x00,0xd4,0xae,0xd3,0x09,0xe2,0x54,0x64,0xcf,0x06,0x01,0x00,0xd2, + 0x27,0xe1,0x1f,0x70,0xe0,0x26,0x6e,0xcf,0x86,0xe5,0x3f,0x6d,0xe4,0xce,0x6c,0xe3, + 0x99,0x6c,0xe2,0x78,0x6c,0xe1,0x67,0x6c,0x10,0x08,0x01,0xff,0xe5,0x88,0x87,0x00, + 0x01,0xff,0xe5,0xba,0xa6,0x00,0xe1,0x74,0x74,0xe0,0xe8,0x73,0xcf,0x86,0xe5,0x22, + 0x73,0xd4,0x3b,0x93,0x37,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x01,0xff,0x66,0x66,0x00, + 0x01,0xff,0x66,0x69,0x00,0x10,0x07,0x01,0xff,0x66,0x6c,0x00,0x01,0xff,0x66,0x66, + 0x69,0x00,0xd1,0x0f,0x10,0x08,0x01,0xff,0x66,0x66,0x6c,0x00,0x01,0xff,0x73,0x74, + 0x00,0x10,0x07,0x01,0xff,0x73,0x74,0x00,0x00,0x00,0x00,0x00,0xe3,0xc8,0x72,0xd2, + 0x11,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xd5,0xb4,0xd5,0xb6,0x00, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xd5,0xb4,0xd5,0xa5,0x00,0x01,0xff,0xd5,0xb4,0xd5, + 0xab,0x00,0x10,0x09,0x01,0xff,0xd5,0xbe,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb4,0xd5, + 0xad,0x00,0xd3,0x09,0xe2,0x40,0x74,0xcf,0x06,0x01,0x00,0xd2,0x13,0xe1,0x30,0x75, + 0xe0,0xc1,0x74,0xcf,0x86,0xe5,0x9e,0x74,0x64,0x8d,0x74,0x06,0xff,0x00,0xe1,0x96, + 0x75,0xe0,0x63,0x75,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x7c, + 0xd3,0x3c,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xef,0xbd,0x81,0x00, + 0x10,0x08,0x01,0xff,0xef,0xbd,0x82,0x00,0x01,0xff,0xef,0xbd,0x83,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xef,0xbd,0x84,0x00,0x01,0xff,0xef,0xbd,0x85,0x00,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x86,0x00,0x01,0xff,0xef,0xbd,0x87,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xef,0xbd,0x88,0x00,0x01,0xff,0xef,0xbd,0x89,0x00,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x8a,0x00,0x01,0xff,0xef,0xbd,0x8b,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x8c,0x00,0x01,0xff,0xef,0xbd,0x8d,0x00,0x10,0x08,0x01,0xff, + 0xef,0xbd,0x8e,0x00,0x01,0xff,0xef,0xbd,0x8f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xef,0xbd,0x90,0x00,0x01,0xff,0xef,0xbd,0x91,0x00,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x92,0x00,0x01,0xff,0xef,0xbd,0x93,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x94,0x00,0x01,0xff,0xef,0xbd,0x95,0x00,0x10,0x08,0x01,0xff, + 0xef,0xbd,0x96,0x00,0x01,0xff,0xef,0xbd,0x97,0x00,0x92,0x1c,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xef,0xbd,0x98,0x00,0x01,0xff,0xef,0xbd,0x99,0x00,0x10,0x08,0x01,0xff, + 0xef,0xbd,0x9a,0x00,0x01,0x00,0x01,0x00,0x83,0xe2,0x87,0xb3,0xe1,0x60,0xb0,0xe0, + 0xdd,0xae,0xcf,0x86,0xe5,0x81,0x9b,0xc4,0xe3,0xc1,0x07,0xe2,0x62,0x06,0xe1,0x11, + 0x86,0xe0,0x09,0x05,0xcf,0x86,0xe5,0xfb,0x02,0xd4,0x1c,0xe3,0x7f,0x76,0xe2,0xd6, + 0x75,0xe1,0xb1,0x75,0xe0,0x8a,0x75,0xcf,0x86,0xe5,0x57,0x75,0x94,0x07,0x63,0x42, + 0x75,0x07,0x00,0x07,0x00,0xe3,0x2b,0x78,0xe2,0xf0,0x77,0xe1,0x77,0x01,0xe0,0x88, + 0x77,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09, + 0x05,0xff,0xf0,0x90,0x90,0xa8,0x00,0x05,0xff,0xf0,0x90,0x90,0xa9,0x00,0x10,0x09, + 0x05,0xff,0xf0,0x90,0x90,0xaa,0x00,0x05,0xff,0xf0,0x90,0x90,0xab,0x00,0xd1,0x12, + 0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xac,0x00,0x05,0xff,0xf0,0x90,0x90,0xad,0x00, + 0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xae,0x00,0x05,0xff,0xf0,0x90,0x90,0xaf,0x00, + 0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb0,0x00,0x05,0xff,0xf0, + 0x90,0x90,0xb1,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb2,0x00,0x05,0xff,0xf0, + 0x90,0x90,0xb3,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb4,0x00,0x05, + 0xff,0xf0,0x90,0x90,0xb5,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb6,0x00,0x05, + 0xff,0xf0,0x90,0x90,0xb7,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff, + 0xf0,0x90,0x90,0xb8,0x00,0x05,0xff,0xf0,0x90,0x90,0xb9,0x00,0x10,0x09,0x05,0xff, + 0xf0,0x90,0x90,0xba,0x00,0x05,0xff,0xf0,0x90,0x90,0xbb,0x00,0xd1,0x12,0x10,0x09, + 0x05,0xff,0xf0,0x90,0x90,0xbc,0x00,0x05,0xff,0xf0,0x90,0x90,0xbd,0x00,0x10,0x09, + 0x05,0xff,0xf0,0x90,0x90,0xbe,0x00,0x05,0xff,0xf0,0x90,0x90,0xbf,0x00,0xd2,0x24, + 0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x80,0x00,0x05,0xff,0xf0,0x90,0x91, + 0x81,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x82,0x00,0x05,0xff,0xf0,0x90,0x91, + 0x83,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x84,0x00,0x05,0xff,0xf0, + 0x90,0x91,0x85,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x86,0x00,0x05,0xff,0xf0, + 0x90,0x91,0x87,0x00,0x94,0x4c,0x93,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff, + 0xf0,0x90,0x91,0x88,0x00,0x05,0xff,0xf0,0x90,0x91,0x89,0x00,0x10,0x09,0x05,0xff, + 0xf0,0x90,0x91,0x8a,0x00,0x05,0xff,0xf0,0x90,0x91,0x8b,0x00,0xd1,0x12,0x10,0x09, + 0x05,0xff,0xf0,0x90,0x91,0x8c,0x00,0x05,0xff,0xf0,0x90,0x91,0x8d,0x00,0x10,0x09, + 0x07,0xff,0xf0,0x90,0x91,0x8e,0x00,0x07,0xff,0xf0,0x90,0x91,0x8f,0x00,0x05,0x00, + 0x05,0x00,0xd0,0xa0,0xcf,0x86,0xd5,0x07,0x64,0x30,0x76,0x07,0x00,0xd4,0x07,0x63, + 0x3d,0x76,0x07,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90, + 0x93,0x98,0x00,0x12,0xff,0xf0,0x90,0x93,0x99,0x00,0x10,0x09,0x12,0xff,0xf0,0x90, + 0x93,0x9a,0x00,0x12,0xff,0xf0,0x90,0x93,0x9b,0x00,0xd1,0x12,0x10,0x09,0x12,0xff, + 0xf0,0x90,0x93,0x9c,0x00,0x12,0xff,0xf0,0x90,0x93,0x9d,0x00,0x10,0x09,0x12,0xff, + 0xf0,0x90,0x93,0x9e,0x00,0x12,0xff,0xf0,0x90,0x93,0x9f,0x00,0xd2,0x24,0xd1,0x12, + 0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa0,0x00,0x12,0xff,0xf0,0x90,0x93,0xa1,0x00, + 0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa2,0x00,0x12,0xff,0xf0,0x90,0x93,0xa3,0x00, + 0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa4,0x00,0x12,0xff,0xf0,0x90,0x93, + 0xa5,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa6,0x00,0x12,0xff,0xf0,0x90,0x93, + 0xa7,0x00,0xcf,0x86,0xe5,0xc6,0x75,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10, + 0x09,0x12,0xff,0xf0,0x90,0x93,0xa8,0x00,0x12,0xff,0xf0,0x90,0x93,0xa9,0x00,0x10, + 0x09,0x12,0xff,0xf0,0x90,0x93,0xaa,0x00,0x12,0xff,0xf0,0x90,0x93,0xab,0x00,0xd1, + 0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xac,0x00,0x12,0xff,0xf0,0x90,0x93,0xad, + 0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xae,0x00,0x12,0xff,0xf0,0x90,0x93,0xaf, + 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb0,0x00,0x12,0xff, + 0xf0,0x90,0x93,0xb1,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb2,0x00,0x12,0xff, + 0xf0,0x90,0x93,0xb3,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb4,0x00, + 0x12,0xff,0xf0,0x90,0x93,0xb5,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb6,0x00, + 0x12,0xff,0xf0,0x90,0x93,0xb7,0x00,0x93,0x28,0x92,0x24,0xd1,0x12,0x10,0x09,0x12, + 0xff,0xf0,0x90,0x93,0xb8,0x00,0x12,0xff,0xf0,0x90,0x93,0xb9,0x00,0x10,0x09,0x12, + 0xff,0xf0,0x90,0x93,0xba,0x00,0x12,0xff,0xf0,0x90,0x93,0xbb,0x00,0x00,0x00,0x12, + 0x00,0xd4,0x1f,0xe3,0xdf,0x76,0xe2,0x6a,0x76,0xe1,0x09,0x76,0xe0,0xea,0x75,0xcf, + 0x86,0xe5,0xb7,0x75,0x94,0x0a,0xe3,0xa2,0x75,0x62,0x99,0x75,0x07,0x00,0x07,0x00, + 0xe3,0xde,0x78,0xe2,0xaf,0x78,0xd1,0x09,0xe0,0x4c,0x78,0xcf,0x06,0x0b,0x00,0xe0, + 0x7f,0x78,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0x80,0x00,0x11,0xff,0xf0,0x90,0xb3,0x81,0x00,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0x82,0x00,0x11,0xff,0xf0,0x90,0xb3,0x83,0x00,0xd1, + 0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x84,0x00,0x11,0xff,0xf0,0x90,0xb3,0x85, + 0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x86,0x00,0x11,0xff,0xf0,0x90,0xb3,0x87, + 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x88,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0x89,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8a,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0x8b,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8c,0x00, + 0x11,0xff,0xf0,0x90,0xb3,0x8d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8e,0x00, + 0x11,0xff,0xf0,0x90,0xb3,0x8f,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11, + 0xff,0xf0,0x90,0xb3,0x90,0x00,0x11,0xff,0xf0,0x90,0xb3,0x91,0x00,0x10,0x09,0x11, + 0xff,0xf0,0x90,0xb3,0x92,0x00,0x11,0xff,0xf0,0x90,0xb3,0x93,0x00,0xd1,0x12,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0x94,0x00,0x11,0xff,0xf0,0x90,0xb3,0x95,0x00,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0x96,0x00,0x11,0xff,0xf0,0x90,0xb3,0x97,0x00,0xd2, + 0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x98,0x00,0x11,0xff,0xf0,0x90, + 0xb3,0x99,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9a,0x00,0x11,0xff,0xf0,0x90, + 0xb3,0x9b,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9c,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0x9d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9e,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0x9f,0x00,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11, + 0xff,0xf0,0x90,0xb3,0xa0,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa1,0x00,0x10,0x09,0x11, + 0xff,0xf0,0x90,0xb3,0xa2,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa3,0x00,0xd1,0x12,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0xa4,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa5,0x00,0x10, + 0x09,0x11,0xff,0xf0,0x90,0xb3,0xa6,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa7,0x00,0xd2, + 0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xa8,0x00,0x11,0xff,0xf0,0x90, + 0xb3,0xa9,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xaa,0x00,0x11,0xff,0xf0,0x90, + 0xb3,0xab,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xac,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0xad,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xae,0x00,0x11,0xff, + 0xf0,0x90,0xb3,0xaf,0x00,0x93,0x23,0x92,0x1f,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0, + 0x90,0xb3,0xb0,0x00,0x11,0xff,0xf0,0x90,0xb3,0xb1,0x00,0x10,0x09,0x11,0xff,0xf0, + 0x90,0xb3,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x15,0xe4,0x91, + 0x7b,0xe3,0x9b,0x79,0xe2,0x94,0x78,0xe1,0xe4,0x77,0xe0,0x9d,0x77,0xcf,0x06,0x0c, + 0x00,0xe4,0xeb,0x7e,0xe3,0x44,0x7e,0xe2,0xed,0x7d,0xd1,0x0c,0xe0,0xb2,0x7d,0xcf, + 0x86,0x65,0x93,0x7d,0x14,0x00,0xe0,0xb6,0x7d,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4, + 0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x80,0x00, + 0x10,0xff,0xf0,0x91,0xa3,0x81,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x82,0x00, + 0x10,0xff,0xf0,0x91,0xa3,0x83,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3, + 0x84,0x00,0x10,0xff,0xf0,0x91,0xa3,0x85,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3, + 0x86,0x00,0x10,0xff,0xf0,0x91,0xa3,0x87,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10, + 0xff,0xf0,0x91,0xa3,0x88,0x00,0x10,0xff,0xf0,0x91,0xa3,0x89,0x00,0x10,0x09,0x10, + 0xff,0xf0,0x91,0xa3,0x8a,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8b,0x00,0xd1,0x12,0x10, + 0x09,0x10,0xff,0xf0,0x91,0xa3,0x8c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8d,0x00,0x10, + 0x09,0x10,0xff,0xf0,0x91,0xa3,0x8e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8f,0x00,0xd3, + 0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x90,0x00,0x10,0xff, + 0xf0,0x91,0xa3,0x91,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x92,0x00,0x10,0xff, + 0xf0,0x91,0xa3,0x93,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x94,0x00, + 0x10,0xff,0xf0,0x91,0xa3,0x95,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x96,0x00, + 0x10,0xff,0xf0,0x91,0xa3,0x97,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0, + 0x91,0xa3,0x98,0x00,0x10,0xff,0xf0,0x91,0xa3,0x99,0x00,0x10,0x09,0x10,0xff,0xf0, + 0x91,0xa3,0x9a,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9b,0x00,0xd1,0x12,0x10,0x09,0x10, + 0xff,0xf0,0x91,0xa3,0x9c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9d,0x00,0x10,0x09,0x10, + 0xff,0xf0,0x91,0xa3,0x9e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9f,0x00,0xd1,0x11,0xe0, + 0x12,0x81,0xcf,0x86,0xe5,0x09,0x81,0xe4,0xd2,0x80,0xcf,0x06,0x00,0x00,0xe0,0xdb, + 0x82,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x09,0xe3,0x10,0x81,0xcf,0x06, + 0x0c,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xe2,0x3b,0x82,0xe1,0x16,0x82,0xd0,0x06, + 0xcf,0x06,0x00,0x00,0xcf,0x86,0xa5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1, + 0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa1, + 0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa3, + 0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa4,0x00,0x14,0xff,0xf0,0x96, + 0xb9,0xa5,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa6,0x00,0x14,0xff,0xf0,0x96, + 0xb9,0xa7,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa8,0x00, + 0x14,0xff,0xf0,0x96,0xb9,0xa9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xaa,0x00, + 0x14,0xff,0xf0,0x96,0xb9,0xab,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9, + 0xac,0x00,0x14,0xff,0xf0,0x96,0xb9,0xad,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9, + 0xae,0x00,0x14,0xff,0xf0,0x96,0xb9,0xaf,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10, + 0x09,0x14,0xff,0xf0,0x96,0xb9,0xb0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb1,0x00,0x10, + 0x09,0x14,0xff,0xf0,0x96,0xb9,0xb2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb3,0x00,0xd1, + 0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb4,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb5, + 0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb6,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb7, + 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb8,0x00,0x14,0xff, + 0xf0,0x96,0xb9,0xb9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xba,0x00,0x14,0xff, + 0xf0,0x96,0xb9,0xbb,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbc,0x00, + 0x14,0xff,0xf0,0x96,0xb9,0xbd,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbe,0x00, + 0x14,0xff,0xf0,0x96,0xb9,0xbf,0x00,0x14,0x00,0xd2,0x14,0xe1,0x25,0x82,0xe0,0x1c, + 0x82,0xcf,0x86,0xe5,0xdd,0x81,0xe4,0x9a,0x81,0xcf,0x06,0x12,0x00,0xd1,0x0b,0xe0, + 0x51,0x83,0xcf,0x86,0xcf,0x06,0x00,0x00,0xe0,0x95,0x8b,0xcf,0x86,0xd5,0x22,0xe4, + 0xd0,0x88,0xe3,0x93,0x88,0xe2,0x38,0x88,0xe1,0x31,0x88,0xe0,0x2a,0x88,0xcf,0x86, + 0xe5,0xfb,0x87,0xe4,0xe2,0x87,0x93,0x07,0x62,0xd1,0x87,0x12,0xe6,0x12,0xe6,0xe4, + 0x36,0x89,0xe3,0x2f,0x89,0xd2,0x09,0xe1,0xb8,0x88,0xcf,0x06,0x10,0x00,0xe1,0x1f, + 0x89,0xe0,0xec,0x88,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1, + 0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa3, + 0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa5, + 0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa6,0x00,0x12,0xff,0xf0,0x9e, + 0xa4,0xa7,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa8,0x00,0x12,0xff,0xf0,0x9e, + 0xa4,0xa9,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xaa,0x00, + 0x12,0xff,0xf0,0x9e,0xa4,0xab,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xac,0x00, + 0x12,0xff,0xf0,0x9e,0xa4,0xad,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4, + 0xae,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xaf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4, + 0xb0,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb1,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10, + 0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb3,0x00,0x10, + 0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb5,0x00,0xd1, + 0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb6,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb7, + 0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb8,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb9, + 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xba,0x00,0x12,0xff, + 0xf0,0x9e,0xa4,0xbb,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbc,0x00,0x12,0xff, + 0xf0,0x9e,0xa4,0xbd,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbe,0x00, + 0x12,0xff,0xf0,0x9e,0xa4,0xbf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa5,0x80,0x00, + 0x12,0xff,0xf0,0x9e,0xa5,0x81,0x00,0x94,0x1e,0x93,0x1a,0x92,0x16,0x91,0x12,0x10, + 0x09,0x12,0xff,0xf0,0x9e,0xa5,0x82,0x00,0x12,0xff,0xf0,0x9e,0xa5,0x83,0x00,0x12, + 0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* nfdi_c0100 */ + 0x57,0x04,0x01,0x00,0xc6,0xe5,0xac,0x13,0xe4,0x41,0x0c,0xe3,0x7a,0x07,0xe2,0xf3, + 0x01,0xc1,0xd0,0x1f,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x15,0x53,0x04,0x01,0x00, + 0x52,0x04,0x01,0x00,0x91,0x09,0x10,0x04,0x01,0x00,0x01,0xff,0x00,0x01,0x00,0x01, + 0x00,0xcf,0x86,0xd5,0xe4,0xd4,0x7c,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x41,0xcc,0x80,0x00,0x01,0xff,0x41,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x41, + 0xcc,0x82,0x00,0x01,0xff,0x41,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x41, + 0xcc,0x88,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x43, + 0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x80,0x00,0x01, + 0xff,0x45,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x82,0x00,0x01,0xff,0x45, + 0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x80,0x00,0x01,0xff,0x49, + 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x82,0x00,0x01,0xff,0x49,0xcc,0x88, + 0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x4e,0xcc,0x83, + 0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x80,0x00,0x01,0xff,0x4f,0xcc,0x81,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x82,0x00,0x01,0xff,0x4f,0xcc,0x83,0x00,0x10, + 0x08,0x01,0xff,0x4f,0xcc,0x88,0x00,0x01,0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01, + 0x00,0x01,0xff,0x55,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x81,0x00,0x01, + 0xff,0x55,0xcc,0x82,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x88,0x00,0x01, + 0xff,0x59,0xcc,0x81,0x00,0x01,0x00,0xd4,0x7c,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x61,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x81,0x00,0x10,0x08,0x01, + 0xff,0x61,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x61,0xcc,0x88,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x01, + 0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x80, + 0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x82,0x00,0x01, + 0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x80,0x00,0x01, + 0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x82,0x00,0x01,0xff,0x69, + 0xcc,0x88,0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x6e, + 0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x81, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x82,0x00,0x01,0xff,0x6f,0xcc,0x83, + 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,0x01,0x00,0xd2,0x1c,0xd1,0x0c,0x10, + 0x04,0x01,0x00,0x01,0xff,0x75,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x81, + 0x00,0x01,0xff,0x75,0xcc,0x82,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x88, + 0x00,0x01,0xff,0x79,0xcc,0x81,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x79,0xcc,0x88, + 0x00,0xe1,0x9a,0x03,0xe0,0xd3,0x01,0xcf,0x86,0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x84, + 0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x86,0x00,0x01,0xff,0x61,0xcc,0x86,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa8,0x00,0x01,0xff,0x61,0xcc,0xa8,0x00,0x10, + 0x08,0x01,0xff,0x43,0xcc,0x81,0x00,0x01,0xff,0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x43,0xcc,0x82,0x00,0x01,0xff,0x63,0xcc,0x82,0x00,0x10, + 0x08,0x01,0xff,0x43,0xcc,0x87,0x00,0x01,0xff,0x63,0xcc,0x87,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x43,0xcc,0x8c,0x00,0x01,0xff,0x63,0xcc,0x8c,0x00,0x10,0x08,0x01, + 0xff,0x44,0xcc,0x8c,0x00,0x01,0xff,0x64,0xcc,0x8c,0x00,0xd3,0x34,0xd2,0x14,0x51, + 0x04,0x01,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x84,0x00,0x01,0xff,0x65,0xcc,0x84, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0x86, + 0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x87,0x00,0x01,0xff,0x65,0xcc,0x87,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0xa8,0x00,0x01,0xff,0x65,0xcc,0xa8, + 0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x8c,0x00,0x01,0xff,0x65,0xcc,0x8c,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x82,0x00,0x01,0xff,0x67,0xcc,0x82,0x00,0x10, + 0x08,0x01,0xff,0x47,0xcc,0x86,0x00,0x01,0xff,0x67,0xcc,0x86,0x00,0xd4,0x74,0xd3, + 0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x87,0x00,0x01,0xff,0x67, + 0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,0xa7,0x00,0x01,0xff,0x67,0xcc,0xa7, + 0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0x82,0x00,0x01,0xff,0x68,0xcc,0x82, + 0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x83,0x00,0x01, + 0xff,0x69,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x84,0x00,0x01,0xff,0x69, + 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x86,0x00,0x01,0xff,0x69, + 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0xa8,0x00,0x01,0xff,0x69,0xcc,0xa8, + 0x00,0xd3,0x30,0xd2,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x49,0xcc,0x87,0x00,0x01, + 0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4a,0xcc,0x82,0x00,0x01,0xff,0x6a, + 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7, + 0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x4c,0xcc,0x81,0x00,0x10, + 0x08,0x01,0xff,0x6c,0xcc,0x81,0x00,0x01,0xff,0x4c,0xcc,0xa7,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x6c,0xcc,0xa7,0x00,0x01,0xff,0x4c,0xcc,0x8c,0x00,0x10,0x08,0x01, + 0xff,0x6c,0xcc,0x8c,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd4,0xd4,0x60,0xd3,0x30,0xd2, + 0x10,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x4e,0xcc,0x81,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x81,0x00,0x01,0xff,0x4e,0xcc,0xa7,0x00,0x10, + 0x08,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x01,0xff,0x4e,0xcc,0x8c,0x00,0xd2,0x10,0x91, + 0x0c,0x10,0x08,0x01,0xff,0x6e,0xcc,0x8c,0x00,0x01,0x00,0x01,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x4f,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0x84,0x00,0x10,0x08,0x01, + 0xff,0x4f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,0x86,0x00,0xd3,0x34,0xd2,0x14,0x91, + 0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x8b,0x00,0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x81,0x00,0x01,0xff,0x72,0xcc,0x81, + 0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa7,0x00,0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c, + 0x00,0x10,0x08,0x01,0xff,0x53,0xcc,0x81,0x00,0x01,0xff,0x73,0xcc,0x81,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x82,0x00,0x01,0xff,0x73,0xcc,0x82,0x00,0x10, + 0x08,0x01,0xff,0x53,0xcc,0xa7,0x00,0x01,0xff,0x73,0xcc,0xa7,0x00,0xd4,0x74,0xd3, + 0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x8c,0x00,0x01,0xff,0x73, + 0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7, + 0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c, + 0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x83,0x00,0x01, + 0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x84,0x00,0x01,0xff,0x75, + 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x86,0x00,0x01,0xff,0x75, + 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x8a,0x00,0x01,0xff,0x75,0xcc,0x8a, + 0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x8b,0x00,0x01, + 0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xa8,0x00,0x01,0xff,0x75, + 0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x82,0x00,0x01,0xff,0x77, + 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,0x82,0x00,0x01,0xff,0x79,0xcc,0x82, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x59,0xcc,0x88,0x00,0x01,0xff,0x5a, + 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x81,0x00,0x01,0xff,0x5a,0xcc,0x87, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x87,0x00,0x01,0xff,0x5a,0xcc,0x8c, + 0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,0x01,0x00,0xd0,0x4a,0xcf,0x86,0x55, + 0x04,0x01,0x00,0xd4,0x2c,0xd3,0x18,0x92,0x14,0x91,0x10,0x10,0x08,0x01,0xff,0x4f, + 0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01, + 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x55,0xcc,0x9b,0x00,0x93, + 0x14,0x92,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x75,0xcc,0x9b,0x00,0x01,0x00,0x01, + 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xb4,0xd4,0x24,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x41,0xcc,0x8c,0x00,0x10, + 0x08,0x01,0xff,0x61,0xcc,0x8c,0x00,0x01,0xff,0x49,0xcc,0x8c,0x00,0xd3,0x46,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8c,0x00,0x01,0xff,0x4f,0xcc,0x8c, + 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x8c,0x00,0xd1, + 0x12,0x10,0x08,0x01,0xff,0x75,0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x84, + 0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x55,0xcc,0x88, + 0xcc,0x81,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81, + 0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x8c,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88, + 0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01, + 0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x88, + 0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,0xd4,0x80,0xd3,0x3a,0xd2, + 0x26,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x87,0xcc,0x84,0x00,0x01,0xff,0x61, + 0xcc,0x87,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc3,0x86,0xcc,0x84,0x00,0x01,0xff, + 0xc3,0xa6,0xcc,0x84,0x00,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,0x8c, + 0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b, + 0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0xa8, + 0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa8, + 0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc6, + 0xb7,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0xd3,0x24,0xd2,0x10,0x91, + 0x0c,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00,0x01,0x00,0x01,0x00,0x91,0x10,0x10, + 0x08,0x01,0xff,0x47,0xcc,0x81,0x00,0x01,0xff,0x67,0xcc,0x81,0x00,0x04,0x00,0xd2, + 0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x4e,0xcc,0x80,0x00,0x04,0xff,0x6e,0xcc,0x80, + 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x8a,0xcc,0x81,0x00,0x01,0xff,0x61,0xcc,0x8a, + 0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xc3,0x86,0xcc,0x81,0x00,0x01,0xff, + 0xc3,0xa6,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xc3,0x98,0xcc,0x81,0x00,0x01,0xff, + 0xc3,0xb8,0xcc,0x81,0x00,0xe2,0x07,0x02,0xe1,0xae,0x01,0xe0,0x93,0x01,0xcf,0x86, + 0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc, + 0x8f,0x00,0x01,0xff,0x61,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x91,0x00, + 0x01,0xff,0x61,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x8f,0x00, + 0x01,0xff,0x65,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x91,0x00,0x01,0xff, + 0x65,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x8f,0x00, + 0x01,0xff,0x69,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x91,0x00,0x01,0xff, + 0x69,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x8f,0x00,0x01,0xff, + 0x6f,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc, + 0x91,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x8f,0x00, + 0x01,0xff,0x72,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0x91,0x00,0x01,0xff, + 0x72,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x8f,0x00,0x01,0xff, + 0x75,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x91,0x00,0x01,0xff,0x75,0xcc, + 0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x04,0xff,0x53,0xcc,0xa6,0x00,0x04,0xff, + 0x73,0xcc,0xa6,0x00,0x10,0x08,0x04,0xff,0x54,0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc, + 0xa6,0x00,0x51,0x04,0x04,0x00,0x10,0x08,0x04,0xff,0x48,0xcc,0x8c,0x00,0x04,0xff, + 0x68,0xcc,0x8c,0x00,0xd4,0x68,0xd3,0x20,0xd2,0x0c,0x91,0x08,0x10,0x04,0x06,0x00, + 0x07,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x08,0x04,0xff,0x41,0xcc,0x87,0x00, + 0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x45,0xcc, + 0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x88,0xcc, + 0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,0x00,0xd1,0x14,0x10,0x0a,0x04,0xff, + 0x4f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,0x00,0x10,0x08, + 0x04,0xff,0x4f,0xcc,0x87,0x00,0x04,0xff,0x6f,0xcc,0x87,0x00,0x93,0x30,0xd2,0x24, + 0xd1,0x14,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x87,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc, + 0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x59,0xcc,0x84,0x00,0x04,0xff,0x79,0xcc, + 0x84,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0xcf,0x86, + 0x95,0x14,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x08,0x00,0x09,0x00,0x09,0x00, + 0x09,0x00,0x01,0x00,0x01,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x18, + 0x53,0x04,0x01,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x04,0x00, + 0x11,0x04,0x04,0x00,0x07,0x00,0x01,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01,0x00, + 0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00, + 0x04,0x00,0x94,0x18,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x04,0x00, + 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,0x00,0x07,0x00,0xe1,0x35,0x01,0xd0, + 0x72,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0xe6,0xd3,0x10,0x52,0x04,0x01,0xe6,0x91, + 0x08,0x10,0x04,0x01,0xe6,0x01,0xe8,0x01,0xdc,0x92,0x0c,0x51,0x04,0x01,0xdc,0x10, + 0x04,0x01,0xe8,0x01,0xd8,0x01,0xdc,0xd4,0x2c,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10, + 0x04,0x01,0xdc,0x01,0xca,0x10,0x04,0x01,0xca,0x01,0xdc,0x51,0x04,0x01,0xdc,0x10, + 0x04,0x01,0xdc,0x01,0xca,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0xca,0x01,0xdc,0x01, + 0xdc,0x01,0xdc,0xd3,0x08,0x12,0x04,0x01,0xdc,0x01,0x01,0xd2,0x0c,0x91,0x08,0x10, + 0x04,0x01,0x01,0x01,0xdc,0x01,0xdc,0x91,0x08,0x10,0x04,0x01,0xdc,0x01,0xe6,0x01, + 0xe6,0xcf,0x86,0xd5,0x7f,0xd4,0x47,0xd3,0x2e,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01, + 0xff,0xcc,0x80,0x00,0x01,0xff,0xcc,0x81,0x00,0x10,0x04,0x01,0xe6,0x01,0xff,0xcc, + 0x93,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcc,0x88,0xcc,0x81,0x00,0x01,0xf0,0x10, + 0x04,0x04,0xe6,0x04,0xdc,0xd2,0x08,0x11,0x04,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10, + 0x04,0x04,0xe6,0x04,0xdc,0x10,0x04,0x04,0xdc,0x06,0xff,0x00,0xd3,0x18,0xd2,0x0c, + 0x51,0x04,0x07,0xe6,0x10,0x04,0x07,0xe6,0x07,0xdc,0x51,0x04,0x07,0xdc,0x10,0x04, + 0x07,0xdc,0x07,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x08,0xe8,0x08,0xdc,0x10,0x04, + 0x08,0xdc,0x08,0xe6,0xd1,0x08,0x10,0x04,0x08,0xe9,0x07,0xea,0x10,0x04,0x07,0xea, + 0x07,0xe9,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0xea,0x10,0x04,0x04,0xe9, + 0x06,0xe6,0x06,0xe6,0x06,0xe6,0xd3,0x13,0x52,0x04,0x0a,0x00,0x91,0x0b,0x10,0x07, + 0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10, + 0x04,0x01,0x00,0x09,0x00,0x51,0x04,0x09,0x00,0x10,0x06,0x01,0xff,0x3b,0x00,0x10, + 0x00,0xd0,0xe1,0xcf,0x86,0xd5,0x7a,0xd4,0x5f,0xd3,0x21,0x52,0x04,0x00,0x00,0xd1, + 0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x10,0x09,0x01,0xff, + 0xce,0x91,0xcc,0x81,0x00,0x01,0xff,0xc2,0xb7,0x00,0xd2,0x1f,0xd1,0x12,0x10,0x09, + 0x01,0xff,0xce,0x95,0xcc,0x81,0x00,0x01,0xff,0xce,0x97,0xcc,0x81,0x00,0x10,0x09, + 0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0x00,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xce, + 0x9f,0xcc,0x81,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xa5,0xcc,0x81,0x00,0x01, + 0xff,0xce,0xa9,0xcc,0x81,0x00,0x93,0x17,0x92,0x13,0x91,0x0f,0x10,0x0b,0x01,0xff, + 0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4, + 0x4a,0xd3,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01, + 0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x88,0x00, + 0x01,0xff,0xce,0xa5,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc, + 0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc, + 0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0x93,0x17,0x92,0x13,0x91,0x0f,0x10, + 0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x81,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0xcf,0x86,0xd5,0x7b,0xd4,0x39,0x53,0x04,0x01,0x00,0xd2,0x16,0x51,0x04, + 0x01,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x88,0x00,0x01,0xff,0xcf,0x85,0xcc, + 0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x01,0xff,0xcf, + 0x85,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x0a,0x00,0xd3, + 0x26,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xcf,0x92,0xcc, + 0x81,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcf,0x92,0xcc,0x88,0x00,0x01,0x00,0x10, + 0x04,0x01,0x00,0x04,0x00,0xd2,0x0c,0x51,0x04,0x06,0x00,0x10,0x04,0x01,0x00,0x04, + 0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0xd4, + 0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x01,0x00,0x01, + 0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x06, + 0x00,0x07,0x00,0x12,0x04,0x07,0x00,0x08,0x00,0xe3,0x47,0x04,0xe2,0xbe,0x02,0xe1, + 0x07,0x01,0xd0,0x8b,0xcf,0x86,0xd5,0x6c,0xd4,0x53,0xd3,0x30,0xd2,0x1f,0xd1,0x12, + 0x10,0x09,0x04,0xff,0xd0,0x95,0xcc,0x80,0x00,0x01,0xff,0xd0,0x95,0xcc,0x88,0x00, + 0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x93,0xcc,0x81,0x00,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x01,0xff,0xd0,0x86,0xcc,0x88,0x00,0x52,0x04,0x01,0x00,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xd0,0x9a,0xcc,0x81,0x00,0x04,0xff,0xd0,0x98,0xcc,0x80,0x00, + 0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x86,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0x92, + 0x11,0x91,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x98,0xcc,0x86,0x00,0x01,0x00, + 0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x92,0x11,0x91,0x0d,0x10,0x04, + 0x01,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5, + 0x57,0x54,0x04,0x01,0x00,0xd3,0x30,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0, + 0xb5,0xcc,0x80,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,0x00,0x10,0x04,0x01,0x00,0x01, + 0xff,0xd0,0xb3,0xcc,0x81,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff, + 0xd1,0x96,0xcc,0x88,0x00,0x52,0x04,0x01,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0, + 0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8,0xcc,0x80,0x00,0x10,0x09,0x01,0xff,0xd1, + 0x83,0xcc,0x86,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x1a,0x52,0x04,0x01,0x00, + 0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb4,0xcc,0x8f,0x00,0x01,0xff,0xd1, + 0xb5,0xcc,0x8f,0x00,0x01,0x00,0xd0,0x2e,0xcf,0x86,0x95,0x28,0x94,0x24,0xd3,0x18, + 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0x51,0x04,0x01,0xe6, + 0x10,0x04,0x01,0xe6,0x0a,0xe6,0x92,0x08,0x11,0x04,0x04,0x00,0x06,0x00,0x04,0x00, + 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xbe,0xd4,0x4a,0xd3,0x2a,0xd2,0x1a,0xd1,0x0d, + 0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x96,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0, + 0xb6,0xcc,0x86,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04, + 0x06,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04, + 0x06,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00, + 0x09,0x00,0xd3,0x3a,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x90,0xcc,0x86, + 0x00,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0x90,0xcc,0x88, + 0x00,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff, + 0xd0,0x95,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,0xd2,0x16,0x51,0x04, + 0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0x98,0xcc,0x88,0x00,0x01,0xff,0xd3,0x99,0xcc, + 0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x96,0xcc,0x88,0x00,0x01,0xff,0xd0, + 0xb6,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0x97,0xcc,0x88,0x00,0x01,0xff,0xd0, + 0xb7,0xcc,0x88,0x00,0xd4,0x74,0xd3,0x3a,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09, + 0x01,0xff,0xd0,0x98,0xcc,0x84,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xd0,0x98,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00, + 0x10,0x09,0x01,0xff,0xd0,0x9e,0xcc,0x88,0x00,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00, + 0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0xa8,0xcc,0x88,0x00,0x01, + 0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,0xad,0xcc,0x88, + 0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x84, + 0x00,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0xd3,0x3a,0xd2,0x24,0xd1,0x12,0x10,0x09, + 0x01,0xff,0xd0,0xa3,0xcc,0x88,0x00,0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,0x10,0x09, + 0x01,0xff,0xd0,0xa3,0xcc,0x8b,0x00,0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,0x91,0x12, + 0x10,0x09,0x01,0xff,0xd0,0xa7,0xcc,0x88,0x00,0x01,0xff,0xd1,0x87,0xcc,0x88,0x00, + 0x08,0x00,0x92,0x16,0x91,0x12,0x10,0x09,0x01,0xff,0xd0,0xab,0xcc,0x88,0x00,0x01, + 0xff,0xd1,0x8b,0xcc,0x88,0x00,0x09,0x00,0x09,0x00,0xd1,0x74,0xd0,0x36,0xcf,0x86, + 0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00, + 0xd4,0x10,0x93,0x0c,0x52,0x04,0x0a,0x00,0x11,0x04,0x0b,0x00,0x0c,0x00,0x10,0x00, + 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00, + 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0xba, + 0xcf,0x86,0xd5,0x4c,0xd4,0x24,0x53,0x04,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04, + 0x14,0x00,0x01,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00, + 0x10,0x00,0x10,0x04,0x10,0x00,0x0d,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04, + 0x00,0x00,0x02,0xdc,0x02,0xe6,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xdc,0x02,0xe6, + 0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xde,0x02,0xdc,0x02,0xe6,0xd4,0x2c, + 0xd3,0x10,0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x08,0xdc,0x02,0xdc,0x02,0xdc, + 0xd2,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xdc,0x02,0xe6,0xd1,0x08,0x10,0x04, + 0x02,0xe6,0x02,0xde,0x10,0x04,0x02,0xe4,0x02,0xe6,0xd3,0x20,0xd2,0x10,0xd1,0x08, + 0x10,0x04,0x01,0x0a,0x01,0x0b,0x10,0x04,0x01,0x0c,0x01,0x0d,0xd1,0x08,0x10,0x04, + 0x01,0x0e,0x01,0x0f,0x10,0x04,0x01,0x10,0x01,0x11,0xd2,0x10,0xd1,0x08,0x10,0x04, + 0x01,0x12,0x01,0x13,0x10,0x04,0x09,0x13,0x01,0x14,0xd1,0x08,0x10,0x04,0x01,0x15, + 0x01,0x16,0x10,0x04,0x01,0x00,0x01,0x17,0xcf,0x86,0xd5,0x28,0x94,0x24,0x93,0x20, + 0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x18,0x10,0x04,0x01,0x19,0x01,0x00, + 0xd1,0x08,0x10,0x04,0x02,0xe6,0x08,0xdc,0x10,0x04,0x08,0x00,0x08,0x12,0x00,0x00, + 0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04, + 0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x93,0x10, + 0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe2,0xfb,0x01,0xe1,0x2b,0x01,0xd0,0xa8,0xcf,0x86,0xd5,0x55,0xd4,0x28,0xd3,0x10, + 0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x10,0x00,0x0a,0x00,0xd2,0x0c, + 0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x08,0x00,0x91,0x08,0x10,0x04,0x01,0x00, + 0x07,0x00,0x07,0x00,0xd3,0x0c,0x52,0x04,0x07,0xe6,0x11,0x04,0x07,0xe6,0x0a,0xe6, + 0xd2,0x10,0xd1,0x08,0x10,0x04,0x0a,0x1e,0x0a,0x1f,0x10,0x04,0x0a,0x20,0x01,0x00, + 0xd1,0x09,0x10,0x05,0x0f,0xff,0x00,0x00,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0xd4, + 0x3d,0x93,0x39,0xd2,0x1a,0xd1,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x10,0x09,0x01, + 0xff,0xd8,0xa7,0xd9,0x93,0x00,0x01,0xff,0xd8,0xa7,0xd9,0x94,0x00,0xd1,0x12,0x10, + 0x09,0x01,0xff,0xd9,0x88,0xd9,0x94,0x00,0x01,0xff,0xd8,0xa7,0xd9,0x95,0x00,0x10, + 0x09,0x01,0xff,0xd9,0x8a,0xd9,0x94,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00, + 0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x86, + 0xd5,0x5c,0xd4,0x20,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04, + 0x01,0x00,0x01,0x1b,0xd1,0x08,0x10,0x04,0x01,0x1c,0x01,0x1d,0x10,0x04,0x01,0x1e, + 0x01,0x1f,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x20,0x01,0x21,0x10,0x04, + 0x01,0x22,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x10,0x04,0x07,0xdc, + 0x07,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x07,0xe6,0x08,0xe6,0x08,0xe6,0xd1,0x08, + 0x10,0x04,0x08,0xdc,0x08,0xe6,0x10,0x04,0x08,0xe6,0x0c,0xdc,0xd4,0x10,0x53,0x04, + 0x01,0x00,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x06,0x00,0x93,0x10,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x01,0x23,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x22, + 0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x08, + 0x11,0x04,0x04,0x00,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00, + 0xcf,0x86,0xd5,0x5b,0xd4,0x2e,0xd3,0x1e,0x92,0x1a,0xd1,0x0d,0x10,0x09,0x01,0xff, + 0xdb,0x95,0xd9,0x94,0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xdb,0x81,0xd9,0x94,0x00, + 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00, + 0x04,0x00,0xd3,0x19,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff, + 0xdb,0x92,0xd9,0x94,0x00,0x11,0x04,0x01,0x00,0x01,0xe6,0x52,0x04,0x01,0xe6,0xd1, + 0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0xd4,0x38,0xd3, + 0x1c,0xd2,0x0c,0x51,0x04,0x01,0xe6,0x10,0x04,0x01,0xe6,0x01,0xdc,0xd1,0x08,0x10, + 0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0xd2,0x10,0xd1,0x08,0x10, + 0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0xdc,0x01,0xe6,0x91,0x08,0x10,0x04,0x01, + 0xe6,0x01,0xdc,0x07,0x00,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x04, + 0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,0x00,0xd1,0xc8,0xd0,0x76,0xcf, + 0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04, + 0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04, + 0x00,0x04,0x24,0x04,0x00,0x04,0x00,0x04,0x00,0xd4,0x14,0x53,0x04,0x04,0x00,0x52, + 0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x07,0x00,0x07,0x00,0xd3,0x1c,0xd2, + 0x0c,0x91,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04, + 0xdc,0x04,0xe6,0x10,0x04,0x04,0xe6,0x04,0xdc,0xd2,0x0c,0x51,0x04,0x04,0xdc,0x10, + 0x04,0x04,0xe6,0x04,0xdc,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10,0x04,0x04, + 0xdc,0x04,0xe6,0xcf,0x86,0xd5,0x3c,0x94,0x38,0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x04, + 0xe6,0x10,0x04,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10, + 0x04,0x04,0xdc,0x04,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10, + 0x04,0x04,0xe6,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x08, + 0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x52,0x04,0x08,0x00,0x11,0x04,0x08,0x00,0x0a, + 0x00,0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93, + 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0xd4,0x14,0x53,0x04,0x09,0x00,0x92,0x0c,0x51, + 0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xe6,0x09,0xe6,0xd3,0x10,0x92,0x0c,0x51, + 0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09, + 0x00,0x10,0x04,0x09,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x14,0xdc,0x14, + 0x00,0xe4,0xf8,0x57,0xe3,0x45,0x3f,0xe2,0xf4,0x3e,0xe1,0xc7,0x2c,0xe0,0x21,0x10, + 0xcf,0x86,0xc5,0xe4,0x80,0x08,0xe3,0xcb,0x03,0xe2,0x61,0x01,0xd1,0x94,0xd0,0x5a, + 0xcf,0x86,0xd5,0x20,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x52,0x04,0x0b,0x00,0x11,0x04, + 0x0b,0x00,0x0b,0xe6,0x92,0x0c,0x51,0x04,0x0b,0xe6,0x10,0x04,0x0b,0x00,0x0b,0xe6, + 0x0b,0xe6,0xd4,0x24,0xd3,0x10,0x52,0x04,0x0b,0xe6,0x91,0x08,0x10,0x04,0x0b,0x00, + 0x0b,0xe6,0x0b,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,0x0b,0xe6, + 0x11,0x04,0x0b,0xe6,0x00,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04, + 0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xcf,0x86,0xd5,0x20,0x54,0x04,0x0c,0x00, + 0x53,0x04,0x0c,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x0c,0xdc,0x0c,0xdc, + 0x51,0x04,0x00,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x13,0x00, + 0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd0,0x4a,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4,0x20,0xd3,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0d,0x00,0x10,0x00,0x0d,0x00,0x0d,0x00,0x52,0x04,0x0d,0x00,0x91,0x08, + 0x10,0x04,0x0d,0x00,0x10,0x00,0x10,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x10,0x00, + 0x10,0x04,0x10,0x00,0x11,0x00,0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x12,0x00, + 0x52,0x04,0x12,0x00,0x11,0x04,0x12,0x00,0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04, + 0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x14,0xdc, + 0x12,0xe6,0x12,0xe6,0xd4,0x30,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x12,0xe6,0x10,0x04, + 0x12,0x00,0x11,0xdc,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xdc,0x0d,0xe6,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x0d,0xe6,0x91,0x08,0x10,0x04,0x0d,0xe6, + 0x0d,0xdc,0x0d,0xdc,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0d,0x1b,0x0d,0x1c, + 0x10,0x04,0x0d,0x1d,0x0d,0xe6,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xdc,0x0d,0xe6, + 0xd2,0x10,0xd1,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x10,0x04,0x0d,0xdc,0x0d,0xe6, + 0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xe6,0x10,0xe6,0xe1,0x3a,0x01,0xd0,0x77,0xcf, + 0x86,0xd5,0x20,0x94,0x1c,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x01, + 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, + 0x00,0xd4,0x1b,0x53,0x04,0x01,0x00,0x92,0x13,0x91,0x0f,0x10,0x04,0x01,0x00,0x01, + 0xff,0xe0,0xa4,0xa8,0xe0,0xa4,0xbc,0x00,0x01,0x00,0x01,0x00,0xd3,0x26,0xd2,0x13, + 0x91,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa4,0xb0,0xe0,0xa4,0xbc,0x00,0x01, + 0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xa4,0xb3,0xe0,0xa4,0xbc,0x00,0x01,0x00, + 0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x91,0x08,0x10,0x04,0x01,0x07, + 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x8c,0xd4,0x18,0x53,0x04,0x01,0x00,0x52,0x04, + 0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x10,0x04,0x0b,0x00,0x0c,0x00, + 0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0xe6,0x10,0x04,0x01,0xdc, + 0x01,0xe6,0x91,0x08,0x10,0x04,0x01,0xe6,0x0b,0x00,0x0c,0x00,0xd2,0x2c,0xd1,0x16, + 0x10,0x0b,0x01,0xff,0xe0,0xa4,0x95,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0x96, + 0xe0,0xa4,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa4,0x97,0xe0,0xa4,0xbc,0x00,0x01, + 0xff,0xe0,0xa4,0x9c,0xe0,0xa4,0xbc,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xa4, + 0xa1,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0xa2,0xe0,0xa4,0xbc,0x00,0x10,0x0b, + 0x01,0xff,0xe0,0xa4,0xab,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0xaf,0xe0,0xa4, + 0xbc,0x00,0x54,0x04,0x01,0x00,0xd3,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00, + 0x0a,0x00,0x10,0x04,0x0a,0x00,0x0c,0x00,0x0c,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04, + 0x10,0x00,0x0b,0x00,0x10,0x04,0x0b,0x00,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00, + 0x08,0x00,0x09,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00, + 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00, + 0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00, + 0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04, + 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00, + 0xd3,0x18,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00, + 0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00, + 0x91,0x08,0x10,0x04,0x01,0x07,0x07,0x00,0x01,0x00,0xcf,0x86,0xd5,0x7b,0xd4,0x42, + 0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04, + 0x00,0x00,0x01,0x00,0xd2,0x17,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04, + 0x00,0x00,0x01,0xff,0xe0,0xa7,0x87,0xe0,0xa6,0xbe,0x00,0xd1,0x0f,0x10,0x0b,0x01, + 0xff,0xe0,0xa7,0x87,0xe0,0xa7,0x97,0x00,0x01,0x09,0x10,0x04,0x08,0x00,0x00,0x00, + 0xd3,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00, + 0x52,0x04,0x00,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xa6,0xa1,0xe0,0xa6,0xbc, + 0x00,0x01,0xff,0xe0,0xa6,0xa2,0xe0,0xa6,0xbc,0x00,0x10,0x04,0x00,0x00,0x01,0xff, + 0xe0,0xa6,0xaf,0xe0,0xa6,0xbc,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x01,0x00,0x11, + 0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x14,0xe6,0x00, + 0x00,0xe2,0x48,0x02,0xe1,0x4f,0x01,0xd0,0xa4,0xcf,0x86,0xd5,0x4c,0xd4,0x34,0xd3, + 0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x10,0x04,0x01,0x00,0x07, + 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01, + 0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x2e,0xd2,0x17,0xd1, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa8,0xb2, + 0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x0b,0x01,0xff, + 0xe0,0xa8,0xb8,0xe0,0xa8,0xbc,0x00,0x00,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00, + 0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x00,0x00,0x01,0x00,0xcf,0x86,0xd5,0x80,0xd4, + 0x34,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51, + 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01, + 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x01, + 0x09,0x00,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x00, + 0x00,0x00,0x00,0xd2,0x25,0xd1,0x0f,0x10,0x04,0x00,0x00,0x01,0xff,0xe0,0xa8,0x96, + 0xe0,0xa8,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa8,0x97,0xe0,0xa8,0xbc,0x00,0x01, + 0xff,0xe0,0xa8,0x9c,0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00, + 0x10,0x0b,0x01,0xff,0xe0,0xa8,0xab,0xe0,0xa8,0xbc,0x00,0x00,0x00,0xd4,0x10,0x93, + 0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x14,0x52, + 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,0x00,0x10,0x04,0x14,0x00,0x00, + 0x00,0x00,0x00,0xd0,0x82,0xcf,0x86,0xd5,0x40,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91, + 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01, + 0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x01,0x00,0x10, + 0x04,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x00, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,0x0c,0x91, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01, + 0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01, + 0x07,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x10,0x52,0x04,0x01, + 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x00, + 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xd4,0x18,0x93,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x07, + 0x00,0x07,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x0d,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x11,0x00,0x13,0x00,0x13,0x00,0xe1,0x24,0x01,0xd0,0x86,0xcf,0x86, + 0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00, + 0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00, + 0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14, + 0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04, + 0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x01,0x00, + 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x01,0x00, + 0x01,0x00,0xcf,0x86,0xd5,0x73,0xd4,0x45,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08, + 0x10,0x04,0x0a,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x0f, + 0x10,0x0b,0x01,0xff,0xe0,0xad,0x87,0xe0,0xad,0x96,0x00,0x00,0x00,0x10,0x04,0x00, + 0x00,0x01,0xff,0xe0,0xad,0x87,0xe0,0xac,0xbe,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff, + 0xe0,0xad,0x87,0xe0,0xad,0x97,0x00,0x01,0x09,0x00,0x00,0xd3,0x0c,0x52,0x04,0x00, + 0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x52,0x04,0x00,0x00,0xd1,0x16,0x10,0x0b,0x01, + 0xff,0xe0,0xac,0xa1,0xe0,0xac,0xbc,0x00,0x01,0xff,0xe0,0xac,0xa2,0xe0,0xac,0xbc, + 0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01, + 0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x0c,0x00,0x0c,0x00,0x00,0x00,0xd0,0xb1,0xcf, + 0x86,0xd5,0x63,0xd4,0x28,0xd3,0x14,0xd2,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x91, + 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd3,0x1f,0xd2,0x0c,0x91, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0, + 0xae,0x92,0xe0,0xaf,0x97,0x00,0x01,0x00,0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04, + 0x00,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x00, + 0x00,0x00,0x01,0x00,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04, + 0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd2,0x0c, + 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00, + 0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x08,0x00,0x01,0x00, + 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xcf,0x86, + 0xd5,0x61,0xd4,0x45,0xd3,0x14,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00, + 0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x08,0x10,0x04,0x01,0x00, + 0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xaf,0x86,0xe0,0xae,0xbe,0x00,0x01,0xff,0xe0, + 0xaf,0x87,0xe0,0xae,0xbe,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xaf,0x86,0xe0, + 0xaf,0x97,0x00,0x01,0x09,0x00,0x00,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0a, + 0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x00, + 0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x08, + 0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x07,0x00,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00, + 0x00,0x00,0x00,0xe3,0x1c,0x04,0xe2,0x1a,0x02,0xd1,0xf3,0xd0,0x76,0xcf,0x86,0xd5, + 0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01, + 0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x91, + 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01, + 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3, + 0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0xd2, + 0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x01, + 0x00,0xcf,0x86,0xd5,0x53,0xd4,0x2f,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10, + 0x04,0x01,0x00,0x00,0x00,0x01,0x00,0xd2,0x13,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0, + 0xb1,0x86,0xe0,0xb1,0x96,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00, + 0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00, + 0x01,0x54,0x10,0x04,0x01,0x5b,0x00,0x00,0x92,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04, + 0x11,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01,0x00, + 0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x52,0x04,0x00,0x00, + 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0a,0x00,0xd0,0x76,0xcf,0x86, + 0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x10,0x00, + 0x01,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00, + 0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04, + 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00, + 0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x07,0x07,0x07,0x00, + 0x01,0x00,0xcf,0x86,0xd5,0x82,0xd4,0x5e,0xd3,0x2a,0xd2,0x13,0x91,0x0f,0x10,0x0b, + 0x01,0xff,0xe0,0xb2,0xbf,0xe0,0xb3,0x95,0x00,0x01,0x00,0x01,0x00,0xd1,0x08,0x10, + 0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3, + 0x95,0x00,0xd2,0x28,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,0x96, + 0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,0x82,0x00,0x01,0xff, + 0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95,0x00,0x91,0x08,0x10,0x04,0x01,0x00, + 0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00, + 0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00, + 0x10,0x04,0x01,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01,0x00, + 0x09,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08, + 0x10,0x04,0x00,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe1,0x06,0x01,0xd0,0x6e,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91, + 0x08,0x10,0x04,0x13,0x00,0x10,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01, + 0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01, + 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01, + 0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01, + 0x00,0x0c,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x0c,0x00,0x13,0x09,0x91,0x08,0x10,0x04,0x13,0x09,0x0a,0x00,0x01, + 0x00,0xcf,0x86,0xd5,0x65,0xd4,0x45,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10, + 0x04,0x0a,0x00,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x08,0x10,0x04,0x01,0x00,0x00, + 0x00,0x10,0x0b,0x01,0xff,0xe0,0xb5,0x86,0xe0,0xb4,0xbe,0x00,0x01,0xff,0xe0,0xb5, + 0x87,0xe0,0xb4,0xbe,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xb5,0x86,0xe0,0xb5, + 0x97,0x00,0x01,0x09,0x10,0x04,0x0c,0x00,0x12,0x00,0xd3,0x10,0x52,0x04,0x00,0x00, + 0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x01,0x00,0x52,0x04,0x12,0x00,0x51,0x04, + 0x12,0x00,0x10,0x04,0x12,0x00,0x11,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04, + 0x01,0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x0c,0x52,0x04, + 0x0a,0x00,0x11,0x04,0x0a,0x00,0x12,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x12,0x00, + 0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x5a,0xcf,0x86,0xd5,0x34,0xd4,0x18,0x93,0x14, + 0xd2,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x04,0x00, + 0x04,0x00,0x04,0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04, + 0x04,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x54,0x04, + 0x04,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x00,0x00,0x04,0x00, + 0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x04,0x00,0x00,0x00, + 0xcf,0x86,0xd5,0x77,0xd4,0x28,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00, + 0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x04,0x09, + 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x04,0x00,0xd3,0x14,0x52,0x04, + 0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x10,0x04,0x04,0x00,0x00,0x00, + 0xd2,0x13,0x51,0x04,0x04,0x00,0x10,0x0b,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8a, + 0x00,0x04,0x00,0xd1,0x19,0x10,0x0b,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8f,0x00, + 0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8f,0xe0,0xb7,0x8a,0x00,0x10,0x0b,0x04,0xff, + 0xe0,0xb7,0x99,0xe0,0xb7,0x9f,0x00,0x04,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x00, + 0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x93,0x14,0xd2,0x08,0x11,0x04,0x00, + 0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe2, + 0x31,0x01,0xd1,0x58,0xd0,0x3a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x67,0x10,0x04, + 0x01,0x09,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xcf,0x86, + 0x95,0x18,0xd4,0x0c,0x53,0x04,0x01,0x00,0x12,0x04,0x01,0x6b,0x01,0x00,0x53,0x04, + 0x01,0x00,0x12,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd0,0x9e,0xcf,0x86,0xd5,0x54, + 0xd4,0x3c,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04, + 0x01,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x15,0x00, + 0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x15,0x00,0x10,0x04,0x01,0x00, + 0x00,0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,0x15,0x00,0xd3,0x08,0x12,0x04, + 0x15,0x00,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0xd4,0x30,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00, + 0x01,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00, + 0xd2,0x08,0x11,0x04,0x15,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00, + 0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x76,0x10,0x04,0x15,0x09, + 0x01,0x00,0x11,0x04,0x01,0x00,0x00,0x00,0xcf,0x86,0x95,0x34,0xd4,0x20,0xd3,0x14, + 0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00, + 0x00,0x00,0x52,0x04,0x01,0x7a,0x11,0x04,0x01,0x00,0x00,0x00,0x53,0x04,0x01,0x00, + 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x01,0x00,0x0d,0x00,0x00,0x00, + 0xe1,0x2b,0x01,0xd0,0x3e,0xcf,0x86,0xd5,0x14,0x54,0x04,0x02,0x00,0x53,0x04,0x02, + 0x00,0x92,0x08,0x11,0x04,0x02,0xdc,0x02,0x00,0x02,0x00,0x54,0x04,0x02,0x00,0xd3, + 0x14,0x52,0x04,0x02,0x00,0xd1,0x08,0x10,0x04,0x02,0x00,0x02,0xdc,0x10,0x04,0x02, + 0x00,0x02,0xdc,0x92,0x0c,0x91,0x08,0x10,0x04,0x02,0x00,0x02,0xd8,0x02,0x00,0x02, + 0x00,0xcf,0x86,0xd5,0x73,0xd4,0x36,0xd3,0x17,0x92,0x13,0x51,0x04,0x02,0x00,0x10, + 0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x82,0xe0,0xbe,0xb7,0x00,0x02,0x00,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x00,0x00,0x02,0x00,0x02,0x00,0x91,0x0f,0x10,0x04,0x02,0x00, + 0x02,0xff,0xe0,0xbd,0x8c,0xe0,0xbe,0xb7,0x00,0x02,0x00,0xd3,0x26,0xd2,0x13,0x51, + 0x04,0x02,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbd,0x91,0xe0,0xbe,0xb7,0x00,0x02,0x00, + 0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x96,0xe0,0xbe,0xb7, + 0x00,0x52,0x04,0x02,0x00,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbd,0x9b,0xe0,0xbe, + 0xb7,0x00,0x02,0x00,0x02,0x00,0xd4,0x27,0x53,0x04,0x02,0x00,0xd2,0x17,0xd1,0x0f, + 0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x80,0xe0,0xbe,0xb5,0x00,0x10,0x04,0x04, + 0x00,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0xd3,0x35,0xd2, + 0x17,0xd1,0x08,0x10,0x04,0x00,0x00,0x02,0x81,0x10,0x04,0x02,0x82,0x02,0xff,0xe0, + 0xbd,0xb1,0xe0,0xbd,0xb2,0x00,0xd1,0x0f,0x10,0x04,0x02,0x84,0x02,0xff,0xe0,0xbd, + 0xb1,0xe0,0xbd,0xb4,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0x00, + 0x02,0x00,0xd2,0x13,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xb3,0xe0,0xbe,0x80, + 0x00,0x02,0x00,0x02,0x82,0x11,0x04,0x02,0x82,0x02,0x00,0xd0,0xd3,0xcf,0x86,0xd5, + 0x65,0xd4,0x27,0xd3,0x1f,0xd2,0x13,0x91,0x0f,0x10,0x04,0x02,0x82,0x02,0xff,0xe0, + 0xbd,0xb1,0xe0,0xbe,0x80,0x00,0x02,0xe6,0x91,0x08,0x10,0x04,0x02,0x09,0x02,0x00, + 0x02,0xe6,0x12,0x04,0x02,0x00,0x0c,0x00,0xd3,0x1f,0xd2,0x13,0x51,0x04,0x02,0x00, + 0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0x92,0xe0,0xbe,0xb7,0x00,0x51,0x04,0x02, + 0x00,0x10,0x04,0x04,0x00,0x02,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x02, + 0x00,0x02,0x00,0x91,0x0f,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0x9c,0xe0,0xbe, + 0xb7,0x00,0x02,0x00,0xd4,0x3d,0xd3,0x26,0xd2,0x13,0x51,0x04,0x02,0x00,0x10,0x0b, + 0x02,0xff,0xe0,0xbe,0xa1,0xe0,0xbe,0xb7,0x00,0x02,0x00,0x51,0x04,0x02,0x00,0x10, + 0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0xa6,0xe0,0xbe,0xb7,0x00,0x52,0x04,0x02,0x00, + 0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xab,0xe0,0xbe,0xb7,0x00,0x02,0x00,0x04, + 0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x02,0x00,0x02,0x00,0x02, + 0x00,0xd2,0x13,0x91,0x0f,0x10,0x04,0x04,0x00,0x02,0xff,0xe0,0xbe,0x90,0xe0,0xbe, + 0xb5,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xcf,0x86, + 0x95,0x4c,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04, + 0x04,0xdc,0x04,0x00,0x52,0x04,0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x00,0x00, + 0x10,0x04,0x0a,0x00,0x04,0x00,0xd3,0x14,0xd2,0x08,0x11,0x04,0x08,0x00,0x0a,0x00, + 0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0x92,0x10,0xd1,0x08,0x10,0x04, + 0x0b,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86, + 0xe5,0xf7,0x04,0xe4,0x79,0x03,0xe3,0x7b,0x01,0xe2,0x04,0x01,0xd1,0x7f,0xd0,0x65, + 0xcf,0x86,0x55,0x04,0x04,0x00,0xd4,0x33,0xd3,0x1f,0xd2,0x0c,0x51,0x04,0x04,0x00, + 0x10,0x04,0x0a,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x0b,0x04,0xff,0xe1,0x80, + 0xa5,0xe1,0x80,0xae,0x00,0x04,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x0a,0x00,0x04, + 0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x04,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x04, + 0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x04,0x00,0x04, + 0x07,0x92,0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0x09,0x10,0x04,0x0a,0x09,0x0a, + 0x00,0x0a,0x00,0xcf,0x86,0x95,0x14,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92, + 0x08,0x11,0x04,0x04,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x2e,0xcf,0x86,0x95, + 0x28,0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a, + 0x00,0x0a,0xdc,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00,0x0b, + 0x00,0x11,0x04,0x0b,0x00,0x0a,0x00,0x01,0x00,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3, + 0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x52, + 0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x54, + 0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x06,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x06,0x00,0x08,0x00,0x10,0x04,0x08, + 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0d,0x00,0x0d,0x00,0xd1,0x3e,0xd0, + 0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x1d,0x54,0x04,0x01,0x00,0x53,0x04,0x01, + 0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b, + 0x00,0x01,0xff,0x00,0x94,0x15,0x93,0x11,0x92,0x0d,0x91,0x09,0x10,0x05,0x01,0xff, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55, + 0x04,0x01,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x0b,0x00,0x0b,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54, + 0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x0b, + 0x00,0xe2,0x21,0x01,0xd1,0x6c,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10, + 0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00, + 0x04,0x00,0x04,0x00,0xcf,0x86,0x95,0x48,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00, + 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04, + 0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0xd3,0x10,0x52,0x04, + 0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08, + 0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00, + 0xd0,0x62,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04, + 0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00, + 0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xd4,0x14,0x53,0x04, + 0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00, + 0xd3,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04, + 0x04,0x00,0x00,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00, + 0x00,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,0xd3,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04, + 0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x52,0x04,0x04,0x00, + 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x93,0x10,0x52,0x04,0x04,0x00, + 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x94,0x14,0x53,0x04, + 0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00, + 0x04,0x00,0xd1,0x9c,0xd0,0x3e,0xcf,0x86,0x95,0x38,0xd4,0x14,0x53,0x04,0x04,0x00, + 0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd3,0x14, + 0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00, + 0x00,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00, + 0x04,0x00,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x93,0x10,0x52,0x04,0x04,0x00,0x51,0x04, + 0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00,0x53,0x04,0x04,0x00,0xd2,0x0c, + 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00, + 0x0c,0xe6,0x10,0x04,0x0c,0xe6,0x08,0xe6,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x53,0x04,0x04,0x00, + 0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a, + 0xcf,0x86,0x95,0x14,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04, + 0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04, + 0x04,0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x11,0x00, + 0x00,0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x00,0x00,0xd3,0x30,0xd2,0x2a, + 0xd1,0x24,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0b,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00, + 0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xd2,0x6c,0xd1,0x24, + 0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00, + 0x93,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x0b,0x00, + 0x0b,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00, + 0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00, + 0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x04,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x46,0xcf,0x86,0xd5,0x28, + 0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x00, + 0x00,0x00,0x06,0x00,0x93,0x10,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x09, + 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x06,0x00,0x93,0x14,0x52,0x04,0x06,0x00, + 0xd1,0x08,0x10,0x04,0x06,0x09,0x06,0x00,0x10,0x04,0x06,0x00,0x00,0x00,0x00,0x00, + 0xcf,0x86,0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,0x06,0x00,0x00,0x00, + 0x00,0x00,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04, + 0x06,0x00,0x00,0x00,0x06,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00, + 0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0xd0,0x1b,0xcf,0x86,0x55,0x04,0x04,0x00, + 0x54,0x04,0x04,0x00,0x93,0x0d,0x52,0x04,0x04,0x00,0x11,0x05,0x04,0xff,0x00,0x04, + 0x00,0x04,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x51, + 0x04,0x04,0x00,0x10,0x04,0x04,0x09,0x04,0x00,0x04,0x00,0x52,0x04,0x04,0x00,0x91, + 0x08,0x10,0x04,0x04,0x00,0x07,0xe6,0x00,0x00,0xd4,0x10,0x53,0x04,0x04,0x00,0x92, + 0x08,0x11,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x08,0x11, + 0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xe4,0xb7,0x03,0xe3,0x58,0x01,0xd2,0x8f,0xd1, + 0x53,0xd0,0x35,0xcf,0x86,0x95,0x2f,0xd4,0x1f,0x53,0x04,0x04,0x00,0xd2,0x0d,0x51, + 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x04,0xff,0x00,0x51,0x05,0x04,0xff,0x00,0x10, + 0x05,0x04,0xff,0x00,0x00,0x00,0x53,0x04,0x04,0x00,0x92,0x08,0x11,0x04,0x04,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00, + 0x53,0x04,0x04,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x04,0x00,0x94,0x18,0x53,0x04,0x04,0x00, + 0x92,0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0xe4,0x10,0x04,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x0b,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x0c, + 0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x42, + 0xcf,0x86,0xd5,0x1c,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00, + 0xd1,0x08,0x10,0x04,0x07,0x00,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0xd4,0x0c, + 0x53,0x04,0x07,0x00,0x12,0x04,0x07,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x10, + 0xd1,0x08,0x10,0x04,0x07,0x00,0x07,0xde,0x10,0x04,0x07,0xe6,0x07,0xdc,0x00,0x00, + 0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00, + 0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0xd4,0x10,0x53,0x04,0x07,0x00, + 0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x07,0x00, + 0x91,0x08,0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a,0xcf,0x86, + 0x55,0x04,0x08,0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00, + 0x0b,0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x95,0x28,0xd4,0x10,0x53,0x04,0x08,0x00, + 0x92,0x08,0x11,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0xd2,0x0c, + 0x51,0x04,0x08,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x08,0x00, + 0x07,0x00,0xd2,0xe4,0xd1,0x80,0xd0,0x2e,0xcf,0x86,0x95,0x28,0x54,0x04,0x08,0x00, + 0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x08,0xe6, + 0xd2,0x0c,0x91,0x08,0x10,0x04,0x08,0xdc,0x08,0x00,0x08,0x00,0x11,0x04,0x00,0x00, + 0x08,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00, + 0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xd4,0x14, + 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00, + 0x0b,0x00,0xd3,0x10,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6, + 0x0b,0xe6,0x52,0x04,0x0b,0xe6,0xd1,0x08,0x10,0x04,0x0b,0xe6,0x00,0x00,0x10,0x04, + 0x00,0x00,0x0b,0xdc,0xd0,0x5e,0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0b,0x00, + 0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0b,0x00,0x92,0x08, + 0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd4,0x10,0x53,0x04,0x0b,0x00,0x52,0x04, + 0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x10,0xe6,0x91,0x08, + 0x10,0x04,0x10,0xe6,0x10,0xdc,0x10,0xdc,0xd2,0x0c,0x51,0x04,0x10,0xdc,0x10,0x04, + 0x10,0xdc,0x10,0xe6,0xd1,0x08,0x10,0x04,0x10,0xe6,0x10,0xdc,0x10,0x04,0x10,0x00, + 0x00,0x00,0xcf,0x06,0x00,0x00,0xe1,0x1e,0x01,0xd0,0xaa,0xcf,0x86,0xd5,0x6e,0xd4, + 0x53,0xd3,0x17,0x52,0x04,0x09,0x00,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1, + 0xac,0x85,0xe1,0xac,0xb5,0x00,0x09,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x09,0xff, + 0xe1,0xac,0x87,0xe1,0xac,0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x89, + 0xe1,0xac,0xb5,0x00,0x09,0x00,0xd1,0x0f,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8b,0xe1, + 0xac,0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8d,0xe1,0xac,0xb5,0x00, + 0x09,0x00,0x93,0x17,0x92,0x13,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac, + 0x91,0xe1,0xac,0xb5,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x54,0x04,0x09,0x00,0xd3, + 0x10,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x07,0x09,0x00,0x09,0x00,0xd2, + 0x13,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xba,0xe1,0xac, + 0xb5,0x00,0x91,0x0f,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xbc,0xe1,0xac,0xb5, + 0x00,0x09,0x00,0xcf,0x86,0xd5,0x3d,0x94,0x39,0xd3,0x31,0xd2,0x25,0xd1,0x16,0x10, + 0x0b,0x09,0xff,0xe1,0xac,0xbe,0xe1,0xac,0xb5,0x00,0x09,0xff,0xe1,0xac,0xbf,0xe1, + 0xac,0xb5,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xad,0x82,0xe1,0xac,0xb5,0x00, + 0x91,0x08,0x10,0x04,0x09,0x09,0x09,0x00,0x09,0x00,0x12,0x04,0x09,0x00,0x00,0x00, + 0x09,0x00,0xd4,0x1c,0x53,0x04,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09,0x00,0x10,0x04, + 0x09,0x00,0x09,0xe6,0x91,0x08,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0xe6,0xd3,0x08, + 0x12,0x04,0x09,0xe6,0x09,0x00,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00, + 0x00,0x00,0x00,0x00,0xd0,0x2e,0xcf,0x86,0x55,0x04,0x0a,0x00,0xd4,0x18,0x53,0x04, + 0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x09,0x0d,0x09,0x11,0x04, + 0x0d,0x00,0x0a,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x0d,0x00, + 0x0d,0x00,0xcf,0x86,0x55,0x04,0x0c,0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x0c,0x00, + 0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x07,0x0c,0x00,0x0c,0x00,0xd3,0x0c,0x92,0x08, + 0x11,0x04,0x0c,0x00,0x0c,0x09,0x00,0x00,0x12,0x04,0x00,0x00,0x0c,0x00,0xe3,0xb2, + 0x01,0xe2,0x09,0x01,0xd1,0x4c,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x0a,0x00,0x54,0x04, + 0x0a,0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00, + 0x0a,0x07,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00, + 0xcf,0x86,0x95,0x1c,0x94,0x18,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00, + 0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00, + 0xd0,0x3a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x54,0x04,0x14,0x00, + 0x53,0x04,0x14,0x00,0xd2,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00, + 0x91,0x08,0x10,0x04,0x00,0x00,0x14,0x00,0x14,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x08, + 0x13,0x04,0x0d,0x00,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x0b,0xe6,0x10,0x04, + 0x0b,0xe6,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x01,0x0b,0xdc,0x0b,0xdc,0x92,0x08, + 0x11,0x04,0x0b,0xdc,0x0b,0xe6,0x0b,0xdc,0xd4,0x28,0xd3,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x01,0x0b,0x01,0xd2,0x0c,0x91,0x08,0x10,0x04, + 0x0b,0x01,0x0b,0x00,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xdc,0x0b,0x00, + 0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0d,0x00,0xd1,0x08, + 0x10,0x04,0x0d,0xe6,0x0d,0x00,0x10,0x04,0x0d,0x00,0x13,0x00,0x92,0x0c,0x51,0x04, + 0x10,0xe6,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06, + 0x07,0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x94,0x0c,0x53,0x04,0x07,0x00,0x12,0x04, + 0x07,0x00,0x08,0x00,0x08,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0xd5,0x40, + 0xd4,0x2c,0xd3,0x10,0x92,0x0c,0x51,0x04,0x08,0xe6,0x10,0x04,0x08,0xdc,0x08,0xe6, + 0x09,0xe6,0xd2,0x0c,0x51,0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x0a,0xe6,0xd1,0x08, + 0x10,0x04,0x0a,0xe6,0x0a,0xea,0x10,0x04,0x0a,0xd6,0x0a,0xdc,0x93,0x10,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x0a,0xca,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0xd4,0x14, + 0x93,0x10,0x52,0x04,0x0a,0xe6,0x51,0x04,0x0a,0xe6,0x10,0x04,0x0a,0xe6,0x10,0xe6, + 0x10,0xe6,0xd3,0x10,0x52,0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x13,0xe8, + 0x13,0xe4,0xd2,0x10,0xd1,0x08,0x10,0x04,0x13,0xe4,0x13,0xdc,0x10,0x04,0x00,0x00, + 0x12,0xe6,0xd1,0x08,0x10,0x04,0x0c,0xe9,0x0b,0xdc,0x10,0x04,0x09,0xe6,0x09,0xdc, + 0xe2,0x80,0x08,0xe1,0x48,0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84, + 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa5,0x00,0x01,0xff, + 0x61,0xcc,0xa5,0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc, + 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x42,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc, + 0xa3,0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00, + 0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x43,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff, + 0x63,0xcc,0xa7,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0x87,0x00,0x01,0xff, + 0x64,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa3,0x00,0x01,0xff, + 0x64,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc, + 0xb1,0x00,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa7,0x00, + 0x01,0xff,0x64,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xad,0x00,0x01,0xff, + 0x64,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc,0x80,0x00, + 0x01,0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc, + 0x81,0x00,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0x45,0xcc,0xad,0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff, + 0x45,0xcc,0xb0,0x00,0x01,0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff, + 0x45,0xcc,0xa7,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08, + 0x01,0xff,0x46,0xcc,0x87,0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc, + 0x84,0x00,0x10,0x08,0x01,0xff,0x48,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00, + 0x10,0x08,0x01,0xff,0x48,0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00, + 0x10,0x08,0x01,0xff,0x48,0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0x49,0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a, + 0x01,0xff,0x49,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00, + 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0x81,0x00,0x01,0xff, + 0x6b,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc, + 0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc, + 0xb1,0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00, + 0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff, + 0x6c,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xb1,0x00,0x01,0xff, + 0x6c,0xcc,0xb1,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4c,0xcc,0xad,0x00,0x01,0xff, + 0x6c,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x4d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc, + 0x81,0x00,0xcf,0x86,0xe5,0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x4d,0xcc,0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01, + 0xff,0x4d,0xcc,0xa3,0x00,0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x4e,0xcc,0x87,0x00,0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x4e, + 0xcc,0xa3,0x00,0x01,0xff,0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x4e,0xcc,0xb1,0x00,0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x4e, + 0xcc,0xad,0x00,0x01,0xff,0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f, + 0xcc,0x83,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01, + 0xff,0x4f,0xcc,0x83,0xcc,0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3, + 0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x80,0x00,0x01, + 0xff,0x6f,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x81, + 0x00,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x50, + 0xcc,0x81,0x00,0x01,0xff,0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x50,0xcc,0x87, + 0x00,0x01,0xff,0x70,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52, + 0xcc,0x87,0x00,0x01,0xff,0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa3, + 0x00,0x01,0xff,0x72,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x52,0xcc,0xa3, + 0xcc,0x84,0x00,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x52, + 0xcc,0xb1,0x00,0x01,0xff,0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10, + 0x08,0x01,0xff,0x53,0xcc,0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10, + 0x0a,0x01,0xff,0x53,0xcc,0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87, + 0x00,0x10,0x0a,0x01,0xff,0x53,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c, + 0xcc,0x87,0x00,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x53,0xcc,0xa3,0xcc,0x87, + 0x00,0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0x87, + 0x00,0x01,0xff,0x74,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,0xa3, + 0x00,0x01,0xff,0x74,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0xb1,0x00,0x01, + 0xff,0x74,0xcc,0xb1,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x54, + 0xcc,0xad,0x00,0x01,0xff,0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xa4, + 0x00,0x01,0xff,0x75,0xcc,0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0xb0, + 0x00,0x01,0xff,0x75,0xcc,0xb0,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xad,0x00,0x01, + 0xff,0x75,0xcc,0xad,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x83, + 0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x55, + 0xcc,0x84,0xcc,0x88,0x00,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0x56,0xcc,0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01, + 0xff,0x56,0xcc,0xa3,0x00,0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x10,0x02,0xcf,0x86, + 0xd5,0xe1,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc, + 0x80,0x00,0x01,0xff,0x77,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x81,0x00, + 0x01,0xff,0x77,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x88,0x00, + 0x01,0xff,0x77,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x87,0x00,0x01,0xff, + 0x77,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0xa3,0x00, + 0x01,0xff,0x77,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x58,0xcc,0x87,0x00,0x01,0xff, + 0x78,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x58,0xcc,0x88,0x00,0x01,0xff, + 0x78,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc, + 0x87,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0x82,0x00, + 0x01,0xff,0x7a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x5a,0xcc,0xa3,0x00,0x01,0xff, + 0x7a,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0xb1,0x00,0x01,0xff, + 0x7a,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x68,0xcc,0xb1,0x00,0x01,0xff,0x74,0xcc, + 0x88,0x00,0x92,0x1d,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01,0xff, + 0x79,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x02,0xff,0xc5,0xbf,0xcc,0x87,0x00,0x0a, + 0x00,0xd4,0x98,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa3, + 0x00,0x01,0xff,0x61,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x89,0x00,0x01, + 0xff,0x61,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x81, + 0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82, + 0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0xd2,0x28,0xd1,0x14,0x10, + 0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89, + 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82, + 0xcc,0x83,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x82,0x00,0x01, + 0xff,0x61,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x81, + 0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10, + 0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80, + 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86, + 0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x83,0x00,0x01, + 0xff,0x61,0xcc,0x86,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x86, + 0x00,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0x45,0xcc,0xa3,0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x45, + 0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45, + 0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82, + 0xcc,0x81,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0xcf,0x86,0xe5,0x31,0x01, + 0xd4,0x90,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,0xcc, + 0x80,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc, + 0x82,0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a, + 0x01,0xff,0x45,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00, + 0x10,0x0a,0x01,0xff,0x45,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc, + 0x82,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x89,0x00,0x01,0xff, + 0x69,0xcc,0x89,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc, + 0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc, + 0xa3,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00, + 0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc,0x81,0x00, + 0x01,0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc, + 0x80,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff, + 0x4f,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a, + 0x01,0xff,0x4f,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00, + 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff, + 0x6f,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x81,0x00, + 0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc, + 0x9b,0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff, + 0x4f,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x89,0x00,0xd4,0x98, + 0xd3,0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x83,0x00, + 0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc, + 0xa3,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0x55,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x55,0xcc, + 0x89,0x00,0x01,0xff,0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff, + 0x55,0xcc,0x9b,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x81,0x00,0x10,0x0a, + 0x01,0xff,0x55,0xcc,0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00, + 0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc, + 0x9b,0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff, + 0x75,0xcc,0x9b,0xcc,0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff, + 0x55,0xcc,0x9b,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0xa3,0x00,0x10,0x08, + 0x01,0xff,0x59,0xcc,0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0x59,0xcc,0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff, + 0x59,0xcc,0x89,0x00,0x01,0xff,0x79,0xcc,0x89,0x00,0x92,0x14,0x91,0x10,0x10,0x08, + 0x01,0xff,0x59,0xcc,0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x0a,0x00,0x0a,0x00, + 0xe1,0xc0,0x04,0xe0,0x80,0x02,0xcf,0x86,0xe5,0x2d,0x01,0xd4,0xa8,0xd3,0x54,0xd2, + 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1, + 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff, + 0xce,0xb1,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc, + 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01, + 0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82, + 0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x91,0xcc,0x93,0x00,0x01,0xff, + 0xce,0x91,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80,0x00, + 0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce, + 0x91,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x81,0x00,0x10, + 0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x91,0xcc,0x94, + 0xcd,0x82,0x00,0xd3,0x42,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc, + 0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc, + 0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10, + 0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94, + 0xcc,0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x95,0xcc, + 0x93,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x95,0xcc, + 0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10, + 0x0b,0x01,0xff,0xce,0x95,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x95,0xcc,0x94, + 0xcc,0x81,0x00,0x00,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01, + 0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01, + 0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80, + 0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff, + 0xce,0xb7,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd, + 0x82,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28,0xd1,0x12,0x10, + 0x09,0x01,0xff,0xce,0x97,0xcc,0x93,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0x00,0x10, + 0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x94, + 0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81,0x00, + 0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc, + 0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x82,0x00,0xd3,0x54,0xd2, + 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9, + 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff, + 0xce,0xb9,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc, + 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01, + 0xff,0xce,0xb9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82, + 0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x93,0x00,0x01,0xff, + 0xce,0x99,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x99,0xcc,0x93,0xcc,0x80,0x00, + 0x01,0xff,0xce,0x99,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce, + 0x99,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x99,0xcc,0x94,0xcc,0x81,0x00,0x10, + 0x0b,0x01,0xff,0xce,0x99,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x99,0xcc,0x94, + 0xcd,0x82,0x00,0xcf,0x86,0xe5,0x13,0x01,0xd4,0x84,0xd3,0x42,0xd2,0x28,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00, + 0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc, + 0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x81, + 0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xce,0x9f,0xcc,0x93,0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,0x00, + 0x10,0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc, + 0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x81, + 0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x54,0xd2,0x28, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff,0xcf,0x85,0xcc, + 0x94,0x00,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf, + 0x85,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93, + 0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff, + 0xcf,0x85,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00, + 0xd2,0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0x00,0x10, + 0x04,0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x0f,0x10,0x04, + 0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x81,0x00,0x10,0x04,0x00,0x00,0x01, + 0xff,0xce,0xa5,0xcc,0x94,0xcd,0x82,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00, + 0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc, + 0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81, + 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89, + 0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28, + 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xa9,0xcc,0x93,0x00,0x01,0xff,0xce,0xa9,0xcc, + 0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce, + 0xa9,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93, + 0xcc,0x81,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff, + 0xce,0xa9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0x00, + 0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01, + 0xff,0xce,0xb1,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01, + 0xff,0xce,0xb5,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x80, + 0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x80, + 0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff, + 0xce,0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x10,0x09,0x01,0xff, + 0xcf,0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x91,0x12,0x10,0x09, + 0x01,0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x00,0x00, + 0xe0,0xe1,0x02,0xcf,0x86,0xe5,0x91,0x01,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16, + 0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc, + 0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xcd,0x85, + 0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d, + 0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc, + 0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82, + 0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30, + 0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce, + 0x91,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80, + 0xcd,0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a, + 0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce, + 0x91,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93, + 0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00, + 0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x85, + 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7, + 0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xcd, + 0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xcd,0x85, + 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff, + 0xce,0xb7,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd, + 0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93, + 0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff, + 0xce,0x97,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc, + 0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81, + 0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d, + 0x01,0xff,0xce,0x97,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc, + 0x94,0xcd,0x82,0xcd,0x85,0x00,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b, + 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd, + 0x85,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01, + 0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff, + 0xcf,0x89,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc, + 0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xcd,0x85, + 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16, + 0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc, + 0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0xcd,0x85, + 0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d, + 0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc, + 0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x82, + 0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd3,0x49, + 0xd2,0x26,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce, + 0xb1,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x80,0xcd,0x85,0x00,0x01, + 0xff,0xce,0xb1,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81, + 0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcd,0x82,0x00,0x01,0xff, + 0xce,0xb1,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce, + 0x91,0xcc,0x86,0x00,0x01,0xff,0xce,0x91,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce, + 0x91,0xcc,0x80,0x00,0x01,0xff,0xce,0x91,0xcc,0x81,0x00,0xd1,0x0d,0x10,0x09,0x01, + 0xff,0xce,0x91,0xcd,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xb9,0x00,0x01, + 0x00,0xcf,0x86,0xe5,0x16,0x01,0xd4,0x8f,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10,0x04, + 0x01,0x00,0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc, + 0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01, + 0xff,0xce,0xb7,0xcc,0x81,0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb7, + 0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12, + 0x10,0x09,0x01,0xff,0xce,0x95,0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x81,0x00, + 0x10,0x09,0x01,0xff,0xce,0x97,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x81,0x00, + 0xd1,0x13,0x10,0x09,0x01,0xff,0xce,0x97,0xcd,0x85,0x00,0x01,0xff,0xe1,0xbe,0xbf, + 0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbe,0xbf,0xcc,0x81,0x00,0x01,0xff,0xe1, + 0xbe,0xbf,0xcd,0x82,0x00,0xd3,0x40,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce, + 0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce, + 0xb9,0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x51, + 0x04,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9, + 0xcc,0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc, + 0x86,0x00,0x01,0xff,0xce,0x99,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc, + 0x80,0x00,0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x04,0x00,0x00,0x01, + 0xff,0xe1,0xbf,0xbe,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbf,0xbe,0xcc,0x81, + 0x00,0x01,0xff,0xe1,0xbf,0xbe,0xcd,0x82,0x00,0xd4,0x93,0xd3,0x4e,0xd2,0x28,0xd1, + 0x12,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84, + 0x00,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85, + 0xcc,0x88,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x93,0x00, + 0x01,0xff,0xcf,0x81,0xcc,0x94,0x00,0x10,0x09,0x01,0xff,0xcf,0x85,0xcd,0x82,0x00, + 0x01,0xff,0xcf,0x85,0xcc,0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01, + 0xff,0xce,0xa5,0xcc,0x86,0x00,0x01,0xff,0xce,0xa5,0xcc,0x84,0x00,0x10,0x09,0x01, + 0xff,0xce,0xa5,0xcc,0x80,0x00,0x01,0xff,0xce,0xa5,0xcc,0x81,0x00,0xd1,0x12,0x10, + 0x09,0x01,0xff,0xce,0xa1,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x80,0x00,0x10, + 0x09,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x01,0xff,0x60,0x00,0xd3,0x3b,0xd2,0x18, + 0x51,0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x80,0xcd,0x85,0x00,0x01, + 0xff,0xcf,0x89,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x81, + 0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcd,0x82,0x00,0x01,0xff, + 0xcf,0x89,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce, + 0x9f,0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce, + 0xa9,0xcc,0x80,0x00,0x01,0xff,0xce,0xa9,0xcc,0x81,0x00,0xd1,0x10,0x10,0x09,0x01, + 0xff,0xce,0xa9,0xcd,0x85,0x00,0x01,0xff,0xc2,0xb4,0x00,0x10,0x04,0x01,0x00,0x00, + 0x00,0xe0,0x7e,0x0c,0xcf,0x86,0xe5,0xbb,0x08,0xe4,0x14,0x06,0xe3,0xf7,0x02,0xe2, + 0xbd,0x01,0xd1,0xd0,0xd0,0x4f,0xcf,0x86,0xd5,0x2e,0x94,0x2a,0xd3,0x18,0x92,0x14, + 0x91,0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01,0xff,0xe2,0x80,0x83,0x00, + 0x01,0x00,0x01,0x00,0x92,0x0d,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff, + 0x00,0x01,0xff,0x00,0x01,0x00,0x94,0x1b,0x53,0x04,0x01,0x00,0xd2,0x09,0x11,0x04, + 0x01,0x00,0x01,0xff,0x00,0x51,0x05,0x01,0xff,0x00,0x10,0x05,0x01,0xff,0x00,0x04, + 0x00,0x01,0x00,0xcf,0x86,0xd5,0x48,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x01,0x00,0x51, + 0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x52,0x04,0x04,0x00,0x11,0x04,0x04, + 0x00,0x06,0x00,0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x06,0x00,0x10,0x04,0x06,0x00,0x07, + 0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x08,0x00,0x10,0x04,0x08,0x00,0x06,0x00,0x52, + 0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x06,0x00,0xd4,0x23,0xd3, + 0x14,0x52,0x05,0x06,0xff,0x00,0x91,0x0a,0x10,0x05,0x0a,0xff,0x00,0x00,0xff,0x00, + 0x0f,0xff,0x00,0x92,0x0a,0x11,0x05,0x0f,0xff,0x00,0x01,0xff,0x00,0x01,0xff,0x00, + 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x00,0x00,0x01,0x00, + 0x01,0x00,0xd0,0x7e,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x53,0x04,0x01,0x00,0x52,0x04, + 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xd3,0x10,0x52,0x04, + 0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0c,0x00,0x0c,0x00,0x52,0x04,0x0c,0x00, + 0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00, + 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x02,0x00,0x91,0x08,0x10,0x04, + 0x03,0x00,0x04,0x00,0x04,0x00,0xd3,0x10,0xd2,0x08,0x11,0x04,0x06,0x00,0x08,0x00, + 0x11,0x04,0x08,0x00,0x0b,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00, + 0x10,0x04,0x0e,0x00,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x11,0x00,0x13,0x00, + 0xcf,0x86,0xd5,0x28,0x54,0x04,0x00,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x01,0xe6, + 0x01,0x01,0x01,0xe6,0xd2,0x0c,0x51,0x04,0x01,0x01,0x10,0x04,0x01,0x01,0x01,0xe6, + 0x91,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x01,0x00,0xd4,0x30,0xd3,0x1c,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x01,0x00,0x01,0xe6,0x04,0x00,0xd1,0x08,0x10,0x04,0x06,0x00, + 0x06,0x01,0x10,0x04,0x06,0x01,0x06,0xe6,0x92,0x10,0xd1,0x08,0x10,0x04,0x06,0xdc, + 0x06,0xe6,0x10,0x04,0x06,0x01,0x08,0x01,0x09,0xdc,0x93,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0a,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x81,0xd0,0x4f, + 0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,0x00,0x51,0x04, + 0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xa9,0x00,0x01,0x00,0x92,0x12,0x51,0x04,0x01, + 0x00,0x10,0x06,0x01,0xff,0x4b,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,0x01,0x00,0x53, + 0x04,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x04, + 0x00,0x07,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0x95, + 0x2c,0xd4,0x18,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0xd1,0x08,0x10,0x04,0x08, + 0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x0b, + 0x00,0x10,0x04,0x0b,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x68,0xcf, + 0x86,0xd5,0x48,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x11,0x00,0x00,0x00,0x53,0x04,0x01,0x00,0x92, + 0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,0x90,0xcc,0xb8,0x00,0x01, + 0xff,0xe2,0x86,0x92,0xcc,0xb8,0x00,0x01,0x00,0x94,0x1a,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,0x94,0xcc,0xb8, + 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x2e,0x94,0x2a,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0xd1,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x87,0x90,0xcc,0xb8, + 0x00,0x10,0x0a,0x01,0xff,0xe2,0x87,0x94,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x87,0x92, + 0xcc,0xb8,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x04,0x00,0x93,0x08,0x12,0x04,0x04,0x00,0x06, + 0x00,0x06,0x00,0xe2,0x38,0x02,0xe1,0x3f,0x01,0xd0,0x68,0xcf,0x86,0xd5,0x3e,0x94, + 0x3a,0xd3,0x16,0x52,0x04,0x01,0x00,0x91,0x0e,0x10,0x0a,0x01,0xff,0xe2,0x88,0x83, + 0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0xd2,0x12,0x91,0x0e,0x10,0x04,0x01,0x00,0x01, + 0xff,0xe2,0x88,0x88,0xcc,0xb8,0x00,0x01,0x00,0x91,0x0e,0x10,0x0a,0x01,0xff,0xe2, + 0x88,0x8b,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x24,0x93,0x20,0x52, + 0x04,0x01,0x00,0xd1,0x0e,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa3,0xcc,0xb8,0x00,0x01, + 0x00,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa5,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01, + 0x00,0xcf,0x86,0xd5,0x48,0x94,0x44,0xd3,0x2e,0xd2,0x12,0x91,0x0e,0x10,0x04,0x01, + 0x00,0x01,0xff,0xe2,0x88,0xbc,0xcc,0xb8,0x00,0x01,0x00,0xd1,0x0e,0x10,0x0a,0x01, + 0xff,0xe2,0x89,0x83,0xcc,0xb8,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe2, + 0x89,0x85,0xcc,0xb8,0x00,0x92,0x12,0x91,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2, + 0x89,0x88,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x40,0xd3,0x1e,0x92, + 0x1a,0xd1,0x0c,0x10,0x08,0x01,0xff,0x3d,0xcc,0xb8,0x00,0x01,0x00,0x10,0x0a,0x01, + 0xff,0xe2,0x89,0xa1,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1, + 0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x89,0x8d,0xcc,0xb8,0x00,0x10,0x08,0x01, + 0xff,0x3c,0xcc,0xb8,0x00,0x01,0xff,0x3e,0xcc,0xb8,0x00,0xd3,0x30,0xd2,0x18,0x91, + 0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xa4,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xa5, + 0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xb2,0xcc,0xb8, + 0x00,0x01,0xff,0xe2,0x89,0xb3,0xcc,0xb8,0x00,0x01,0x00,0x92,0x18,0x91,0x14,0x10, + 0x0a,0x01,0xff,0xe2,0x89,0xb6,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xb7,0xcc,0xb8, + 0x00,0x01,0x00,0x01,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x50,0x94,0x4c,0xd3,0x30,0xd2, + 0x18,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xba,0xcc,0xb8,0x00,0x01,0xff,0xe2, + 0x89,0xbb,0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0x82, + 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x83,0xcc,0xb8,0x00,0x01,0x00,0x92,0x18,0x91, + 0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0x86,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x87, + 0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x30,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xa2,0xcc,0xb8,0x00,0x01, + 0xff,0xe2,0x8a,0xa8,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xa9,0xcc,0xb8, + 0x00,0x01,0xff,0xe2,0x8a,0xab,0xcc,0xb8,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01, + 0x00,0xd4,0x5c,0xd3,0x2c,0x92,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xbc, + 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xbd,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2, + 0x8a,0x91,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x92,0xcc,0xb8,0x00,0x01,0x00,0xd2, + 0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xb2,0xcc,0xb8,0x00,0x01, + 0xff,0xe2,0x8a,0xb3,0xcc,0xb8,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xb4, + 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0xb5,0xcc,0xb8,0x00,0x01,0x00,0x93,0x0c,0x92, + 0x08,0x11,0x04,0x01,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xd1,0x64,0xd0,0x3e,0xcf, + 0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x20,0x53,0x04,0x01,0x00,0x92, + 0x18,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x80,0x88,0x00,0x10,0x08,0x01, + 0xff,0xe3,0x80,0x89,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01, + 0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x04,0x00,0x04,0x00,0xd0, + 0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51, + 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0xd5, + 0x2c,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,0x06,0x00,0x10, + 0x04,0x06,0x00,0x07,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x08, + 0x00,0x08,0x00,0x08,0x00,0x12,0x04,0x08,0x00,0x09,0x00,0xd4,0x14,0x53,0x04,0x09, + 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xd3, + 0x08,0x12,0x04,0x0c,0x00,0x10,0x00,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10, + 0x00,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,0xd3,0xa6,0xd2, + 0x74,0xd1,0x40,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x18,0x93,0x14,0x52, + 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x01,0x00,0x92, + 0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x14,0x53, + 0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x06, + 0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,0x06,0x00,0x10,0x04,0x06, + 0x00,0x07,0x00,0xd1,0x06,0xcf,0x06,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54, + 0x04,0x01,0x00,0x93,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x06,0x00,0x06, + 0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x13,0x04,0x04, + 0x00,0x06,0x00,0xd2,0xdc,0xd1,0x48,0xd0,0x26,0xcf,0x86,0x95,0x20,0x54,0x04,0x01, + 0x00,0xd3,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x07,0x00,0x06,0x00,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x08,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55, + 0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x04,0x00,0x06, + 0x00,0x06,0x00,0x52,0x04,0x06,0x00,0x11,0x04,0x06,0x00,0x08,0x00,0xd0,0x5e,0xcf, + 0x86,0xd5,0x2c,0xd4,0x10,0x53,0x04,0x06,0x00,0x92,0x08,0x11,0x04,0x06,0x00,0x07, + 0x00,0x07,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0x52, + 0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0a,0x00,0x0b,0x00,0xd4,0x10,0x93, + 0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xd3,0x10,0x92, + 0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x52,0x04,0x0a, + 0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x1c,0x94, + 0x18,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b, + 0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0b,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51, + 0x04,0x0b,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0c,0x00,0x0b,0x00,0x0b,0x00,0xd1, + 0xa8,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10, + 0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x0c,0x00,0x01, + 0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x01,0x00,0x01,0x00,0x94,0x14,0x53, + 0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x01,0x00,0x01, + 0x00,0x01,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x18,0x53,0x04,0x01,0x00,0x52,0x04,0x01, + 0x00,0xd1,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x10,0x04,0x0c,0x00,0x01,0x00,0xd3, + 0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0c,0x00,0x51,0x04,0x0c, + 0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x0c,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x06,0x00,0x93,0x0c,0x52,0x04,0x06,0x00,0x11, + 0x04,0x06,0x00,0x01,0x00,0x01,0x00,0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01, + 0x00,0x93,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x0c,0x00,0x0c, + 0x00,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c, + 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10, + 0x04,0x01,0x00,0x0c,0x00,0xcf,0x86,0xd5,0x2c,0x94,0x28,0xd3,0x10,0x52,0x04,0x08, + 0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09, + 0x00,0x10,0x04,0x09,0x00,0x0d,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0d,0x00,0x0c, + 0x00,0x06,0x00,0x94,0x0c,0x53,0x04,0x06,0x00,0x12,0x04,0x06,0x00,0x0a,0x00,0x06, + 0x00,0xe4,0x39,0x01,0xd3,0x0c,0xd2,0x06,0xcf,0x06,0x04,0x00,0xcf,0x06,0x06,0x00, + 0xd2,0x30,0xd1,0x06,0xcf,0x06,0x06,0x00,0xd0,0x06,0xcf,0x06,0x06,0x00,0xcf,0x86, + 0x95,0x1e,0x54,0x04,0x06,0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x0e, + 0x10,0x0a,0x06,0xff,0xe2,0xab,0x9d,0xcc,0xb8,0x00,0x06,0x00,0x06,0x00,0x06,0x00, + 0xd1,0x80,0xd0,0x3a,0xcf,0x86,0xd5,0x28,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,0x04, + 0x07,0x00,0x11,0x04,0x07,0x00,0x08,0x00,0xd3,0x08,0x12,0x04,0x08,0x00,0x09,0x00, + 0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x94,0x0c, + 0x93,0x08,0x12,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x30, + 0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00, + 0x10,0x00,0x10,0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00, + 0x0b,0x00,0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x10,0x00,0x10,0x00,0x54,0x04, + 0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x10,0x00, + 0xd0,0x32,0xcf,0x86,0xd5,0x14,0x54,0x04,0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00, + 0x11,0x04,0x10,0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00, + 0xd2,0x08,0x11,0x04,0x10,0x00,0x14,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x10,0x00, + 0x10,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x10,0x00,0x15,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x92,0x0c,0x51,0x04, + 0x10,0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd4,0x0c,0x53,0x04, + 0x14,0x00,0x12,0x04,0x14,0x00,0x11,0x00,0x53,0x04,0x14,0x00,0x52,0x04,0x14,0x00, + 0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0xe3,0xb9,0x01,0xd2,0xac,0xd1, + 0x68,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x08,0x00,0x94,0x14,0x53,0x04,0x08,0x00,0x52, + 0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x08,0x00,0xcf, + 0x86,0xd5,0x18,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x52,0x04,0x08,0x00,0x51, + 0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0xd4,0x14,0x53,0x04,0x09,0x00,0x52, + 0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0xd3,0x10,0x92, + 0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0a,0x00,0x0a,0x00,0x09,0x00,0x52,0x04,0x0a, + 0x00,0x11,0x04,0x0a,0x00,0x0b,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0x55, + 0x04,0x08,0x00,0xd4,0x1c,0x53,0x04,0x08,0x00,0xd2,0x0c,0x51,0x04,0x08,0x00,0x10, + 0x04,0x08,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xe6,0xd3, + 0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0d,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xd1,0x6c,0xd0,0x2a,0xcf,0x86,0x55, + 0x04,0x08,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10, + 0x04,0x00,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d, + 0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x55,0x04,0x08,0x00,0xd4,0x1c,0xd3,0x0c,0x52, + 0x04,0x08,0x00,0x11,0x04,0x08,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00, + 0x00,0x10,0x04,0x00,0x00,0x08,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10, + 0x04,0x00,0x00,0x0c,0x09,0xd0,0x5a,0xcf,0x86,0xd5,0x18,0x54,0x04,0x08,0x00,0x93, + 0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x00, + 0x00,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08, + 0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00, + 0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00, + 0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0xcf, + 0x86,0x95,0x40,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10, + 0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08, + 0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08, + 0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00, + 0x00,0x0a,0xe6,0xd2,0x9c,0xd1,0x68,0xd0,0x32,0xcf,0x86,0xd5,0x14,0x54,0x04,0x08, + 0x00,0x53,0x04,0x08,0x00,0x52,0x04,0x0a,0x00,0x11,0x04,0x08,0x00,0x0a,0x00,0x54, + 0x04,0x0a,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0d, + 0x00,0x0d,0x00,0x12,0x04,0x0d,0x00,0x10,0x00,0xcf,0x86,0x95,0x30,0x94,0x2c,0xd3, + 0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x12,0x00,0x91,0x08,0x10, + 0x04,0x12,0x00,0x13,0x00,0x13,0x00,0xd2,0x08,0x11,0x04,0x13,0x00,0x14,0x00,0x51, + 0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf, + 0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51,0x04,0x04, + 0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04, + 0x00,0x54,0x04,0x04,0x00,0x93,0x08,0x12,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xd1, + 0x06,0xcf,0x06,0x04,0x00,0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0xd5,0x14,0x54, + 0x04,0x04,0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x00, + 0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x04,0x00,0x12,0x04,0x04,0x00,0x00,0x00,0xcf, + 0x86,0xe5,0xa6,0x05,0xe4,0x9f,0x05,0xe3,0x96,0x04,0xe2,0xe4,0x03,0xe1,0xc0,0x01, + 0xd0,0x3e,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,0xd2,0x0c, + 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0xda,0x01,0xe4,0x91,0x08,0x10,0x04,0x01,0xe8, + 0x01,0xde,0x01,0xe0,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x04,0x00,0x10,0x04, + 0x04,0x00,0x06,0x00,0x51,0x04,0x06,0x00,0x10,0x04,0x04,0x00,0x01,0x00,0xcf,0x86, + 0xd5,0xaa,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81, + 0x8b,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x8d,0xe3,0x82, + 0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81, + 0x8f,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x91,0xe3,0x82, + 0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x93,0xe3,0x82,0x99, + 0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x95,0xe3,0x82,0x99,0x00,0x01,0x00, + 0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x97,0xe3,0x82,0x99,0x00,0x01, + 0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x99,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f, + 0x10,0x0b,0x01,0xff,0xe3,0x81,0x9b,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01, + 0xff,0xe3,0x81,0x9d,0xe3,0x82,0x99,0x00,0x01,0x00,0xd4,0x53,0xd3,0x3c,0xd2,0x1e, + 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x9f,0xe3,0x82,0x99,0x00,0x01,0x00,0x10, + 0x0b,0x01,0xff,0xe3,0x81,0xa1,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x04, + 0x01,0x00,0x01,0xff,0xe3,0x81,0xa4,0xe3,0x82,0x99,0x00,0x10,0x04,0x01,0x00,0x01, + 0xff,0xe3,0x81,0xa6,0xe3,0x82,0x99,0x00,0x92,0x13,0x91,0x0f,0x10,0x04,0x01,0x00, + 0x01,0xff,0xe3,0x81,0xa8,0xe3,0x82,0x99,0x00,0x01,0x00,0x01,0x00,0xd3,0x4a,0xd2, + 0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,0xaf,0xe3,0x82,0x99,0x00,0x01,0xff, + 0xe3,0x81,0xaf,0xe3,0x82,0x9a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x81,0xb2, + 0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb2,0xe3,0x82,0x9a, + 0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb5,0xe3,0x82,0x99,0x00,0x01,0xff, + 0xe3,0x81,0xb5,0xe3,0x82,0x9a,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01, + 0xff,0xe3,0x81,0xb8,0xe3,0x82,0x99,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb8,0xe3, + 0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,0xbb,0xe3,0x82, + 0x99,0x00,0x01,0xff,0xe3,0x81,0xbb,0xe3,0x82,0x9a,0x00,0x01,0x00,0xd0,0xee,0xcf, + 0x86,0xd5,0x42,0x54,0x04,0x01,0x00,0xd3,0x1b,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10, + 0x0b,0x01,0xff,0xe3,0x81,0x86,0xe3,0x82,0x99,0x00,0x06,0x00,0x10,0x04,0x06,0x00, + 0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x08,0x10,0x04,0x01,0x08, + 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0x9d,0xe3,0x82,0x99, + 0x00,0x06,0x00,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x01, + 0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3, + 0x82,0xab,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xad,0xe3, + 0x82,0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3, + 0x82,0xaf,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb1,0xe3, + 0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb3,0xe3,0x82, + 0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb5,0xe3,0x82,0x99,0x00,0x01, + 0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb7,0xe3,0x82,0x99,0x00, + 0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb9,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1, + 0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbb,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b, + 0x01,0xff,0xe3,0x82,0xbd,0xe3,0x82,0x99,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd5,0xd4, + 0x53,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbf,0xe3,0x82, + 0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0x81,0xe3,0x82,0x99,0x00,0x01, + 0x00,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x84,0xe3,0x82,0x99,0x00, + 0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x86,0xe3,0x82,0x99,0x00,0x92,0x13,0x91, + 0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x88,0xe3,0x82,0x99,0x00,0x01,0x00, + 0x01,0x00,0xd3,0x4a,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,0x83,0x8f,0xe3, + 0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x8f,0xe3,0x82,0x9a,0x00,0x10,0x04,0x01,0x00, + 0x01,0xff,0xe3,0x83,0x92,0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3, + 0x83,0x92,0xe3,0x82,0x9a,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0x95,0xe3, + 0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x95,0xe3,0x82,0x9a,0x00,0xd2,0x1e,0xd1,0x0f, + 0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x98,0xe3,0x82,0x99,0x00,0x10,0x0b,0x01, + 0xff,0xe3,0x83,0x98,0xe3,0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,0x0b,0x01,0xff, + 0xe3,0x83,0x9b,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x9b,0xe3,0x82,0x9a,0x00, + 0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x22,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b, + 0x01,0xff,0xe3,0x82,0xa6,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x01, + 0xff,0xe3,0x83,0xaf,0xe3,0x82,0x99,0x00,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff, + 0xe3,0x83,0xb0,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0xb1,0xe3,0x82,0x99,0x00, + 0x10,0x0b,0x01,0xff,0xe3,0x83,0xb2,0xe3,0x82,0x99,0x00,0x01,0x00,0x51,0x04,0x01, + 0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0xbd,0xe3,0x82,0x99,0x00,0x06,0x00,0xd1,0x65, + 0xd0,0x46,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x91,0x08, + 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x18,0x53,0x04, + 0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,0x00,0x10,0x04, + 0x13,0x00,0x14,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x15,0x93,0x11, + 0x52,0x04,0x01,0x00,0x91,0x09,0x10,0x05,0x01,0xff,0x00,0x01,0x00,0x01,0x00,0x01, + 0x00,0x01,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x54, + 0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,0x08,0x00,0x0a,0x00,0x94, + 0x0c,0x93,0x08,0x12,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xd2,0xa4,0xd1, + 0x5c,0xd0,0x22,0xcf,0x86,0x95,0x1c,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52, + 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x10,0x04,0x07,0x00,0x00, + 0x00,0x01,0x00,0xcf,0x86,0xd5,0x20,0xd4,0x0c,0x93,0x08,0x12,0x04,0x01,0x00,0x0b, + 0x00,0x0b,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x06,0x00,0x06, + 0x00,0x06,0x00,0x06,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01, + 0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55, + 0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01, + 0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0xd5,0x10,0x94,0x0c,0x53, + 0x04,0x01,0x00,0x12,0x04,0x01,0x00,0x07,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x53, + 0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x16, + 0x00,0xd1,0x30,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54, + 0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x01,0x00,0x01, + 0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x01,0x00,0x53, + 0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x07,0x00,0x54,0x04,0x01, + 0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x07,0x00,0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xd1,0x48,0xd0,0x40,0xcf, + 0x86,0xd5,0x06,0xcf,0x06,0x04,0x00,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x2c,0xd2, + 0x06,0xcf,0x06,0x04,0x00,0xd1,0x06,0xcf,0x06,0x04,0x00,0xd0,0x1a,0xcf,0x86,0x55, + 0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x07,0x00,0xcf,0x06,0x01,0x00,0xcf,0x86,0xcf, + 0x06,0x01,0x00,0xcf,0x86,0xcf,0x06,0x01,0x00,0xe2,0x71,0x05,0xd1,0x8c,0xd0,0x08, + 0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xd4,0x06, + 0xcf,0x06,0x01,0x00,0xd3,0x06,0xcf,0x06,0x01,0x00,0xd2,0x06,0xcf,0x06,0x01,0x00, + 0xd1,0x06,0xcf,0x06,0x01,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x10, + 0x93,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x08,0x00,0x08,0x00,0x53,0x04, + 0x08,0x00,0x12,0x04,0x08,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0xd3,0x08, + 0x12,0x04,0x0a,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0d,0x00, + 0x11,0x00,0x11,0x00,0x93,0x0c,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x13,0x00, + 0x13,0x00,0x94,0x14,0x53,0x04,0x13,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04, + 0x13,0x00,0x14,0x00,0x14,0x00,0x00,0x00,0xe0,0xdb,0x04,0xcf,0x86,0xe5,0xdf,0x01, + 0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x74,0xd2,0x6e,0xd1,0x06,0xcf,0x06,0x04,0x00, + 0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00, + 0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xd4,0x10,0x93,0x0c, + 0x92,0x08,0x11,0x04,0x04,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x93,0x10,0x52,0x04, + 0x04,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86, + 0x95,0x24,0x94,0x20,0x93,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00, + 0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x06,0x00,0x10,0x04,0x04,0x00,0x00,0x00, + 0x00,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x06,0x0a,0x00,0xd2,0x84,0xd1,0x4c,0xd0,0x16, + 0xcf,0x86,0x55,0x04,0x0a,0x00,0x94,0x0c,0x53,0x04,0x0a,0x00,0x12,0x04,0x0a,0x00, + 0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x0a,0x00,0xd4,0x1c,0xd3,0x0c,0x92,0x08, + 0x11,0x04,0x0c,0x00,0x0a,0x00,0x0a,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00, + 0x10,0x04,0x0a,0x00,0x0a,0xe6,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0d,0xe6,0x52,0x04, + 0x0d,0xe6,0x11,0x04,0x0a,0xe6,0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04, + 0x0a,0x00,0x53,0x04,0x0a,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04, + 0x11,0xe6,0x0d,0xe6,0x0b,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00, + 0x93,0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x00,0x00,0xd1,0x40, + 0xd0,0x3a,0xcf,0x86,0xd5,0x24,0x54,0x04,0x08,0x00,0xd3,0x10,0x52,0x04,0x08,0x00, + 0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x09,0x00,0x92,0x0c,0x51,0x04,0x09,0x00, + 0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,0x04, + 0x09,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x06,0x0a,0x00,0xd0,0x5e, + 0xcf,0x86,0xd5,0x28,0xd4,0x18,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0xd1,0x08, + 0x10,0x04,0x0a,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x11,0x00,0x93,0x0c,0x92,0x08, + 0x11,0x04,0x0c,0x00,0x0d,0x00,0x10,0x00,0x10,0x00,0xd4,0x1c,0x53,0x04,0x0c,0x00, + 0xd2,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0d,0x00,0x10,0x00,0x51,0x04,0x10,0x00, + 0x10,0x04,0x12,0x00,0x14,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x10,0x00,0x11,0x00, + 0x11,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x1c, + 0x94,0x18,0x93,0x14,0xd2,0x08,0x11,0x04,0x00,0x00,0x15,0x00,0x51,0x04,0x15,0x00, + 0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x00,0x00,0xd3,0x10, + 0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x92,0x0c, + 0x51,0x04,0x0d,0x00,0x10,0x04,0x0c,0x00,0x0a,0x00,0x0a,0x00,0xe4,0xf2,0x02,0xe3, + 0x65,0x01,0xd2,0x98,0xd1,0x48,0xd0,0x36,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10, + 0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x09,0x08,0x00,0x08,0x00, + 0x08,0x00,0xd4,0x0c,0x53,0x04,0x08,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x53,0x04, + 0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04, + 0x09,0x00,0x54,0x04,0x09,0x00,0x13,0x04,0x09,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06, + 0x0a,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08, + 0x10,0x04,0x0a,0x09,0x12,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00, + 0x0a,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x00,0x00,0x00,0x00, + 0x54,0x04,0x0b,0xe6,0xd3,0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00, + 0x52,0x04,0x0b,0x00,0x11,0x04,0x11,0x00,0x14,0x00,0xd1,0x60,0xd0,0x22,0xcf,0x86, + 0x55,0x04,0x0a,0x00,0x94,0x18,0x53,0x04,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00, + 0x10,0x04,0x0a,0x00,0x0a,0xdc,0x11,0x04,0x0a,0xdc,0x0a,0x00,0x0a,0x00,0xcf,0x86, + 0xd5,0x24,0x54,0x04,0x0a,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04, + 0x0a,0x00,0x0a,0x09,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04, + 0x00,0x00,0x0a,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00, + 0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04, + 0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04, + 0x0b,0x00,0x0b,0x07,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x34,0xd4,0x20,0xd3,0x10, + 0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00,0x52,0x04, + 0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x53,0x04,0x0b,0x00, + 0xd2,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x0b,0x00,0x54,0x04, + 0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04, + 0x10,0x00,0x00,0x00,0xd2,0xd0,0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0a,0x00, + 0x54,0x04,0x0a,0x00,0x93,0x10,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04, + 0x0a,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0a,0x00, + 0x52,0x04,0x0a,0x00,0x11,0x04,0x0a,0x00,0x00,0x00,0x53,0x04,0x0a,0x00,0x92,0x08, + 0x11,0x04,0x0a,0x00,0x00,0x00,0x0a,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00, + 0x12,0x04,0x0b,0x00,0x10,0x00,0xd0,0x3a,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04, + 0x0b,0x00,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0xe6, + 0xd1,0x08,0x10,0x04,0x0b,0xdc,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xe6,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x11,0x04,0x0b,0x00,0x0b,0xe6, + 0xcf,0x86,0xd5,0x2c,0xd4,0x18,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00, + 0x0b,0xe6,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x00,0x00, + 0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,0x54,0x04, + 0x0d,0x00,0x93,0x10,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x09, + 0x00,0x00,0x00,0x00,0xd1,0x8c,0xd0,0x72,0xcf,0x86,0xd5,0x4c,0xd4,0x30,0xd3,0x18, + 0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00, + 0x10,0x04,0x0c,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00, + 0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x93,0x18,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x0c,0x00,0x51,0x04, + 0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00, + 0x10,0x04,0x0c,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x94,0x10, + 0x93,0x0c,0x52,0x04,0x11,0x00,0x11,0x04,0x10,0x00,0x15,0x00,0x00,0x00,0x11,0x00, + 0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0xd4,0x14,0x53,0x04, + 0x0b,0x00,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0x09,0x00,0x00, + 0x53,0x04,0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x06, + 0x02,0xff,0xff,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xd1,0x76,0xd0,0x09,0xcf,0x86, + 0xcf,0x06,0x02,0xff,0xff,0xcf,0x86,0x85,0xd4,0x07,0xcf,0x06,0x02,0xff,0xff,0xd3, + 0x07,0xcf,0x06,0x02,0xff,0xff,0xd2,0x07,0xcf,0x06,0x02,0xff,0xff,0xd1,0x07,0xcf, + 0x06,0x02,0xff,0xff,0xd0,0x18,0xcf,0x86,0x55,0x05,0x02,0xff,0xff,0x94,0x0d,0x93, + 0x09,0x12,0x05,0x02,0xff,0xff,0x00,0x00,0x00,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x24, + 0x94,0x20,0xd3,0x10,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00, + 0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00, + 0x0b,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x12,0x04,0x0b,0x00,0x00,0x00, + 0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00, + 0xe4,0x9c,0x10,0xe3,0x16,0x08,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x08,0x04,0xe0, + 0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0x10,0x08,0x01, + 0xff,0xe8,0xbb,0x8a,0x00,0x01,0xff,0xe8,0xb3,0x88,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe6,0xbb,0x91,0x00,0x01,0xff,0xe4,0xb8,0xb2,0x00,0x10,0x08,0x01,0xff,0xe5, + 0x8f,0xa5,0x00,0x01,0xff,0xe9,0xbe,0x9c,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe9,0xbe,0x9c,0x00,0x01,0xff,0xe5,0xa5,0x91,0x00,0x10,0x08,0x01,0xff,0xe9, + 0x87,0x91,0x00,0x01,0xff,0xe5,0x96,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5, + 0xa5,0x88,0x00,0x01,0xff,0xe6,0x87,0xb6,0x00,0x10,0x08,0x01,0xff,0xe7,0x99,0xa9, + 0x00,0x01,0xff,0xe7,0xbe,0x85,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe8,0x98,0xbf,0x00,0x01,0xff,0xe8,0x9e,0xba,0x00,0x10,0x08,0x01,0xff,0xe8, + 0xa3,0xb8,0x00,0x01,0xff,0xe9,0x82,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6, + 0xa8,0x82,0x00,0x01,0xff,0xe6,0xb4,0x9b,0x00,0x10,0x08,0x01,0xff,0xe7,0x83,0x99, + 0x00,0x01,0xff,0xe7,0x8f,0x9e,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8, + 0x90,0xbd,0x00,0x01,0xff,0xe9,0x85,0xaa,0x00,0x10,0x08,0x01,0xff,0xe9,0xa7,0xb1, + 0x00,0x01,0xff,0xe4,0xba,0x82,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x8d,0xb5, + 0x00,0x01,0xff,0xe6,0xac,0x84,0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x9b,0x00,0x01, + 0xff,0xe8,0x98,0xad,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe9,0xb8,0x9e,0x00,0x01,0xff,0xe5,0xb5,0x90,0x00,0x10,0x08,0x01,0xff,0xe6, + 0xbf,0xab,0x00,0x01,0xff,0xe8,0x97,0x8d,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8, + 0xa5,0xa4,0x00,0x01,0xff,0xe6,0x8b,0x89,0x00,0x10,0x08,0x01,0xff,0xe8,0x87,0x98, + 0x00,0x01,0xff,0xe8,0xa0,0x9f,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5, + 0xbb,0x8a,0x00,0x01,0xff,0xe6,0x9c,0x97,0x00,0x10,0x08,0x01,0xff,0xe6,0xb5,0xaa, + 0x00,0x01,0xff,0xe7,0x8b,0xbc,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x83,0x8e, + 0x00,0x01,0xff,0xe4,0xbe,0x86,0x00,0x10,0x08,0x01,0xff,0xe5,0x86,0xb7,0x00,0x01, + 0xff,0xe5,0x8b,0x9e,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6, + 0x93,0x84,0x00,0x01,0xff,0xe6,0xab,0x93,0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x90, + 0x00,0x01,0xff,0xe7,0x9b,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x80,0x81, + 0x00,0x01,0xff,0xe8,0x98,0x86,0x00,0x10,0x08,0x01,0xff,0xe8,0x99,0x9c,0x00,0x01, + 0xff,0xe8,0xb7,0xaf,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9c,0xb2, + 0x00,0x01,0xff,0xe9,0xad,0xaf,0x00,0x10,0x08,0x01,0xff,0xe9,0xb7,0xba,0x00,0x01, + 0xff,0xe7,0xa2,0x8c,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xa5,0xbf,0x00,0x01, + 0xff,0xe7,0xb6,0xa0,0x00,0x10,0x08,0x01,0xff,0xe8,0x8f,0x89,0x00,0x01,0xff,0xe9, + 0x8c,0x84,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0x10,0x08, + 0x01,0xff,0xe5,0xa3,0x9f,0x00,0x01,0xff,0xe5,0xbc,0x84,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe7,0xb1,0xa0,0x00,0x01,0xff,0xe8,0x81,0xbe,0x00,0x10,0x08,0x01,0xff, + 0xe7,0x89,0xa2,0x00,0x01,0xff,0xe7,0xa3,0x8a,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe8,0xb3,0x82,0x00,0x01,0xff,0xe9,0x9b,0xb7,0x00,0x10,0x08,0x01,0xff, + 0xe5,0xa3,0x98,0x00,0x01,0xff,0xe5,0xb1,0xa2,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe6,0xa8,0x93,0x00,0x01,0xff,0xe6,0xb7,0x9a,0x00,0x10,0x08,0x01,0xff,0xe6,0xbc, + 0x8f,0x00,0x01,0xff,0xe7,0xb4,0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe7,0xb8,0xb7,0x00,0x01,0xff,0xe9,0x99,0x8b,0x00,0x10,0x08,0x01,0xff, + 0xe5,0x8b,0x92,0x00,0x01,0xff,0xe8,0x82,0x8b,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe5,0x87,0x9c,0x00,0x01,0xff,0xe5,0x87,0x8c,0x00,0x10,0x08,0x01,0xff,0xe7,0xa8, + 0x9c,0x00,0x01,0xff,0xe7,0xb6,0xbe,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe8,0x8f,0xb1,0x00,0x01,0xff,0xe9,0x99,0xb5,0x00,0x10,0x08,0x01,0xff,0xe8,0xae, + 0x80,0x00,0x01,0xff,0xe6,0x8b,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xa8, + 0x82,0x00,0x01,0xff,0xe8,0xab,0xbe,0x00,0x10,0x08,0x01,0xff,0xe4,0xb8,0xb9,0x00, + 0x01,0xff,0xe5,0xaf,0xa7,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe6,0x80,0x92,0x00,0x01,0xff,0xe7,0x8e,0x87,0x00,0x10,0x08,0x01,0xff, + 0xe7,0x95,0xb0,0x00,0x01,0xff,0xe5,0x8c,0x97,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe7,0xa3,0xbb,0x00,0x01,0xff,0xe4,0xbe,0xbf,0x00,0x10,0x08,0x01,0xff,0xe5,0xbe, + 0xa9,0x00,0x01,0xff,0xe4,0xb8,0x8d,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe6,0xb3,0x8c,0x00,0x01,0xff,0xe6,0x95,0xb8,0x00,0x10,0x08,0x01,0xff,0xe7,0xb4, + 0xa2,0x00,0x01,0xff,0xe5,0x8f,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xa1, + 0x9e,0x00,0x01,0xff,0xe7,0x9c,0x81,0x00,0x10,0x08,0x01,0xff,0xe8,0x91,0x89,0x00, + 0x01,0xff,0xe8,0xaa,0xaa,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe6,0xae,0xba,0x00,0x01,0xff,0xe8,0xbe,0xb0,0x00,0x10,0x08,0x01,0xff,0xe6,0xb2, + 0x88,0x00,0x01,0xff,0xe6,0x8b,0xbe,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x8b, + 0xa5,0x00,0x01,0xff,0xe6,0x8e,0xa0,0x00,0x10,0x08,0x01,0xff,0xe7,0x95,0xa5,0x00, + 0x01,0xff,0xe4,0xba,0xae,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x85, + 0xa9,0x00,0x01,0xff,0xe5,0x87,0x89,0x00,0x10,0x08,0x01,0xff,0xe6,0xa2,0x81,0x00, + 0x01,0xff,0xe7,0xb3,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x89,0xaf,0x00, + 0x01,0xff,0xe8,0xab,0x92,0x00,0x10,0x08,0x01,0xff,0xe9,0x87,0x8f,0x00,0x01,0xff, + 0xe5,0x8b,0xb5,0x00,0xe0,0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x91,0x82,0x00,0x01,0xff,0xe5,0xa5, + 0xb3,0x00,0x10,0x08,0x01,0xff,0xe5,0xbb,0xac,0x00,0x01,0xff,0xe6,0x97,0x85,0x00, + 0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xbf,0xbe,0x00,0x01,0xff,0xe7,0xa4,0xaa,0x00, + 0x10,0x08,0x01,0xff,0xe9,0x96,0xad,0x00,0x01,0xff,0xe9,0xa9,0xaa,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xba,0x97,0x00,0x01,0xff,0xe9,0xbb,0x8e,0x00, + 0x10,0x08,0x01,0xff,0xe5,0x8a,0x9b,0x00,0x01,0xff,0xe6,0x9b,0x86,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe6,0xad,0xb7,0x00,0x01,0xff,0xe8,0xbd,0xa2,0x00,0x10,0x08, + 0x01,0xff,0xe5,0xb9,0xb4,0x00,0x01,0xff,0xe6,0x86,0x90,0x00,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x88,0x80,0x00,0x01,0xff,0xe6,0x92,0x9a,0x00, + 0x10,0x08,0x01,0xff,0xe6,0xbc,0xa3,0x00,0x01,0xff,0xe7,0x85,0x89,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe7,0x92,0x89,0x00,0x01,0xff,0xe7,0xa7,0x8a,0x00,0x10,0x08, + 0x01,0xff,0xe7,0xb7,0xb4,0x00,0x01,0xff,0xe8,0x81,0xaf,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe8,0xbc,0xa6,0x00,0x01,0xff,0xe8,0x93,0xae,0x00,0x10,0x08, + 0x01,0xff,0xe9,0x80,0xa3,0x00,0x01,0xff,0xe9,0x8d,0x8a,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe5,0x88,0x97,0x00,0x01,0xff,0xe5,0x8a,0xa3,0x00,0x10,0x08,0x01,0xff, + 0xe5,0x92,0xbd,0x00,0x01,0xff,0xe7,0x83,0x88,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xa3,0x82,0x00,0x01,0xff,0xe8,0xaa,0xaa,0x00, + 0x10,0x08,0x01,0xff,0xe5,0xbb,0x89,0x00,0x01,0xff,0xe5,0xbf,0xb5,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe6,0x8d,0xbb,0x00,0x01,0xff,0xe6,0xae,0xae,0x00,0x10,0x08, + 0x01,0xff,0xe7,0xb0,0xbe,0x00,0x01,0xff,0xe7,0x8d,0xb5,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe4,0xbb,0xa4,0x00,0x01,0xff,0xe5,0x9b,0xb9,0x00,0x10,0x08, + 0x01,0xff,0xe5,0xaf,0xa7,0x00,0x01,0xff,0xe5,0xb6,0xba,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe6,0x80,0x9c,0x00,0x01,0xff,0xe7,0x8e,0xb2,0x00,0x10,0x08,0x01,0xff, + 0xe7,0x91,0xa9,0x00,0x01,0xff,0xe7,0xbe,0x9a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe8,0x81,0x86,0x00,0x01,0xff,0xe9,0x88,0xb4,0x00,0x10,0x08, + 0x01,0xff,0xe9,0x9b,0xb6,0x00,0x01,0xff,0xe9,0x9d,0x88,0x00,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe9,0xa0,0x98,0x00,0x01,0xff,0xe4,0xbe,0x8b,0x00,0x10,0x08,0x01,0xff, + 0xe7,0xa6,0xae,0x00,0x01,0xff,0xe9,0x86,0xb4,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe9,0x9a,0xb8,0x00,0x01,0xff,0xe6,0x83,0xa1,0x00,0x10,0x08,0x01,0xff, + 0xe4,0xba,0x86,0x00,0x01,0xff,0xe5,0x83,0x9a,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe5,0xaf,0xae,0x00,0x01,0xff,0xe5,0xb0,0xbf,0x00,0x10,0x08,0x01,0xff,0xe6,0x96, + 0x99,0x00,0x01,0xff,0xe6,0xa8,0x82,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0x87,0x8e,0x00,0x01,0xff,0xe7, + 0x99,0x82,0x00,0x10,0x08,0x01,0xff,0xe8,0x93,0xbc,0x00,0x01,0xff,0xe9,0x81,0xbc, + 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xbe,0x8d,0x00,0x01,0xff,0xe6,0x9a,0x88, + 0x00,0x10,0x08,0x01,0xff,0xe9,0x98,0xae,0x00,0x01,0xff,0xe5,0x8a,0x89,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x9d,0xbb,0x00,0x01,0xff,0xe6,0x9f,0xb3, + 0x00,0x10,0x08,0x01,0xff,0xe6,0xb5,0x81,0x00,0x01,0xff,0xe6,0xba,0x9c,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe7,0x90,0x89,0x00,0x01,0xff,0xe7,0x95,0x99,0x00,0x10, + 0x08,0x01,0xff,0xe7,0xa1,0xab,0x00,0x01,0xff,0xe7,0xb4,0x90,0x00,0xd3,0x40,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xa1,0x9e,0x00,0x01,0xff,0xe5,0x85,0xad, + 0x00,0x10,0x08,0x01,0xff,0xe6,0x88,0xae,0x00,0x01,0xff,0xe9,0x99,0xb8,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe5,0x80,0xab,0x00,0x01,0xff,0xe5,0xb4,0x99,0x00,0x10, + 0x08,0x01,0xff,0xe6,0xb7,0xaa,0x00,0x01,0xff,0xe8,0xbc,0xaa,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe5,0xbe,0x8b,0x00,0x01,0xff,0xe6,0x85,0x84,0x00,0x10, + 0x08,0x01,0xff,0xe6,0xa0,0x97,0x00,0x01,0xff,0xe7,0x8e,0x87,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe9,0x9a,0x86,0x00,0x01,0xff,0xe5,0x88,0xa9,0x00,0x10,0x08,0x01, + 0xff,0xe5,0x90,0x8f,0x00,0x01,0xff,0xe5,0xb1,0xa5,0x00,0xd4,0x80,0xd3,0x40,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x98,0x93,0x00,0x01,0xff,0xe6,0x9d,0x8e, + 0x00,0x10,0x08,0x01,0xff,0xe6,0xa2,0xa8,0x00,0x01,0xff,0xe6,0xb3,0xa5,0x00,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe7,0x90,0x86,0x00,0x01,0xff,0xe7,0x97,0xa2,0x00,0x10, + 0x08,0x01,0xff,0xe7,0xbd,0xb9,0x00,0x01,0xff,0xe8,0xa3,0x8f,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe8,0xa3,0xa1,0x00,0x01,0xff,0xe9,0x87,0x8c,0x00,0x10, + 0x08,0x01,0xff,0xe9,0x9b,0xa2,0x00,0x01,0xff,0xe5,0x8c,0xbf,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe6,0xba,0xba,0x00,0x01,0xff,0xe5,0x90,0x9d,0x00,0x10,0x08,0x01, + 0xff,0xe7,0x87,0x90,0x00,0x01,0xff,0xe7,0x92,0x98,0x00,0xd3,0x40,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x01,0xff,0xe8,0x97,0xba,0x00,0x01,0xff,0xe9,0x9a,0xa3,0x00,0x10, + 0x08,0x01,0xff,0xe9,0xb1,0x97,0x00,0x01,0xff,0xe9,0xba,0x9f,0x00,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe6,0x9e,0x97,0x00,0x01,0xff,0xe6,0xb7,0x8b,0x00,0x10,0x08,0x01, + 0xff,0xe8,0x87,0xa8,0x00,0x01,0xff,0xe7,0xab,0x8b,0x00,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x01,0xff,0xe7,0xac,0xa0,0x00,0x01,0xff,0xe7,0xb2,0x92,0x00,0x10,0x08,0x01, + 0xff,0xe7,0x8b,0x80,0x00,0x01,0xff,0xe7,0x82,0x99,0x00,0xd1,0x10,0x10,0x08,0x01, + 0xff,0xe8,0xad,0x98,0x00,0x01,0xff,0xe4,0xbb,0x80,0x00,0x10,0x08,0x01,0xff,0xe8, + 0x8c,0xb6,0x00,0x01,0xff,0xe5,0x88,0xba,0x00,0xe2,0xad,0x06,0xe1,0xc4,0x03,0xe0, + 0xcb,0x01,0xcf,0x86,0xd5,0xe4,0xd4,0x74,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x01,0xff,0xe5,0x88,0x87,0x00,0x01,0xff,0xe5,0xba,0xa6,0x00,0x10,0x08,0x01,0xff, + 0xe6,0x8b,0x93,0x00,0x01,0xff,0xe7,0xb3,0x96,0x00,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe5,0xae,0x85,0x00,0x01,0xff,0xe6,0xb4,0x9e,0x00,0x10,0x08,0x01,0xff,0xe6,0x9a, + 0xb4,0x00,0x01,0xff,0xe8,0xbc,0xbb,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff, + 0xe8,0xa1,0x8c,0x00,0x01,0xff,0xe9,0x99,0x8d,0x00,0x10,0x08,0x01,0xff,0xe8,0xa6, + 0x8b,0x00,0x01,0xff,0xe5,0xbb,0x93,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0xe5,0x85, + 0x80,0x00,0x01,0xff,0xe5,0x97,0x80,0x00,0x01,0x00,0xd3,0x34,0xd2,0x18,0xd1,0x0c, + 0x10,0x08,0x01,0xff,0xe5,0xa1,0x9a,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe6,0x99, + 0xb4,0x00,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe5,0x87,0x9e,0x00, + 0x10,0x08,0x01,0xff,0xe7,0x8c,0xaa,0x00,0x01,0xff,0xe7,0x9b,0x8a,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xa4,0xbc,0x00,0x01,0xff,0xe7,0xa5,0x9e,0x00, + 0x10,0x08,0x01,0xff,0xe7,0xa5,0xa5,0x00,0x01,0xff,0xe7,0xa6,0x8f,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe9,0x9d,0x96,0x00,0x01,0xff,0xe7,0xb2,0xbe,0x00,0x10,0x08, + 0x01,0xff,0xe7,0xbe,0xbd,0x00,0x01,0x00,0xd4,0x64,0xd3,0x30,0xd2,0x18,0xd1,0x0c, + 0x10,0x08,0x01,0xff,0xe8,0x98,0x92,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe8,0xab, + 0xb8,0x00,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe9,0x80,0xb8,0x00, + 0x10,0x08,0x01,0xff,0xe9,0x83,0xbd,0x00,0x01,0x00,0xd2,0x14,0x51,0x04,0x01,0x00, + 0x10,0x08,0x01,0xff,0xe9,0xa3,0xaf,0x00,0x01,0xff,0xe9,0xa3,0xbc,0x00,0xd1,0x10, + 0x10,0x08,0x01,0xff,0xe9,0xa4,0xa8,0x00,0x01,0xff,0xe9,0xb6,0xb4,0x00,0x10,0x08, + 0x0d,0xff,0xe9,0x83,0x9e,0x00,0x0d,0xff,0xe9,0x9a,0xb7,0x00,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x06,0xff,0xe4,0xbe,0xae,0x00,0x06,0xff,0xe5,0x83,0xa7,0x00, + 0x10,0x08,0x06,0xff,0xe5,0x85,0x8d,0x00,0x06,0xff,0xe5,0x8b,0x89,0x00,0xd1,0x10, + 0x10,0x08,0x06,0xff,0xe5,0x8b,0xa4,0x00,0x06,0xff,0xe5,0x8d,0x91,0x00,0x10,0x08, + 0x06,0xff,0xe5,0x96,0x9d,0x00,0x06,0xff,0xe5,0x98,0x86,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x06,0xff,0xe5,0x99,0xa8,0x00,0x06,0xff,0xe5,0xa1,0x80,0x00,0x10,0x08, + 0x06,0xff,0xe5,0xa2,0xa8,0x00,0x06,0xff,0xe5,0xb1,0xa4,0x00,0xd1,0x10,0x10,0x08, + 0x06,0xff,0xe5,0xb1,0xae,0x00,0x06,0xff,0xe6,0x82,0x94,0x00,0x10,0x08,0x06,0xff, + 0xe6,0x85,0xa8,0x00,0x06,0xff,0xe6,0x86,0x8e,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4, + 0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe6,0x87,0xb2,0x00,0x06, + 0xff,0xe6,0x95,0x8f,0x00,0x10,0x08,0x06,0xff,0xe6,0x97,0xa2,0x00,0x06,0xff,0xe6, + 0x9a,0x91,0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe6,0xa2,0x85,0x00,0x06,0xff,0xe6, + 0xb5,0xb7,0x00,0x10,0x08,0x06,0xff,0xe6,0xb8,0x9a,0x00,0x06,0xff,0xe6,0xbc,0xa2, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0x85,0xae,0x00,0x06,0xff,0xe7, + 0x88,0xab,0x00,0x10,0x08,0x06,0xff,0xe7,0x90,0xa2,0x00,0x06,0xff,0xe7,0xa2,0x91, + 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa4,0xbe,0x00,0x06,0xff,0xe7,0xa5,0x89, + 0x00,0x10,0x08,0x06,0xff,0xe7,0xa5,0x88,0x00,0x06,0xff,0xe7,0xa5,0x90,0x00,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa5,0x96,0x00,0x06,0xff,0xe7, + 0xa5,0x9d,0x00,0x10,0x08,0x06,0xff,0xe7,0xa6,0x8d,0x00,0x06,0xff,0xe7,0xa6,0x8e, + 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa9,0x80,0x00,0x06,0xff,0xe7,0xaa,0x81, + 0x00,0x10,0x08,0x06,0xff,0xe7,0xaf,0x80,0x00,0x06,0xff,0xe7,0xb7,0xb4,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xb8,0x89,0x00,0x06,0xff,0xe7,0xb9,0x81, + 0x00,0x10,0x08,0x06,0xff,0xe7,0xbd,0xb2,0x00,0x06,0xff,0xe8,0x80,0x85,0x00,0xd1, + 0x10,0x10,0x08,0x06,0xff,0xe8,0x87,0xad,0x00,0x06,0xff,0xe8,0x89,0xb9,0x00,0x10, + 0x08,0x06,0xff,0xe8,0x89,0xb9,0x00,0x06,0xff,0xe8,0x91,0x97,0x00,0xd4,0x75,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe8,0xa4,0x90,0x00,0x06,0xff,0xe8, + 0xa6,0x96,0x00,0x10,0x08,0x06,0xff,0xe8,0xac,0x81,0x00,0x06,0xff,0xe8,0xac,0xb9, + 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe8,0xb3,0x93,0x00,0x06,0xff,0xe8,0xb4,0x88, + 0x00,0x10,0x08,0x06,0xff,0xe8,0xbe,0xb6,0x00,0x06,0xff,0xe9,0x80,0xb8,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe9,0x9b,0xa3,0x00,0x06,0xff,0xe9,0x9f,0xbf, + 0x00,0x10,0x08,0x06,0xff,0xe9,0xa0,0xbb,0x00,0x0b,0xff,0xe6,0x81,0xb5,0x00,0x91, + 0x11,0x10,0x09,0x0b,0xff,0xf0,0xa4,0x8b,0xae,0x00,0x0b,0xff,0xe8,0x88,0x98,0x00, + 0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe4,0xb8,0xa6,0x00, + 0x08,0xff,0xe5,0x86,0xb5,0x00,0x10,0x08,0x08,0xff,0xe5,0x85,0xa8,0x00,0x08,0xff, + 0xe4,0xbe,0x80,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0x85,0x85,0x00,0x08,0xff, + 0xe5,0x86,0x80,0x00,0x10,0x08,0x08,0xff,0xe5,0x8b,0x87,0x00,0x08,0xff,0xe5,0x8b, + 0xba,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0x96,0x9d,0x00,0x08,0xff, + 0xe5,0x95,0x95,0x00,0x10,0x08,0x08,0xff,0xe5,0x96,0x99,0x00,0x08,0xff,0xe5,0x97, + 0xa2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0xa1,0x9a,0x00,0x08,0xff,0xe5,0xa2, + 0xb3,0x00,0x10,0x08,0x08,0xff,0xe5,0xa5,0x84,0x00,0x08,0xff,0xe5,0xa5,0x94,0x00, + 0xe0,0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x08,0xff,0xe5,0xa9,0xa2,0x00,0x08,0xff,0xe5,0xac,0xa8,0x00,0x10,0x08, + 0x08,0xff,0xe5,0xbb,0x92,0x00,0x08,0xff,0xe5,0xbb,0x99,0x00,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe5,0xbd,0xa9,0x00,0x08,0xff,0xe5,0xbe,0xad,0x00,0x10,0x08,0x08,0xff, + 0xe6,0x83,0x98,0x00,0x08,0xff,0xe6,0x85,0x8e,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe6,0x84,0x88,0x00,0x08,0xff,0xe6,0x86,0x8e,0x00,0x10,0x08,0x08,0xff, + 0xe6,0x85,0xa0,0x00,0x08,0xff,0xe6,0x87,0xb2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe6,0x88,0xb4,0x00,0x08,0xff,0xe6,0x8f,0x84,0x00,0x10,0x08,0x08,0xff,0xe6,0x90, + 0x9c,0x00,0x08,0xff,0xe6,0x91,0x92,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe6,0x95,0x96,0x00,0x08,0xff,0xe6,0x99,0xb4,0x00,0x10,0x08,0x08,0xff, + 0xe6,0x9c,0x97,0x00,0x08,0xff,0xe6,0x9c,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe6,0x9d,0x96,0x00,0x08,0xff,0xe6,0xad,0xb9,0x00,0x10,0x08,0x08,0xff,0xe6,0xae, + 0xba,0x00,0x08,0xff,0xe6,0xb5,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe6,0xbb,0x9b,0x00,0x08,0xff,0xe6,0xbb,0x8b,0x00,0x10,0x08,0x08,0xff,0xe6,0xbc, + 0xa2,0x00,0x08,0xff,0xe7,0x80,0x9e,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x85, + 0xae,0x00,0x08,0xff,0xe7,0x9e,0xa7,0x00,0x10,0x08,0x08,0xff,0xe7,0x88,0xb5,0x00, + 0x08,0xff,0xe7,0x8a,0xaf,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe7,0x8c,0xaa,0x00,0x08,0xff,0xe7,0x91,0xb1,0x00,0x10,0x08,0x08,0xff, + 0xe7,0x94,0x86,0x00,0x08,0xff,0xe7,0x94,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe7,0x98,0x9d,0x00,0x08,0xff,0xe7,0x98,0x9f,0x00,0x10,0x08,0x08,0xff,0xe7,0x9b, + 0x8a,0x00,0x08,0xff,0xe7,0x9b,0x9b,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe7,0x9b,0xb4,0x00,0x08,0xff,0xe7,0x9d,0x8a,0x00,0x10,0x08,0x08,0xff,0xe7,0x9d, + 0x80,0x00,0x08,0xff,0xe7,0xa3,0x8c,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0xaa, + 0xb1,0x00,0x08,0xff,0xe7,0xaf,0x80,0x00,0x10,0x08,0x08,0xff,0xe7,0xb1,0xbb,0x00, + 0x08,0xff,0xe7,0xb5,0x9b,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe7,0xb7,0xb4,0x00,0x08,0xff,0xe7,0xbc,0xbe,0x00,0x10,0x08,0x08,0xff,0xe8,0x80, + 0x85,0x00,0x08,0xff,0xe8,0x8d,0x92,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0x8f, + 0xaf,0x00,0x08,0xff,0xe8,0x9d,0xb9,0x00,0x10,0x08,0x08,0xff,0xe8,0xa5,0x81,0x00, + 0x08,0xff,0xe8,0xa6,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xa6, + 0x96,0x00,0x08,0xff,0xe8,0xaa,0xbf,0x00,0x10,0x08,0x08,0xff,0xe8,0xab,0xb8,0x00, + 0x08,0xff,0xe8,0xab,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xac,0x81,0x00, + 0x08,0xff,0xe8,0xab,0xbe,0x00,0x10,0x08,0x08,0xff,0xe8,0xab,0xad,0x00,0x08,0xff, + 0xe8,0xac,0xb9,0x00,0xcf,0x86,0x95,0xde,0xd4,0x81,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x08,0xff,0xe8,0xae,0x8a,0x00,0x08,0xff,0xe8,0xb4,0x88,0x00,0x10,0x08, + 0x08,0xff,0xe8,0xbc,0xb8,0x00,0x08,0xff,0xe9,0x81,0xb2,0x00,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe9,0x86,0x99,0x00,0x08,0xff,0xe9,0x89,0xb6,0x00,0x10,0x08,0x08,0xff, + 0xe9,0x99,0xbc,0x00,0x08,0xff,0xe9,0x9b,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x08,0xff,0xe9,0x9d,0x96,0x00,0x08,0xff,0xe9,0x9f,0x9b,0x00,0x10,0x08,0x08,0xff, + 0xe9,0x9f,0xbf,0x00,0x08,0xff,0xe9,0xa0,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff, + 0xe9,0xa0,0xbb,0x00,0x08,0xff,0xe9,0xac,0x92,0x00,0x10,0x08,0x08,0xff,0xe9,0xbe, + 0x9c,0x00,0x08,0xff,0xf0,0xa2,0xa1,0x8a,0x00,0xd3,0x45,0xd2,0x22,0xd1,0x12,0x10, + 0x09,0x08,0xff,0xf0,0xa2,0xa1,0x84,0x00,0x08,0xff,0xf0,0xa3,0x8f,0x95,0x00,0x10, + 0x08,0x08,0xff,0xe3,0xae,0x9d,0x00,0x08,0xff,0xe4,0x80,0x98,0x00,0xd1,0x11,0x10, + 0x08,0x08,0xff,0xe4,0x80,0xb9,0x00,0x08,0xff,0xf0,0xa5,0x89,0x89,0x00,0x10,0x09, + 0x08,0xff,0xf0,0xa5,0xb3,0x90,0x00,0x08,0xff,0xf0,0xa7,0xbb,0x93,0x00,0x92,0x14, + 0x91,0x10,0x10,0x08,0x08,0xff,0xe9,0xbd,0x83,0x00,0x08,0xff,0xe9,0xbe,0x8e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x94,0x01,0xe0,0x08,0x01,0xcf,0x86,0xd5,0x42, + 0xd4,0x14,0x93,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00, + 0x00,0x00,0x00,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00, + 0x01,0x00,0x01,0x00,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x00,0x00,0x04,0xff, + 0xd7,0x99,0xd6,0xb4,0x00,0x10,0x04,0x01,0x1a,0x01,0xff,0xd7,0xb2,0xd6,0xb7,0x00, + 0xd4,0x42,0x53,0x04,0x01,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff, + 0xd7,0xa9,0xd7,0x81,0x00,0x01,0xff,0xd7,0xa9,0xd7,0x82,0x00,0xd1,0x16,0x10,0x0b, + 0x01,0xff,0xd7,0xa9,0xd6,0xbc,0xd7,0x81,0x00,0x01,0xff,0xd7,0xa9,0xd6,0xbc,0xd7, + 0x82,0x00,0x10,0x09,0x01,0xff,0xd7,0x90,0xd6,0xb7,0x00,0x01,0xff,0xd7,0x90,0xd6, + 0xb8,0x00,0xd3,0x43,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x90,0xd6,0xbc, + 0x00,0x01,0xff,0xd7,0x91,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x92,0xd6,0xbc, + 0x00,0x01,0xff,0xd7,0x93,0xd6,0xbc,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x94, + 0xd6,0xbc,0x00,0x01,0xff,0xd7,0x95,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x96, + 0xd6,0xbc,0x00,0x00,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x98,0xd6, + 0xbc,0x00,0x01,0xff,0xd7,0x99,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x9a,0xd6, + 0xbc,0x00,0x01,0xff,0xd7,0x9b,0xd6,0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7, + 0x9c,0xd6,0xbc,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xd7,0x9e,0xd6,0xbc,0x00,0x00, + 0x00,0xcf,0x86,0x95,0x85,0x94,0x81,0xd3,0x3e,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01, + 0xff,0xd7,0xa0,0xd6,0xbc,0x00,0x01,0xff,0xd7,0xa1,0xd6,0xbc,0x00,0x10,0x04,0x00, + 0x00,0x01,0xff,0xd7,0xa3,0xd6,0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7,0xa4, + 0xd6,0xbc,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xd7,0xa6,0xd6,0xbc,0x00,0x01,0xff, + 0xd7,0xa7,0xd6,0xbc,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0xa8,0xd6, + 0xbc,0x00,0x01,0xff,0xd7,0xa9,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0xaa,0xd6, + 0xbc,0x00,0x01,0xff,0xd7,0x95,0xd6,0xb9,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7, + 0x91,0xd6,0xbf,0x00,0x01,0xff,0xd7,0x9b,0xd6,0xbf,0x00,0x10,0x09,0x01,0xff,0xd7, + 0xa4,0xd6,0xbf,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04, + 0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00, + 0x0c,0x00,0x0c,0x00,0xcf,0x86,0x95,0x24,0xd4,0x10,0x93,0x0c,0x92,0x08,0x11,0x04, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00, + 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd3,0x5a,0xd2,0x06, + 0xcf,0x06,0x01,0x00,0xd1,0x14,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x95,0x08, + 0x14,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54,0x04, + 0x01,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0xcf,0x86,0xd5,0x0c,0x94,0x08,0x13,0x04,0x01,0x00,0x00,0x00,0x05,0x00, + 0x54,0x04,0x05,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04, + 0x06,0x00,0x07,0x00,0x00,0x00,0xd2,0xce,0xd1,0xa5,0xd0,0x37,0xcf,0x86,0xd5,0x15, + 0x54,0x05,0x06,0xff,0x00,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00,0x00, + 0x00,0x00,0x00,0x94,0x1c,0xd3,0x10,0x52,0x04,0x01,0xe6,0x51,0x04,0x0a,0xe6,0x10, + 0x04,0x0a,0xe6,0x10,0xdc,0x52,0x04,0x10,0xdc,0x11,0x04,0x10,0xdc,0x11,0xe6,0x01, + 0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10, + 0x04,0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00,0x07,0x00,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x01, + 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd4,0x18,0xd3,0x10,0x52, + 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x12,0x04,0x01, + 0x00,0x00,0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06, + 0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd0,0x06,0xcf, + 0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01, + 0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00, + 0x00,0x01,0xff,0x00,0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10, + 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00, + 0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x94,0x14, + 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0xd0,0x2f,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x15,0x93,0x11, + 0x92,0x0d,0x91,0x09,0x10,0x05,0x01,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, + 0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01, + 0x00,0x00,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x18,0xd3,0x0c,0x92,0x08,0x11,0x04,0x00, + 0x00,0x01,0x00,0x01,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3, + 0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x00, + 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd4,0x20,0xd3, + 0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52, + 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x53,0x05,0x00, + 0xff,0x00,0xd2,0x0d,0x91,0x09,0x10,0x05,0x00,0xff,0x00,0x04,0x00,0x04,0x00,0x91, + 0x08,0x10,0x04,0x03,0x00,0x01,0x00,0x01,0x00,0x83,0xe2,0x46,0x3e,0xe1,0x1f,0x3b, + 0xe0,0x9c,0x39,0xcf,0x86,0xe5,0x40,0x26,0xc4,0xe3,0x16,0x14,0xe2,0xef,0x11,0xe1, + 0xd0,0x10,0xe0,0x60,0x07,0xcf,0x86,0xe5,0x53,0x03,0xe4,0x4c,0x02,0xe3,0x3d,0x01, + 0xd2,0x94,0xd1,0x70,0xd0,0x4a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x07,0x00, + 0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00, + 0xd4,0x14,0x93,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00, + 0x00,0x00,0x07,0x00,0x53,0x04,0x07,0x00,0xd2,0x0c,0x51,0x04,0x07,0x00,0x10,0x04, + 0x07,0x00,0x00,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0xcf,0x86, + 0x95,0x20,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00, + 0x00,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00, + 0x00,0x00,0xd0,0x06,0xcf,0x06,0x07,0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x54,0x04, + 0x07,0x00,0x53,0x04,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00, + 0x00,0x00,0x00,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x94,0x1c,0x93,0x18, + 0xd2,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x51,0x04,0x00,0x00, + 0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,0x04,0x07,0x00,0x93,0x10, + 0x52,0x04,0x07,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00, + 0xcf,0x06,0x08,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x2c,0xd4,0x20,0x53,0x04,0x08,0x00, + 0xd2,0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x10,0x00,0xd1,0x08,0x10,0x04, + 0x10,0x00,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x53,0x04,0x0a,0x00,0x12,0x04, + 0x0a,0x00,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04, + 0x00,0x00,0x0a,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00, + 0x91,0x08,0x10,0x04,0x0a,0x00,0x0a,0xdc,0x00,0x00,0xd2,0x5e,0xd1,0x06,0xcf,0x06, + 0x00,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00, + 0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x0a,0x00, + 0xcf,0x86,0xd5,0x18,0x54,0x04,0x0a,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x10,0xdc,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x53,0x04, + 0x10,0x00,0x12,0x04,0x10,0x00,0x00,0x00,0xd1,0x70,0xd0,0x36,0xcf,0x86,0xd5,0x18, + 0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,0x00,0x51,0x04,0x05,0x00, + 0x10,0x04,0x05,0x00,0x10,0x00,0x94,0x18,0xd3,0x08,0x12,0x04,0x05,0x00,0x00,0x00, + 0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x13,0x00,0x13,0x00,0x05,0x00, + 0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x05,0x00,0x92,0x0c,0x51,0x04,0x05,0x00, + 0x10,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x0c, + 0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x10,0xe6,0x92,0x0c,0x51,0x04,0x10,0xe6, + 0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04, + 0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04, + 0x00,0x00,0x07,0x00,0x08,0x00,0xcf,0x86,0x95,0x1c,0xd4,0x0c,0x93,0x08,0x12,0x04, + 0x08,0x00,0x00,0x00,0x08,0x00,0x93,0x0c,0x52,0x04,0x08,0x00,0x11,0x04,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0xba,0xd2,0x80,0xd1,0x34,0xd0,0x1a,0xcf,0x86, + 0x55,0x04,0x05,0x00,0x94,0x10,0x93,0x0c,0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00, + 0x07,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0x95,0x14,0x94,0x10,0x53,0x04,0x05,0x00, + 0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0xd0,0x2a, + 0xcf,0x86,0xd5,0x14,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00, + 0x11,0x04,0x07,0x00,0x00,0x00,0x94,0x10,0x53,0x04,0x07,0x00,0x92,0x08,0x11,0x04, + 0x07,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xcf,0x86,0xd5,0x10,0x54,0x04,0x12,0x00, + 0x93,0x08,0x12,0x04,0x12,0x00,0x00,0x00,0x12,0x00,0x54,0x04,0x12,0x00,0x53,0x04, + 0x12,0x00,0x12,0x04,0x12,0x00,0x00,0x00,0xd1,0x34,0xd0,0x12,0xcf,0x86,0x55,0x04, + 0x10,0x00,0x94,0x08,0x13,0x04,0x10,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04, + 0x10,0x00,0x94,0x18,0xd3,0x08,0x12,0x04,0x10,0x00,0x00,0x00,0x52,0x04,0x00,0x00, + 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0xcf,0x06,0x00,0x00, + 0xd2,0x06,0xcf,0x06,0x10,0x00,0xd1,0x40,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00, + 0x54,0x04,0x10,0x00,0x93,0x10,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04, + 0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x10,0x00,0x93,0x0c, + 0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x08,0x13,0x04, + 0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe4,0xce,0x02,0xe3,0x45,0x01, + 0xd2,0xd0,0xd1,0x70,0xd0,0x52,0xcf,0x86,0xd5,0x20,0x94,0x1c,0xd3,0x0c,0x52,0x04, + 0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00, + 0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,0x04,0x07,0x00,0xd3,0x10,0x52,0x04, + 0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0xd2,0x0c,0x91,0x08, + 0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x00,0x00, + 0x10,0x04,0x00,0x00,0x07,0x00,0xcf,0x86,0x95,0x18,0x54,0x04,0x0b,0x00,0x93,0x10, + 0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00, + 0x10,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00, + 0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x94,0x14, + 0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00, + 0x10,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x11,0x00,0xd3,0x14, + 0xd2,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x11,0x04,0x11,0x00, + 0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x11,0x00,0x11,0x00, + 0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x1c,0x54,0x04,0x09,0x00,0x53,0x04,0x09,0x00, + 0xd2,0x08,0x11,0x04,0x09,0x00,0x0b,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00, + 0x09,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00, + 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0xcf,0x06,0x00,0x00, + 0xd0,0x1a,0xcf,0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,0x00,0x53,0x04,0x0d,0x00, + 0x52,0x04,0x00,0x00,0x11,0x04,0x11,0x00,0x0d,0x00,0xcf,0x86,0x95,0x14,0x54,0x04, + 0x11,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x11,0x00,0x11,0x00,0x11,0x00, + 0x11,0x00,0xd2,0xec,0xd1,0xa4,0xd0,0x76,0xcf,0x86,0xd5,0x48,0xd4,0x28,0xd3,0x14, + 0x52,0x04,0x08,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x10,0x04,0x08,0x00, + 0x00,0x00,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x08,0x00,0x08,0xdc,0x10,0x04, + 0x08,0x00,0x08,0xe6,0xd3,0x10,0x52,0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x00,0x00, + 0x08,0x00,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x54,0x04,0x08,0x00,0xd3,0x0c,0x52,0x04,0x08,0x00,0x11,0x04,0x14,0x00, + 0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x08,0xe6,0x08,0x01,0x10,0x04,0x08,0xdc, + 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x08,0x09,0xcf,0x86,0x95,0x28, + 0xd4,0x14,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0xd0,0x0a,0xcf,0x86,0x15,0x04,0x10,0x00, + 0x00,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x24,0xd3,0x14,0x52,0x04,0x10,0x00, + 0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0xe6,0x10,0x04,0x10,0xdc,0x00,0x00,0x92,0x0c, + 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x52,0x04, + 0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd1,0x54, + 0xd0,0x26,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x52,0x04, + 0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00, + 0x0b,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x0b,0x00,0x93,0x0c, + 0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x0b,0x00,0x54,0x04,0x0b,0x00, + 0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00, + 0x0b,0x00,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x54,0x04,0x10,0x00,0xd3,0x0c,0x92,0x08, + 0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00, + 0x10,0x00,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x14, + 0x53,0x04,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00, + 0x10,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x96,0xd2,0x68,0xd1,0x24,0xd0,0x06, + 0xcf,0x06,0x0b,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x0b,0x00,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd0,0x1e,0xcf,0x86,0x55,0x04,0x11,0x00,0x54,0x04,0x11,0x00,0x93,0x10,0x92,0x0c, + 0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86, + 0x55,0x04,0x11,0x00,0x54,0x04,0x11,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x11,0x00, + 0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x11,0x00, + 0x11,0x00,0xd1,0x28,0xd0,0x22,0xcf,0x86,0x55,0x04,0x14,0x00,0xd4,0x0c,0x93,0x08, + 0x12,0x04,0x14,0x00,0x14,0xe6,0x00,0x00,0x53,0x04,0x14,0x00,0x92,0x08,0x11,0x04, + 0x14,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd2,0x2a, + 0xd1,0x24,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04, + 0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04, + 0x0b,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x58,0xd0,0x12,0xcf,0x86,0x55,0x04, + 0x14,0x00,0x94,0x08,0x13,0x04,0x14,0x00,0x00,0x00,0x14,0x00,0xcf,0x86,0x95,0x40, + 0xd4,0x24,0xd3,0x0c,0x52,0x04,0x14,0x00,0x11,0x04,0x14,0x00,0x14,0xdc,0xd2,0x0c, + 0x51,0x04,0x14,0xe6,0x10,0x04,0x14,0xe6,0x14,0xdc,0x91,0x08,0x10,0x04,0x14,0xe6, + 0x14,0xdc,0x14,0xdc,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0xdc,0x14,0x00, + 0x14,0x00,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x15,0x00, + 0x93,0x10,0x52,0x04,0x15,0x00,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00, + 0x00,0x00,0xcf,0x86,0xe5,0x0f,0x06,0xe4,0xf8,0x03,0xe3,0x02,0x02,0xd2,0xfb,0xd1, + 0x4c,0xd0,0x06,0xcf,0x06,0x0c,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x1c,0xd3,0x10,0x52, + 0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x09,0x0c,0x00,0x52,0x04,0x0c, + 0x00,0x11,0x04,0x0c,0x00,0x00,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x0c, + 0x00,0x0c,0x00,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00, + 0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x09,0xd0,0x69,0xcf,0x86,0xd5, + 0x32,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0xd2,0x15,0x51,0x04,0x0b,0x00,0x10, + 0x0d,0x0b,0xff,0xf0,0x91,0x82,0x99,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x91,0x11, + 0x10,0x0d,0x0b,0xff,0xf0,0x91,0x82,0x9b,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x0b, + 0x00,0xd4,0x1d,0x53,0x04,0x0b,0x00,0x92,0x15,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b, + 0x00,0x0b,0xff,0xf0,0x91,0x82,0xa5,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x53,0x04, + 0x0b,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0b,0x09,0x10,0x04,0x0b,0x07, + 0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x20,0x94,0x1c,0xd3,0x0c,0x92,0x08,0x11,0x04, + 0x0b,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00, + 0x14,0x00,0x00,0x00,0x0d,0x00,0xd4,0x14,0x53,0x04,0x0d,0x00,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0d,0x00,0x92,0x08, + 0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0xd1,0x96,0xd0,0x5c,0xcf,0x86,0xd5,0x18, + 0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xe6,0x0d,0x00, + 0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd4,0x26,0x53,0x04,0x0d,0x00,0x52,0x04,0x0d,0x00, + 0x51,0x04,0x0d,0x00,0x10,0x0d,0x0d,0xff,0xf0,0x91,0x84,0xb1,0xf0,0x91,0x84,0xa7, + 0x00,0x0d,0xff,0xf0,0x91,0x84,0xb2,0xf0,0x91,0x84,0xa7,0x00,0x93,0x18,0xd2,0x0c, + 0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x0d,0x09,0x91,0x08,0x10,0x04,0x0d,0x09, + 0x00,0x00,0x0d,0x00,0x0d,0x00,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04, + 0x0d,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + 0x54,0x04,0x10,0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00, + 0x10,0x07,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd0,0x06, + 0xcf,0x06,0x0d,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x2c,0xd3,0x10,0x92,0x0c,0x91,0x08, + 0x10,0x04,0x0d,0x09,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04, + 0x0d,0x00,0x11,0x00,0x10,0x04,0x11,0x07,0x11,0x00,0x91,0x08,0x10,0x04,0x11,0x00, + 0x10,0x00,0x00,0x00,0x53,0x04,0x0d,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04, + 0x10,0x00,0x11,0x00,0x11,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x52,0x04,0x10,0x00, + 0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xc8,0xd1,0x48, + 0xd0,0x42,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x93,0x10,0x92,0x0c,0x51,0x04, + 0x10,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x54,0x04,0x10,0x00, + 0xd3,0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0x09,0x10,0x04, + 0x10,0x07,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x12,0x00, + 0x00,0x00,0xcf,0x06,0x00,0x00,0xd0,0x52,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x10, + 0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04, + 0x00,0x00,0x11,0x00,0x53,0x04,0x11,0x00,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00, + 0x10,0x04,0x00,0x00,0x11,0x00,0x94,0x10,0x53,0x04,0x11,0x00,0x92,0x08,0x11,0x04, + 0x11,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x18, + 0x53,0x04,0x10,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0x07,0x10,0x04, + 0x10,0x09,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00, + 0x00,0x00,0x00,0x00,0xe1,0x27,0x01,0xd0,0x8a,0xcf,0x86,0xd5,0x44,0xd4,0x2c,0xd3, + 0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x10,0x00,0x10,0x00,0x91,0x08,0x10, + 0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10, + 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10, + 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0xd4, + 0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10, + 0x00,0x10,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10, + 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd2,0x0c,0x51,0x04,0x10, + 0x00,0x10,0x04,0x00,0x00,0x14,0x07,0x91,0x08,0x10,0x04,0x10,0x07,0x10,0x00,0x10, + 0x00,0xcf,0x86,0xd5,0x6a,0xd4,0x42,0xd3,0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10, + 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0xd2,0x19,0xd1,0x08,0x10, + 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0xff,0xf0,0x91,0x8d,0x87,0xf0, + 0x91,0x8c,0xbe,0x00,0x91,0x11,0x10,0x0d,0x10,0xff,0xf0,0x91,0x8d,0x87,0xf0,0x91, + 0x8d,0x97,0x00,0x10,0x09,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11, + 0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x52, + 0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd4,0x1c,0xd3, + 0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,0xe6,0x52,0x04,0x10,0xe6,0x91, + 0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x10,0xe6,0x91, + 0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe3, + 0x30,0x01,0xd2,0xb7,0xd1,0x48,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x95,0x3c, + 0xd4,0x1c,0x93,0x18,0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x09,0x12,0x00, + 0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x07,0x12,0x00,0x12,0x00,0x53,0x04,0x12,0x00, + 0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x00,0x00,0x12,0x00,0xd1,0x08,0x10,0x04, + 0x00,0x00,0x12,0x00,0x10,0x04,0x14,0xe6,0x15,0x00,0x00,0x00,0xd0,0x45,0xcf,0x86, + 0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0xd2,0x15,0x51,0x04, + 0x10,0x00,0x10,0x04,0x10,0x00,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xba, + 0x00,0xd1,0x11,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xb0,0x00, + 0x10,0x00,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xbd,0x00,0x10, + 0x00,0xcf,0x86,0x95,0x24,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10, + 0x04,0x10,0x09,0x10,0x07,0x10,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11, + 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0, + 0x40,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x0c,0x52,0x04,0x10, + 0x00,0x11,0x04,0x10,0x00,0x00,0x00,0xd2,0x1e,0x51,0x04,0x10,0x00,0x10,0x0d,0x10, + 0xff,0xf0,0x91,0x96,0xb8,0xf0,0x91,0x96,0xaf,0x00,0x10,0xff,0xf0,0x91,0x96,0xb9, + 0xf0,0x91,0x96,0xaf,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x10,0x09,0xcf, + 0x86,0x95,0x2c,0xd4,0x1c,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x07,0x10, + 0x00,0x10,0x00,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,0x11,0x00,0x11,0x00,0x53, + 0x04,0x11,0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0xd2, + 0xa0,0xd1,0x5c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53, + 0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x10, + 0x09,0xcf,0x86,0xd5,0x24,0xd4,0x14,0x93,0x10,0x52,0x04,0x10,0x00,0x91,0x08,0x10, + 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11, + 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12, + 0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x2a,0xcf, + 0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,0x00,0xd3,0x10,0x52,0x04,0x0d,0x00,0x51, + 0x04,0x0d,0x00,0x10,0x04,0x0d,0x09,0x0d,0x07,0x92,0x0c,0x91,0x08,0x10,0x04,0x15, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x14,0x94,0x10,0x53,0x04,0x0d, + 0x00,0x92,0x08,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1, + 0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x54,0x04,0x11,0x00,0x53,0x04,0x11,0x00,0xd2, + 0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00, + 0x00,0x11,0x00,0x11,0x00,0x94,0x14,0x53,0x04,0x11,0x00,0x92,0x0c,0x51,0x04,0x11, + 0x00,0x10,0x04,0x11,0x00,0x11,0x09,0x00,0x00,0x11,0x00,0xcf,0x06,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xe4,0x59,0x01,0xd3,0xb2,0xd2,0x5c,0xd1,0x28,0xd0,0x22,0xcf,0x86, + 0x55,0x04,0x14,0x00,0x54,0x04,0x14,0x00,0x53,0x04,0x14,0x00,0x92,0x10,0xd1,0x08, + 0x10,0x04,0x14,0x00,0x14,0x09,0x10,0x04,0x14,0x07,0x14,0x00,0x00,0x00,0xcf,0x06, + 0x00,0x00,0xd0,0x0a,0xcf,0x86,0x15,0x04,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04, + 0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04, + 0x10,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04, + 0x00,0x00,0x10,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04, + 0x00,0x00,0x94,0x10,0x53,0x04,0x15,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x15,0x00, + 0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x15,0x00,0x53,0x04,0x15,0x00, + 0x92,0x08,0x11,0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x94,0x1c,0x93,0x18,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x15,0x09,0x15,0x00,0x15,0x00,0x91,0x08,0x10,0x04,0x15,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xa0,0xd1,0x3c,0xd0,0x1e,0xcf,0x86, + 0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x93,0x10,0x52,0x04,0x13,0x00,0x91,0x08, + 0x10,0x04,0x13,0x09,0x13,0x00,0x13,0x00,0x13,0x00,0xcf,0x86,0x95,0x18,0x94,0x14, + 0x93,0x10,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x13,0x09, + 0x00,0x00,0x13,0x00,0x13,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x2c,0xd4,0x10,0x93,0x0c, + 0x52,0x04,0x13,0x00,0x11,0x04,0x15,0x00,0x13,0x00,0x13,0x00,0x53,0x04,0x13,0x00, + 0xd2,0x0c,0x91,0x08,0x10,0x04,0x13,0x00,0x13,0x09,0x13,0x00,0x91,0x08,0x10,0x04, + 0x13,0x00,0x14,0x00,0x13,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x13,0x00, + 0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04, + 0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe3,0xa9,0x01,0xd2, + 0xb0,0xd1,0x6c,0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x12,0x00,0x92, + 0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x54, + 0x04,0x12,0x00,0xd3,0x10,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12, + 0x00,0x00,0x00,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x12, + 0x09,0xcf,0x86,0xd5,0x14,0x94,0x10,0x93,0x0c,0x52,0x04,0x12,0x00,0x11,0x04,0x12, + 0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x94,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12, + 0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xd0,0x3e,0xcf, + 0x86,0xd5,0x14,0x54,0x04,0x12,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x12, + 0x00,0x12,0x00,0x12,0x00,0xd4,0x14,0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x93,0x10,0x52,0x04,0x12,0x00,0x51, + 0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1, + 0xa0,0xd0,0x52,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3,0x10,0x52,0x04,0x13,0x00,0x51, + 0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10, + 0x04,0x00,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x54,0x04,0x13,0x00,0xd3,0x10,0x52, + 0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0xd2,0x0c,0x51, + 0x04,0x00,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x00, + 0x00,0x13,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0x93,0x14,0xd2,0x0c,0x51,0x04,0x13, + 0x00,0x10,0x04,0x13,0x07,0x13,0x00,0x11,0x04,0x13,0x09,0x13,0x00,0x00,0x00,0x53, + 0x04,0x13,0x00,0x92,0x08,0x11,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x94,0x20,0xd3, + 0x10,0x52,0x04,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x92, + 0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd0, + 0x52,0xcf,0x86,0xd5,0x3c,0xd4,0x14,0x53,0x04,0x14,0x00,0x52,0x04,0x14,0x00,0x51, + 0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x14, + 0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x14, + 0x09,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94, + 0x10,0x53,0x04,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xd2,0x2a,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x14,0x00,0x53,0x04,0x14, + 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1, + 0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x15, + 0x00,0x54,0x04,0x15,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x15,0x00,0x00,0x00,0x00, + 0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0xd0, + 0xca,0xcf,0x86,0xd5,0xc2,0xd4,0x54,0xd3,0x06,0xcf,0x06,0x09,0x00,0xd2,0x06,0xcf, + 0x06,0x09,0x00,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x09,0x00,0xcf,0x86,0x55,0x04,0x09, + 0x00,0x94,0x14,0x53,0x04,0x09,0x00,0x52,0x04,0x09,0x00,0x51,0x04,0x09,0x00,0x10, + 0x04,0x09,0x00,0x10,0x00,0x10,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x10, + 0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x11,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x68,0xd2,0x46,0xd1,0x40,0xd0, + 0x06,0xcf,0x06,0x09,0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0xd4,0x20,0xd3,0x10,0x92, + 0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10, + 0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x09, + 0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x11, + 0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x95,0x10,0x94,0x0c,0x93, + 0x08,0x12,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x4c,0xd4,0x06,0xcf, + 0x06,0x0b,0x00,0xd3,0x40,0xd2,0x3a,0xd1,0x34,0xd0,0x2e,0xcf,0x86,0x55,0x04,0x0b, + 0x00,0xd4,0x14,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10, + 0x04,0x0b,0x00,0x00,0x00,0x53,0x04,0x15,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x15, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x4c,0xd0,0x44,0xcf, + 0x86,0xd5,0x3c,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x11,0x00,0xd2, + 0x2a,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x93, + 0x10,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00, + 0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xe0,0xd2,0x01,0xcf,0x86,0xd5,0x06,0xcf,0x06, + 0x00,0x00,0xe4,0x0b,0x01,0xd3,0x06,0xcf,0x06,0x0c,0x00,0xd2,0x84,0xd1,0x50,0xd0, + 0x1e,0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0x92, + 0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5, + 0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10, + 0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x10,0x00,0xd2,0x08,0x11, + 0x04,0x10,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0xd0,0x06,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,0x00,0x00,0x10,0x00,0xd4,0x10,0x53, + 0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x93,0x10,0x52, + 0x04,0x10,0x01,0x91,0x08,0x10,0x04,0x10,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xd1, + 0x6c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x93,0x10,0x52, + 0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x10,0xe6,0x10,0x00,0x10,0x00,0xcf, + 0x86,0xd5,0x24,0xd4,0x10,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00, + 0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x00, + 0x00,0x10,0x00,0x10,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10, + 0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x00, + 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd0,0x0e,0xcf,0x86,0x95, + 0x08,0x14,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf, + 0x06,0x00,0x00,0xd2,0x30,0xd1,0x0c,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x06,0x14, + 0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x14,0x00,0x53,0x04,0x14,0x00,0x92, + 0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xd1,0x4c,0xd0,0x06,0xcf,0x06,0x0d,0x00,0xcf,0x86,0xd5,0x2c,0x94, + 0x28,0xd3,0x10,0x52,0x04,0x0d,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x15,0x00,0x15, + 0x00,0xd2,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x51,0x04,0x00, + 0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0d,0x00,0x54,0x04,0x0d,0x00,0x53,0x04,0x0d, + 0x00,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x15,0x00,0xd0, + 0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x15,0x00,0x52,0x04,0x00,0x00,0x51, + 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x00,0x00,0xcf,0x86,0x55, + 0x04,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x13, + 0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xcf,0x06,0x12,0x00,0xe2, + 0xc6,0x01,0xd1,0x8e,0xd0,0x86,0xcf,0x86,0xd5,0x48,0xd4,0x06,0xcf,0x06,0x12,0x00, + 0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x06,0xcf,0x06,0x12,0x00,0xd1,0x06,0xcf,0x06, + 0x12,0x00,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,0x04,0x12,0x00,0xd4,0x14, + 0x53,0x04,0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x14,0x00, + 0x14,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x14,0x00,0x15,0x00,0x15,0x00,0x00,0x00, + 0xd4,0x36,0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x2a,0xd1,0x06,0xcf,0x06,0x12,0x00, + 0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,0x04,0x12,0x00,0x54,0x04,0x12,0x00, + 0x93,0x10,0x92,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0xa2,0xd4,0x9c,0xd3,0x74, + 0xd2,0x26,0xd1,0x20,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x94,0x10,0x93,0x0c,0x92,0x08, + 0x11,0x04,0x0c,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0xcf,0x06, + 0x13,0x00,0xcf,0x06,0x13,0x00,0xd1,0x48,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04, + 0x13,0x00,0x53,0x04,0x13,0x00,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04, + 0x13,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x00,0x00,0x93,0x10, + 0x92,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x94,0x0c,0x93,0x08,0x12,0x04,0x00,0x00,0x15,0x00,0x00,0x00,0x13,0x00,0xcf,0x06, + 0x13,0x00,0xd2,0x22,0xd1,0x06,0xcf,0x06,0x13,0x00,0xd0,0x06,0xcf,0x06,0x13,0x00, + 0xcf,0x86,0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x53,0x04,0x13,0x00,0x12,0x04, + 0x13,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06, + 0x00,0x00,0xd3,0x7f,0xd2,0x79,0xd1,0x34,0xd0,0x06,0xcf,0x06,0x10,0x00,0xcf,0x86, + 0x55,0x04,0x10,0x00,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00, + 0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00, + 0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd0,0x3f,0xcf,0x86,0xd5,0x2c, + 0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0xd2,0x08,0x11,0x04,0x10,0x00,0x00,0x00, + 0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x01,0x10,0x00,0x94,0x0d,0x93,0x09,0x12,0x05, + 0x10,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xe1,0x96,0x04,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xcf,0x86,0xe5,0x33,0x04,0xe4,0x83,0x02,0xe3,0xf8,0x01,0xd2,0x26,0xd1,0x06,0xcf, + 0x06,0x05,0x00,0xd0,0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x55,0x04,0x05,0x00,0x54, + 0x04,0x05,0x00,0x93,0x0c,0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x00,0x00,0x00, + 0x00,0xd1,0xef,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x05,0x00,0x94,0x20,0xd3,0x10,0x52, + 0x04,0x05,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0xd5, + 0x2a,0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,0x00,0x51,0x04,0x05, + 0x00,0x10,0x0d,0x05,0xff,0xf0,0x9d,0x85,0x97,0xf0,0x9d,0x85,0xa5,0x00,0x05,0xff, + 0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0x00,0xd4,0x75,0xd3,0x61,0xd2,0x44,0xd1, + 0x22,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85, + 0xae,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xaf, + 0x00,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85, + 0xb0,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xb1, + 0x00,0xd1,0x15,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0, + 0x9d,0x85,0xb2,0x00,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0x01,0xd2,0x08,0x11,0x04, + 0x05,0x01,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x05,0xe2,0x05,0xd8,0xd3,0x12, + 0x92,0x0d,0x51,0x04,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0xff,0x00,0x05,0xff,0x00, + 0x92,0x0e,0x51,0x05,0x05,0xff,0x00,0x10,0x05,0x05,0xff,0x00,0x05,0xdc,0x05,0xdc, + 0xd0,0x97,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x05,0xdc, + 0x10,0x04,0x05,0xdc,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x05,0xe6,0x05,0xe6, + 0x92,0x08,0x11,0x04,0x05,0xe6,0x05,0xdc,0x05,0x00,0x05,0x00,0xd4,0x14,0x53,0x04, + 0x05,0x00,0xd2,0x08,0x11,0x04,0x05,0x00,0x05,0xe6,0x11,0x04,0x05,0xe6,0x05,0x00, + 0x53,0x04,0x05,0x00,0xd2,0x15,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x05,0xff, + 0xf0,0x9d,0x86,0xb9,0xf0,0x9d,0x85,0xa5,0x00,0xd1,0x1e,0x10,0x0d,0x05,0xff,0xf0, + 0x9d,0x86,0xba,0xf0,0x9d,0x85,0xa5,0x00,0x05,0xff,0xf0,0x9d,0x86,0xb9,0xf0,0x9d, + 0x85,0xa5,0xf0,0x9d,0x85,0xae,0x00,0x10,0x11,0x05,0xff,0xf0,0x9d,0x86,0xba,0xf0, + 0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xae,0x00,0x05,0xff,0xf0,0x9d,0x86,0xb9,0xf0,0x9d, + 0x85,0xa5,0xf0,0x9d,0x85,0xaf,0x00,0xcf,0x86,0xd5,0x31,0xd4,0x21,0x93,0x1d,0x92, + 0x19,0x91,0x15,0x10,0x11,0x05,0xff,0xf0,0x9d,0x86,0xba,0xf0,0x9d,0x85,0xa5,0xf0, + 0x9d,0x85,0xaf,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x53,0x04,0x05,0x00, + 0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x11,0x00,0x94,0x14,0x53,0x04,0x11,0x00, + 0x92,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd2,0x44,0xd1,0x28,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0x95,0x1c,0x94,0x18, + 0x93,0x14,0xd2,0x08,0x11,0x04,0x08,0x00,0x08,0xe6,0x91,0x08,0x10,0x04,0x08,0xe6, + 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00, + 0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x14,0x00,0x93,0x08,0x12,0x04,0x14,0x00, + 0x00,0x00,0x00,0x00,0xd1,0x40,0xd0,0x06,0xcf,0x06,0x07,0x00,0xcf,0x86,0xd5,0x18, + 0x54,0x04,0x07,0x00,0x93,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04, + 0x07,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x09,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04, + 0x09,0x00,0x14,0x00,0x14,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe3,0x5f,0x01,0xd2,0xb4,0xd1,0x24,0xd0, + 0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x95,0x18,0x54,0x04,0x05,0x00,0x93,0x10,0x52, + 0x04,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x05, + 0x00,0xd0,0x6a,0xcf,0x86,0xd5,0x18,0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52, + 0x04,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05,0x00,0xd4,0x34,0xd3, + 0x1c,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0xd1,0x08,0x10, + 0x04,0x00,0x00,0x05,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x05,0x00,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05, + 0x00,0x53,0x04,0x05,0x00,0xd2,0x0c,0x51,0x04,0x05,0x00,0x10,0x04,0x00,0x00,0x05, + 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0x95,0x20,0x94, + 0x1c,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x05,0x00,0x07,0x00,0x05,0x00,0x91, + 0x08,0x10,0x04,0x00,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0xd1, + 0xa4,0xd0,0x6a,0xcf,0x86,0xd5,0x48,0xd4,0x28,0xd3,0x10,0x52,0x04,0x05,0x00,0x51, + 0x04,0x05,0x00,0x10,0x04,0x00,0x00,0x05,0x00,0xd2,0x0c,0x51,0x04,0x05,0x00,0x10, + 0x04,0x05,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x05,0x00,0x05,0x00,0xd3, + 0x10,0x52,0x04,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05,0x00,0x52, + 0x04,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05,0x00,0x54,0x04,0x05, + 0x00,0x53,0x04,0x05,0x00,0xd2,0x0c,0x51,0x04,0x05,0x00,0x10,0x04,0x00,0x00,0x05, + 0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0xcf,0x86,0x95,0x34,0xd4, + 0x20,0xd3,0x14,0x52,0x04,0x05,0x00,0xd1,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x10, + 0x04,0x05,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x05,0x00,0x05,0x00,0x93, + 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x05,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x05, + 0x00,0x05,0x00,0xcf,0x06,0x05,0x00,0xd2,0x26,0xd1,0x06,0xcf,0x06,0x05,0x00,0xd0, + 0x1a,0xcf,0x86,0x55,0x04,0x05,0x00,0x94,0x10,0x93,0x0c,0x52,0x04,0x05,0x00,0x11, + 0x04,0x08,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0xcf,0x06,0x05,0x00,0xd1,0x06,0xcf, + 0x06,0x05,0x00,0xd0,0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53, + 0x04,0x05,0x00,0xd2,0x08,0x11,0x04,0x05,0x00,0x09,0x00,0x11,0x04,0x00,0x00,0x05, + 0x00,0x05,0x00,0x05,0x00,0xd4,0x52,0xd3,0x06,0xcf,0x06,0x11,0x00,0xd2,0x46,0xd1, + 0x06,0xcf,0x06,0x11,0x00,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0xd4,0x0c,0x53,0x04,0x11, + 0x00,0x12,0x04,0x11,0x00,0x00,0x00,0x53,0x04,0x00,0x00,0x92,0x0c,0x51,0x04,0x00, + 0x00,0x10,0x04,0x00,0x00,0x11,0x00,0x11,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x00,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xe0,0xc2,0x03,0xcf,0x86, + 0xe5,0x03,0x01,0xd4,0xfc,0xd3,0xc0,0xd2,0x66,0xd1,0x60,0xd0,0x5a,0xcf,0x86,0xd5, + 0x2c,0xd4,0x14,0x93,0x10,0x52,0x04,0x12,0xe6,0x51,0x04,0x12,0xe6,0x10,0x04,0x12, + 0xe6,0x00,0x00,0x12,0xe6,0x53,0x04,0x12,0xe6,0x92,0x10,0xd1,0x08,0x10,0x04,0x12, + 0xe6,0x00,0x00,0x10,0x04,0x00,0x00,0x12,0xe6,0x12,0xe6,0x94,0x28,0xd3,0x18,0xd2, + 0x0c,0x51,0x04,0x12,0xe6,0x10,0x04,0x00,0x00,0x12,0xe6,0x91,0x08,0x10,0x04,0x12, + 0xe6,0x00,0x00,0x12,0xe6,0x92,0x0c,0x51,0x04,0x12,0xe6,0x10,0x04,0x12,0xe6,0x00, + 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x54,0xd0, + 0x36,0xcf,0x86,0x55,0x04,0x15,0x00,0xd4,0x14,0x53,0x04,0x15,0x00,0x52,0x04,0x15, + 0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x15, + 0xe6,0x51,0x04,0x15,0xe6,0x10,0x04,0x15,0xe6,0x15,0x00,0x52,0x04,0x15,0x00,0x11, + 0x04,0x15,0x00,0x00,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x15,0x00,0xd2, + 0x08,0x11,0x04,0x15,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x15,0x00,0x00,0x00,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xd2,0x36,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x15,0x00,0xd4,0x0c,0x53,0x04,0x15,0x00,0x12, + 0x04,0x15,0x00,0x15,0xe6,0x53,0x04,0x15,0x00,0xd2,0x08,0x11,0x04,0x15,0x00,0x00, + 0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0xcf,0x06,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xd4,0x82,0xd3,0x7c,0xd2,0x3e,0xd1,0x06,0xcf,0x06,0x10,0x00,0xd0, + 0x06,0xcf,0x06,0x10,0x00,0xcf,0x86,0x95,0x2c,0xd4,0x18,0x93,0x14,0x52,0x04,0x10, + 0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10, + 0x00,0x93,0x10,0x52,0x04,0x10,0xdc,0x51,0x04,0x10,0xdc,0x10,0x04,0x10,0xdc,0x00, + 0x00,0x00,0x00,0x00,0x00,0xd1,0x38,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x95, + 0x2c,0xd4,0x18,0xd3,0x08,0x12,0x04,0x12,0x00,0x12,0xe6,0x92,0x0c,0x51,0x04,0x12, + 0xe6,0x10,0x04,0x12,0x07,0x15,0x00,0x00,0x00,0x53,0x04,0x12,0x00,0xd2,0x08,0x11, + 0x04,0x12,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x12,0x00,0x00,0x00,0xcf,0x06,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xd3,0x82,0xd2,0x48,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x00, + 0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x93,0x10,0x92,0x0c,0x91, + 0x08,0x10,0x04,0x00,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd0,0x1e,0xcf, + 0x86,0x55,0x04,0x14,0x00,0x54,0x04,0x14,0x00,0x93,0x10,0x52,0x04,0x14,0x00,0x91, + 0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1, + 0x34,0xd0,0x2e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x54,0x04,0x15, + 0x00,0x53,0x04,0x15,0x00,0x52,0x04,0x15,0x00,0x11,0x04,0x15,0x00,0x00,0x00,0xcf, + 0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xe2,0xb2,0x01,0xe1,0x41,0x01,0xd0,0x6e,0xcf, + 0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x0d,0x00,0x91,0x08,0x10,0x04,0x00, + 0x00,0x0d,0x00,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd4,0x30,0xd3,0x20,0xd2,0x10,0xd1, + 0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0xd1,0x08,0x10, + 0x04,0x0d,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x92,0x0c,0x91,0x08,0x10, + 0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x0d, + 0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0x0d,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x00, + 0x00,0x0d,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x00,0x00,0xcf,0x86,0xd5,0x74,0xd4, + 0x34,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0x51, + 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00, + 0x00,0x0d,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d, + 0x00,0x0d,0x00,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x10, + 0x04,0x0d,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x0d,0x00,0x00,0x00,0x10,0x04,0x00, + 0x00,0x0d,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x10,0x04,0x00, + 0x00,0x0d,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x10,0x04,0x00,0x00,0x0d, + 0x00,0xd4,0x30,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x10, + 0x04,0x0d,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x0d,0x00,0x00,0x00,0x10,0x04,0x00, + 0x00,0x0d,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0x0d, + 0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0x0d, + 0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0xd1,0x08,0x10, + 0x04,0x0d,0x00,0x00,0x00,0x10,0x04,0x0d,0x00,0x00,0x00,0xd0,0x56,0xcf,0x86,0xd5, + 0x20,0xd4,0x14,0x53,0x04,0x0d,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,0x00, + 0x00,0x0d,0x00,0x0d,0x00,0x53,0x04,0x0d,0x00,0x12,0x04,0x0d,0x00,0x00,0x00,0xd4, + 0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x91, + 0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10, + 0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x53,0x04,0x0d,0x00,0x12,0x04,0x0d,0x00,0x00, + 0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x93,0x0c,0x92,0x08,0x11, + 0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xe5, + 0x96,0x05,0xe4,0x28,0x03,0xe3,0xed,0x01,0xd2,0xa0,0xd1,0x1c,0xd0,0x16,0xcf,0x86, + 0x55,0x04,0x0a,0x00,0x94,0x0c,0x53,0x04,0x0a,0x00,0x12,0x04,0x0a,0x00,0x00,0x00, + 0x0a,0x00,0xcf,0x06,0x0a,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x10,0x54,0x04,0x0a,0x00, + 0x93,0x08,0x12,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x53,0x04,0x0c,0x00, + 0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0xd3,0x10, + 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x52,0x04, + 0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x10,0x00,0xcf,0x86,0xd5,0x28, + 0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00, + 0x0c,0x00,0x0c,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00, + 0x0c,0x00,0x0c,0x00,0x0c,0x00,0x54,0x04,0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00, + 0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd1,0xe4,0xd0,0x5a,0xcf,0x86,0xd5,0x20, + 0x94,0x1c,0x53,0x04,0x0b,0x00,0xd2,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00, + 0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0xd4,0x14, + 0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00, + 0x14,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0c,0x00, + 0x0c,0x00,0x52,0x04,0x0c,0x00,0xd1,0x08,0x10,0x04,0x0c,0x00,0x0b,0x00,0x10,0x04, + 0x0c,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x4c,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x51,0x04, + 0x0c,0x00,0x10,0x04,0x0b,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0b,0x00, + 0x0c,0x00,0xd2,0x08,0x11,0x04,0x0c,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04, + 0x0b,0x00,0x0c,0x00,0xd3,0x10,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04, + 0x0c,0x00,0x0b,0x00,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00, + 0x0b,0x00,0xd4,0x18,0x53,0x04,0x0c,0x00,0xd2,0x08,0x11,0x04,0x0c,0x00,0x0d,0x00, + 0x91,0x08,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0c,0x00,0xd2,0x10, + 0xd1,0x08,0x10,0x04,0x0c,0x00,0x0b,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0xd1,0x08, + 0x10,0x04,0x0b,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0xd0,0x4e,0xcf,0x86, + 0xd5,0x34,0xd4,0x14,0x53,0x04,0x0c,0x00,0xd2,0x08,0x11,0x04,0x0c,0x00,0x0b,0x00, + 0x11,0x04,0x0b,0x00,0x0c,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00, + 0x0c,0x00,0x0c,0x00,0x0c,0x00,0x92,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00, + 0x12,0x00,0x12,0x00,0x94,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08, + 0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00, + 0x94,0x10,0x93,0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00, + 0x0c,0x00,0xd2,0x7e,0xd1,0x78,0xd0,0x3e,0xcf,0x86,0xd5,0x1c,0x94,0x18,0x93,0x14, + 0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0b,0x00,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04, + 0x0b,0x00,0x0c,0x00,0x0c,0x00,0x92,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00, + 0x12,0x00,0x00,0x00,0xcf,0x86,0xd5,0x24,0xd4,0x14,0x53,0x04,0x0b,0x00,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x0c,0x92,0x08, + 0x11,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x10,0x93,0x0c,0x52,0x04, + 0x13,0x00,0x11,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00, + 0xd1,0x58,0xd0,0x3a,0xcf,0x86,0x55,0x04,0x0c,0x00,0xd4,0x20,0xd3,0x10,0x92,0x0c, + 0x91,0x08,0x10,0x04,0x0c,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10,0x00, + 0x91,0x08,0x10,0x04,0x10,0x00,0x11,0x00,0x11,0x00,0x93,0x10,0x52,0x04,0x0c,0x00, + 0x51,0x04,0x0c,0x00,0x10,0x04,0x10,0x00,0x0c,0x00,0x0c,0x00,0xcf,0x86,0x55,0x04, + 0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0x52,0x04,0x0c,0x00,0x91,0x08, + 0x10,0x04,0x0c,0x00,0x10,0x00,0x11,0x00,0xd0,0x16,0xcf,0x86,0x95,0x10,0x54,0x04, + 0x0c,0x00,0x93,0x08,0x12,0x04,0x0c,0x00,0x10,0x00,0x10,0x00,0x0c,0x00,0xcf,0x86, + 0xd5,0x34,0xd4,0x28,0xd3,0x10,0x52,0x04,0x0c,0x00,0x91,0x08,0x10,0x04,0x0c,0x00, + 0x10,0x00,0x0c,0x00,0xd2,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x10,0x00, + 0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x11,0x00,0x93,0x08,0x12,0x04,0x11,0x00, + 0x10,0x00,0x10,0x00,0x54,0x04,0x0c,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04, + 0x0c,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x11,0x00,0xd3,0xfc,0xd2,0x6c,0xd1,0x3c, + 0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00, + 0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x10,0x00,0xcf,0x86, + 0x95,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x10,0x00, + 0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xd0,0x06,0xcf,0x06,0x0c,0x00, + 0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0xd2,0x0c, + 0x91,0x08,0x10,0x04,0x10,0x00,0x0c,0x00,0x0c,0x00,0xd1,0x08,0x10,0x04,0x0c,0x00, + 0x10,0x00,0x10,0x04,0x10,0x00,0x11,0x00,0xd1,0x54,0xd0,0x1a,0xcf,0x86,0x55,0x04, + 0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0x52,0x04,0x0c,0x00,0x11,0x04, + 0x0c,0x00,0x10,0x00,0xcf,0x86,0xd5,0x1c,0x94,0x18,0xd3,0x08,0x12,0x04,0x0d,0x00, + 0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x11,0x00,0x11,0x00, + 0x0c,0x00,0xd4,0x08,0x13,0x04,0x0c,0x00,0x10,0x00,0x53,0x04,0x10,0x00,0x92,0x0c, + 0x51,0x04,0x10,0x00,0x10,0x04,0x12,0x00,0x10,0x00,0x10,0x00,0xd0,0x1e,0xcf,0x86, + 0x55,0x04,0x10,0x00,0x94,0x14,0x93,0x10,0x52,0x04,0x10,0x00,0x91,0x08,0x10,0x04, + 0x12,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00, + 0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04, + 0x10,0x00,0x0c,0x00,0x0c,0x00,0xe2,0x19,0x01,0xd1,0xa8,0xd0,0x7e,0xcf,0x86,0xd5, + 0x4c,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0d,0x00,0x0c,0x00,0x0c, + 0x00,0x0c,0x00,0x0c,0x00,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x0d, + 0x00,0x0c,0x00,0xd1,0x08,0x10,0x04,0x0c,0x00,0x0d,0x00,0x10,0x04,0x0c,0x00,0x0d, + 0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0c,0x00,0x0d,0x00,0x10,0x04,0x0c,0x00,0x0d, + 0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x0d,0x00,0xd4,0x1c,0xd3,0x0c,0x52, + 0x04,0x0c,0x00,0x11,0x04,0x0c,0x00,0x0d,0x00,0x52,0x04,0x0c,0x00,0x91,0x08,0x10, + 0x04,0x0d,0x00,0x0c,0x00,0x0d,0x00,0x93,0x10,0x52,0x04,0x0c,0x00,0x91,0x08,0x10, + 0x04,0x0d,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xcf,0x86,0x95,0x24,0x94,0x20,0x93, + 0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0c,0x00,0x10,0x00,0x10,0x04,0x10,0x00,0x11, + 0x00,0x91,0x08,0x10,0x04,0x11,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x10,0x00,0x10, + 0x00,0xd0,0x06,0xcf,0x06,0x0c,0x00,0xcf,0x86,0xd5,0x30,0xd4,0x10,0x93,0x0c,0x52, + 0x04,0x0c,0x00,0x11,0x04,0x0c,0x00,0x10,0x00,0x10,0x00,0x93,0x1c,0xd2,0x10,0xd1, + 0x08,0x10,0x04,0x11,0x00,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,0x91,0x08,0x10, + 0x04,0x13,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x53,0x04,0x10,0x00,0x52, + 0x04,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd3,0x10,0x52, + 0x04,0x10,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,0x92,0x10,0xd1, + 0x08,0x10,0x04,0x13,0x00,0x14,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd1, + 0x1c,0xd0,0x06,0xcf,0x06,0x0c,0x00,0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c, + 0x00,0x93,0x08,0x12,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x10, + 0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x10,0x00,0xd3,0x10,0x52,0x04,0x10,0x00,0x91, + 0x08,0x10,0x04,0x10,0x00,0x14,0x00,0x14,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x0c,0x53,0x04,0x15,0x00,0x12,0x04,0x15, + 0x00,0x00,0x00,0x00,0x00,0xe4,0x40,0x02,0xe3,0xc9,0x01,0xd2,0x5c,0xd1,0x34,0xd0, + 0x16,0xcf,0x86,0x95,0x10,0x94,0x0c,0x53,0x04,0x10,0x00,0x12,0x04,0x10,0x00,0x00, + 0x00,0x10,0x00,0x10,0x00,0xcf,0x86,0x95,0x18,0xd4,0x08,0x13,0x04,0x10,0x00,0x00, + 0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0xd0,0x22,0xcf,0x86,0xd5,0x0c,0x94,0x08,0x13,0x04,0x10,0x00,0x00,0x00,0x10, + 0x00,0x94,0x10,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00, + 0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0xc0,0xd0,0x5e,0xcf,0x86,0xd5,0x30,0xd4, + 0x14,0x53,0x04,0x13,0x00,0x52,0x04,0x13,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x15, + 0x00,0x15,0x00,0x53,0x04,0x11,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x12, + 0x00,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,0xd4,0x08,0x13, + 0x04,0x12,0x00,0x13,0x00,0xd3,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x12,0x00,0x13, + 0x00,0x10,0x04,0x13,0x00,0x12,0x00,0x12,0x00,0x52,0x04,0x12,0x00,0x51,0x04,0x12, + 0x00,0x10,0x04,0x12,0x00,0x15,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x12, + 0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,0x53, + 0x04,0x12,0x00,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13, + 0x00,0xd4,0x0c,0x53,0x04,0x13,0x00,0x12,0x04,0x13,0x00,0x14,0x00,0xd3,0x1c,0xd2, + 0x10,0xd1,0x08,0x10,0x04,0x14,0x00,0x15,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x51, + 0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10, + 0x04,0x14,0x00,0x15,0x00,0x14,0x00,0xd0,0x62,0xcf,0x86,0xd5,0x24,0xd4,0x14,0x93, + 0x10,0x52,0x04,0x11,0x00,0x91,0x08,0x10,0x04,0x11,0x00,0x12,0x00,0x12,0x00,0x12, + 0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x12,0x00,0x13,0x00,0x13,0x00,0x14,0x00,0xd4, + 0x2c,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x91, + 0x08,0x10,0x04,0x00,0x00,0x15,0x00,0x15,0x00,0xd2,0x0c,0x51,0x04,0x15,0x00,0x10, + 0x04,0x15,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x15,0x00,0x53,0x04,0x14,0x00,0x92, + 0x08,0x11,0x04,0x14,0x00,0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x30,0x94,0x2c,0xd3, + 0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x11,0x00,0x14,0x00,0x10,0x04,0x14,0x00,0x15, + 0x00,0x15,0x00,0xd2,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x91, + 0x08,0x10,0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x13,0x00,0x94,0x14,0x93,0x10,0x52, + 0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,0x14, + 0x00,0xd2,0x70,0xd1,0x40,0xd0,0x06,0xcf,0x06,0x15,0x00,0xcf,0x86,0xd5,0x10,0x54, + 0x04,0x15,0x00,0x93,0x08,0x12,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd4,0x10,0x53, + 0x04,0x14,0x00,0x52,0x04,0x14,0x00,0x11,0x04,0x14,0x00,0x00,0x00,0xd3,0x08,0x12, + 0x04,0x15,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00, + 0x00,0x00,0x00,0xd0,0x2a,0xcf,0x86,0x95,0x24,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51, + 0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x0c,0x52, + 0x04,0x15,0x00,0x11,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00, + 0x00,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00, + 0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55, + 0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11, + 0x04,0x00,0x00,0x02,0x00,0xe4,0xf9,0x12,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00, + 0xd2,0xc2,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd0,0x44,0xcf,0x86,0xd5,0x3c, + 0xd4,0x06,0xcf,0x06,0x05,0x00,0xd3,0x06,0xcf,0x06,0x05,0x00,0xd2,0x2a,0xd1,0x06, + 0xcf,0x06,0x05,0x00,0xd0,0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x95,0x18,0x54,0x04, + 0x05,0x00,0x93,0x10,0x52,0x04,0x05,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x0b,0x00,0xcf,0x06,0x0b,0x00,0xcf,0x86, + 0xd5,0x3c,0xd4,0x06,0xcf,0x06,0x0b,0x00,0xd3,0x06,0xcf,0x06,0x0b,0x00,0xd2,0x06, + 0xcf,0x06,0x0b,0x00,0xd1,0x24,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04, + 0x0b,0x00,0x93,0x10,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xcf,0x06,0x0c,0x00,0xcf,0x06,0x0c,0x00,0xd4,0x32,0xd3,0x2c, + 0xd2,0x26,0xd1,0x20,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54,0x04,0x0c,0x00,0x53,0x04, + 0x0c,0x00,0x52,0x04,0x0c,0x00,0x11,0x04,0x0c,0x00,0x00,0x00,0x11,0x00,0xcf,0x06, + 0x11,0x00,0xcf,0x06,0x11,0x00,0xcf,0x06,0x11,0x00,0xcf,0x06,0x11,0x00,0xcf,0x06, + 0x11,0x00,0xd1,0x48,0xd0,0x40,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x11,0x00,0xd4,0x06, + 0xcf,0x06,0x11,0x00,0xd3,0x06,0xcf,0x06,0x11,0x00,0xd2,0x26,0xd1,0x06,0xcf,0x06, + 0x11,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,0x11,0x00,0x94,0x10,0x93,0x0c,0x92,0x08, + 0x11,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x00,0xcf,0x06,0x13,0x00, + 0xcf,0x06,0x13,0x00,0xcf,0x86,0xcf,0x06,0x13,0x00,0xd0,0x44,0xcf,0x86,0xd5,0x06, + 0xcf,0x06,0x13,0x00,0xd4,0x36,0xd3,0x06,0xcf,0x06,0x13,0x00,0xd2,0x06,0xcf,0x06, + 0x13,0x00,0xd1,0x06,0xcf,0x06,0x13,0x00,0xd0,0x06,0xcf,0x06,0x13,0x00,0xcf,0x86, + 0x55,0x04,0x13,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x13,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86, + 0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x68,0x11,0xe3,0x51,0x10,0xe2,0x17,0x08,0xe1, + 0x06,0x04,0xe0,0x03,0x02,0xcf,0x86,0xe5,0x06,0x01,0xd4,0x82,0xd3,0x41,0xd2,0x21, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,0xff,0xe4,0xb8,0xb8,0x00, + 0x10,0x08,0x05,0xff,0xe4,0xb9,0x81,0x00,0x05,0xff,0xf0,0xa0,0x84,0xa2,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe4,0xbd,0xa0,0x00,0x05,0xff,0xe4,0xbe,0xae,0x00,0x10, + 0x08,0x05,0xff,0xe4,0xbe,0xbb,0x00,0x05,0xff,0xe5,0x80,0x82,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe5,0x81,0xba,0x00,0x05,0xff,0xe5,0x82,0x99,0x00,0x10, + 0x08,0x05,0xff,0xe5,0x83,0xa7,0x00,0x05,0xff,0xe5,0x83,0x8f,0x00,0xd1,0x11,0x10, + 0x08,0x05,0xff,0xe3,0x92,0x9e,0x00,0x05,0xff,0xf0,0xa0,0x98,0xba,0x00,0x10,0x08, + 0x05,0xff,0xe5,0x85,0x8d,0x00,0x05,0xff,0xe5,0x85,0x94,0x00,0xd3,0x42,0xd2,0x21, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x85,0xa4,0x00,0x05,0xff,0xe5,0x85,0xb7,0x00, + 0x10,0x09,0x05,0xff,0xf0,0xa0,0x94,0x9c,0x00,0x05,0xff,0xe3,0x92,0xb9,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe5,0x85,0xa7,0x00,0x05,0xff,0xe5,0x86,0x8d,0x00,0x10, + 0x09,0x05,0xff,0xf0,0xa0,0x95,0x8b,0x00,0x05,0xff,0xe5,0x86,0x97,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x86,0xa4,0x00,0x05,0xff,0xe4,0xbb,0x8c,0x00, + 0x10,0x08,0x05,0xff,0xe5,0x86,0xac,0x00,0x05,0xff,0xe5,0x86,0xb5,0x00,0xd1,0x11, + 0x10,0x09,0x05,0xff,0xf0,0xa9,0x87,0x9f,0x00,0x05,0xff,0xe5,0x87,0xb5,0x00,0x10, + 0x08,0x05,0xff,0xe5,0x88,0x83,0x00,0x05,0xff,0xe3,0x93,0x9f,0x00,0xd4,0x80,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x88,0xbb,0x00,0x05,0xff,0xe5, + 0x89,0x86,0x00,0x10,0x08,0x05,0xff,0xe5,0x89,0xb2,0x00,0x05,0xff,0xe5,0x89,0xb7, + 0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe3,0x94,0x95,0x00,0x05,0xff,0xe5,0x8b,0x87, + 0x00,0x10,0x08,0x05,0xff,0xe5,0x8b,0x89,0x00,0x05,0xff,0xe5,0x8b,0xa4,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x8b,0xba,0x00,0x05,0xff,0xe5,0x8c,0x85, + 0x00,0x10,0x08,0x05,0xff,0xe5,0x8c,0x86,0x00,0x05,0xff,0xe5,0x8c,0x97,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe5,0x8d,0x89,0x00,0x05,0xff,0xe5,0x8d,0x91,0x00,0x10, + 0x08,0x05,0xff,0xe5,0x8d,0x9a,0x00,0x05,0xff,0xe5,0x8d,0xb3,0x00,0xd3,0x39,0xd2, + 0x18,0x91,0x10,0x10,0x08,0x05,0xff,0xe5,0x8d,0xbd,0x00,0x05,0xff,0xe5,0x8d,0xbf, + 0x00,0x05,0xff,0xe5,0x8d,0xbf,0x00,0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa0,0xa8, + 0xac,0x00,0x05,0xff,0xe7,0x81,0xb0,0x00,0x10,0x08,0x05,0xff,0xe5,0x8f,0x8a,0x00, + 0x05,0xff,0xe5,0x8f,0x9f,0x00,0xd2,0x21,0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa0, + 0xad,0xa3,0x00,0x05,0xff,0xe5,0x8f,0xab,0x00,0x10,0x08,0x05,0xff,0xe5,0x8f,0xb1, + 0x00,0x05,0xff,0xe5,0x90,0x86,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x92,0x9e, + 0x00,0x05,0xff,0xe5,0x90,0xb8,0x00,0x10,0x08,0x05,0xff,0xe5,0x91,0x88,0x00,0x05, + 0xff,0xe5,0x91,0xa8,0x00,0xcf,0x86,0xe5,0x02,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,0x93,0xb6,0x00, + 0x10,0x08,0x05,0xff,0xe5,0x94,0x90,0x00,0x05,0xff,0xe5,0x95,0x93,0x00,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe5,0x95,0xa3,0x00,0x05,0xff,0xe5,0x96,0x84,0x00,0x10,0x08, + 0x05,0xff,0xe5,0x96,0x84,0x00,0x05,0xff,0xe5,0x96,0x99,0x00,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe5,0x96,0xab,0x00,0x05,0xff,0xe5,0x96,0xb3,0x00,0x10,0x08, + 0x05,0xff,0xe5,0x97,0x82,0x00,0x05,0xff,0xe5,0x9c,0x96,0x00,0xd1,0x10,0x10,0x08, + 0x05,0xff,0xe5,0x98,0x86,0x00,0x05,0xff,0xe5,0x9c,0x97,0x00,0x10,0x08,0x05,0xff, + 0xe5,0x99,0x91,0x00,0x05,0xff,0xe5,0x99,0xb4,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe5,0x88,0x87,0x00,0x05,0xff,0xe5,0xa3,0xae,0x00,0x10,0x08, + 0x05,0xff,0xe5,0x9f,0x8e,0x00,0x05,0xff,0xe5,0x9f,0xb4,0x00,0xd1,0x10,0x10,0x08, + 0x05,0xff,0xe5,0xa0,0x8d,0x00,0x05,0xff,0xe5,0x9e,0x8b,0x00,0x10,0x08,0x05,0xff, + 0xe5,0xa0,0xb2,0x00,0x05,0xff,0xe5,0xa0,0xb1,0x00,0xd2,0x21,0xd1,0x11,0x10,0x08, + 0x05,0xff,0xe5,0xa2,0xac,0x00,0x05,0xff,0xf0,0xa1,0x93,0xa4,0x00,0x10,0x08,0x05, + 0xff,0xe5,0xa3,0xb2,0x00,0x05,0xff,0xe5,0xa3,0xb7,0x00,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe5,0xa4,0x86,0x00,0x05,0xff,0xe5,0xa4,0x9a,0x00,0x10,0x08,0x05,0xff,0xe5, + 0xa4,0xa2,0x00,0x05,0xff,0xe5,0xa5,0xa2,0x00,0xd4,0x7b,0xd3,0x42,0xd2,0x22,0xd1, + 0x12,0x10,0x09,0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa, + 0x00,0x10,0x08,0x05,0xff,0xe5,0xa7,0xac,0x00,0x05,0xff,0xe5,0xa8,0x9b,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe5,0xa8,0xa7,0x00,0x05,0xff,0xe5,0xa7,0x98,0x00,0x10, + 0x08,0x05,0xff,0xe5,0xa9,0xa6,0x00,0x05,0xff,0xe3,0x9b,0xae,0x00,0xd2,0x18,0x91, + 0x10,0x10,0x08,0x05,0xff,0xe3,0x9b,0xbc,0x00,0x05,0xff,0xe5,0xac,0x88,0x00,0x05, + 0xff,0xe5,0xac,0xbe,0x00,0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0xa7,0x88,0x00, + 0x05,0xff,0xe5,0xaf,0x83,0x00,0x10,0x08,0x05,0xff,0xe5,0xaf,0x98,0x00,0x05,0xff, + 0xe5,0xaf,0xa7,0x00,0xd3,0x41,0xd2,0x21,0xd1,0x11,0x10,0x08,0x05,0xff,0xe5,0xaf, + 0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0x10,0x08,0x05,0xff,0xe5,0xaf,0xbf, + 0x00,0x05,0xff,0xe5,0xb0,0x86,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0xbd,0x93, + 0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0x10,0x08,0x05,0xff,0xe3,0x9e,0x81,0x00,0x05, + 0xff,0xe5,0xb1,0xa0,0x00,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0xb1,0xae, + 0x00,0x05,0xff,0xe5,0xb3,0x80,0x00,0x10,0x08,0x05,0xff,0xe5,0xb2,0x8d,0x00,0x05, + 0xff,0xf0,0xa1,0xb7,0xa4,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe5,0xb5,0x83,0x00, + 0x05,0xff,0xf0,0xa1,0xb7,0xa6,0x00,0x10,0x08,0x05,0xff,0xe5,0xb5,0xae,0x00,0x05, + 0xff,0xe5,0xb5,0xab,0x00,0xe0,0x04,0x02,0xcf,0x86,0xd5,0xfe,0xd4,0x82,0xd3,0x40, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0xb5,0xbc,0x00,0x05,0xff,0xe5,0xb7, + 0xa1,0x00,0x10,0x08,0x05,0xff,0xe5,0xb7,0xa2,0x00,0x05,0xff,0xe3,0xa0,0xaf,0x00, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0xb7,0xbd,0x00,0x05,0xff,0xe5,0xb8,0xa8,0x00, + 0x10,0x08,0x05,0xff,0xe5,0xb8,0xbd,0x00,0x05,0xff,0xe5,0xb9,0xa9,0x00,0xd2,0x21, + 0xd1,0x11,0x10,0x08,0x05,0xff,0xe3,0xa1,0xa2,0x00,0x05,0xff,0xf0,0xa2,0x86,0x83, + 0x00,0x10,0x08,0x05,0xff,0xe3,0xa1,0xbc,0x00,0x05,0xff,0xe5,0xba,0xb0,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe5,0xba,0xb3,0x00,0x05,0xff,0xe5,0xba,0xb6,0x00,0x10, + 0x08,0x05,0xff,0xe5,0xbb,0x8a,0x00,0x05,0xff,0xf0,0xaa,0x8e,0x92,0x00,0xd3,0x3b, + 0xd2,0x22,0xd1,0x11,0x10,0x08,0x05,0xff,0xe5,0xbb,0xbe,0x00,0x05,0xff,0xf0,0xa2, + 0x8c,0xb1,0x00,0x10,0x09,0x05,0xff,0xf0,0xa2,0x8c,0xb1,0x00,0x05,0xff,0xe8,0x88, + 0x81,0x00,0x51,0x08,0x05,0xff,0xe5,0xbc,0xa2,0x00,0x10,0x08,0x05,0xff,0xe3,0xa3, + 0x87,0x00,0x05,0xff,0xf0,0xa3,0x8a,0xb8,0x00,0xd2,0x21,0xd1,0x11,0x10,0x09,0x05, + 0xff,0xf0,0xa6,0x87,0x9a,0x00,0x05,0xff,0xe5,0xbd,0xa2,0x00,0x10,0x08,0x05,0xff, + 0xe5,0xbd,0xab,0x00,0x05,0xff,0xe3,0xa3,0xa3,0x00,0xd1,0x10,0x10,0x08,0x05,0xff, + 0xe5,0xbe,0x9a,0x00,0x05,0xff,0xe5,0xbf,0x8d,0x00,0x10,0x08,0x05,0xff,0xe5,0xbf, + 0x97,0x00,0x05,0xff,0xe5,0xbf,0xb9,0x00,0xd4,0x81,0xd3,0x41,0xd2,0x20,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe6,0x82,0x81,0x00,0x05,0xff,0xe3,0xa4,0xba,0x00,0x10,0x08, + 0x05,0xff,0xe3,0xa4,0x9c,0x00,0x05,0xff,0xe6,0x82,0x94,0x00,0xd1,0x11,0x10,0x09, + 0x05,0xff,0xf0,0xa2,0x9b,0x94,0x00,0x05,0xff,0xe6,0x83,0x87,0x00,0x10,0x08,0x05, + 0xff,0xe6,0x85,0x88,0x00,0x05,0xff,0xe6,0x85,0x8c,0x00,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe6,0x85,0x8e,0x00,0x05,0xff,0xe6,0x85,0x8c,0x00,0x10,0x08,0x05, + 0xff,0xe6,0x85,0xba,0x00,0x05,0xff,0xe6,0x86,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe6,0x86,0xb2,0x00,0x05,0xff,0xe6,0x86,0xa4,0x00,0x10,0x08,0x05,0xff,0xe6, + 0x86,0xaf,0x00,0x05,0xff,0xe6,0x87,0x9e,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe6,0x87,0xb2,0x00,0x05,0xff,0xe6,0x87,0xb6,0x00,0x10,0x08,0x05, + 0xff,0xe6,0x88,0x90,0x00,0x05,0xff,0xe6,0x88,0x9b,0x00,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe6,0x89,0x9d,0x00,0x05,0xff,0xe6,0x8a,0xb1,0x00,0x10,0x08,0x05,0xff,0xe6, + 0x8b,0x94,0x00,0x05,0xff,0xe6,0x8d,0x90,0x00,0xd2,0x21,0xd1,0x11,0x10,0x09,0x05, + 0xff,0xf0,0xa2,0xac,0x8c,0x00,0x05,0xff,0xe6,0x8c,0xbd,0x00,0x10,0x08,0x05,0xff, + 0xe6,0x8b,0xbc,0x00,0x05,0xff,0xe6,0x8d,0xa8,0x00,0xd1,0x10,0x10,0x08,0x05,0xff, + 0xe6,0x8e,0x83,0x00,0x05,0xff,0xe6,0x8f,0xa4,0x00,0x10,0x09,0x05,0xff,0xf0,0xa2, + 0xaf,0xb1,0x00,0x05,0xff,0xe6,0x90,0xa2,0x00,0xcf,0x86,0xe5,0x03,0x01,0xd4,0x81, + 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x8f,0x85,0x00,0x05,0xff, + 0xe6,0x8e,0xa9,0x00,0x10,0x08,0x05,0xff,0xe3,0xa8,0xae,0x00,0x05,0xff,0xe6,0x91, + 0xa9,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x91,0xbe,0x00,0x05,0xff,0xe6,0x92, + 0x9d,0x00,0x10,0x08,0x05,0xff,0xe6,0x91,0xb7,0x00,0x05,0xff,0xe3,0xa9,0xac,0x00, + 0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x95,0x8f,0x00,0x05,0xff,0xe6,0x95, + 0xac,0x00,0x10,0x09,0x05,0xff,0xf0,0xa3,0x80,0x8a,0x00,0x05,0xff,0xe6,0x97,0xa3, + 0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x9b,0xb8,0x00,0x05,0xff,0xe6,0x99,0x89, + 0x00,0x10,0x08,0x05,0xff,0xe3,0xac,0x99,0x00,0x05,0xff,0xe6,0x9a,0x91,0x00,0xd3, + 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe3,0xac,0x88,0x00,0x05,0xff,0xe3, + 0xab,0xa4,0x00,0x10,0x08,0x05,0xff,0xe5,0x86,0x92,0x00,0x05,0xff,0xe5,0x86,0x95, + 0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x9c,0x80,0x00,0x05,0xff,0xe6,0x9a,0x9c, + 0x00,0x10,0x08,0x05,0xff,0xe8,0x82,0xad,0x00,0x05,0xff,0xe4,0x8f,0x99,0x00,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x9c,0x97,0x00,0x05,0xff,0xe6,0x9c,0x9b, + 0x00,0x10,0x08,0x05,0xff,0xe6,0x9c,0xa1,0x00,0x05,0xff,0xe6,0x9d,0x9e,0x00,0xd1, + 0x11,0x10,0x08,0x05,0xff,0xe6,0x9d,0x93,0x00,0x05,0xff,0xf0,0xa3,0x8f,0x83,0x00, + 0x10,0x08,0x05,0xff,0xe3,0xad,0x89,0x00,0x05,0xff,0xe6,0x9f,0xba,0x00,0xd4,0x82, + 0xd3,0x41,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0x9e,0x85,0x00,0x05,0xff, + 0xe6,0xa1,0x92,0x00,0x10,0x08,0x05,0xff,0xe6,0xa2,0x85,0x00,0x05,0xff,0xf0,0xa3, + 0x91,0xad,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xa2,0x8e,0x00,0x05,0xff,0xe6, + 0xa0,0x9f,0x00,0x10,0x08,0x05,0xff,0xe6,0xa4,0x94,0x00,0x05,0xff,0xe3,0xae,0x9d, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xa5,0x82,0x00,0x05,0xff,0xe6, + 0xa6,0xa3,0x00,0x10,0x08,0x05,0xff,0xe6,0xa7,0xaa,0x00,0x05,0xff,0xe6,0xaa,0xa8, + 0x00,0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa3,0x9a,0xa3,0x00,0x05,0xff,0xe6,0xab, + 0x9b,0x00,0x10,0x08,0x05,0xff,0xe3,0xb0,0x98,0x00,0x05,0xff,0xe6,0xac,0xa1,0x00, + 0xd3,0x42,0xd2,0x21,0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa3,0xa2,0xa7,0x00,0x05, + 0xff,0xe6,0xad,0x94,0x00,0x10,0x08,0x05,0xff,0xe3,0xb1,0x8e,0x00,0x05,0xff,0xe6, + 0xad,0xb2,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xae,0x9f,0x00,0x05,0xff,0xe6, + 0xae,0xba,0x00,0x10,0x08,0x05,0xff,0xe6,0xae,0xbb,0x00,0x05,0xff,0xf0,0xa3,0xaa, + 0x8d,0x00,0xd2,0x23,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa1,0xb4,0x8b,0x00,0x05, + 0xff,0xf0,0xa3,0xab,0xba,0x00,0x10,0x08,0x05,0xff,0xe6,0xb1,0x8e,0x00,0x05,0xff, + 0xf0,0xa3,0xb2,0xbc,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xb2,0xbf,0x00,0x05, + 0xff,0xe6,0xb3,0x8d,0x00,0x10,0x08,0x05,0xff,0xe6,0xb1,0xa7,0x00,0x05,0xff,0xe6, + 0xb4,0x96,0x00,0xe1,0x1d,0x04,0xe0,0x0c,0x02,0xcf,0x86,0xe5,0x08,0x01,0xd4,0x82, + 0xd3,0x41,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff, + 0xe6,0xb5,0xb7,0x00,0x10,0x08,0x05,0xff,0xe6,0xb5,0x81,0x00,0x05,0xff,0xe6,0xb5, + 0xa9,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xb5,0xb8,0x00,0x05,0xff,0xe6,0xb6, + 0x85,0x00,0x10,0x09,0x05,0xff,0xf0,0xa3,0xb4,0x9e,0x00,0x05,0xff,0xe6,0xb4,0xb4, + 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe6,0xb8,0xaf,0x00,0x05,0xff,0xe6, + 0xb9,0xae,0x00,0x10,0x08,0x05,0xff,0xe3,0xb4,0xb3,0x00,0x05,0xff,0xe6,0xbb,0x8b, + 0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe6,0xbb,0x87,0x00,0x05,0xff,0xf0,0xa3,0xbb, + 0x91,0x00,0x10,0x08,0x05,0xff,0xe6,0xb7,0xb9,0x00,0x05,0xff,0xe6,0xbd,0xae,0x00, + 0xd3,0x42,0xd2,0x22,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,0x9e,0x00,0x05, + 0xff,0xf0,0xa3,0xbe,0x8e,0x00,0x10,0x08,0x05,0xff,0xe6,0xbf,0x86,0x00,0x05,0xff, + 0xe7,0x80,0xb9,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0x80,0x9e,0x00,0x05,0xff, + 0xe7,0x80,0x9b,0x00,0x10,0x08,0x05,0xff,0xe3,0xb6,0x96,0x00,0x05,0xff,0xe7,0x81, + 0x8a,0x00,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff, + 0xe7,0x81,0xb7,0x00,0x10,0x08,0x05,0xff,0xe7,0x82,0xad,0x00,0x05,0xff,0xf0,0xa0, + 0x94,0xa5,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0, + 0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xf0,0xa4, + 0x8e,0xab,0x00,0xd4,0x7b,0xd3,0x43,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7, + 0x88,0xa8,0x00,0x05,0xff,0xe7,0x88,0xb5,0x00,0x10,0x08,0x05,0xff,0xe7,0x89,0x90, + 0x00,0x05,0xff,0xf0,0xa4,0x98,0x88,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0x8a, + 0x80,0x00,0x05,0xff,0xe7,0x8a,0x95,0x00,0x10,0x09,0x05,0xff,0xf0,0xa4,0x9c,0xb5, + 0x00,0x05,0xff,0xf0,0xa4,0xa0,0x94,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff, + 0xe7,0x8d,0xba,0x00,0x05,0xff,0xe7,0x8e,0x8b,0x00,0x10,0x08,0x05,0xff,0xe3,0xba, + 0xac,0x00,0x05,0xff,0xe7,0x8e,0xa5,0x00,0x51,0x08,0x05,0xff,0xe3,0xba,0xb8,0x00, + 0x10,0x08,0x05,0xff,0xe7,0x91,0x87,0x00,0x05,0xff,0xe7,0x91,0x9c,0x00,0xd3,0x42, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0x91,0xb1,0x00,0x05,0xff,0xe7,0x92, + 0x85,0x00,0x10,0x08,0x05,0xff,0xe7,0x93,0x8a,0x00,0x05,0xff,0xe3,0xbc,0x9b,0x00, + 0xd1,0x11,0x10,0x08,0x05,0xff,0xe7,0x94,0xa4,0x00,0x05,0xff,0xf0,0xa4,0xb0,0xb6, + 0x00,0x10,0x08,0x05,0xff,0xe7,0x94,0xbe,0x00,0x05,0xff,0xf0,0xa4,0xb2,0x92,0x00, + 0xd2,0x22,0xd1,0x11,0x10,0x08,0x05,0xff,0xe7,0x95,0xb0,0x00,0x05,0xff,0xf0,0xa2, + 0x86,0x9f,0x00,0x10,0x08,0x05,0xff,0xe7,0x98,0x90,0x00,0x05,0xff,0xf0,0xa4,0xbe, + 0xa1,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa4,0xbe,0xb8,0x00,0x05,0xff,0xf0, + 0xa5,0x81,0x84,0x00,0x10,0x08,0x05,0xff,0xe3,0xbf,0xbc,0x00,0x05,0xff,0xe4,0x80, + 0x88,0x00,0xcf,0x86,0xe5,0x04,0x01,0xd4,0x7d,0xd3,0x3c,0xd2,0x23,0xd1,0x11,0x10, + 0x08,0x05,0xff,0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0x10,0x09, + 0x05,0xff,0xf0,0xa5,0x83,0xb2,0x00,0x05,0xff,0xf0,0xa5,0x84,0x99,0x00,0x91,0x11, + 0x10,0x09,0x05,0xff,0xf0,0xa5,0x84,0xb3,0x00,0x05,0xff,0xe7,0x9c,0x9e,0x00,0x05, + 0xff,0xe7,0x9c,0x9f,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0x9d,0x8a, + 0x00,0x05,0xff,0xe4,0x80,0xb9,0x00,0x10,0x08,0x05,0xff,0xe7,0x9e,0x8b,0x00,0x05, + 0xff,0xe4,0x81,0x86,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe4,0x82,0x96,0x00,0x05, + 0xff,0xf0,0xa5,0x90,0x9d,0x00,0x10,0x08,0x05,0xff,0xe7,0xa1,0x8e,0x00,0x05,0xff, + 0xe7,0xa2,0x8c,0x00,0xd3,0x43,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0xa3, + 0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0x98,0xa6, + 0x00,0x05,0xff,0xe7,0xa5,0x96,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0x9a, + 0x9a,0x00,0x05,0xff,0xf0,0xa5,0x9b,0x85,0x00,0x10,0x08,0x05,0xff,0xe7,0xa6,0x8f, + 0x00,0x05,0xff,0xe7,0xa7,0xab,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe4, + 0x84,0xaf,0x00,0x05,0xff,0xe7,0xa9,0x80,0x00,0x10,0x08,0x05,0xff,0xe7,0xa9,0x8a, + 0x00,0x05,0xff,0xe7,0xa9,0x8f,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5, + 0xbc,0x00,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa, + 0xa7,0x00,0x05,0xff,0xe7,0xab,0xae,0x00,0xd4,0x83,0xd3,0x42,0xd2,0x21,0xd1,0x11, + 0x10,0x08,0x05,0xff,0xe4,0x88,0x82,0x00,0x05,0xff,0xf0,0xa5,0xae,0xab,0x00,0x10, + 0x08,0x05,0xff,0xe7,0xaf,0x86,0x00,0x05,0xff,0xe7,0xaf,0x89,0x00,0xd1,0x11,0x10, + 0x08,0x05,0xff,0xe4,0x88,0xa7,0x00,0x05,0xff,0xf0,0xa5,0xb2,0x80,0x00,0x10,0x08, + 0x05,0xff,0xe7,0xb3,0x92,0x00,0x05,0xff,0xe4,0x8a,0xa0,0x00,0xd2,0x21,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe7,0xb3,0xa8,0x00,0x05,0xff,0xe7,0xb3,0xa3,0x00,0x10,0x08, + 0x05,0xff,0xe7,0xb4,0x80,0x00,0x05,0xff,0xf0,0xa5,0xbe,0x86,0x00,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe7,0xb5,0xa3,0x00,0x05,0xff,0xe4,0x8c,0x81,0x00,0x10,0x08,0x05, + 0xff,0xe7,0xb7,0x87,0x00,0x05,0xff,0xe7,0xb8,0x82,0x00,0xd3,0x44,0xd2,0x22,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe7,0xb9,0x85,0x00,0x05,0xff,0xe4,0x8c,0xb4,0x00,0x10, + 0x09,0x05,0xff,0xf0,0xa6,0x88,0xa8,0x00,0x05,0xff,0xf0,0xa6,0x89,0x87,0x00,0xd1, + 0x11,0x10,0x08,0x05,0xff,0xe4,0x8d,0x99,0x00,0x05,0xff,0xf0,0xa6,0x8b,0x99,0x00, + 0x10,0x08,0x05,0xff,0xe7,0xbd,0xba,0x00,0x05,0xff,0xf0,0xa6,0x8c,0xbe,0x00,0xd2, + 0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe7,0xbe,0x95,0x00,0x05,0xff,0xe7,0xbf,0xba, + 0x00,0x10,0x08,0x05,0xff,0xe8,0x80,0x85,0x00,0x05,0xff,0xf0,0xa6,0x93,0x9a,0x00, + 0xd1,0x11,0x10,0x09,0x05,0xff,0xf0,0xa6,0x94,0xa3,0x00,0x05,0xff,0xe8,0x81,0xa0, + 0x00,0x10,0x09,0x05,0xff,0xf0,0xa6,0x96,0xa8,0x00,0x05,0xff,0xe8,0x81,0xb0,0x00, + 0xe0,0x11,0x02,0xcf,0x86,0xe5,0x07,0x01,0xd4,0x85,0xd3,0x42,0xd2,0x21,0xd1,0x11, + 0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0x10, + 0x08,0x05,0xff,0xe8,0x82,0xb2,0x00,0x05,0xff,0xe8,0x84,0x83,0x00,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe4,0x90,0x8b,0x00,0x05,0xff,0xe8,0x84,0xbe,0x00,0x10,0x08,0x05, + 0xff,0xe5,0xaa,0xb5,0x00,0x05,0xff,0xf0,0xa6,0x9e,0xa7,0x00,0xd2,0x23,0xd1,0x12, + 0x10,0x09,0x05,0xff,0xf0,0xa6,0x9e,0xb5,0x00,0x05,0xff,0xf0,0xa3,0x8e,0x93,0x00, + 0x10,0x09,0x05,0xff,0xf0,0xa3,0x8e,0x9c,0x00,0x05,0xff,0xe8,0x88,0x81,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe8,0x88,0x84,0x00,0x05,0xff,0xe8,0xbe,0x9e,0x00,0x10, + 0x08,0x05,0xff,0xe4,0x91,0xab,0x00,0x05,0xff,0xe8,0x8a,0x91,0x00,0xd3,0x41,0xd2, + 0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x8a,0x8b,0x00,0x05,0xff,0xe8,0x8a,0x9d, + 0x00,0x10,0x08,0x05,0xff,0xe5,0x8a,0xb3,0x00,0x05,0xff,0xe8,0x8a,0xb1,0x00,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe8,0x8a,0xb3,0x00,0x05,0xff,0xe8,0x8a,0xbd,0x00,0x10, + 0x08,0x05,0xff,0xe8,0x8b,0xa6,0x00,0x05,0xff,0xf0,0xa6,0xac,0xbc,0x00,0xd2,0x20, + 0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x8b,0xa5,0x00,0x05,0xff,0xe8,0x8c,0x9d,0x00, + 0x10,0x08,0x05,0xff,0xe8,0x8d,0xa3,0x00,0x05,0xff,0xe8,0x8e,0xad,0x00,0xd1,0x10, + 0x10,0x08,0x05,0xff,0xe8,0x8c,0xa3,0x00,0x05,0xff,0xe8,0x8e,0xbd,0x00,0x10,0x08, + 0x05,0xff,0xe8,0x8f,0xa7,0x00,0x05,0xff,0xe8,0x91,0x97,0x00,0xd4,0x85,0xd3,0x43, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f, + 0x8a,0x00,0x10,0x08,0x05,0xff,0xe8,0x8f,0x8c,0x00,0x05,0xff,0xe8,0x8f,0x9c,0x00, + 0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa6,0xb0,0xb6,0x00,0x05,0xff,0xf0,0xa6,0xb5, + 0xab,0x00,0x10,0x09,0x05,0xff,0xf0,0xa6,0xb3,0x95,0x00,0x05,0xff,0xe4,0x94,0xab, + 0x00,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x93,0xb1,0x00,0x05,0xff,0xe8, + 0x93,0xb3,0x00,0x10,0x08,0x05,0xff,0xe8,0x94,0x96,0x00,0x05,0xff,0xf0,0xa7,0x8f, + 0x8a,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe8,0x95,0xa4,0x00,0x05,0xff,0xf0,0xa6, + 0xbc,0xac,0x00,0x10,0x08,0x05,0xff,0xe4,0x95,0x9d,0x00,0x05,0xff,0xe4,0x95,0xa1, + 0x00,0xd3,0x42,0xd2,0x22,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00, + 0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0x10,0x08,0x05,0xff,0xe4,0x95,0xab,0x00,0x05, + 0xff,0xe8,0x99,0x90,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x99,0x9c,0x00,0x05, + 0xff,0xe8,0x99,0xa7,0x00,0x10,0x08,0x05,0xff,0xe8,0x99,0xa9,0x00,0x05,0xff,0xe8, + 0x9a,0xa9,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9a,0x88,0x00,0x05, + 0xff,0xe8,0x9c,0x8e,0x00,0x10,0x08,0x05,0xff,0xe8,0x9b,0xa2,0x00,0x05,0xff,0xe8, + 0x9d,0xb9,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8, + 0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,0x86,0x00,0x05,0xff,0xe4,0x97,0x97, + 0x00,0xcf,0x86,0xe5,0x08,0x01,0xd4,0x83,0xd3,0x41,0xd2,0x20,0xd1,0x10,0x10,0x08, + 0x05,0xff,0xe8,0x9f,0xa1,0x00,0x05,0xff,0xe8,0xa0,0x81,0x00,0x10,0x08,0x05,0xff, + 0xe4,0x97,0xb9,0x00,0x05,0xff,0xe8,0xa1,0xa0,0x00,0xd1,0x11,0x10,0x08,0x05,0xff, + 0xe8,0xa1,0xa3,0x00,0x05,0xff,0xf0,0xa7,0x99,0xa7,0x00,0x10,0x08,0x05,0xff,0xe8, + 0xa3,0x97,0x00,0x05,0xff,0xe8,0xa3,0x9e,0x00,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe4,0x98,0xb5,0x00,0x05,0xff,0xe8,0xa3,0xba,0x00,0x10,0x08,0x05,0xff,0xe3, + 0x92,0xbb,0x00,0x05,0xff,0xf0,0xa7,0xa2,0xae,0x00,0xd1,0x11,0x10,0x09,0x05,0xff, + 0xf0,0xa7,0xa5,0xa6,0x00,0x05,0xff,0xe4,0x9a,0xbe,0x00,0x10,0x08,0x05,0xff,0xe4, + 0x9b,0x87,0x00,0x05,0xff,0xe8,0xaa,0xa0,0x00,0xd3,0x41,0xd2,0x21,0xd1,0x10,0x10, + 0x08,0x05,0xff,0xe8,0xab,0xad,0x00,0x05,0xff,0xe8,0xae,0x8a,0x00,0x10,0x08,0x05, + 0xff,0xe8,0xb1,0x95,0x00,0x05,0xff,0xf0,0xa7,0xb2,0xa8,0x00,0xd1,0x10,0x10,0x08, + 0x05,0xff,0xe8,0xb2,0xab,0x00,0x05,0xff,0xe8,0xb3,0x81,0x00,0x10,0x08,0x05,0xff, + 0xe8,0xb4,0x9b,0x00,0x05,0xff,0xe8,0xb5,0xb7,0x00,0xd2,0x22,0xd1,0x12,0x10,0x09, + 0x05,0xff,0xf0,0xa7,0xbc,0xaf,0x00,0x05,0xff,0xf0,0xa0,0xa0,0x84,0x00,0x10,0x08, + 0x05,0xff,0xe8,0xb7,0x8b,0x00,0x05,0xff,0xe8,0xb6,0xbc,0x00,0xd1,0x11,0x10,0x08, + 0x05,0xff,0xe8,0xb7,0xb0,0x00,0x05,0xff,0xf0,0xa0,0xa3,0x9e,0x00,0x10,0x08,0x05, + 0xff,0xe8,0xbb,0x94,0x00,0x05,0xff,0xe8,0xbc,0xb8,0x00,0xd4,0x84,0xd3,0x43,0xd2, + 0x22,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa8,0x97,0x92,0x00,0x05,0xff,0xf0,0xa8, + 0x97,0xad,0x00,0x10,0x08,0x05,0xff,0xe9,0x82,0x94,0x00,0x05,0xff,0xe9,0x83,0xb1, + 0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe9,0x84,0x91,0x00,0x05,0xff,0xf0,0xa8,0x9c, + 0xae,0x00,0x10,0x08,0x05,0xff,0xe9,0x84,0x9b,0x00,0x05,0xff,0xe9,0x88,0xb8,0x00, + 0xd2,0x20,0xd1,0x10,0x10,0x08,0x05,0xff,0xe9,0x8b,0x97,0x00,0x05,0xff,0xe9,0x8b, + 0x98,0x00,0x10,0x08,0x05,0xff,0xe9,0x89,0xbc,0x00,0x05,0xff,0xe9,0x8f,0xb9,0x00, + 0xd1,0x11,0x10,0x08,0x05,0xff,0xe9,0x90,0x95,0x00,0x05,0xff,0xf0,0xa8,0xaf,0xba, + 0x00,0x10,0x08,0x05,0xff,0xe9,0x96,0x8b,0x00,0x05,0xff,0xe4,0xa6,0x95,0x00,0xd3, + 0x43,0xd2,0x21,0xd1,0x11,0x10,0x08,0x05,0xff,0xe9,0x96,0xb7,0x00,0x05,0xff,0xf0, + 0xa8,0xb5,0xb7,0x00,0x10,0x08,0x05,0xff,0xe4,0xa7,0xa6,0x00,0x05,0xff,0xe9,0x9b, + 0x83,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe5,0xb6,0xb2,0x00,0x05,0xff,0xe9,0x9c, + 0xa3,0x00,0x10,0x09,0x05,0xff,0xf0,0xa9,0x85,0x85,0x00,0x05,0xff,0xf0,0xa9,0x88, + 0x9a,0x00,0xd2,0x21,0xd1,0x10,0x10,0x08,0x05,0xff,0xe4,0xa9,0xae,0x00,0x05,0xff, + 0xe4,0xa9,0xb6,0x00,0x10,0x08,0x05,0xff,0xe9,0x9f,0xa0,0x00,0x05,0xff,0xf0,0xa9, + 0x90,0x8a,0x00,0x91,0x11,0x10,0x08,0x05,0xff,0xe4,0xaa,0xb2,0x00,0x05,0xff,0xf0, + 0xa9,0x92,0x96,0x00,0x05,0xff,0xe9,0xa0,0x8b,0x00,0xe2,0x10,0x01,0xe1,0x09,0x01, + 0xe0,0x02,0x01,0xcf,0x86,0x95,0xfb,0xd4,0x82,0xd3,0x41,0xd2,0x21,0xd1,0x11,0x10, + 0x08,0x05,0xff,0xe9,0xa0,0xa9,0x00,0x05,0xff,0xf0,0xa9,0x96,0xb6,0x00,0x10,0x08, + 0x05,0xff,0xe9,0xa3,0xa2,0x00,0x05,0xff,0xe4,0xac,0xb3,0x00,0xd1,0x10,0x10,0x08, + 0x05,0xff,0xe9,0xa4,0xa9,0x00,0x05,0xff,0xe9,0xa6,0xa7,0x00,0x10,0x08,0x05,0xff, + 0xe9,0xa7,0x82,0x00,0x05,0xff,0xe9,0xa7,0xbe,0x00,0xd2,0x21,0xd1,0x11,0x10,0x08, + 0x05,0xff,0xe4,0xaf,0x8e,0x00,0x05,0xff,0xf0,0xa9,0xac,0xb0,0x00,0x10,0x08,0x05, + 0xff,0xe9,0xac,0x92,0x00,0x05,0xff,0xe9,0xb1,0x80,0x00,0xd1,0x10,0x10,0x08,0x05, + 0xff,0xe9,0xb3,0xbd,0x00,0x05,0xff,0xe4,0xb3,0x8e,0x00,0x10,0x08,0x05,0xff,0xe4, + 0xb3,0xad,0x00,0x05,0xff,0xe9,0xb5,0xa7,0x00,0xd3,0x44,0xd2,0x23,0xd1,0x11,0x10, + 0x09,0x05,0xff,0xf0,0xaa,0x83,0x8e,0x00,0x05,0xff,0xe4,0xb3,0xb8,0x00,0x10,0x09, + 0x05,0xff,0xf0,0xaa,0x84,0x85,0x00,0x05,0xff,0xf0,0xaa,0x88,0x8e,0x00,0xd1,0x11, + 0x10,0x09,0x05,0xff,0xf0,0xaa,0x8a,0x91,0x00,0x05,0xff,0xe9,0xba,0xbb,0x00,0x10, + 0x08,0x05,0xff,0xe4,0xb5,0x96,0x00,0x05,0xff,0xe9,0xbb,0xb9,0x00,0xd2,0x20,0xd1, + 0x10,0x10,0x08,0x05,0xff,0xe9,0xbb,0xbe,0x00,0x05,0xff,0xe9,0xbc,0x85,0x00,0x10, + 0x08,0x05,0xff,0xe9,0xbc,0x8f,0x00,0x05,0xff,0xe9,0xbc,0x96,0x00,0x91,0x11,0x10, + 0x08,0x05,0xff,0xe9,0xbc,0xbb,0x00,0x05,0xff,0xf0,0xaa,0x98,0x80,0x00,0x00,0x00, + 0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x06, + 0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00, + 0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00, + 0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xd3,0x08, + 0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd1,0x08, + 0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86, + 0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06, + 0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06, + 0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04, + 0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xcf,0x86,0xd5,0xc0, + 0xd4,0x60,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06, + 0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06, + 0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00, + 0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06, + 0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04, + 0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00, + 0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06, + 0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00, + 0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00, + 0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xd4,0x60, + 0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00, + 0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06, + 0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00, + 0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00, + 0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xd3,0x08, + 0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd1,0x08, + 0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86, + 0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06, + 0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06, + 0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04, + 0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xe0,0x83,0x01,0xcf, + 0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf, + 0x86,0xcf,0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf, + 0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf, + 0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1, + 0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00, + 0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00, + 0x00,0x02,0x00,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00, + 0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf, + 0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54, + 0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02, + 0x00,0xd4,0x60,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00, + 0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf, + 0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54, + 0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02, + 0x00,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00, + 0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00, + 0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3, + 0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00, + 0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00, + 0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xcf, + 0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf, + 0x86,0xcf,0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf, + 0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf, + 0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1, + 0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00, + 0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00, + 0x00,0x02,0x00,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf, + 0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00, + 0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf, + 0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54, + 0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02, + 0x00,0xd4,0xd9,0xd3,0x81,0xd2,0x79,0xd1,0x71,0xd0,0x69,0xcf,0x86,0xd5,0x60,0xd4, + 0x59,0xd3,0x52,0xd2,0x33,0xd1,0x2c,0xd0,0x25,0xcf,0x86,0x95,0x1e,0x94,0x19,0x93, + 0x14,0x92,0x0f,0x91,0x0a,0x10,0x05,0x00,0xff,0x00,0x05,0xff,0x00,0x00,0xff,0x00, + 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x05,0xff,0x00,0xcf,0x06,0x05,0xff, + 0x00,0xcf,0x06,0x00,0xff,0x00,0xd1,0x07,0xcf,0x06,0x07,0xff,0x00,0xd0,0x07,0xcf, + 0x06,0x07,0xff,0x00,0xcf,0x86,0x55,0x05,0x07,0xff,0x00,0x14,0x05,0x07,0xff,0x00, + 0x00,0xff,0x00,0xcf,0x06,0x00,0xff,0x00,0xcf,0x06,0x00,0xff,0x00,0xcf,0x06,0x00, + 0xff,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86, + 0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd1,0x08,0xcf,0x86, + 0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x06, + 0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00, + 0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06, + 0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00, + 0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xcf,0x86,0xcf,0x06,0x02,0x00, + 0x81,0x80,0xcf,0x86,0x85,0x84,0xcf,0x86,0xcf,0x06,0x02,0x00,0x00,0x00,0x00,0x00 +}; diff --git a/include/e2fsprogs/ext2fs/utf8n.h b/include/e2fsprogs/ext2fs/utf8n.h new file mode 100755 index 0000000..c214f58 --- /dev/null +++ b/include/e2fsprogs/ext2fs/utf8n.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 SGI. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* This code is copied from the linux kernel. We have a userspace + * version here to such that hashes will match that implementation. + */ + +#ifndef UTF8NORM_H +#define UTF8NORM_H + +#include +#include +#include + +/* Encoding a unicode version number as a single unsigned int. */ +#define UNICODE_MAJ_SHIFT (16) +#define UNICODE_MIN_SHIFT (8) + +#define UNICODE_AGE(MAJ, MIN, REV) \ + (((unsigned int)(MAJ) << UNICODE_MAJ_SHIFT) | \ + ((unsigned int)(MIN) << UNICODE_MIN_SHIFT) | \ + ((unsigned int)(REV))) + +/* Highest unicode version supported by the data tables. */ +extern int utf8version_is_supported(uint8_t maj, uint8_t min, uint8_t rev); +extern int utf8version_latest(void); + +/* + * Look for the correct const struct utf8data for a unicode version. + * Returns NULL if the version requested is too new. + * + * Two normalization forms are supported: nfdi and nfdicf. + * + * nfdi: + * - Apply unicode normalization form NFD. + * - Remove any Default_Ignorable_Code_Point. + * + * nfdicf: + * - Apply unicode normalization form NFD. + * - Remove any Default_Ignorable_Code_Point. + * - Apply a full casefold (C + F). + */ +extern const struct utf8data *utf8nfdi(unsigned int maxage); +extern const struct utf8data *utf8nfdicf(unsigned int maxage); + +/* + * Determine the maximum age of any unicode character in the string. + * Returns 0 if only unassigned code points are present. + * Returns -1 if the input is not valid UTF-8. + */ +extern int utf8agemax(const struct utf8data *data, const char *s); +extern int utf8nagemax(const struct utf8data *data, const char *s, size_t len); + +/* + * Determine the minimum age of any unicode character in the string. + * Returns 0 if any unassigned code points are present. + * Returns -1 if the input is not valid UTF-8. + */ +extern int utf8agemin(const struct utf8data *data, const char *s); +extern int utf8nagemin(const struct utf8data *data, const char *s, size_t len); + +/* + * Determine the length of the normalized from of the string, + * excluding any terminating NULL byte. + * Returns 0 if only ignorable code points are present. + * Returns -1 if the input is not valid UTF-8. + */ +extern ssize_t utf8len(const struct utf8data *data, const char *s); +extern ssize_t utf8nlen(const struct utf8data *data, const char *s, size_t len); + +/* Needed in struct utf8cursor below. */ +#define UTF8HANGULLEAF (12) + +/* + * Cursor structure used by the normalizer. + */ +struct utf8cursor { + const struct utf8data *data; + const char *s; + const char *p; + const char *ss; + const char *sp; + unsigned int len; + unsigned int slen; + short int ccc; + short int nccc; + unsigned char hangul[UTF8HANGULLEAF]; +}; + +/* + * Initialize a utf8cursor to normalize a string. + * Returns 0 on success. + * Returns -1 on failure. + */ +extern int utf8cursor(struct utf8cursor *u8c, const struct utf8data *data, + const char *s); +extern int utf8ncursor(struct utf8cursor *u8c, const struct utf8data *data, + const char *s, size_t len); + +/* + * Get the next byte in the normalization. + * Returns a value > 0 && < 256 on success. + * Returns 0 when the end of the normalization is reached. + * Returns -1 if the string being normalized is not valid UTF-8. + */ +extern int utf8byte(struct utf8cursor *u8c); + +#endif /* UTF8NORM_H */ diff --git a/include/e2fsprogs/magic.h b/include/e2fsprogs/magic.h new file mode 100755 index 0000000..29961f3 --- /dev/null +++ b/include/e2fsprogs/magic.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) Christos Zoulas 2003. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _MAGIC_H +#define _MAGIC_H + +#include + +#define MAGIC_NONE 0x0000000 /* No flags */ +#define MAGIC_DEBUG 0x0000001 /* Turn on debugging */ +#define MAGIC_SYMLINK 0x0000002 /* Follow symlinks */ +#define MAGIC_COMPRESS 0x0000004 /* Check inside compressed files */ +#define MAGIC_DEVICES 0x0000008 /* Look at the contents of devices */ +#define MAGIC_MIME_TYPE 0x0000010 /* Return the MIME type */ +#define MAGIC_CONTINUE 0x0000020 /* Return all matches */ +#define MAGIC_CHECK 0x0000040 /* Print warnings to stderr */ +#define MAGIC_PRESERVE_ATIME 0x0000080 /* Restore access time on exit */ +#define MAGIC_RAW 0x0000100 /* Don't convert unprintable chars */ +#define MAGIC_ERROR 0x0000200 /* Handle ENOENT etc as real errors */ +#define MAGIC_MIME_ENCODING 0x0000400 /* Return the MIME encoding */ +#define MAGIC_MIME (MAGIC_MIME_TYPE|MAGIC_MIME_ENCODING) +#define MAGIC_APPLE 0x0000800 /* Return the Apple creator/type */ +#define MAGIC_EXTENSION 0x1000000 /* Return a /-separated list of + * extensions */ +#define MAGIC_COMPRESS_TRANSP 0x2000000 /* Check inside compressed files + * but not report compression */ +#define MAGIC_NO_COMPRESS_FORK 0x4000000 /* Don't allow decompression that + * needs to fork */ +#define MAGIC_NODESC (MAGIC_EXTENSION|MAGIC_MIME|MAGIC_APPLE) + +#define MAGIC_NO_CHECK_COMPRESS 0x0001000 /* Don't check for compressed files */ +#define MAGIC_NO_CHECK_TAR 0x0002000 /* Don't check for tar files */ +#define MAGIC_NO_CHECK_SOFT 0x0004000 /* Don't check magic entries */ +#define MAGIC_NO_CHECK_APPTYPE 0x0008000 /* Don't check application type */ +#define MAGIC_NO_CHECK_ELF 0x0010000 /* Don't check for elf details */ +#define MAGIC_NO_CHECK_TEXT 0x0020000 /* Don't check for text files */ +#define MAGIC_NO_CHECK_CDF 0x0040000 /* Don't check for cdf files */ +#define MAGIC_NO_CHECK_CSV 0x0080000 /* Don't check for CSV files */ +#define MAGIC_NO_CHECK_TOKENS 0x0100000 /* Don't check tokens */ +#define MAGIC_NO_CHECK_ENCODING 0x0200000 /* Don't check text encodings */ +#define MAGIC_NO_CHECK_JSON 0x0400000 /* Don't check for JSON files */ +#define MAGIC_NO_CHECK_SIMH 0x0800000 /* Don't check for SIMH tape files */ + +/* No built-in tests; only consult the magic file */ +#define MAGIC_NO_CHECK_BUILTIN ( \ + MAGIC_NO_CHECK_COMPRESS | \ + MAGIC_NO_CHECK_TAR | \ +/* MAGIC_NO_CHECK_SOFT | */ \ + MAGIC_NO_CHECK_APPTYPE | \ + MAGIC_NO_CHECK_ELF | \ + MAGIC_NO_CHECK_TEXT | \ + MAGIC_NO_CHECK_CSV | \ + MAGIC_NO_CHECK_CDF | \ + MAGIC_NO_CHECK_TOKENS | \ + MAGIC_NO_CHECK_ENCODING | \ + MAGIC_NO_CHECK_JSON | \ + MAGIC_NO_CHECK_SIMH | \ + 0 \ +) + +#define MAGIC_SNPRINTB "\177\020\ +b\0debug\0\ +b\1symlink\0\ +b\2compress\0\ +b\3devices\0\ +b\4mime_type\0\ +b\5continue\0\ +b\6check\0\ +b\7preserve_atime\0\ +b\10raw\0\ +b\11error\0\ +b\12mime_encoding\0\ +b\13apple\0\ +b\14no_check_compress\0\ +b\15no_check_tar\0\ +b\16no_check_soft\0\ +b\17no_check_sapptype\0\ +b\20no_check_elf\0\ +b\21no_check_text\0\ +b\22no_check_cdf\0\ +b\23no_check_csv\0\ +b\24no_check_tokens\0\ +b\25no_check_encoding\0\ +b\26no_check_json\0\ +b\27no_check_simh\0\ +b\30extension\0\ +b\31transp_compression\0\ +" + +/* Defined for backwards compatibility (renamed) */ +#define MAGIC_NO_CHECK_ASCII MAGIC_NO_CHECK_TEXT + +/* Defined for backwards compatibility; do nothing */ +#define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */ +#define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */ + +#define MAGIC_VERSION 545 /* This implementation */ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct magic_set *magic_t; +magic_t magic_open(int); +void magic_close(magic_t); + +const char *magic_getpath(const char *, int); +const char *magic_file(magic_t, const char *); +const char *magic_descriptor(magic_t, int); +const char *magic_buffer(magic_t, const void *, size_t); + +const char *magic_error(magic_t); +int magic_getflags(magic_t); +int magic_setflags(magic_t, int); + +int magic_version(void); +int magic_load(magic_t, const char *); +int magic_load_buffers(magic_t, void **, size_t *, size_t); + +int magic_compile(magic_t, const char *); +int magic_check(magic_t, const char *); +int magic_list(magic_t, const char *); +int magic_errno(magic_t); + +#define MAGIC_PARAM_INDIR_MAX 0 +#define MAGIC_PARAM_NAME_MAX 1 +#define MAGIC_PARAM_ELF_PHNUM_MAX 2 +#define MAGIC_PARAM_ELF_SHNUM_MAX 3 +#define MAGIC_PARAM_ELF_NOTES_MAX 4 +#define MAGIC_PARAM_REGEX_MAX 5 +#define MAGIC_PARAM_BYTES_MAX 6 +#define MAGIC_PARAM_ENCODING_MAX 7 +#define MAGIC_PARAM_ELF_SHSIZE_MAX 8 + +int magic_setparam(magic_t, int, const void *); +int magic_getparam(magic_t, int, void *); + +#ifdef __cplusplus +}; +#endif + +#endif /* _MAGIC_H */ diff --git a/include/e2fsprogs/misc/create_inode.h b/include/e2fsprogs/misc/create_inode.h new file mode 100755 index 0000000..b5eeb42 --- /dev/null +++ b/include/e2fsprogs/misc/create_inode.h @@ -0,0 +1,57 @@ +#ifndef _CREATE_INODE_H +#define _CREATE_INODE_H + +#include +#include +#include +#include "et/com_err.h" +#include "e2p/e2p.h" +#include "ext2fs/ext2fs.h" + +struct hdlink_s +{ + dev_t src_dev; + ino_t src_ino; + ext2_ino_t dst_ino; +}; + +struct hdlinks_s +{ + int count; + int size; + struct hdlink_s *hdl; +}; + +#define HDLINK_CNT (4) + +struct fs_ops_callbacks { + errcode_t (* create_new_inode)(ext2_filsys fs, const char *target_path, + const char *name, ext2_ino_t parent_ino, ext2_ino_t root, + mode_t mode); + errcode_t (* end_create_new_inode)(ext2_filsys fs, + const char *target_path, const char *name, + ext2_ino_t parent_ino, ext2_ino_t root, mode_t mode); +}; + +extern int no_copy_xattrs; /* this should eventually be a flag + passed to populate_fs3() */ + +/* For populating the filesystem */ +extern errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, + const char *source_dir, ext2_ino_t root); +extern errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino, + const char *source_dir, ext2_ino_t root, + struct fs_ops_callbacks *fs_callbacks); +extern errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, + const char *name, unsigned int st_mode, + unsigned int st_rdev); +extern errcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd, + const char *name, char *target, + ext2_ino_t root); +extern errcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd, + const char *name, ext2_ino_t root); +extern errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, + const char *src, const char *dest, + ext2_ino_t root); + +#endif /* _CREATE_INODE_H */ diff --git a/include/e2fsprogs/misc/mke2fs.h b/include/e2fsprogs/misc/mke2fs.h new file mode 100755 index 0000000..ce72cb3 --- /dev/null +++ b/include/e2fsprogs/misc/mke2fs.h @@ -0,0 +1,30 @@ +/* + * mke2fs.h + * + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + * 2003, 2004, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* mke2fs.c */ +extern const char * program_name; +extern int quiet; +extern int verbose; +extern int zero_hugefile; +extern char **fs_types; + +extern char *get_string_from_profile(char **types, const char *opt, + const char *def_val); +extern int get_int_from_profile(char **types, const char *opt, int def_val); +extern int get_bool_from_profile(char **types, const char *opt, int def_val); +extern int int_log10(unsigned long long arg); + +/* mk_hugefiles.c */ +extern errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name); + + + diff --git a/include/e2fsprogs/misc/util.h b/include/e2fsprogs/misc/util.h new file mode 100755 index 0000000..ccdc7fb --- /dev/null +++ b/include/e2fsprogs/misc/util.h @@ -0,0 +1,29 @@ +/* + * util.h --- header file defining prototypes for helper functions + * used by tune2fs and mke2fs + * + * Copyright 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +extern int journal_size; +extern int journal_fc_size; +extern int journal_flags; +extern char *journal_device; +extern char *journal_location_string; + +#ifndef HAVE_STRCASECMP +extern int strcasecmp (char *s1, char *s2); +#endif +extern char *get_progname(char *argv_zero); +extern void proceed_question(int delay); +extern void parse_journal_opts(const char *opts); +extern void check_mount(const char *device, int force, const char *type); +extern void figure_journal_size(struct ext2fs_journal_params *jparams, + int requested_j_size, int requested_fc_size, ext2_filsys fs); +extern void print_check_message(int, unsigned int); +extern void dump_mmp_msg(struct mmp_struct *mmp, const char *msg); diff --git a/include/e2fsprogs/support/argv_parse.h b/include/e2fsprogs/support/argv_parse.h new file mode 100755 index 0000000..86f4564 --- /dev/null +++ b/include/e2fsprogs/support/argv_parse.h @@ -0,0 +1,43 @@ +/* + * argv_parse.h --- header file for the argv parser. + * + * This file defines the interface for the functions argv_parse() and + * argv_free(). + * + *********************************************************************** + * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv) + * + * This function takes as its first argument a string which it will + * parse into an argv argument vector, with each white-space separated + * word placed into its own slot in the argv. This function handles + * double quotes and backslashes so that the parsed words can contain + * special characters. The count of the number words found in the + * parsed string, as well as the argument vector, are returned into + * ret_argc and ret_argv, respectively. + *********************************************************************** + * extern void argv_free(char **argv); + * + * This function frees the argument vector created by argv_parse(). + *********************************************************************** + * + * Copyright 1999 by Theodore Ts'o. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose with or without fee is hereby granted, provided that + * the above copyright notice and this permission notice appear in all + * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + * it sick that the U.S. culture of lawsuit-happy lawyers requires + * this kind of disclaimer?) + * + * Version 1.1, modified 2/27/1999 + */ + +extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv); +extern void argv_free(char **argv); diff --git a/include/e2fsprogs/support/common.h b/include/e2fsprogs/support/common.h new file mode 100755 index 0000000..00a9375 --- /dev/null +++ b/include/e2fsprogs/support/common.h @@ -0,0 +1,36 @@ +/* + * + * Various things common for all utilities + * + */ + +#ifndef __QUOTA_COMMON_H__ +#define __QUOTA_COMMON_H__ + +#if EXT2_FLAT_INCLUDES +#include "e2_types.h" +#else +#include +#endif /* EXT2_FLAT_INCLUDES */ + +/* #define DEBUG_QUOTA 1 */ + +#ifndef __attribute__ +# if !defined __GNUC__ || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif +#endif + +#define log_err(format, arg ...) \ + fprintf(stderr, "[ERROR] %s:%d:%s: " format "\n", \ + __FILE__, __LINE__, __func__, ## arg) + +#ifdef DEBUG_QUOTA +# define log_debug(format, arg ...) \ + fprintf(stderr, "[DEBUG] %s:%d:%s: " format "\n", \ + __FILE__, __LINE__, __func__, ## arg) +#else +# define log_debug(...) +#endif + +#endif /* __QUOTA_COMMON_H__ */ diff --git a/include/e2fsprogs/support/cstring.h b/include/e2fsprogs/support/cstring.h new file mode 100755 index 0000000..7f80f41 --- /dev/null +++ b/include/e2fsprogs/support/cstring.h @@ -0,0 +1,6 @@ +/* + * cstring.h -- header file for C string parse/print utilities + */ + +extern int parse_c_string(char *str); +extern void print_c_string(FILE *f, const char *cp, int len); diff --git a/include/e2fsprogs/support/devname.h b/include/e2fsprogs/support/devname.h new file mode 100755 index 0000000..cc19561 --- /dev/null +++ b/include/e2fsprogs/support/devname.h @@ -0,0 +1,19 @@ +/* + * devname.c --- Figure out if a pathname is ext* or something else. + * + * Copyright (C) 2022 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef DEVNAME_H_ +#define DEVNAME_H_ + +#include "blkid/blkid.h" + +char *get_devname(blkid_cache cache, const char *token, const char *value); + +#endif /* DEVNAME_H_ */ diff --git a/include/e2fsprogs/support/dict.h b/include/e2fsprogs/support/dict.h new file mode 100755 index 0000000..2d87cc0 --- /dev/null +++ b/include/e2fsprogs/support/dict.h @@ -0,0 +1,147 @@ +/* + * Dictionary Abstract Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $ + * $Name: kazlib_1_20 $ + * The work has been modified. + */ + +#ifndef DICT_H +#define DICT_H + +#include +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#include "sfx.h" +#endif + +/* + * Blurb for inclusion into C++ translation units + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long dictcount_t; +#define DICTCOUNT_T_MAX ULONG_MAX + +/* + * The dictionary is implemented as a red-black tree + */ + +typedef enum { dnode_red, dnode_black } dnode_color_t; + +typedef struct dnode_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + struct dnode_t *dict_left; + struct dnode_t *dict_right; + struct dnode_t *dict_parent; + dnode_color_t dict_color; + const void *dict_key; + void *dict_data; +#else + int dict_dummy; +#endif +} dnode_t; + +typedef int (*dict_comp_t)(const void *, const void *, const void *); +typedef dnode_t *(*dnode_alloc_t)(void *); +typedef void (*dnode_free_t)(dnode_t *, void *); + +typedef struct dict_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + dnode_t dict_nilnode; + dictcount_t dict_nodecount; + dictcount_t dict_maxcount; + dict_comp_t dict_compare; + dnode_alloc_t dict_allocnode; + dnode_free_t dict_freenode; + void *dict_context; + const void *cmp_ctx; + int dict_dupes; +#else + int dict_dummmy; +#endif +} dict_t; + +typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); + +typedef struct dict_load_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + dict_t *dict_dictptr; + dnode_t dict_nilnode; +#else + int dict_dummmy; +#endif +} dict_load_t; + +extern dict_t *dict_create(dictcount_t, dict_comp_t); +extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *); +extern void dict_set_cmp_context(dict_t *, const void *); +extern void dict_destroy(dict_t *); +extern void dict_free_nodes(dict_t *); +extern void dict_free(dict_t *); +extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t); +extern void dict_init_like(dict_t *, const dict_t *); +extern int dict_verify(dict_t *); +extern int dict_similar(const dict_t *, const dict_t *); +extern dnode_t *dict_lookup(dict_t *, const void *); +extern dnode_t *dict_lower_bound(dict_t *, const void *); +extern dnode_t *dict_upper_bound(dict_t *, const void *); +extern void dict_insert(dict_t *, dnode_t *, const void *); +extern dnode_t *dict_delete(dict_t *, dnode_t *); +extern int dict_alloc_insert(dict_t *, const void *, void *); +extern void dict_delete_free(dict_t *, dnode_t *); +extern dnode_t *dict_first(dict_t *); +extern dnode_t *dict_last(dict_t *); +extern dnode_t *dict_next(dict_t *, dnode_t *); +extern dnode_t *dict_prev(dict_t *, dnode_t *); +extern dictcount_t dict_count(dict_t *); +extern int dict_isempty(dict_t *); +extern int dict_isfull(dict_t *); +extern int dict_contains(dict_t *, dnode_t *); +extern void dict_allow_dupes(dict_t *); +extern int dnode_is_in_a_dict(dnode_t *); +extern dnode_t *dnode_create(void *); +extern dnode_t *dnode_init(dnode_t *, void *); +extern void dnode_destroy(dnode_t *); +extern void *dnode_get(dnode_t *); +extern const void *dnode_getkey(dnode_t *); +extern void dnode_put(dnode_t *, void *); +extern void dict_process(dict_t *, void *, dnode_process_t); +extern void dict_load_begin(dict_load_t *, dict_t *); +extern void dict_load_next(dict_load_t *, dnode_t *, const void *); +extern void dict_load_end(dict_load_t *); +extern void dict_merge(dict_t *, dict_t *); + +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount) +#else +#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount) +#endif +#define dict_count(D) ((D)->dict_nodecount) +#define dict_isempty(D) ((D)->dict_nodecount == 0) +#define dnode_get(N) ((N)->dict_data) +#define dnode_getkey(N) ((N)->dict_key) +#define dnode_put(N, X) ((N)->dict_data = (X)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/e2fsprogs/support/dqblk_v2.h b/include/e2fsprogs/support/dqblk_v2.h new file mode 100755 index 0000000..d12512a --- /dev/null +++ b/include/e2fsprogs/support/dqblk_v2.h @@ -0,0 +1,31 @@ +/* + * Header file for disk format of new quotafile format + * + * Jan Kara - sponsored by SuSE CR + */ + +#ifndef __QUOTA_DQBLK_V2_H__ +#define __QUOTA_DQBLK_V2_H__ + +#include "quotaio_tree.h" + +/* Structure for format specific information */ +struct v2_mem_dqinfo { + struct qtree_mem_dqinfo dqi_qtree; + unsigned int dqi_flags; /* Flags set in quotafile */ + unsigned int dqi_used_entries; /* Number of entries in file - + updated by scan_dquots */ + unsigned int dqi_data_blocks; /* Number of data blocks in file - + updated by scan_dquots */ +}; + +struct v2_mem_dqblk { + long long dqb_off; /* Offset of dquot in file */ +}; + +struct quotafile_ops; /* Will be defined later in quotaio.h */ + +/* Operations above this format */ +extern struct quotafile_ops quotafile_ops_2; + +#endif /* __QUOTA_DQBLK_V2_H__ */ diff --git a/include/e2fsprogs/support/nls-enable.h b/include/e2fsprogs/support/nls-enable.h new file mode 100755 index 0000000..2f62c01 --- /dev/null +++ b/include/e2fsprogs/support/nls-enable.h @@ -0,0 +1,21 @@ +#if defined(ENABLE_NLS) && !defined(DEBUGFS) +#include +#include +#define _(a) (gettext (a)) +#ifdef gettext_noop +#define N_(a) gettext_noop (a) +#else +#define N_(a) (a) +#endif +#define P_(singular, plural, n) (ngettext (singular, plural, n)) +#ifndef NLS_CAT_NAME +#define NLS_CAT_NAME "e2fsprogs" +#endif +#ifndef LOCALEDIR +#define LOCALEDIR "/usr/share/locale" +#endif +#else +#define _(a) (a) +#define N_(a) a +#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural)) +#endif diff --git a/include/e2fsprogs/support/plausible.h b/include/e2fsprogs/support/plausible.h new file mode 100755 index 0000000..b85150c --- /dev/null +++ b/include/e2fsprogs/support/plausible.h @@ -0,0 +1,29 @@ +/* + * plausible.h --- header file defining prototypes for helper functions + * used by tune2fs and mke2fs + * + * Copyright 2014 by Oracle, Inc. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef PLAUSIBLE_H_ +#define PLAUSIBLE_H_ + +/* + * Flags for check_plausibility() + */ +#define CHECK_BLOCK_DEV 0x0001 +#define CREATE_FILE 0x0002 +#define CHECK_FS_EXIST 0x0004 +#define VERBOSE_CREATE 0x0008 +#define NO_SIZE 0x0010 +#define QUIET_CHECK 0x0020 + +extern int check_plausibility(const char *device, int flags, + int *ret_is_dev); + +#endif /* PLAUSIBLE_H_ */ diff --git a/include/e2fsprogs/support/print_fs_flags.h b/include/e2fsprogs/support/print_fs_flags.h new file mode 100755 index 0000000..bdd58a0 --- /dev/null +++ b/include/e2fsprogs/support/print_fs_flags.h @@ -0,0 +1,5 @@ +/* + * print_flags.h -- header file for printing the fs flags + */ + +void print_fs_flags(FILE * f, unsigned long flags); diff --git a/include/e2fsprogs/support/prof_err.h b/include/e2fsprogs/support/prof_err.h new file mode 100755 index 0000000..e8066dd --- /dev/null +++ b/include/e2fsprogs/support/prof_err.h @@ -0,0 +1,49 @@ +/* + * prof_err.h: + * This file is automatically generated; please do not edit it. + */ + +#include + +#define PROF_VERSION (-1429577728L) +#define PROF_MAGIC_NODE (-1429577727L) +#define PROF_NO_SECTION (-1429577726L) +#define PROF_NO_RELATION (-1429577725L) +#define PROF_ADD_NOT_SECTION (-1429577724L) +#define PROF_SECTION_WITH_VALUE (-1429577723L) +#define PROF_BAD_LINK_LIST (-1429577722L) +#define PROF_BAD_GROUP_LVL (-1429577721L) +#define PROF_BAD_PARENT_PTR (-1429577720L) +#define PROF_MAGIC_ITERATOR (-1429577719L) +#define PROF_SET_SECTION_VALUE (-1429577718L) +#define PROF_EINVAL (-1429577717L) +#define PROF_READ_ONLY (-1429577716L) +#define PROF_SECTION_NOTOP (-1429577715L) +#define PROF_SECTION_SYNTAX (-1429577714L) +#define PROF_RELATION_SYNTAX (-1429577713L) +#define PROF_EXTRA_CBRACE (-1429577712L) +#define PROF_MISSING_OBRACE (-1429577711L) +#define PROF_MAGIC_PROFILE (-1429577710L) +#define PROF_MAGIC_SECTION (-1429577709L) +#define PROF_TOPSECTION_ITER_NOSUPP (-1429577708L) +#define PROF_INVALID_SECTION (-1429577707L) +#define PROF_END_OF_SECTIONS (-1429577706L) +#define PROF_BAD_NAMESET (-1429577705L) +#define PROF_NO_PROFILE (-1429577704L) +#define PROF_MAGIC_FILE (-1429577703L) +#define PROF_FAIL_OPEN (-1429577702L) +#define PROF_EXISTS (-1429577701L) +#define PROF_BAD_BOOLEAN (-1429577700L) +#define PROF_BAD_INTEGER (-1429577699L) +#define PROF_MAGIC_FILE_DATA (-1429577698L) +extern const struct error_table et_prof_error_table; +extern void initialize_prof_error_table(void); + +/* For compatibility with Heimdal */ +extern void initialize_prof_error_table_r(struct et_list **list); + +#define ERROR_TABLE_BASE_prof (-1429577728L) + +/* for compatibility with older versions... */ +#define init_prof_err_tbl initialize_prof_error_table +#define prof_err_base ERROR_TABLE_BASE_prof diff --git a/include/e2fsprogs/support/profile.h b/include/e2fsprogs/support/profile.h new file mode 100755 index 0000000..aec870a --- /dev/null +++ b/include/e2fsprogs/support/profile.h @@ -0,0 +1,107 @@ +/* + * profile.h + * + * Copyright (C) 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original MIT software. + * M.I.T. makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef _PROFILE_H +#define _PROFILE_H + +typedef struct _profile_t *profile_t; + +typedef void (*profile_syntax_err_cb_t)(const char *file, long err, + int line_num); + +/* + * Used by the profile iterator in prof_get.c + */ +#define PROFILE_ITER_LIST_SECTION 0x0001 +#define PROFILE_ITER_SECTIONS_ONLY 0x0002 +#define PROFILE_ITER_RELATIONS_ONLY 0x0004 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +long profile_init + (const char * const *files, profile_t *ret_profile); + +void profile_release + (profile_t profile); + +long profile_set_default + (profile_t profile, const char *def_string); + +long profile_get_string + (profile_t profile, const char *name, const char *subname, + const char *subsubname, const char *def_val, + char **ret_string); +long profile_get_integer + (profile_t profile, const char *name, const char *subname, + const char *subsubname, int def_val, + int *ret_default); + +long profile_get_uint + (profile_t profile, const char *name, const char *subname, + const char *subsubname, unsigned int def_val, + unsigned int *ret_int); + +long profile_get_double + (profile_t profile, const char *name, const char *subname, + const char *subsubname, double def_val, + double *ret_float); + +long profile_get_boolean + (profile_t profile, const char *name, const char *subname, + const char *subsubname, int def_val, + int *ret_default); + +long profile_iterator_create + (profile_t profile, const char *const *names, + int flags, void **ret_iter); + +void profile_iterator_free + (void **iter_p); + +long profile_iterator + (void **iter_p, char **ret_name, char **ret_value); + +profile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _KRB5_H */ diff --git a/include/e2fsprogs/support/profile_helpers.h b/include/e2fsprogs/support/profile_helpers.h new file mode 100755 index 0000000..af63ca5 --- /dev/null +++ b/include/e2fsprogs/support/profile_helpers.h @@ -0,0 +1,28 @@ +/* + * profile_helpers.h -- Function prototypes for profile helper functions + * + * Copyright (C) 2006 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +long profile_get_values + (profile_t profile, const char *const *names, char ***ret_values); + +void profile_free_list + (char **list); + +long profile_get_relation_names + (profile_t profile, const char **names, char ***ret_names); + +long profile_get_subsection_names + (profile_t profile, const char **names, char ***ret_names); + +void profile_release_string (char *str); + +long profile_init_path + (const char * filelist, profile_t *ret_profile); + diff --git a/include/e2fsprogs/support/quotaio.h b/include/e2fsprogs/support/quotaio.h new file mode 100755 index 0000000..84fac35 --- /dev/null +++ b/include/e2fsprogs/support/quotaio.h @@ -0,0 +1,268 @@ +/** quotaio.h + * + * Interface to the quota library. + * + * The quota library provides interface for creating and updating the quota + * files and the ext4 superblock fields. It supports the new VFS_V1 quota + * format. The quota library also provides support for keeping track of quotas + * in memory. + * The typical way to use the quota library is as follows: + * { + * quota_ctx_t qctx; + * + * quota_init_context(&qctx, fs, QUOTA_ALL_BIT); + * { + * quota_compute_usage(qctx); + * AND/OR + * quota_data_add/quota_data_sub/quota_data_inodes(); + * } + * quota_write_inode(qctx, USRQUOTA); + * quota_write_inode(qctx, GRPQUOTA); + * quota_release_context(&qctx); + * } + * + * This initial version does not support reading the quota files. This support + * will be added in near future. + * + * Aditya Kali + * Header of IO operations for quota utilities + * + * Jan Kara + */ + +#ifndef GUARD_QUOTAIO_H +#define GUARD_QUOTAIO_H + +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "dqblk_v2.h" + +typedef int64_t qsize_t; /* Type in which we store size limitations */ + +enum quota_type { + USRQUOTA = 0, + GRPQUOTA = 1, + PRJQUOTA = 2, + MAXQUOTAS = 3, +}; + +#if MAXQUOTAS > 32 +#error "cannot have more than 32 quota types to fit in qtype_bits" +#endif + +#define QUOTA_USR_BIT (1 << USRQUOTA) +#define QUOTA_GRP_BIT (1 << GRPQUOTA) +#define QUOTA_PRJ_BIT (1 << PRJQUOTA) +#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT | QUOTA_PRJ_BIT) + +typedef struct quota_ctx *quota_ctx_t; +struct dict_t; + +struct quota_ctx { + ext2_filsys fs; + struct dict_t *quota_dict[MAXQUOTAS]; + struct quota_handle *quota_file[MAXQUOTAS]; +}; + +/* + * Definitions of magics and versions of current quota files + */ +#define INITQMAGICS {\ + 0xd9c01f11, /* USRQUOTA */\ + 0xd9c01927, /* GRPQUOTA */\ + 0xd9c03f14 /* PRJQUOTA */\ +} + +/* Size of blocks in which are counted size limits in generic utility parts */ +#define QUOTABLOCK_BITS 10 +#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS) +#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS) + +/* Quota format type IDs */ +#define QFMT_VFS_OLD 1 +#define QFMT_VFS_V0 2 +#define QFMT_VFS_V1 4 + +/* + * The following constants define the default amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +#define IOFL_INFODIRTY 0x01 /* Did info change? */ + +struct quotafile_ops; + +/* Generic information about quotafile */ +struct util_dqinfo { + time_t dqi_bgrace; /* Block grace time for given quotafile */ + time_t dqi_igrace; /* Inode grace time for given quotafile */ + union { + struct v2_mem_dqinfo v2_mdqi; + } u; /* Format specific info about quotafile */ +}; + +struct quota_file { + ext2_filsys fs; + ext2_ino_t ino; + ext2_file_t e2_file; +}; + +/* Structure for one opened quota file */ +struct quota_handle { + enum quota_type qh_type; /* Type of quotafile */ + int qh_fmt; /* Quotafile format */ + int qh_file_flags; + int qh_io_flags; /* IO flags for file */ + struct quota_file qh_qf; + unsigned int (*e2fs_read)(struct quota_file *qf, ext2_loff_t offset, + void *buf, unsigned int size); + unsigned int (*e2fs_write)(struct quota_file *qf, ext2_loff_t offset, + void *buf, unsigned int size); + struct quotafile_ops *qh_ops; /* Operations on quotafile */ + struct util_dqinfo qh_info; /* Generic quotafile info */ +}; + +/* Utility quota block */ +struct util_dqblk { + qsize_t dqb_ihardlimit; + qsize_t dqb_isoftlimit; + qsize_t dqb_curinodes; + qsize_t dqb_bhardlimit; + qsize_t dqb_bsoftlimit; + qsize_t dqb_curspace; + time_t dqb_btime; + time_t dqb_itime; + union { + struct v2_mem_dqblk v2_mdqb; + } u; /* Format specific dquot information */ +}; + +/* Structure for one loaded quota */ +struct dquot { + struct dquot *dq_next; /* Pointer to next dquot in the list */ + qid_t dq_id; /* ID dquot belongs to */ + int dq_flags; /* Some flags for utils */ + struct quota_handle *dq_h; /* Handle of quotafile for this dquot */ + struct util_dqblk dq_dqb; /* Parsed data of dquot */ +}; + +#define DQF_SEEN 0x0001 + +/* Structure of quotafile operations */ +struct quotafile_ops { + /* Check whether quotafile is in our format */ + int (*check_file) (struct quota_handle *h, int type, int fmt); + /* Open quotafile */ + int (*init_io) (struct quota_handle *h); + /* Create new quotafile */ + int (*new_io) (struct quota_handle *h); + /* Write all changes and close quotafile */ + int (*end_io) (struct quota_handle *h); + /* Write info about quotafile */ + int (*write_info) (struct quota_handle *h); + /* Read dquot into memory */ + struct dquot *(*read_dquot) (struct quota_handle *h, qid_t id); + /* Write given dquot to disk */ + int (*commit_dquot) (struct dquot *dquot); + /* Scan quotafile and call callback on every structure */ + int (*scan_dquots) (struct quota_handle *h, + int (*process_dquot) (struct dquot *dquot, + void *data), + void *data); + /* Function to print format specific file information */ + int (*report) (struct quota_handle *h, int verbose); +}; + +/* This might go into a special header file but that sounds a bit silly... */ +extern struct quotafile_ops quotafile_ops_meta; + +/* Open existing quotafile of given type (and verify its format) on given + * filesystem. */ +errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h, + ext2_ino_t qf_ino, enum quota_type type, + int fmt, int flags); + + +/* Create new quotafile of specified format on given filesystem */ +errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, + enum quota_type qtype, int fmt); + +/* Close quotafile */ +errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h); + +/* Get empty quota structure */ +struct dquot *get_empty_dquot(void); + +errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino); + +const char *quota_type2name(enum quota_type qtype); +ext2_ino_t quota_type2inum(enum quota_type qtype, struct ext2_super_block *); + +void update_grace_times(struct dquot *q); + +/* size for the buffer returned by quota_get_qf_name(); must be greater + than maxlen of extensions[] and fmtnames[] (plus 2) found in quotaio.c */ +#define QUOTA_NAME_LEN 16 + +const char *quota_get_qf_name(enum quota_type, int fmt, char *buf); + +/* In mkquota.c */ +errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, + unsigned int qtype_bits); +void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino, int adjust); +void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino, qsize_t space); +void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino, qsize_t space); +errcode_t quota_write_inode(quota_ctx_t qctx, enum quota_type qtype); +/* Flags for quota_read_all_dquots() */ +#define QREAD_USAGE 0x01 +#define QREAD_LIMITS 0x02 +errcode_t quota_read_all_dquots(quota_ctx_t qctx, ext2_ino_t qf_ino, + enum quota_type type, unsigned int flags); +errcode_t quota_compute_usage(quota_ctx_t qctx); +void quota_release_context(quota_ctx_t *qctx); +errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype); +int quota_file_exists(ext2_filsys fs, enum quota_type qtype); +void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype); +errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype, + int *usage_inconsistent); +int parse_quota_opts(const char *opts, int (*func)(char *)); + +/* parse_qtype.c */ +int parse_quota_types(const char *in_str, unsigned int *qtype_bits, + char **err_token); + +/* + * Return pointer to reserved inode field in superblock for given quota type. + * + * This allows the caller to get or set the quota inode by type without the + * need for the quota array to be contiguous in the superblock. + */ +static inline ext2_ino_t *quota_sb_inump(struct ext2_super_block *sb, + enum quota_type qtype) +{ + switch (qtype) { + case USRQUOTA: + return &sb->s_usr_quota_inum; + case GRPQUOTA: + return &sb->s_grp_quota_inum; + case PRJQUOTA: + return &sb->s_prj_quota_inum; + default: + return NULL; + } + + return NULL; +} + +#endif /* GUARD_QUOTAIO_H */ diff --git a/include/e2fsprogs/support/quotaio_tree.h b/include/e2fsprogs/support/quotaio_tree.h new file mode 100755 index 0000000..b0b7257 --- /dev/null +++ b/include/e2fsprogs/support/quotaio_tree.h @@ -0,0 +1,64 @@ +/* + * Definitions of structures for vfsv0 quota format + */ + +#ifndef _LINUX_QUOTA_TREE_H +#define _LINUX_QUOTA_TREE_H + +#include + +typedef __u32 qid_t; /* Type in which we store ids in memory */ + +#define QT_TREEOFF 1 /* Offset of tree in file in blocks */ +#define QT_TREEDEPTH 4 /* Depth of quota tree */ +#define QT_BLKSIZE_BITS 10 +#define QT_BLKSIZE (1 << QT_BLKSIZE_BITS) /* Size of block with quota + * structures */ + +/* + * Structure of header of block with quota structures. It is padded to 16 bytes + * so there will be space for exactly 21 quota-entries in a block + */ +struct qt_disk_dqdbheader { + __le32 dqdh_next_free; /* Number of next block with free + * entry */ + __le32 dqdh_prev_free; /* Number of previous block with free + * entry */ + __le16 dqdh_entries; /* Number of valid entries in block */ + __le16 dqdh_pad1; + __le32 dqdh_pad2; +} __attribute__ ((packed)); + +struct dquot; +struct quota_handle; + +/* Operations */ +struct qtree_fmt_operations { + /* Convert given entry from in memory format to disk one */ + void (*mem2disk_dqblk)(void *disk, struct dquot *dquot); + /* Convert given entry from disk format to in memory one */ + void (*disk2mem_dqblk)(struct dquot *dquot, void *disk); + /* Is this structure for given id? */ + int (*is_id)(void *disk, struct dquot *dquot); +}; + +/* In-memory copy of version specific information */ +struct qtree_mem_dqinfo { + unsigned int dqi_blocks; /* # of blocks in quota file */ + unsigned int dqi_free_blk; /* First block in list of free blocks */ + unsigned int dqi_free_entry; /* First block with free entry */ + unsigned int dqi_entry_size; /* Size of quota entry in quota file */ + struct qtree_fmt_operations *dqi_ops; /* Operations for entry + * manipulation */ +}; + +void qtree_write_dquot(struct dquot *dquot); +struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id); +void qtree_delete_dquot(struct dquot *dquot); +int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk); +int qtree_scan_dquots(struct quota_handle *h, + int (*process_dquot) (struct dquot *, void *), void *data); + +int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info); + +#endif /* _LINUX_QUOTAIO_TREE_H */ diff --git a/include/e2fsprogs/support/quotaio_v2.h b/include/e2fsprogs/support/quotaio_v2.h new file mode 100755 index 0000000..35054ca --- /dev/null +++ b/include/e2fsprogs/support/quotaio_v2.h @@ -0,0 +1,69 @@ +/* + * + * Header file for disk format of new quotafile format + * + */ + +#ifndef GUARD_QUOTAIO_V2_H +#define GUARD_QUOTAIO_V2_H + +#include +#include "quotaio.h" + +/* Offset of info header in file */ +#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) +/* Supported version of quota-tree format */ +#define V2_VERSION_R1 1 +#define V2_VERSION_R0 0 + +struct v2_disk_dqheader { + __le32 dqh_magic; /* Magic number identifying file */ + __le32 dqh_version; /* File version */ +} __attribute__ ((packed)); + +/* Flags for version specific files */ +#define V2_DQF_MASK 0x0000 /* Mask for all valid ondisk flags */ + +/* Header with type and version specific information */ +struct v2_disk_dqinfo { + __le32 dqi_bgrace; /* Time before block soft limit becomes + * hard limit */ + __le32 dqi_igrace; /* Time before inode soft limit becomes + * hard limit */ + __le32 dqi_flags; /* Flags for quotafile (DQF_*) */ + __le32 dqi_blocks; /* Number of blocks in file */ + __le32 dqi_free_blk; /* Number of first free block in the list */ + __le32 dqi_free_entry; /* Number of block with at least one + * free entry */ +} __attribute__ ((packed)); + +struct v2r0_disk_dqblk { + __le32 dqb_id; /* id this quota applies to */ + __le32 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __le32 dqb_isoftlimit; /* preferred inode limit */ + __le32 dqb_curinodes; /* current # allocated inodes */ + __le32 dqb_bhardlimit; /* absolute limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le32 dqb_bsoftlimit; /* preferred limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le64 dqb_curspace; /* current space occupied (in bytes) */ + __le64 dqb_btime; /* time limit for excessive disk use */ + __le64 dqb_itime; /* time limit for excessive inode use */ +} __attribute__ ((packed)); + +struct v2r1_disk_dqblk { + __le32 dqb_id; /* id this quota applies to */ + __le32 dqb_pad; + __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __le64 dqb_isoftlimit; /* preferred inode limit */ + __le64 dqb_curinodes; /* current # allocated inodes */ + __le64 dqb_bhardlimit; /* absolute limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le64 dqb_bsoftlimit; /* preferred limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le64 dqb_curspace; /* current space occupied (in bytes) */ + __le64 dqb_btime; /* time limit for excessive disk use */ + __le64 dqb_itime; /* time limit for excessive inode use */ +} __attribute__ ((packed)); + +#endif diff --git a/include/e2fsprogs/support/sort_r.h b/include/e2fsprogs/support/sort_r.h new file mode 100755 index 0000000..8473ca8 --- /dev/null +++ b/include/e2fsprogs/support/sort_r.h @@ -0,0 +1,325 @@ +/* Isaac Turner 29 April 2014 Public Domain */ +#ifndef SORT_R_H_ +#define SORT_R_H_ + +#include +#include + +/* + +sort_r function to be exported. + +Parameters: + base is the array to be sorted + nel is the number of elements in the array + width is the size in bytes of each element of the array + compar is the comparison function + arg is a pointer to be passed to the comparison function + +void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg); + +*/ + +#define _SORT_R_INLINE inline + +#if (defined HAVE_GNU_QSORT_R) +# define _SORT_R_GNU +#elif (defined HAVE_BSD_QSORT_R) +# define _SORT_R_BSD +#elif (defined __gnu_hurd__ || defined __GNU__ || \ + defined __MINGW32__ || defined __GLIBC__) +# define _SORT_R_GNU +#elif (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ + defined __FreeBSD__ || defined __DragonFly__) +# define _SORT_R_BSD +#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__) +# define _SORT_R_WINDOWS +# undef _SORT_R_INLINE +# define _SORT_R_INLINE __inline +#else + /* Using our own recursive quicksort sort_r_simple() */ +#endif + +#if (defined NESTED_QSORT && NESTED_QSORT == 0) +# undef NESTED_QSORT +#endif + +#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp)) + +/* swap a and b */ +/* a and b must not be equal! */ +static _SORT_R_INLINE void sort_r_swap(char *__restrict a, char *__restrict b, + size_t w) +{ + char tmp, *end = a+w; + for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); } +} + +/* swap a, b iff a>b */ +/* a and b must not be equal! */ +/* __restrict is same as restrict but better support on old machines */ +static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, + char *__restrict b, size_t w, + int (*compar)(const void *_a, + const void *_b, + void *_arg), + void *arg) +{ + if(compar(a, b, arg) > 0) { + sort_r_swap(a, b, w); + return 1; + } + return 0; +} + +/* +Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr, +with the smallest swap so that the blocks are in the opposite order. Blocks may +be internally re-ordered e.g. + + 12345ab -> ab34512 + 123abc -> abc123 + 12abcde -> deabc12 +*/ +static _SORT_R_INLINE void sort_r_swap_blocks(char *ptr, size_t na, size_t nb) +{ + if(na > 0 && nb > 0) { + if(na > nb) { sort_r_swap(ptr, ptr+na, nb); } + else { sort_r_swap(ptr, ptr+nb, na); } + } +} + +/* Implement recursive quicksort ourselves */ +/* Note: quicksort is not stable, equivalent values may be swapped */ +static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, + int (*compar)(const void *_a, + const void *_b, + void *_arg), + void *arg) +{ + char *b = (char *)base, *end = b + nel*w; + + /* for(size_t i=0; i b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {} + } + } + else + { + /* nel > 6; Quicksort */ + + int cmp; + char *pl, *ple, *pr, *pre, *pivot; + char *last = b+w*(nel-1), *tmp; + + /* + Use median of second, middle and second-last items as pivot. + First and last may have been swapped with pivot and therefore be extreme + */ + char *l[3]; + l[0] = b + w; + l[1] = b+w*(nel/2); + l[2] = last - w; + + /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */ + + if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); } + if(compar(l[1],l[2],arg) > 0) { + SORT_R_SWAP(l[1], l[2], tmp); + if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); } + } + + /* swap mid value (l[1]), and last element to put pivot as last element */ + if(l[1] != last) { sort_r_swap(l[1], last, w); } + + /* + pl is the next item on the left to be compared to the pivot + pr is the last item on the right that was compared to the pivot + ple is the left position to put the next item that equals the pivot + ple is the last right position where we put an item that equals the pivot + + v- end (beyond the array) + EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE. + ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is) + + Pivot comparison key: + E = equal, L = less than, u = unknown, G = greater than, E = equal + */ + pivot = last; + ple = pl = b; + pre = pr = last; + + /* + Strategy: + Loop into the list from the left and right at the same time to find: + - an item on the left that is greater than the pivot + - an item on the right that is less than the pivot + Once found, they are swapped and the loop continues. + Meanwhile items that are equal to the pivot are moved to the edges of the + array. + */ + while(pl < pr) { + /* Move left hand items which are equal to the pivot to the far left. + break when we find an item that is greater than the pivot */ + for(; pl < pr; pl += w) { + cmp = compar(pl, pivot, arg); + if(cmp > 0) { break; } + else if(cmp == 0) { + if(ple < pl) { sort_r_swap(ple, pl, w); } + ple += w; + } + } + /* break if last batch of left hand items were equal to pivot */ + if(pl >= pr) { break; } + /* Move right hand items which are equal to the pivot to the far right. + break when we find an item that is less than the pivot */ + for(; pl < pr; ) { + pr -= w; /* Move right pointer onto an unprocessed item */ + cmp = compar(pr, pivot, arg); + if(cmp == 0) { + pre -= w; + if(pr < pre) { sort_r_swap(pr, pre, w); } + } + else if(cmp < 0) { + if(pl < pr) { sort_r_swap(pl, pr, w); } + pl += w; + break; + } + } + } + + pl = pr; /* pr may have gone below pl */ + + /* + Now we need to go from: EEELLLGGGGEEEE + to: LLLEEEEEEEGGGG + + Pivot comparison key: + E = equal, L = less than, u = unknown, G = greater than, E = equal + */ + sort_r_swap_blocks(b, ple-b, pl-ple); + sort_r_swap_blocks(pr, pre-pr, end-pre); + + /*for(size_t i=0; icompar)(a, b, ss->arg); + } + + #endif + + #if defined _SORT_R_GNU + + typedef int(* __compar_d_fn_t)(const void *, const void *, void *); + extern void qsort_r(void *base, size_t nel, size_t width, + __compar_d_fn_t __compar, void *arg) + __attribute__((nonnull (1, 4))); + + #endif + + /* implementation */ + + static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, + const void *_b, void *_arg), + void *arg) + { + #if defined _SORT_R_GNU + + #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)) + + /* no qsort_r in glibc before 2.8, need to use nested qsort */ + sort_r_simple(base, nel, width, compar, arg); + + #else + + qsort_r(base, nel, width, compar, arg); + + #endif + + #elif defined _SORT_R_BSD + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_r(base, nel, width, &tmp, sort_r_arg_swap); + + #elif defined _SORT_R_WINDOWS + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_s(base, nel, width, sort_r_arg_swap, &tmp); + + #else + + /* Fall back to our own quicksort implementation */ + sort_r_simple(base, nel, width, compar, arg); + + #endif + } + +#endif /* !NESTED_QSORT */ + +#undef _SORT_R_INLINE +#undef _SORT_R_WINDOWS +#undef _SORT_R_GNU +#undef _SORT_R_BSD + +#endif /* SORT_R_H_ */ diff --git a/include/e2fsprogs/uuid/uuid.h b/include/e2fsprogs/uuid/uuid.h new file mode 100755 index 0000000..ca846da --- /dev/null +++ b/include/e2fsprogs/uuid/uuid.h @@ -0,0 +1,103 @@ +/* + * Public include file for the UUID library + * + * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#ifndef _UUID_UUID_H +#define _UUID_UUID_H + +#include +#ifndef _WIN32 +#include +#endif +#include + +typedef unsigned char uuid_t[16]; + +/* UUID Variant definitions */ +#define UUID_VARIANT_NCS 0 +#define UUID_VARIANT_DCE 1 +#define UUID_VARIANT_MICROSOFT 2 +#define UUID_VARIANT_OTHER 3 + +/* UUID Type definitions */ +#define UUID_TYPE_DCE_TIME 1 +#define UUID_TYPE_DCE_RANDOM 4 + +/* Allow UUID constants to be defined */ +#ifdef __GNUC__ +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ + static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} +#else +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ + static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* clear.c */ +void uuid_clear(uuid_t uu); + +/* compare.c */ +int uuid_compare(const uuid_t uu1, const uuid_t uu2); + +/* copy.c */ +void uuid_copy(uuid_t dst, const uuid_t src); + +/* gen_uuid.c */ +void uuid_generate(uuid_t out); +void uuid_generate_random(uuid_t out); +void uuid_generate_time(uuid_t out); + +/* isnull.c */ +int uuid_is_null(const uuid_t uu); + +/* parse.c */ +int uuid_parse(const char *in, uuid_t uu); + +/* unparse.c */ +void uuid_unparse(const uuid_t uu, char *out); +void uuid_unparse_lower(const uuid_t uu, char *out); +void uuid_unparse_upper(const uuid_t uu, char *out); + +/* uuid_time.c */ +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); +int uuid_type(const uuid_t uu); +int uuid_variant(const uuid_t uu); + +#ifdef __cplusplus +} +#endif + +#endif /* _UUID_UUID_H */ diff --git a/include/e2fsprogs/uuid/uuidP.h b/include/e2fsprogs/uuid/uuidP.h new file mode 100755 index 0000000..6c0fd80 --- /dev/null +++ b/include/e2fsprogs/uuid/uuidP.h @@ -0,0 +1,71 @@ +/* + * uuid.h -- private header file for uuids + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#ifdef HAVE_INTTYPES_H +#include +#else +#include +#endif +#include + +#include + +/* + * Offset between 15-Oct-1582 and 1-Jan-70 + */ +#define TIME_OFFSET_HIGH 0x01B21DD2 +#define TIME_OFFSET_LOW 0x13814000 + +struct uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint16_t clock_seq; + uint8_t node[6]; +}; + +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GNUC_PREREQ(maj, min) 0 +#endif +#endif + +/* + * prototypes + */ +void uuid_pack(const struct uuid *uu, uuid_t ptr); +void uuid_unpack(const uuid_t in, struct uuid *uu); diff --git a/include/e2fsprogs/uuid/uuid_types.h b/include/e2fsprogs/uuid/uuid_types.h new file mode 100755 index 0000000..35e5151 --- /dev/null +++ b/include/e2fsprogs/uuid/uuid_types.h @@ -0,0 +1,45 @@ +/* + * If linux/types.h is already been included, assume it has defined + * everything we need. (cross fingers) Other header files may have + * also defined the types that we need. + */ +#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \ + !defined(_EXT2_TYPES_H) && !defined(_UUID_TYPES_H)) +#define _UUID_TYPES_H + +typedef unsigned char __u8; +typedef __signed__ char __s8; +typedef unsigned short __u16; +typedef __signed__ short __s16; +typedef unsigned int __u32; +typedef __signed__ int __s32; +typedef unsigned long long __u64; +typedef __signed__ long long __s64; +#endif + +#include //uintptr_t + +/* endian checking stuff */ +#ifndef EXT2_ENDIAN_H_ +#define EXT2_ENDIAN_H_ + +#ifdef __CHECKER__ +#ifndef __bitwise +#define __bitwise __attribute__((bitwise)) +#endif +#define __force __attribute__((force)) +#else +#ifndef __bitwise +#define __bitwise +#endif +#define __force +#endif + +typedef __u16 __bitwise __le16; +typedef __u32 __bitwise __le32; +typedef __u64 __bitwise __le64; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __be64; + +#endif /* EXT2_ENDIAN_H_ */ diff --git a/include/e2fsprogs/uuid/uuidd.h b/include/e2fsprogs/uuid/uuidd.h new file mode 100755 index 0000000..c71f4b7 --- /dev/null +++ b/include/e2fsprogs/uuid/uuidd.h @@ -0,0 +1,54 @@ +/* + * Definitions used by the uuidd daemon + * + * Copyright (C) 2007 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#ifndef _UUID_UUIDD_H +#define _UUID_UUIDD_H + +#define UUIDD_DIR "/var/lib/libuuid" +#define UUIDD_SOCKET_PATH UUIDD_DIR "/request" +#define UUIDD_PIDFILE_PATH UUIDD_DIR "/uuidd.pid" +#define UUIDD_PATH "/usr/sbin/uuidd" + +#define UUIDD_OP_GETPID 0 +#define UUIDD_OP_GET_MAXOP 1 +#define UUIDD_OP_TIME_UUID 2 +#define UUIDD_OP_RANDOM_UUID 3 +#define UUIDD_OP_BULK_TIME_UUID 4 +#define UUIDD_OP_BULK_RANDOM_UUID 5 +#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID + +extern void uuid__generate_time(uuid_t out, int *num); +extern void uuid__generate_random(uuid_t out, int *num); + +#endif /* _UUID_UUID_H */ diff --git a/include/e2fsprogs/version.h b/include/e2fsprogs/version.h new file mode 100755 index 0000000..e3ba95a --- /dev/null +++ b/include/e2fsprogs/version.h @@ -0,0 +1,13 @@ +/* + * version.h --- controls the version number printed by the e2fs + * programs. + * + * Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2005, 2006, 2007, 2008, 2009, 2010 by Theodore Ts'o. This + * file may be redistributed under the GNU Public License v2. + */ + +#define E2FSPROGS_VERSION "1.46.6 [pmt-static]" +#define E2FSPROGS_VERSION_PRIVATE "1.46.6" +#define EXT2FS_LIB_VERSION_PRIVATE "android-static-369-g8ed4b2673" +#define E2FSPROGS_DATE "1-Feb-2023" diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100755 index 0000000..899a377 --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,336 @@ +# By YZBruh + +# Copyright 2024 Partition Manager +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######## +# 2.9.0 +######## + +LOCAL_PATH := $(call my-dir) + +include $(LOCAL_PATH)/../build/config/env.mk + +PMT_CXXFLAGS = \ + -O3 \ + -Wall \ + -Wextra \ + -Werror \ + -Wno-vla-cxx-extension \ + -Wno-nullability-completeness \ + -Wno-writable-strings \ + -Wno-unused-parameter \ + -Wno-unused-command-line-argument \ + -Wno-nullability-extension \ + -Wno-reorder-init-list \ + -Wno-gnu-zero-variadic-macro-arguments \ + -D__NDK_BUILD \ + $(PMT_EXTRA_CXXFLAGS) +E2FSPROGS_DEFAULT_CFLAGS = \ + -std=c17 \ + -Wall \ + -Werror \ + -Wno-pointer-arith \ + -Wno-sign-compare \ + -Wno-type-limits \ + -Wno-typedef-redefinition \ + -Wno-unused-parameter \ + -Wno-unused-command-line-argument \ + -fPIC \ + -pthread + +ifneq ($(PMT_ENABLE_DEBUG),) + PMT_CXXFLAGS += -gdwarf-5 -fsanitize=address +endif + +PMT := PartitionManager +MKE2FS := e2fsprogs/mke2fs +LIB := e2fsprogs/lib +LIBEXT2FS := $(LIB)/ext2fs +LIBEXT2_UUID := $(LIB)/uuid +LIBEXT2_E2P := $(LIB)/e2p +LIBEXT2_QUOTA := $(LIB)/support +LIBEXT2_MISC := $(LIB)/misc +LIBEXT2_COM_ERR := $(LIB)/et +LIBEXT2_BLKID := $(LIB)/blkid +INC_DIR := ../include/e2fsprogs +E2FSPROGS_INCLUDES := \ + $(INC_DIR)/misc \ + $(INC_DIR)/blkid \ + $(INC_DIR)/e2p \ + $(INC_DIR)/et \ + $(INC_DIR)/ext2fs \ + $(INC_DIR)/ss \ + $(INC_DIR)/support \ + $(INC_DIR)/uuid \ + $(INC_DIR)/e2fsck \ + $(INC_DIR) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2fs +LOCAL_SRC_FILES := \ + $(LIBEXT2FS)/devname.c \ + $(LIBEXT2FS)/ext2_err.c \ + $(LIBEXT2FS)/alloc.c \ + $(LIBEXT2FS)/alloc_sb.c \ + $(LIBEXT2FS)/alloc_stats.c \ + $(LIBEXT2FS)/alloc_tables.c \ + $(LIBEXT2FS)/atexit.c \ + $(LIBEXT2FS)/badblocks.c \ + $(LIBEXT2FS)/bb_inode.c \ + $(LIBEXT2FS)/bitmaps.c \ + $(LIBEXT2FS)/bitops.c \ + $(LIBEXT2FS)/blkmap64_ba.c \ + $(LIBEXT2FS)/blkmap64_rb.c \ + $(LIBEXT2FS)/blknum.c \ + $(LIBEXT2FS)/block.c \ + $(LIBEXT2FS)/bmap.c \ + $(LIBEXT2FS)/check_desc.c \ + $(LIBEXT2FS)/crc16.c \ + $(LIBEXT2FS)/crc32c.c \ + $(LIBEXT2FS)/csum.c \ + $(LIBEXT2FS)/closefs.c \ + $(LIBEXT2FS)/dblist.c \ + $(LIBEXT2FS)/dblist_dir.c \ + $(LIBEXT2FS)/digest_encode.c \ + $(LIBEXT2FS)/dirblock.c \ + $(LIBEXT2FS)/dirhash.c \ + $(LIBEXT2FS)/dir_iterate.c \ + $(LIBEXT2FS)/dupfs.c \ + $(LIBEXT2FS)/expanddir.c \ + $(LIBEXT2FS)/ext_attr.c \ + $(LIBEXT2FS)/extent.c \ + $(LIBEXT2FS)/fallocate.c \ + $(LIBEXT2FS)/fileio.c \ + $(LIBEXT2FS)/finddev.c \ + $(LIBEXT2FS)/flushb.c \ + $(LIBEXT2FS)/freefs.c \ + $(LIBEXT2FS)/gen_bitmap.c \ + $(LIBEXT2FS)/gen_bitmap64.c \ + $(LIBEXT2FS)/get_num_dirs.c \ + $(LIBEXT2FS)/get_pathname.c \ + $(LIBEXT2FS)/getsize.c \ + $(LIBEXT2FS)/getsectsize.c \ + $(LIBEXT2FS)/hashmap.c \ + $(LIBEXT2FS)/i_block.c \ + $(LIBEXT2FS)/icount.c \ + $(LIBEXT2FS)/imager.c \ + $(LIBEXT2FS)/ind_block.c \ + $(LIBEXT2FS)/initialize.c \ + $(LIBEXT2FS)/inline.c \ + $(LIBEXT2FS)/inline_data.c \ + $(LIBEXT2FS)/inode.c \ + $(LIBEXT2FS)/io_manager.c \ + $(LIBEXT2FS)/ismounted.c \ + $(LIBEXT2FS)/link.c \ + $(LIBEXT2FS)/llseek.c \ + $(LIBEXT2FS)/lookup.c \ + $(LIBEXT2FS)/mmp.c \ + $(LIBEXT2FS)/mkdir.c \ + $(LIBEXT2FS)/mkjournal.c \ + $(LIBEXT2FS)/namei.c \ + $(LIBEXT2FS)/native.c \ + $(LIBEXT2FS)/newdir.c \ + $(LIBEXT2FS)/nls_utf8.c \ + $(LIBEXT2FS)/openfs.c \ + $(LIBEXT2FS)/progress.c \ + $(LIBEXT2FS)/punch.c \ + $(LIBEXT2FS)/qcow2.c \ + $(LIBEXT2FS)/rbtree.c \ + $(LIBEXT2FS)/read_bb.c \ + $(LIBEXT2FS)/read_bb_file.c \ + $(LIBEXT2FS)/res_gdt.c \ + $(LIBEXT2FS)/rw_bitmaps.c \ + $(LIBEXT2FS)/sha256.c \ + $(LIBEXT2FS)/sha512.c \ + $(LIBEXT2FS)/swapfs.c \ + $(LIBEXT2FS)/symlink.c \ + $(LIBEXT2FS)/undo_io.c \ + $(LIBEXT2FS)/unix_io.c \ + $(LIBEXT2FS)/sparse_io.c \ + $(LIBEXT2FS)/unlink.c \ + $(LIBEXT2FS)/valid_blk.c \ + $(LIBEXT2FS)/version.c \ + $(LIBEXT2FS)/test_io.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := \ + $(E2FSPROGS_DEFAULT_CFLAGS) \ + -Wno-unused-but-set-variable + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_blkid +LOCAL_SRC_FILES := \ + $(LIBEXT2_BLKID)/cache.c \ + $(LIBEXT2_BLKID)/dev.c \ + $(LIBEXT2_BLKID)/devname.c \ + $(LIBEXT2_BLKID)/devno.c \ + $(LIBEXT2_BLKID)/getsize.c \ + $(LIBEXT2_BLKID)/llseek.c \ + $(LIBEXT2_BLKID)/probe.c \ + $(LIBEXT2_BLKID)/read.c \ + $(LIBEXT2_BLKID)/resolve.c \ + $(LIBEXT2_BLKID)/save.c \ + $(LIBEXT2_BLKID)/tag.c \ + $(LIBEXT2_BLKID)/version.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := \ + $(E2FSPROGS_DEFAULT_CFLAGS) \ + -Wno-error=attributes \ + -Wno-error=pointer-sign \ + -Wno-unused-but-set-variable \ + -fno-strict-aliasing + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_uuid +LOCAL_SRC_FILES := \ + $(LIBEXT2_UUID)/clear.c \ + $(LIBEXT2_UUID)/compare.c \ + $(LIBEXT2_UUID)/copy.c \ + $(LIBEXT2_UUID)/gen_uuid.c \ + $(LIBEXT2_UUID)/isnull.c \ + $(LIBEXT2_UUID)/pack.c \ + $(LIBEXT2_UUID)/parse.c \ + $(LIBEXT2_UUID)/unpack.c \ + $(LIBEXT2_UUID)/unparse.c \ + $(LIBEXT2_UUID)/uuid_time.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := $(E2FSPROGS_DEFAULT_CFLAGS) + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_e2p +LOCAL_SRC_FILES := \ + $(LIBEXT2_E2P)/crypto_mode.c \ + $(LIBEXT2_E2P)/encoding.c \ + $(LIBEXT2_E2P)/errcode.c \ + $(LIBEXT2_E2P)/feature.c \ + $(LIBEXT2_E2P)/fgetflags.c \ + $(LIBEXT2_E2P)/fgetproject.c \ + $(LIBEXT2_E2P)/fgetversion.c \ + $(LIBEXT2_E2P)/fsetflags.c \ + $(LIBEXT2_E2P)/fsetproject.c \ + $(LIBEXT2_E2P)/fsetversion.c \ + $(LIBEXT2_E2P)/getflags.c \ + $(LIBEXT2_E2P)/getversion.c \ + $(LIBEXT2_E2P)/hashstr.c \ + $(LIBEXT2_E2P)/iod.c \ + $(LIBEXT2_E2P)/ljs.c \ + $(LIBEXT2_E2P)/ls.c \ + $(LIBEXT2_E2P)/mntopts.c \ + $(LIBEXT2_E2P)/ostype.c \ + $(LIBEXT2_E2P)/parse_num.c \ + $(LIBEXT2_E2P)/pe.c \ + $(LIBEXT2_E2P)/percent.c \ + $(LIBEXT2_E2P)/pf.c \ + $(LIBEXT2_E2P)/ps.c \ + $(LIBEXT2_E2P)/setflags.c \ + $(LIBEXT2_E2P)/setversion.c \ + $(LIBEXT2_E2P)/uuid.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := \ + $(E2FSPROGS_DEFAULT_CFLAGS) \ + -Wno-error=attributes + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_quota +LOCAL_SRC_FILES := \ + $(LIBEXT2_QUOTA)/dict.c \ + $(LIBEXT2_QUOTA)/mkquota.c \ + $(LIBEXT2_QUOTA)/parse_qtype.c \ + $(LIBEXT2_QUOTA)/plausible.c \ + $(LIBEXT2_QUOTA)/prof_err.c \ + $(LIBEXT2_QUOTA)/profile.c \ + $(LIBEXT2_QUOTA)/profile_helpers.c \ + $(LIBEXT2_QUOTA)/quotaio.c \ + $(LIBEXT2_QUOTA)/quotaio_tree.c \ + $(LIBEXT2_QUOTA)/quotaio_v2.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := $(E2FSPROGS_DEFAULT_CFLAGS) + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_misc +LOCAL_SRC_FILES := $(LIBEXT2_MISC)/create_inode.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := \ + $(E2FSPROGS_DEFAULT_CFLAGS) \ + -Wno-error=format-extra-args + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libext2_com_err +LOCAL_SRC_FILES := \ + $(LIBEXT2_COM_ERR)/com_err.c \ + $(LIBEXT2_COM_ERR)/com_right.c \ + $(LIBEXT2_COM_ERR)/error_message.c \ + $(LIBEXT2_COM_ERR)/et_name.c \ + $(LIBEXT2_COM_ERR)/init_et.c +LOCAL_C_INCLUDES := $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := $(E2FSPROGS_DEFAULT_CFLAGS) + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := pmt +LOCAL_SRC_FILES := \ + $(PMT)/Debug.cpp \ + $(PMT)/Root.cpp \ + $(PMT)/PartitionManager.cpp \ + $(PMT)/PartitionTool.cpp \ + $(PMT)/ListPartitions.cpp \ + $(PMT)/Version.cpp \ + $(PMT)/GetState.cpp \ + $(PMT)/Tools.cpp \ + $(PMT)/LanguageTools.cpp \ + $(PMT)/Languages.cpp \ + $(PMT)/Help.cpp + $(MKE2FS)/default_profile.c \ + $(MKE2FS)/mk_hugefiles.c \ + $(MKE2FS)/mke2fs.c \ + $(MKE2FS)/util.c +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../include \ + $(LOCAL_PATH)/../include/PartitionManager \ + $(E2FSPROGS_INCLUDES) +LOCAL_CFLAGS := $(PMT_CXXFLAGS) +LOCAL_STATIC_LIBRARIES := \ + libext2fs \ + libext2_blkid \ + libext2_uuid \ + libext2_e2p \ + libext2_quota \ + libext2_misc \ + libext2_com_err +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libcutils + +include $(BUILD_EXECUTABLE) diff --git a/build/others/makefile.applicationmk b/jni/Application.mk similarity index 98% rename from build/others/makefile.applicationmk rename to jni/Application.mk index 5fcf2d7..ef1bb01 100755 --- a/build/others/makefile.applicationmk +++ b/jni/Application.mk @@ -15,7 +15,7 @@ # limitations under the License. ######## -# 2.8.0 +# 2.9.0 ######## # architecture diff --git a/jni/Makefile b/jni/Makefile deleted file mode 100755 index 773333d..0000000 --- a/jni/Makefile +++ /dev/null @@ -1,157 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##### -# sub-make for building package -##### - -THIS_IS = src - -include ../Makefile.inc - -ifeq ($(INC_OLDENV),true) - include $(BUILD)/config/oldenv.mk -endif - -INCLUDE_DIR := $(realpath ../include) -PMT_INCDIR := $(INCLUDE_DIR)/pmt - -# the presence of all source files that are on this list will be checked -SRCS_REQ := \ - place-holder/Debug.cpp \ - place-holder/Help.cpp \ - place-holder/GetState.cpp \ - place-holder/LanguageTools.cpp \ - place-holder/Languages.cpp \ - place-holder/PartitionTool.cpp \ - place-holder/PartitionManager.cpp \ - place-holder/Root.cpp \ - place-holder/Tools.cpp \ - place-holder/Version.cpp - -# objects to be used when executable file is created -OBJS_EXEC := \ - $(SOURCE_DIR)/Debug.o \ - $(SOURCE_DIR)/Root.o \ - $(SOURCE_DIR)/PartitionManager.o \ - $(SOURCE_DIR)/PartitionTool.o \ - $(SOURCE_DIR)/ListPartitions.o \ - $(SOURCE_DIR)/Help.o \ - $(SOURCE_DIR)/Version.o \ - $(SOURCE_DIR)/GetState.o \ - $(SOURCE_DIR)/Tools.o \ - $(SOURCE_DIR)/Languages.o \ - $(SOURCE_DIR)/LanguageTools.o - -HEADERS_REQ := \ - $(PMT_INCDIR)/PartitionManager/Deprecates.h \ - $(PMT_INCDIR)/PartitionManager/HelpFn.h \ - $(PMT_INCDIR)/PartitionManager/PartitionManager.h \ - $(PMT_INCDIR)/PartitionManager/StringKeys.h \ - $(PMT_INCDIR)/PartitionManager/VersionFnVars.h - -PROGRESS_LIST := \ - welcome \ - wait \ - $(SRCS_REQ) \ - $(HEADERS_REQ) \ - pr_obj \ - $(OBJS) \ - make_outdirs \ - make_executable \ - wait \ - end_progress - -# all target for building -all: $(PROGRESS_LIST) - -welcome: - @ rm -f $(BUILD)/config/oldenv.mk - @ echo " ---- Partition Manager Builder ---- " \ - && $(E_NS) - $(E) " - Version: $(VERSION)" - $(E) " - Version code: $(VERSION_CODE)" \ - && $(E_NS) - $(E) " -------------------------------- " \ - && $(E_NS) - $(E) " - Checking required source files..." - -pr_obj: - $(E) " - Building objects..." - -wait: - @ sleep 2 - -make_outdirs: - @ rm -rf $(IN_OUT_DIR) - @ mkdir -p $(BINARY_DIR) - @ mkdir -p $(PACKAGE_DIR) - -place-holder/%.cpp: - $(E) " CHK $(SOURCE_DIRNAME)/`basename $@`" - @ if [ ! -f "$(SOURCE_DIR)/`basename $@`" ]; then \ - $(E_NS) " ==> Couldn't found required source file: $(SOURCE_DIRNAME)/`basename $@`"; \ - exit 1; \ - fi - -$(PMT_INCDIR)/%.h: - $(E) " CHK include/PartitionManager/`basename $@`" - @ if [ ! -f "$(INCLUDE_DIR)/PartitionManager/`basename $@`" ]; then \ - $(E_NS) " ==> Couldn't found required header file: include/PartitionManager/`basename $@`"; \ - exit 1; \ - fi - -$(SOURCE_DIR)/%.o: $(SOURCE_DIR)/%.cpp - $(E) " CXX $(SOURCE_DIRNAME)/`basename $@`" - @ $(CXX) -x c++ $(CXXFLAGS) -c "$<" || exit 1 - -make_executable: - $(E) " - Making executable file..." - $(E) " LD $(TARGET)" - @ $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS_EXEC) || exit 1 - -end_progress: - @ abort_build() { \ - [ -d "$(PACKAGE_DIR)" ] \ - && rm -rf "$(PACKAGE_DIR)"; \ - [ -d "$(BINARY_DIR)" ] \ - && rm -rf "$(BINARY_DIR)"; \ - [ -d "$(STATICLIB_DIR)" ] \ - && rm -rf "$(STATICLIB_DIR)"; \ - exit 1; \ - }; \ - mv $(TARGET) $(BINARY_DIR) || abort_build; \ - $(E_NS) " - Generating package..."; \ - cp $(BINARY_DIR)/$(TARGET) $(PACKAGE_DIR) || abort_build; \ - $(E_NS) " XZ $(OUT_DIRNAME)/package/$(TARGET)-`date +%Y%m%d`.xz" - xz $(PACKAGE_DIR)/$(TARGET) || abort_build; \ - sleep 1; \ - mv $(PACKAGE_DIR)/$(TARGET).xz $(PACKAGE_DIR)/$(TARGET)-`date +%Y%m%d`.xz || abort_build - $(E) " - Success" && $(E_NS) - @ sleep 1 - $(E) " ----------------------------------- " - -.PHONY: clean -clean: - $(eval OBJS = $(wildcard $(SOURCE_DIR)/*.o)) - $(info Cleaning files...) - $(foreach obj, \ - $(OBJS), \ - $(call m_stat_nn,$(SOURCE_DIRNAME)/$(shell basename $(obj))) \ - $(call erase,$(obj)) \ - ) - -# end \ No newline at end of file diff --git a/jni/Debug.cpp b/jni/PartitionManager/Debug.cpp similarity index 100% rename from jni/Debug.cpp rename to jni/PartitionManager/Debug.cpp diff --git a/jni/GetState.cpp b/jni/PartitionManager/GetState.cpp similarity index 100% rename from jni/GetState.cpp rename to jni/PartitionManager/GetState.cpp diff --git a/jni/Help.cpp b/jni/PartitionManager/Help.cpp similarity index 68% rename from jni/Help.cpp rename to jni/PartitionManager/Help.cpp index 615d05c..667ebe2 100755 --- a/jni/Help.cpp +++ b/jni/PartitionManager/Help.cpp @@ -43,23 +43,32 @@ void Functions::DisplayHelp(void) VLOGD("DisplayHelp: Printing...\n"); LOGD("%s: %s %s\n", Display::UsingDocDispString->usage_docstr, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l1); LOGD(" %s: %s %s\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l2); - LOGD(" %s: %s %s\n\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l3); - LOGD("%s: \n", Display::UsingDocDispString->docs_strs_l4); - LOGD(" -l, --logical %s\n", Display::UsingDocDispString->docs_strs_l5); - LOGD(" -c, --context %s\n", Display::UsingDocDispString->docs_strs_l6); - LOGD(" -p, --list %s\n", Display::UsingDocDispString->docs_strs_l7); - LOGD(" -s, --silent %s\n", Display::UsingDocDispString->docs_strs_l8); - LOGD(" -f, --force %s\n", Display::UsingDocDispString->docs_strs_l9); - LOGD(" -V, --verbose %s\n", Display::UsingDocDispString->docs_strs_l10); - LOGD(" -S, --set-lang %s\n", Display::UsingDocDispString->docs_strs_l11); - LOGD(" -v, --version %s\n", Display::UsingDocDispString->docs_strs_l12); - LOGD(" --help %s\n\n", Display::UsingDocDispString->docs_strs_l13); - LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l14); - LOGD(" %s backup boot_a -c /dev/block/platform/bootdevice/by-name\n", Strings::ExecutingName.c_str()); + LOGD(" %s: %s %s\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l3); + LOGD(" %s: %s %s\n\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l4); + LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l5); + LOGD(" -l, --logical %s\n", Display::UsingDocDispString->docs_strs_l6); + LOGD(" -P, --search-path %s\n", Display::UsingDocDispString->docs_strs_l7); + LOGD(" -p, --list %s\n", Display::UsingDocDispString->docs_strs_l8); + LOGD(" -s, --silent %s\n", Display::UsingDocDispString->docs_strs_l9); + LOGD(" -f, --force %s\n", Display::UsingDocDispString->docs_strs_l10); + LOGD(" -V, --verbose %s\n", Display::UsingDocDispString->docs_strs_l11); + LOGD(" -S, --set-lang %s\n", Display::UsingDocDispString->docs_strs_l12); + LOGD(" -v, --version %s\n", Display::UsingDocDispString->docs_strs_l13); + LOGD(" --help %s\n\n", Display::UsingDocDispString->docs_strs_l14); + LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l15); + LOGD(" --only-size %s\n", Display::UsingDocDispString->docs_strs_l16); + LOGD(" --as-byte %s\n", Display::UsingDocDispString->docs_strs_l17); + LOGD(" --as-kilobyte %s\n", Display::UsingDocDispString->docs_strs_l18); + LOGD(" --as-megabyte %s\n", Display::UsingDocDispString->docs_strs_l19); + LOGD(" --as-gigabyte %s\n\n", Display::UsingDocDispString->docs_strs_l20); + LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l21); + LOGD(" %s backup boot_a -P /dev/block/platform/bootdevice/by-name\n", Strings::ExecutingName.c_str()); LOGD(" %s flash boot_a /sdcard/twrp/boot.img -c /dev/block/platform/bootdevice/by-name\n", Strings::ExecutingName.c_str()); LOGD(" %s format system_a ext4 --logical\n", Strings::ExecutingName.c_str()); - LOGD(" %s -c /dev/block/platform/bootdevice/by-name --list\n\n", Strings::ExecutingName.c_str()); - LOGD("%s \n", Display::UsingDocDispString->docs_strs_l15); + LOGD(" %s -P /dev/block/platform/bootdevice/by-name --list\n", Strings::ExecutingName.c_str()); + LOGD(" %s partition-size boot --as-byte\n", Strings::ExecutingName.c_str()); + LOGD(" %s partition-size system --only-size --as-gigabyte --logical\n\n", Strings::ExecutingName.c_str()); + LOGD("%s \n", Display::UsingDocDispString->docs_strs_l22); } /* end of code */ diff --git a/jni/LanguageTools.cpp b/jni/PartitionManager/LanguageTools.cpp similarity index 83% rename from jni/LanguageTools.cpp rename to jni/PartitionManager/LanguageTools.cpp index 75d24c6..3128ca8 100755 --- a/jni/LanguageTools.cpp +++ b/jni/PartitionManager/LanguageTools.cpp @@ -26,14 +26,13 @@ using namespace PartitionManager; /* pmt's man doc file path on termux */ +#define INTERNAL_STORAGE_DIR "/sdcard" #define TERMUX_PMT_MANDOC "/data/data/com.termux/files/usr/share/man/man8/pmt.8.gz" #define PMTLANG_CONF "/sdcard/.pmtlang.conf" #define PMT_SW_POINT "/sdcard/.pmtlangsw" struct langdb_general* Display::UsingDispString = nullptr; - static fstream langconf; - string supp_langs[] = { "en", "tr", @@ -41,7 +40,13 @@ string supp_langs[] = { }; static bool -LangControl(const string lang) +InternalStorageDirFound(void) +{ + return (Functions::GetState(INTERNAL_STORAGE_DIR, "dir") == 0) ? true : false; +} + +static bool +LanguageControl(const string& lang) { for (int i = 0; !supp_langs[i].empty(); i++) { @@ -61,6 +66,10 @@ bool Functions::LoadLanguage(void) if (Functions::GetState(TERMUX_PMT_MANDOC) == 0) Booleans::InstalledOnTermux = true; + VLOGD("LoadLanguage: checking internal storage dir: `%s'\n", INTERNAL_STORAGE_DIR); + if (!InternalStorageDirFound()) + LOGE("PartitionManagerLoadLanguage: internal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR); + VLOGD("LoadLanguage: trying to open `%s' with 'open '\n", PMTLANG_CONF); langconf.open(PMTLANG_CONF, ios::in | ios::out); @@ -128,21 +137,25 @@ SetTr: void Functions::SetLanguage(const string& lang, unsigned short null_conf_stat) { VLOGD("SetLanguage: checking speficed language (from input).\n"); - if (!LangControl(lang.c_str())) + if (!LanguageControl(lang)) LOGE("Unknown language: %s.\n", lang.c_str()); langconf.close(); + VLOGD("SetLanguage: checking internal storage dir: `%s'\n", INTERNAL_STORAGE_DIR); + if (!InternalStorageDirFound()) + LOGE("PartitionManagerSetLanguage: internal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR); + VLOGD("SetLanguage: trying to open `%s' with 'open '\n", PMTLANG_CONF); langconf.open(PMTLANG_CONF, ios::out | ios::trunc); if (!langconf.is_open()) - LOGE("Failed!!! Cannot open/write config file.\n"); + LOGE("PartitionManagerLanguageTools: Cannot open/write config file!!!\n"); VLOGD("SetLanguage: write \"%s\" to `%s' with 'std '\n", lang.c_str(), PMTLANG_CONF); langconf << lang; if (!langconf) - LOGE("Failed!!! Couldn't write config!\n"); + LOGE("PartitionManagerLanguageTools: Couldn't write config!!!\n"); else langconf.close(); diff --git a/jni/Languages.cpp b/jni/PartitionManager/Languages.cpp similarity index 69% rename from jni/Languages.cpp rename to jni/PartitionManager/Languages.cpp index 3a3ed98..0298106 100755 --- a/jni/Languages.cpp +++ b/jni/PartitionManager/Languages.cpp @@ -42,26 +42,30 @@ struct langdb_general LangEn = { .expected_backup_arg = "Expected backup argument 2 (1 of them are not mandatory), retrieved", .expected_flash_arg = "Expected flash argument 2, retrieved", .expected_format_arg = "Expected format argument 2, retrieved", + .expected_partsz_arg = "Expacted partition-size argument 2, retrieved", .missing_operand = "Missing operand", .multiple_wiewers = "Multiple viewers can't be used on the same line.", - .common_symbol_rule = "When specifying arguments for an option, ensure they do not begin with '-'. Each argument must correspond correctly to its respective option.", + .symbol_rule = "When specifying arguments for an option, ensure they do not begin with '-'. Each argument must correspond correctly to its respective option.", .req_part_name = "Partition name required.", .part_not_found = "Partition not found! Maybe a logical partition?", .unsupported_fs = "Formatter: unsupported filesystem", - .cannot_stat = "Can't retrieve file status", + .cannot_stat = "Cannot stat", .ffile_more_part = "Flash file size exceeds partition capacity. Use force mode to avoid this error (not recommended, riscy!).", .cannot_get_bsz = "Failed to retrieve partition block size.", .format_fail = "Formatting failed! There is a possibility of data damage.", + .fail_get_psize = "Cannot get partition size", .depr_backup_opt = "These options for the backup are unavailable.", .depr_flash_opt = "These options for the flash are unavailable.", .depr_format_opt = "These options for the format are unavailable.", - .depr_Vlicense_opt = "No memory for unnecessary options!", + .depr_Vlicense_opt = "Deprecated because it was unnecessary.", .depr_ch_list_opt = "Use -p argument for listing partitions.", + .depr_ch_sp_opt = "Use -P (--search-path) argument instead of -c (--context).", .not_spec_opt = "Specify the necessary arguments, not option", .some_spec = "You may have indicated options, but they don't work much unless you speficy a main transaction", .logical_warn = "This device uses logical partitions.", .ab_warn = "This device uses A/B partition style.", .out_not_spec = "Output file name not specified. Using created name", + .no_found_on_process = "The file that was processed was not found. Something wen wrong...", .please_rerun = "Please rerun the command.", .part_disk_sz = "Partition (backup) size", .flash_file_sz = "Flash file size", @@ -78,6 +82,7 @@ struct langdb_general LangEn = { .warn = "WARNING", .fatal = "FATAL ERROR", .is_requires_arg = "requires an argument", + .only_partsz_args = "Flags can be used only in partition size view were identified. But target not this", .unknw_arg = "unknown option", .switching_lang = "Switching language...", .welcome = "language!", @@ -89,12 +94,16 @@ struct langdb_general LangEn = { .depr_opt_str = "DEPRECATED OPTION", .switched_opt_str = "SWITCHED OPTION", .not_changed_opt = "not changed", - .compiler_str = "Compiler", + .compiler_str = "compiler", .version_str = "version", .bin_str = "binary", + .part_name = "Partition name", + .part_type = "Partition is dynamic", .fs_str = "Filesystem", .unknw_str = "unknown", - .by_str = "By" + .by_str = "By", + .yes = "true", + .no = "false" }; struct langdb_general LangTr = { @@ -115,9 +124,10 @@ struct langdb_general LangTr = { .expected_backup_arg = "Beklenen yedekleme argümanı 2 (bir tanesi zorunlu değil), alınan", .expected_flash_arg = "Beklenen flaş argümanı 2, alınan", .expected_format_arg = "Beklenen format argümanı 2, alınan", + .expected_partsz_arg = "Beklenen partition-size argümanı 1, alınan", .missing_operand = "İşlem belirtilmedi", .multiple_wiewers = "Birden fazla görüntüleme işlemi yapan fonksiyonlar bir arada kullanılamaz. Aynı anda sadece bir tanesi kullanılabilir.", - .common_symbol_rule = "Bir seçeneğin argümanını verirken argüman önüne '-' sembolü getirilemez. Sembolü kaldırın ve tekrar deneyin.", + .symbol_rule = "Bir seçeneğin argümanını verirken argüman önüne '-' sembolü getirilemez. Sembolü kaldırın ve tekrar deneyin.", .req_part_name = "Bölüm adı gereklidir.", .part_not_found = "Bölüm bulunamadı! Belki mantıksal (logical) bir bölümdür?", .unsupported_fs = "Formatlayıcı: desteklenmeyen dosya sistemi:", @@ -125,16 +135,19 @@ struct langdb_general LangTr = { .ffile_more_part = "Flaşlanacak dosyanın boyutu mevcut bölüm boyutundan fazla. Bu hatayla karşılaşmak istemiyorsanız zorlama (force) modu kullanın (bunu yapmanız asla önerilmez).", .cannot_get_bsz = "Bölüm blok boyutu tespit edilemedi!", .format_fail = "Formatlama başarısız oldu. Bazı şeyler zarar görmüş olabilir!", + .fail_get_psize = "Bölüm boyutu alınamadı", .depr_backup_opt = "Yedek için artık bu seçeneği kullanamazsınız.", .depr_flash_opt = "Flaşlama için artık bu seçeneği kullanamazsınız.", .depr_format_opt = "Formatlama için artıi bu seçeneği kullanamazsınız.", .depr_Vlicense_opt = "Gereksiz seçeneklere bellek yok!", .depr_ch_list_opt = "Listeleme için -p seçeneğini kullanabilirsiniz.", + .depr_ch_sp_opt = "Özel arama dizini belirtmek için -P (--search-path) seçeneğini kullanabilirsiniz.", .logical_warn = "Bu cihaz mantıksal (logical) bölümlere sahip.", - .not_spec_opt = "Seçenek değil, gerekli argümanları verin", + .not_spec_opt = "Seçenek değil, şuan gerekli argümanları verin", .some_spec = "Seçenek belirtmiş olabilirsiniz fakat, ana işlem belirtmedikçe pek işe yaramazlar", .ab_warn = "Bu cihazın bazı bölümleri A/B kullanıyor.", .out_not_spec = "Çıktı dosya adı belirtilmedi. Oluşturulan çıktı adı", + .no_found_on_process = "İşlenmekte olan dosya bulunamadı. Bir şeyler yanlış...", .please_rerun = "Lütfen yeniden çalıştırın", .part_disk_sz = "Bölümün (yedek) boyutu", .flash_file_sz = "Flaşlanacak dosyanın boyutu", @@ -151,6 +164,7 @@ struct langdb_general LangTr = { .warn = "UYARI", .fatal = "KRİTİK HATA", .is_requires_arg = "bir argüman gereklidir", + .only_partsz_args = "Sadece bölüm boyutu görüntülemesinde kullanılabilecek bayraklar tespit edildi. Ama hedef bu değil", .unknw_arg = "bilinmeyen seçenek", .switching_lang = "Dil değiştiriliyor...", .welcome = "diline hoş geldiniz!", @@ -162,30 +176,41 @@ struct langdb_general LangTr = { .depr_opt_str = "KALDIRILMIŞ SEÇENEK", .switched_opt_str = "DEĞİŞTİRİLMİŞ SEÇENEK", .not_changed_opt = "değiştirilmedi", - .compiler_str = "Derleyici", + .compiler_str = "derleyicisi", .version_str = "versiyon", .bin_str = "yapı", + .part_name = "Bölüm adı", + .part_type = "Dinamik bölüm", .fs_str = "Dosya sistemi", .unknw_str = "bilinmeyen", - .by_str = "Çeviriyi yapan(lar):" + .by_str = "Çeviriyi yapan(lar):", + .yes = "evet", + .no = "hayır" }; struct langdb_docs LangDocEn = { .docs_strs_l1 = "[OPTIONS] backup PARTITION [OUTPUT] [OPTIONS]...", .docs_strs_l2 = "[OPTIONS] flash PARTITION FILE [OPTIONS]...", .docs_strs_l3 = "[OPTIONS] format PARTITION FILE_SYSTEM[ext/2/3/4] [OPTIONS]...", - .docs_strs_l4 = "Options", - .docs_strs_l5 = "It is meant to determine whether the target partition is logical.", - .docs_strs_l6 = "It is meant to specify a custom /dev context. Only normal partitions (default: /dev/block/by-name).", - .docs_strs_l7 = "List partitions.", - .docs_strs_l8 = "Information and warning messages are silenced in normal work.", - .docs_strs_l9 = "Force mode. Some things are ignored.", - .docs_strs_l10 = "Verbose mode. Print detailed informations etc.", - .docs_strs_l11 = "Set current language.", - .docs_strs_l12 = "See version.", - .docs_strs_l13 = "See this help message.", - .docs_strs_l14 = "Examples", - .docs_strs_l15 = "Report bugs and suggestions to", + .docs_strs_l4 = "[OPTIONS] partition-size PARTITION [OPTIONS]...", + .docs_strs_l5 = "Options", + .docs_strs_l6 = "It is meant to determine whether the target partition is logical.", + .docs_strs_l7 = "It is meant to specify a custom partition search path. Only normal partitions (default: /dev/block/by-name).", + .docs_strs_l8 = "List partitions.", + .docs_strs_l9 = "Information and warning messages are silenced in normal work.", + .docs_strs_l10 = "Force mode. Some things are ignored.", + .docs_strs_l11 = "Verbose mode. Print detailed informations etc.", + .docs_strs_l12 = "Set current language.", + .docs_strs_l13 = "See version.", + .docs_strs_l14 = "See this help message.", + .docs_strs_l15 = "partition-size flags", + .docs_strs_l16 = "Only the size is displayed, the partition name etc is not displayed.", + .docs_strs_l17 = "Display size as byte.", + .docs_strs_l18 = "Display size as kilobyte.", + .docs_strs_l19 = "Display size as megabyte.", + .docs_strs_l20 = "Display size as gigabyte.", + .docs_strs_l21 = "Examples", + .docs_strs_l22 = "Report bugs and suggestions to", .or_str = "or", .usage_docstr = "Usage" }; @@ -194,18 +219,25 @@ struct langdb_docs LangDocTr = { .docs_strs_l1 = "[SEÇENEKLER] backup BÖLÜM [ÇIKTI] [SEÇENEKLER]...", .docs_strs_l2 = "[SEÇENEKLER] flash BÖLÜM DOSYA [SEÇENEKLER]...", .docs_strs_l3 = "[SEÇENEKLER] format BÖLÜM DOSYA_SİSTEMİ[ext/2/3/4] [SEÇENEKLER]...", - .docs_strs_l4 = "Seçenekler", - .docs_strs_l5 = "Mantıksal (logical) bölüm ile işlem yapın.", - .docs_strs_l6 = "Özel /dev bağlamı belirtin. Sadece normal bölümler içindir (Varsayılan: /dev/block/by-name).", - .docs_strs_l7 = "Bölümler listelenir.", - .docs_strs_l8 = "Bilgi ve uyarı mesajları susturulur.", - .docs_strs_l9 = "Zorlama modu. Bazı şeyler göz ardı edilir.", - .docs_strs_l10 = "Ayrıntılı bilgi modu. Daha fazla bilgi mesajı verilir.", - .docs_strs_l11 = "Mevcut dili ayarlayın.", - .docs_strs_l12 = "Sürümü görüntüleyin.", - .docs_strs_l13 = "Bu yardım mesajını görüntüleyin.", - .docs_strs_l14 = "Örnekler", - .docs_strs_l15 = "Sorunları ve önerileri şuraya bildirin:", + .docs_strs_l4 = "[SEÇENEKLER] partition-size BÖLÜM [SEÇENEKLER]...", + .docs_strs_l5 = "Seçenekler", + .docs_strs_l6 = "Mantıksal (logical) bölüm ile işlem yapın.", + .docs_strs_l7 = "Özel bir bölüm arama dizini belirtin. Sadece normal bölümler içindir (Varsayılan: /dev/block/by-name).", + .docs_strs_l8 = "Bölümler listelenir.", + .docs_strs_l9 = "Bilgi ve uyarı mesajları susturulur.", + .docs_strs_l10 = "Zorlama modu. Bazı şeyler göz ardı edilir.", + .docs_strs_l11 = "Ayrıntılı bilgi modu. Daha fazla bilgi mesajı verilir.", + .docs_strs_l12 = "Mevcut dili ayarlayın.", + .docs_strs_l13 = "Sürümü görüntüleyin.", + .docs_strs_l14 = "Bu yardım mesajını görüntüleyin.", + .docs_strs_l15 = "partition-size bayrakları", + .docs_strs_l16 = "Boyut görüntülenirken bölüm adı vb gibi bilgiler verilmez, sadece boyut görüntülenir.", + .docs_strs_l17 = "Boyutu bayt olarak görüntüleyin.", + .docs_strs_l18 = "Boyutu kilobayt olarak görüntüleyin.", + .docs_strs_l19 = "Boyutu megabyte olarak görüntüleyin.", + .docs_strs_l20 = "Boyutu gigabayt olarak görüntüleyin.", + .docs_strs_l21 = "Örnekler", + .docs_strs_l22 = "Sorunları ve önerileri şuraya bildirin:", .or_str = "yada", .usage_docstr = "Kullanımı" }; diff --git a/jni/ListPartitions.cpp b/jni/PartitionManager/ListPartitions.cpp similarity index 53% rename from jni/ListPartitions.cpp rename to jni/PartitionManager/ListPartitions.cpp index 0fc94d7..12a05c9 100755 --- a/jni/ListPartitions.cpp +++ b/jni/PartitionManager/ListPartitions.cpp @@ -25,49 +25,52 @@ using namespace PartitionManager; -#define CUR_DEV_CNTX "/dev/block/by-name" -#define LGC_DEV_CNTX "/dev/block/mapper" +#define CUR_DEV_SP "/dev/block/by-name" +#define LGC_DEV_SP "/dev/block/mapper" -static DIR *dir; +static DIR* Directory; static int -list(const string& operation, const char* target_dir) +ListDir(const string& TargetDir, const bool ListTargetDir = false) { static int count; - struct dirent **list; - bool list_parts = (operation == "print") ? true : false; + struct dirent **List; + bool ListParts = (ListTargetDir) ? true : false; - dir = nullptr; - dir = opendir(target_dir); + Directory = nullptr; + Directory = opendir(TargetDir.c_str()); - if (list_parts) + if (ListParts) { - count = scandir(target_dir, &list, nullptr, alphasort); + count = scandir(TargetDir.c_str(), &List, nullptr, alphasort); if (count < 0) - LOGE("%s: `%s': %s\n", Display::UsingDispString->not_readdir, target_dir, strqerror()); + LOGE("%s: `%s': %s\n", + Display::UsingDispString->not_readdir, + TargetDir.c_str(), + strqerror()); for (int i = 0; i < count; i++) { - if (list[i]->d_name[0] != '.' \ - && strncmp(list[i]->d_name, "com.", 4) != 0 \ - && strcmp(list[i]->d_name, "by-uuid") != 0 \ - && strcmp(list[i]->d_name, "userdata") != 0) - LOGD(" - [ %-16s ]\n", list[i]->d_name); + if (List[i]->d_name[0] != '.' + && strncmp(List[i]->d_name, "com.", 4) != 0 + && strcmp(List[i]->d_name, "by-uuid") != 0 + && strcmp(List[i]->d_name, "userdata") != 0) + LOGD(" - [ %-16s ]\n", List[i]->d_name); - free(list[i]); + free(List[i]); } - free(list); - list = nullptr; + free(List); + List = nullptr; goto directory; } directory: - if (dir != nullptr) + if (Directory != nullptr) { - closedir(dir); + closedir(Directory); return 0; } else @@ -79,33 +82,39 @@ directory: /* list existing partitions */ int Functions::ListPartitions(void) { - VLOGD("ListPartitions: selecting context...\n"); - string acc_cxt = (Booleans::UseCustomContext) ? Strings::CustomContext : CUR_DEV_CNTX; + VLOGD("ListPartitions: selecting search path...\n"); + string AccessDir = (Booleans::UseCustomSearchPath) ? Strings::CustomSearchPath : CUR_DEV_SP; - VLOGD("ListPartitions: trying to access `%s'...\n", acc_cxt.c_str()); - if (list("access", acc_cxt.c_str()) != 0) + VLOGD("ListPartitions: trying to access `%s'...\n", AccessDir.c_str()); + if (ListDir(AccessDir) != 0) { if (!Booleans::ForceMode) - LOGE("%s: `%s': %s\n", Display::UsingDispString->not_open, acc_cxt.c_str(), strqerror()); + LOGE("%s: `%s': %s\n", + Display::UsingDispString->not_open, + AccessDir.c_str(), + strqerror()); else return 1; } else { LOGD("%s:\n", Display::UsingDispString->list_of_general); - list("print", acc_cxt.c_str()); + ListDir(AccessDir, true); } if (Booleans::UsesLogical) { - VLOGD("ListPartitions: checking for listing `%s'...\n", LGC_DEV_CNTX); + VLOGD("ListPartitions: checking for listing `%s'...\n", LGC_DEV_SP); - if (list("access", LGC_DEV_CNTX) != 0) - LOGE("%s: `%s': %s\n", Display::UsingDispString->not_open, LGC_DEV_CNTX, strqerror()); + if (ListDir(LGC_DEV_SP) != 0) + LOGE("%s: `%s': %s\n", + Display::UsingDispString->not_open, + LGC_DEV_SP, + strqerror()); else { LOGD("\n%s:\n", Display::UsingDispString->list_of_logc); - list("print", LGC_DEV_CNTX); + ListDir(LGC_DEV_SP, true); } } diff --git a/jni/PartitionManager.cpp b/jni/PartitionManager/PartitionManager.cpp similarity index 69% rename from jni/PartitionManager.cpp rename to jni/PartitionManager/PartitionManager.cpp index cc4fa66..3a20a7e 100755 --- a/jni/PartitionManager.cpp +++ b/jni/PartitionManager/PartitionManager.cpp @@ -21,17 +21,19 @@ #define INC_STAT #define INC_LIBGEN #define INC_STRINGKEYS +#define IS_MAIN #include #include #include #include +#include /* add value to variables that are added globally and are not worth */ namespace PartitionManager { namespace Strings { string OutputName = ""; - string CustomContext = ""; + string CustomSearchPath = ""; string TargetPartition = ""; string TargetFlashFile = ""; string TargetFormatFS = ""; @@ -42,22 +44,27 @@ namespace PartitionManager { namespace Booleans { bool UseLogical = false; - bool UseCustomContext = false; + bool UseCustomSearchPath = false; bool UsesSlots = false; bool UsesLogical = false; + bool OnlyViewSize = false; bool SilentEnabled = false; bool FlashMode = false; bool BackupMode = false; bool FormatMode = false; + bool PartSizeViewMode = false; bool ForceMode = false; bool VerboseMode = false; bool InstalledOnTermux = false; - bool ActivateRoot = false; } /* namespace Booleans */ + + namespace Integers { + int PartSizeViewType = VIEW_AS_MIB; + } /* namespace Integers */ } /* namespace PartitionManager */ /* variable for use in control of '-' expression */ -static string common_symbol_rule; +static string SymbolRule; namespace PartitionManager { namespace Functions { @@ -67,19 +74,19 @@ namespace Functions { * the beginning of the given word */ static void -CheckOptSymbol(const string symbol) +CheckOptSymbol(const string& Symbol) { - if (!symbol.empty()) + if (!Symbol.empty()) { - if (strncmp(symbol.c_str(), "-", 1) == 0) - LOGE("%s\n", common_symbol_rule.c_str()); + if (strncmp(Symbol.c_str(), "-", 1) == 0) + LOGE("%s\n", SymbolRule.c_str()); } } static bool -ControlArg(const char* argv_holder) +ControlArg(const char* ArgvHolder) { - if (argv_holder[0] != '-') + if (ArgvHolder[0] != '-') return true; return false; @@ -93,15 +100,16 @@ deprecated(const char opt, const char* deprecation_message, const char* opt_long { VLOGE("Deprecated Option: -%c (--%s). Printing error...\n", opt, opt_long); DEPR_HANDLE(opt, opt_long, deprecation_message); + exit(1); } static void -PrContextInput(const string& context) +PrSpInput(const string& sp) { - PartitionManager::Booleans::UseCustomContext = true; - PartitionManager::Strings::CustomContext = context; - PartitionManager::Functions::CheckOptSymbol(PartitionManager::Strings::CustomContext); + PartitionManager::Booleans::UseCustomSearchPath = true; + PartitionManager::Strings::CustomSearchPath = sp; + PartitionManager::Functions::CheckOptSymbol(PartitionManager::Strings::CustomSearchPath); } using namespace PartitionManager; @@ -137,7 +145,7 @@ public: } } - virtual void ArgumentProcessor(int searchOn, int total, char** arguments) { /* dummy, it's place holder */ } + virtual void ArgumentProcessor(int searchOn, int total, char** arguments) { /* dummy */ } }; class PartitionManagerBackup : public PartitionManagerBase { @@ -218,6 +226,25 @@ public: } }; +class PartitionManagerPartSize : public PartitionManagerBase { +public: + void ArgumentProcessor(int searchOn, int total, char** arguments) override + { + BaseFunctionName = "partition-size"; + StartCode = 4; + IsRequiredOnlyOneArg = true; + + GenericNumericalController(searchOn, total, Display::UsingDispString->expected_partsz_arg); + + if (Functions::ControlArg(arguments[searchOn])) + Strings::TargetPartition = arguments[searchOn]; + else + LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + + Functions::CheckOptSymbol(Strings::TargetPartition); + } +}; + int main(int argc, char** argv) { Strings::ExecutingName = basename(argv[0]); @@ -237,6 +264,7 @@ int main(int argc, char** argv) PartitionManagerBackup BackupArgProcessorBase; PartitionManagerFlash FlashArgProcessorBase; PartitionManagerFormat FormatArgProcessorBase; + PartitionManagerPartSize PartSizeArgProcessorBase; VLOGD("Main function started. Setting up locale. Calling 'setlocale '\n"); setlocale(LC_ALL, ""); @@ -272,7 +300,7 @@ int main(int argc, char** argv) abort(); } - common_symbol_rule = Display::UsingDispString->common_symbol_rule; + SymbolRule = Display::UsingDispString->symbol_rule; argc = argc_n; int argc_parse = (argc - 1); char** args_ctrl = args; @@ -285,6 +313,7 @@ int main(int argc, char** argv) static bool MultipleViewers = false; static bool SetLanguageReq = false; static bool SomeSpec = false; + static bool PartSizeArgSpeficed = false; static char* SpeficedLanguagePr; static string Option; static string Target; @@ -310,26 +339,38 @@ int main(int argc, char** argv) { case '-': if (Option == "--backup") - deprecated('b', Display::UsingDispString->depr_backup_opt, "backup"); + deprecated('b', + Display::UsingDispString->depr_backup_opt, + "backup"); else if (Option == "--flash") - deprecated('F', Display::UsingDispString->depr_flash_opt, "flash"); + deprecated('F', + Display::UsingDispString->depr_flash_opt, + "flash"); else if (Option == "--format") - deprecated('r', Display::UsingDispString->depr_format_opt, "format"); + deprecated('r', + Display::UsingDispString->depr_format_opt, + "format"); else if (Option == "--license") - deprecated('L', Display::UsingDispString->depr_Vlicense_opt, "license"); + deprecated('L', + Display::UsingDispString->depr_Vlicense_opt, + "license"); + else if (Option == "--context") + deprecated('c', + Display::UsingDispString->depr_ch_sp_opt, + "context"); else if (Option == "--logical") { VLOGD("Logical partition type specified.\n"); LogicalSpeficy = true; break; } - else if (Option == "--context") + else if (Option == "--search-path") { - VLOGD("Custom context specified.\n"); + VLOGD("Custom search path specified.\n"); if (argc_parse > 1) - PrContextInput(args_ctrl[1]); + PrSpInput(args_ctrl[1]); else - LOGE("--context: %s.\n%s `%s --help' %s.\n", \ + LOGE("--search-path: %s.\n%s `%s --help' %s.\n", \ Display::UsingDispString->is_requires_arg, \ Display::UsingDispString->try_h, \ Strings::ExecutingName.c_str(), \ @@ -372,11 +413,41 @@ int main(int argc, char** argv) SpeficedLanguagePr = args_ctrl[1]; } else - LOGE("--set-language: %s.\n%s `%s --help' %s.\n", \ - Display::UsingDispString->is_requires_arg, \ - Display::UsingDispString->try_h, \ - Strings::ExecutingName.c_str(), \ - Display::UsingDispString->for_more); + LOGE("--set-language: %s.\n%s `%s --help' %s.\n", + Display::UsingDispString->is_requires_arg, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); + break; + } + else if (Option == "--as-byte") + { + PartSizeArgSpeficed = true; + Integers::PartSizeViewType = VIEW_AS_BYTE; + break; + } + else if (Option == "--as-kilobyte") + { + PartSizeArgSpeficed = true; + Integers::PartSizeViewType = VIEW_AS_KIB; + break; + } + else if (Option == "--as-megabyte") + { + PartSizeArgSpeficed = true; + Integers::PartSizeViewType = VIEW_AS_MIB; + break; + } + else if (Option == "--as-gigabyte") + { + PartSizeArgSpeficed = true; + Integers::PartSizeViewType = VIEW_AS_GIB; + break; + } + else if (Option == "--only-size") + { + PartSizeArgSpeficed = true; + Booleans::OnlyViewSize = true; break; } else if (Option == "--version") @@ -398,46 +469,59 @@ int main(int argc, char** argv) else { VLOGE("Unknown Option: %s\n", args_ctrl[0]); - LOGE("%s: %s.\n%s `%s --help' %s.\n", args_ctrl[0], \ - Display::UsingDispString->unknw_arg, \ - Display::UsingDispString->try_h, \ - Strings::ExecutingName.c_str(), \ - Display::UsingDispString->for_more); + LOGE("%s: %s.\n%s `%s --help' %s.\n", args_ctrl[0], + Display::UsingDispString->unknw_arg, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); } break; case 'b': - deprecated('b', Display::UsingDispString->depr_backup_opt, "backup"); + deprecated('b', + Display::UsingDispString->depr_backup_opt, + "backup"); break; case 'F': - deprecated('F', Display::UsingDispString->depr_flash_opt, "flash"); + deprecated('F', + Display::UsingDispString->depr_flash_opt, + "flash"); break; case 'r': - deprecated('r', Display::UsingDispString->depr_format_opt, "format"); + deprecated('r', + Display::UsingDispString->depr_format_opt, + "format"); break; case 'L': - deprecated('L', Display::UsingDispString->depr_Vlicense_opt, "license"); + deprecated('L', + Display::UsingDispString->depr_Vlicense_opt, + "license"); break; case 'D': - deprecated('D', Display::UsingDispString->depr_ch_list_opt); + deprecated('D', + Display::UsingDispString->depr_ch_list_opt); break; + case 'c': + deprecated('c', + Display::UsingDispString->depr_ch_sp_opt, + "context"); case 'l': VLOGD("Logical partition type specified.\n"); LogicalSpeficy = true; continue; - case 'c': - VLOGD("Custom context speficed.\n"); + case 'P': + VLOGD("Custom search path speficed.\n"); if (argc_parse > 1) { - VLOGE("Context inputs: getting inputs...\n"); - PrContextInput(args_ctrl[1]); + VLOGE("Search-path inputs: getting inputs...\n"); + PrSpInput(args_ctrl[1]); continue; } else - LOGE("-c: %s.\n%s `%s --help' %s.\n", \ - Display::UsingDispString->is_requires_arg, \ - Display::UsingDispString->try_h, \ - Strings::ExecutingName.c_str(), \ - Display::UsingDispString->for_more); + LOGE("-P: %s.\n%s `%s --help' %s.\n", + Display::UsingDispString->is_requires_arg, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); break; case 'p': VLOGD("It was requested to list the partitions.\n"); @@ -467,11 +551,11 @@ int main(int argc, char** argv) continue; } else - LOGE("-S: %s.\n%s `%s --help' %s.\n", \ - Display::UsingDispString->is_requires_arg, \ - Display::UsingDispString->try_h, \ - Strings::ExecutingName.c_str(), \ - Display::UsingDispString->for_more); + LOGE("-S: %s.\n%s `%s --help' %s.\n", + Display::UsingDispString->is_requires_arg, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); case 'v': VLOGD("The version info was requested to be displayed.\n"); ViewVersion = true; @@ -482,11 +566,12 @@ int main(int argc, char** argv) break; default: VLOGE("Unknown Option: -%c\n", args_ctrl[0][x]); - LOGE("-%c: %s.\n%s `%s --help' %s.\n", args_ctrl[0][x], \ - Display::UsingDispString->unknw_arg, \ - Display::UsingDispString->try_h, \ - Strings::ExecutingName.c_str(), \ - Display::UsingDispString->for_more); + LOGE("-%c: %s.\n%s `%s --help' %s.\n", + args_ctrl[0][x], + Display::UsingDispString->unknw_arg, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); } break; @@ -539,6 +624,12 @@ int main(int argc, char** argv) Booleans::FormatMode = true; break; } + else if (Target == "partition-size") + { + Base = &PartSizeArgProcessorBase; + Booleans::PartSizeViewMode = true; + break; + } else { Target = ""; @@ -566,13 +657,21 @@ int main(int argc, char** argv) if (Display::UsingDispString->welcome_ != nullptr) LOGD("%s", Display::UsingDispString->welcome_); - LOGD("%s %s %s %s.\n", Display::UsingDispString->language, Display::UsingDispString->welcome, Display::UsingDispString->by_str, Display::UsingDispString->lang_by_s); + LOGD("%s %s %s %s.\n", + Display::UsingDispString->language, + Display::UsingDispString->welcome, + Display::UsingDispString->by_str, + Display::UsingDispString->lang_by_s); } /* check argument total */ VLOGD("argc (arguments) total: %d.\n", argc); if (argc < 2) - LOGE("%s.\n%s '%s --help' %s.\n", Display::UsingDispString->missing_operand, Display::UsingDispString->try_h, Strings::ExecutingName.c_str(), Display::UsingDispString->for_more); + LOGE("%s.\n%s '%s --help' %s.\n", + Display::UsingDispString->missing_operand, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); /* stop the program if multiple viewer is used */ if (MultipleViewers) @@ -581,6 +680,12 @@ int main(int argc, char** argv) LOGE("%s\n", Display::UsingDispString->multiple_wiewers); } + if (!Booleans::PartSizeViewMode && PartSizeArgSpeficed) + { + VLOGE("Related flags were detected, although some partition size was not requested.\n"); + LOGE("%s.\n", Display::UsingDispString->only_partsz_args); + } + /* controller to handle viewer */ if (ViewHelp) { @@ -607,23 +712,32 @@ int main(int argc, char** argv) if (SetLanguageReq) { VLOGD("The language was asked to adjust. Calling SetLanguage()...\n"); - LOGD("%s: %s\n", Strings::ExecutingName.c_str(), Display::UsingDispString->switching_lang); + LOGD("%s: %s\n", + Strings::ExecutingName.c_str(), + Display::UsingDispString->switching_lang); Functions::SetLanguage(SpeficedLanguagePr, 0); sleep(2); VLOGD("SetLanguage() completed.\n"); - LOGD("%s: %s.\n", Strings::ExecutingName.c_str(), Display::UsingDispString->please_rerun); + LOGD("%s: %s.\n", + Strings::ExecutingName.c_str(), + Display::UsingDispString->please_rerun); return 0; } if (Target.empty()) { VLOGE("There's no job to do.\n"); - LOGD("%s: %s.\n", Strings::ExecutingName.c_str(), Display::UsingDispString->missing_operand); + LOGD("%s: %s.\n", + Strings::ExecutingName.c_str(), + Display::UsingDispString->missing_operand); if (SomeSpec) LOGD("%s.\n", Display::UsingDispString->some_spec); - LOGD("%s '%s --help' %s.\n",Display::UsingDispString->try_h, Strings::ExecutingName.c_str(), Display::UsingDispString->for_more); + LOGD("%s '%s --help' %s.\n", + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); exit(1); } @@ -637,7 +751,9 @@ int main(int argc, char** argv) && Strings::TargetFormatFS != "ext2") { VLOGE("Unsupported file system: %s.\n", Strings::TargetFormatFS.c_str()); - LOGE("%s: %s\n", Display::UsingDispString->unsupported_fs, Strings::TargetFormatFS.c_str()); + LOGE("%s: %s\n", + Display::UsingDispString->unsupported_fs, + Strings::TargetFormatFS.c_str()); } } @@ -662,35 +778,49 @@ int main(int argc, char** argv) SearchResult = Functions::GetState(Strings::TargetFlashFile); if (SearchResult == 1) - LOGE("%s: `%s': %s\n", Display::UsingDispString->cannot_stat, Strings::TargetFlashFile.c_str(), strqerror()); + LOGE("%s: `%s': %s\n", + Display::UsingDispString->cannot_stat, + Strings::TargetFlashFile.c_str(), + strqerror()); else if (SearchResult == -1) - LOGE("`%s': %s\n", Strings::TargetFlashFile.c_str(), Display::UsingDispString->not_file); + LOGE("`%s': %s\n", + Strings::TargetFlashFile.c_str(), + Display::UsingDispString->not_file); } - /* custom context checker */ - if (Booleans::UseCustomContext) + /* custom search path checker */ + if (Booleans::UseCustomSearchPath) { - VLOGD("The status of the \"dev\" is controlled in the specified custom /dev context...\n"); - if (strncmp(Strings::CustomContext.c_str(), "/dev", 4) != 0) + VLOGD("The status of the \"dev\" is controlled in the specified custom /dev search path...\n"); + if (strncmp(Strings::CustomSearchPath.c_str(), "/dev", 4) != 0) { if (!Booleans::ForceMode) LOGE("%s\n", Display::UsingDispString->not_in_dev); } - VLOGD("The specified custom /dev context is being put in countless...\n"); - SearchResult = Functions::GetState(Strings::CustomContext, "dir"); + VLOGD("The specified custom /dev search path is being put in countless...\n"); + SearchResult = Functions::GetState(Strings::CustomSearchPath, "dir"); if (SearchResult == 1) - LOGE("%s: `%s': %s\n", Display::UsingDispString->cannot_stat, Strings::CustomContext.c_str(), strqerror()); + LOGE("%s: `%s': %s\n", + Display::UsingDispString->cannot_stat, + Strings::CustomSearchPath.c_str(), + strqerror()); else if (SearchResult == -1) - LOGE("`%s': %s\n", Strings::CustomContext.c_str(), Display::UsingDispString->not_dir); + LOGE("`%s': %s\n", + Strings::CustomSearchPath.c_str(), + Display::UsingDispString->not_dir); } VLOGD("The partition specification status is controlled...\n"); if (Strings::TargetPartition.empty()) { if (!Booleans::ForceMode) - LOGE("%s\n%s `%s --help' %s\n", Display::UsingDispString->req_part_name, Display::UsingDispString->try_h, Strings::ExecutingName.c_str(), Display::UsingDispString->for_more); + LOGE("%s\n%s `%s --help' %s\n", + Display::UsingDispString->req_part_name, + Display::UsingDispString->try_h, + Strings::ExecutingName.c_str(), + Display::UsingDispString->for_more); } else { diff --git a/jni/PartitionManager/PartitionTool.cpp b/jni/PartitionManager/PartitionTool.cpp new file mode 100755 index 0000000..d717010 --- /dev/null +++ b/jni/PartitionManager/PartitionTool.cpp @@ -0,0 +1,92 @@ +/* By YZBruh */ + +/** + * Copyright 2024 Partition Manager + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INC_MAIN_LIBS + +#include +#include + +static int +GetProperty(const char* _Nonnull property, const char* desired_val, const char* desired_val2 = nullptr) +{ + char val[PROP_VALUE_MAX]; + int len = __system_property_get(property, val); + + VLOGD("GetProperty: get property value: '%s'\n", property); + if (len > 0) + { + VLOGD("GetProperty: %s=%s\n", property, val); + + VLOGD("GetProperty: comparing '%s' property value '%s'\n", property, desired_val); + if (strcmp(val, desired_val) == 0) + { + VLOGD("GetProperty: '%s' is '%s'. Stop (0).\n", property, desired_val); + return 0; + } + else + { + VLOGE("GetProperty: '%s' property is not '%s'. Comparing desired value 2 (if speficed).\n", property, desired_val); + + if (desired_val2 != nullptr) + { + if (strcmp(val, desired_val2) == 0) + { + VLOGD("GetProperty: '%s' is '%s'.Stop (0).\n", property, desired_val2); + return 0; + } + else + { + VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val2); + return 1; + } + } + else + { + VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val); + return 1; + } + } + } + else + { + VLOGE("GetProperty: cannot get property '%s'. No such property or empty. Stop (1).\n", property); + return 1; + } + + return 2; +} + +using namespace PartitionManager; + +/* check parts */ +void Functions::CheckDevPoint(void) +{ + /* true = ab | false = a only */ + Booleans::UsesSlots = (GetProperty("ro.boot.slot_suffix", "_a", "_b") == 0 || GetProperty("ro.boot.slot", "_a", "_b") == 0) ? true : false; + + if (Booleans::UsesSlots) + VLOGW("CheckDevPoint: 1 warning generated: A/B partitions status.\n"); + + /* true = logical | false = normal */ + Booleans::UsesLogical = (GetProperty("ro.boot.dynamic_partitions", "true") == 0) ? true : false; + + if (Booleans::UsesLogical) + VLOGW("CheckDevPoint: 1 warning generated: logical partitions status.\n"); +} + +/* end of code */ diff --git a/jni/Root.cpp b/jni/PartitionManager/Root.cpp similarity index 100% rename from jni/Root.cpp rename to jni/PartitionManager/Root.cpp diff --git a/jni/PartitionManager/Tools.cpp b/jni/PartitionManager/Tools.cpp new file mode 100755 index 0000000..c68f70c --- /dev/null +++ b/jni/PartitionManager/Tools.cpp @@ -0,0 +1,347 @@ +/* By YZBruh */ + +/** + * Copyright 2024 Partition Manager + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INC_MAIN_LIBS +#define INC_STAT +#define INC_LIBGEN +#define INC_DEBUGERS +#define INC_TOOLS_REQS +#define INC_STRINGKEYS + +#include +#include +#include + +namespace PartitionManager { +namespace Functions { + +/** + * it is meant to calculate the size of the quickly given file. + * its purpose is for rapid processing + */ +static long long +CalculateSizeLongLong(const string& fp) +{ + VLOGD("CalculateSizeLongLong: calculating file size: `%s'\n", fp.c_str()); + + VLOGD("CalculateSizeLongLong: reading `%s' with 'ifstream '\n", fp.c_str()); + ifstream file(fp, ios::binary | ios::ate); + + return (!file) ? -1 : static_cast(file.tellg()); +} + +/** + * error that the partition is not found. + * It's for quick action. + */ +static void +PartitionNotFound(const char* p) { LOGE("%s: %s\n", p, Display::UsingDispString->part_not_found); } + +/* the partitions are meant to quickly find. */ +static void +SearchPartition(const string& fp) +{ + VLOGD("SearchPartition: calling GetState()...\n"); + static int op = GetState(fp, "blk"); + + if (op == 1) + PartitionNotFound(basename(fp.c_str())); + else if (op == -1 && !Booleans::ForceMode) + LOGE("%s\n", Display::UsingDispString->not_block); +} + +static void +PrintInfo(ushort_t pcode, double psz, double fsz) +{ + LOGD("##########################################\n"); + LOGD("# --> %s: %s\n", + Display::UsingDispString->part_name, + Strings::TargetPartition.c_str()); + LOGD("# --> %s: %s\n", + Display::UsingDispString->part_type, + (Booleans::UseLogical) ? Display::UsingDispString->yes : Display::UsingDispString->no); + + if (psz != -1) + LOGD("# --> %s: %.2fMB\n", + Display::UsingDispString->part_disk_sz, + psz); + else + LOGD("# --> %s: %s\n", + Display::UsingDispString->warn, + Display::UsingDispString->part_disk_sz_fail); + + if (pcode == 3) + { + if (fsz != -1) + LOGD("# --> %s: %.2fMB\n", + Display::UsingDispString->flash_file_sz, + fsz); + else + LOGW("# --> %s: %s\n", + Display::UsingDispString->warn, + Display::UsingDispString->flash_file_sz_fail); + } + + LOGD("##########################################\n"); +} + +static bool +IsDoubleOf1024(float size) +{ + float num = size / 1024; + char str[35]; + sprintf(str, "%f", num); + + return (strstr(str, ".000000") != nullptr) ? true : false; +} + +} /* namespace Functions */ +} /* namespace PartitionManager */ + +using namespace PartitionManager; + +int Functions::Start(ushort_t progress_code) +{ + /* Some required variables */ + fstream sourceF, targetF; + string accessPrefix, opName; + long long copiedData = 0; + bool IsFirstProcessOnTarget = true; + + if (Booleans::UseLogical) + accessPrefix = "/dev/block/mapper/" + Strings::TargetPartition; + else + accessPrefix = (Booleans::UseCustomSearchPath) ? (Strings::CustomSearchPath) + ("/") + (Strings::TargetPartition) : ("/dev/block/by-name/") + (Strings::TargetPartition); + + VLOGD("PartitionManager: calling SearchPartition() for searching partition (path); `%s'\n", accessPrefix.c_str()); + Functions::SearchPartition(accessPrefix); + + static long long count = (long long)(CalculateSizeLongLong(accessPrefix) + ((1024 * 1024) * 4)); + const int BFSIZE = (Functions::IsDoubleOf1024((float)Functions::CalculateSizeLongLong(accessPrefix))) ? 1024 : 1; + char buffer[BFSIZE]; + double FlashFileSize = 0; + + double PartitionSize = (double)(static_cast(Functions::CalculateSizeLongLong(accessPrefix)) / (1024 * 1024)); + if (!Strings::TargetFlashFile.empty()) + FlashFileSize = (double)(static_cast(Functions::CalculateSizeLongLong(Strings::TargetFlashFile)) / (1024 * 1024)); + + if (progress_code != 4) PrintInfo(progress_code, PartitionSize, FlashFileSize); + + if (progress_code == 1) + { + VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", accessPrefix.c_str()); + sourceF.open(accessPrefix, ios::binary | ios::in); + if (!sourceF.is_open()) + LOGE("%s: %s: %s\n", + Display::UsingDispString->not_read, + accessPrefix.c_str(), + strqerror()); + + /* determine output */ + if (Strings::OutputName == Strings::TargetPartition) + { + opName = Strings::OutputName + ".img"; + VLOGW("PartitionManager: output not speficed. Selecting automaticly.\n"); + LOGW("%s: %s\n", + Display::UsingDispString->out_not_spec, + opName.c_str()); + } + else + opName = Strings::OutputName; + + VLOGD("Checking output status...\n"); + if (GetState(opName) == 0) + LOGE("'%s': File exits.\n", opName.c_str()); + + VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", opName.c_str()); + targetF.open(opName, ios::binary | ios::out); + if (!targetF.is_open()) + LOGE("%s: %s: %s\n", + Display::UsingDispString->not_gen, + opName.c_str(), + strqerror()); + + VLOGD("PartitionManager: read (partition) and write (output) 'read, write '\n"); + /* start writing */ + while (sourceF.read(buffer, BFSIZE) && copiedData < count) + { + if (GetState(opName) != 0 && IsFirstProcessOnTarget) + LOGE("%s\n", Display::UsingDispString->no_found_on_process); + + streamsize readed_data = sourceF.gcount(); + targetF.write(buffer, readed_data); + + if (targetF.fail() || targetF.bad()) + { + if (Functions::GetState(opName) == 0) + remove(opName.c_str()); + LOGF("%s: %s: %s\n", + Display::UsingDispString->not_write, + opName.c_str(), + strqerror()); + } + + IsFirstProcessOnTarget = false; + copiedData += readed_data; + } + + /* close files */ + sourceF.close(); + targetF.close(); + + LOGD("%s: %s\n", + Display::UsingDispString->success_backup, + opName.c_str()); + } + else if (progress_code == 2) + { + if (PartitionSize != -1 && FlashFileSize != -1) + { + if (FlashFileSize > PartitionSize && !Booleans::ForceMode) + LOGE("%s\n", Display::UsingDispString->ffile_more_part); + } + + VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", Strings::TargetFlashFile.c_str()); + sourceF.open(Strings::TargetFlashFile, ios::binary | ios::in); + if (!sourceF.is_open()) + LOGF("%s: %s: %s\n", + Display::UsingDispString->not_read, + Strings::TargetFlashFile.c_str(), + strqerror()); + + VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", accessPrefix.c_str()); + targetF.open(accessPrefix, ios::binary | ios::in | ios::out | ios::trunc); + if (!targetF.is_open()) + LOGF("%s: %s: %s\n", + Display::UsingDispString->not_read, + accessPrefix.c_str(), + strqerror()); + + VLOGD("PartitionManager: read (flash file) and write (partition) 'read, write '\n"); + /* start writing */ + while (sourceF.read(buffer, BFSIZE) && copiedData < count) + { + streamsize readed_data = sourceF.gcount(); + targetF.write(buffer, readed_data); + + if (targetF.fail() || targetF.bad()) + LOGF("%s: %s: %s\n", + Display::UsingDispString->not_write, + accessPrefix.c_str(), + strqerror()); + + copiedData += readed_data; + } + + sourceF.close(); + targetF.close(); + + LOGD("%s.\n", Display::UsingDispString->success_flash); + } + else if (progress_code == 3) + { + /* get target partition block size */ + VLOGD("PartitionManager: getting block size `%s' with 'statfs '\n", accessPrefix.c_str()); + + struct statfs file_sys_inf; + if (statfs(accessPrefix.c_str(), &file_sys_inf) != 0) + LOGE("%s\n", Display::UsingDispString->cannot_get_bsz); + + /* generate mke2fs argument list */ + VLOGD("PartitionManager: generating mke2fs argument list...\n"); + char bsize[25] = ""; + sprintf(bsize, "%lu", file_sys_inf.f_bsize); + char* arguments[] = { + "mke2fs-static", + "-Fq", + "-t", + (char*)Strings::TargetFormatFS.c_str(), + "-b", + (char*)bsize, + (char*)accessPrefix.c_str(), + }; + + LOGD("%s: `%s'. %s: %s\n", + Display::UsingDispString->formatting, + accessPrefix.c_str(), + Display::UsingDispString->fs_str, + Strings::TargetFormatFS.c_str()); + + /* run mke2fs */ + VLOGD("PartitionManager: calling mke2fs_main...\n"); + if (mke2fs_main(sizeof(arguments), arguments) != 0) + LOGF("%s\n", Display::UsingDispString->format_fail); + + LOGD("%s.\n", Display::UsingDispString->success_format); + } + else if (progress_code == 4) + { + VLOGD("PartitionManager: getting size of '%s' (long long)\n", accessPrefix.c_str()); + long long psize = (long long)CalculateSizeLongLong(accessPrefix); + + if (psize == -1) + { + VLOGE("PartitionManager: cannot get partition size!\n"); + LOGE("%s: %s\n", + Display::UsingDispString->fail_get_psize, + strqerror()); + } + + static char* SizeType; + static char Holder[50]; + + if (!Booleans::OnlyViewSize) + { + sprintf(Holder, "%s: ", Strings::TargetPartition.c_str()); + + if (Integers::PartSizeViewType == VIEW_AS_BYTE) SizeType = "B"; + else if (Integers::PartSizeViewType == VIEW_AS_KIB) SizeType = "KB"; + else if (Integers::PartSizeViewType == VIEW_AS_MIB) SizeType = "MB"; + else if (Integers::PartSizeViewType == VIEW_AS_GIB) SizeType = "GB"; + } + else + SizeType = ""; + + VLOGD("PartitionManager: Displaying partition size...\n"); + + if (Integers::PartSizeViewType == VIEW_AS_BYTE) + LOGD("%s%llu%s\n", + Holder, + (long long)psize, + SizeType); + else if (Integers::PartSizeViewType == VIEW_AS_KIB) + LOGD("%s%lu%s\n", + Holder, + (long)(psize / 1024), + SizeType); + else if (Integers::PartSizeViewType == VIEW_AS_MIB) + LOGD("%s%.2f%s\n", + Holder, + (double)(static_cast(psize) / (1024 * 1024)), + SizeType); + else if (Integers::PartSizeViewType == VIEW_AS_GIB) + LOGD("%s%.2f%s\n", + Holder, + (double)(static_cast(psize) / (1024 * 1024 * 1024)), + SizeType); + } + + return 0; +} + +/* end of code */ diff --git a/jni/Version.cpp b/jni/PartitionManager/Version.cpp similarity index 61% rename from jni/Version.cpp rename to jni/PartitionManager/Version.cpp index dfd66cd..10cb1be 100755 --- a/jni/Version.cpp +++ b/jni/PartitionManager/Version.cpp @@ -28,24 +28,47 @@ using namespace PartitionManager; void Functions::DisplayVersion(void) { VLOGD("DisplayVersion: printing main info...\n"); - LOGD("%s %s %d.%d.%d (C++) (%d%d%d) ", Strings::ExecutingName.c_str(), Display::UsingDispString->version_str, PMT_MAJOR, PMT_MINOR, PMT_PATCHLEVEL, PMT_MAJOR, PMT_MINOR, PMT_PATCHLEVEL); + LOGD("%s %s %d.%d.%d (%d%d%d / C++) ", + Strings::ExecutingName.c_str(), + Display::UsingDispString->version_str, + PMT_MAJOR, + PMT_MINOR, + PMT_PATCHLEVEL, + PMT_MAJOR, + PMT_MINOR, + PMT_PATCHLEVEL); #if __SIZEOF_POINTER__ == 4 LOGD("32-bit %s\n", Display::UsingDispString->bin_str); #elif __SIZEOF_POINTER__ == 8 LOGD("64-bit %s\n", Display::UsingDispString->bin_str); #else - LOGD("<%s> %s\n", Display::UsingDispString->unknw_str, Display::UsingDispString->bin_str); + LOGD("<%s> %s\n", + Display::UsingDispString->unknw_str, + Display::UsingDispString->bin_str); #endif + LOGD("mke2fs %s %s (%s)\n", + Display::UsingDispString->version_str, + E2FSPROGS_VERSION_PRIVATE, + E2FSPROGS_DATE); + LOGD("libext2fs %s %s (%s / %s)\n", + Display::UsingDispString->version_str, + E2FSPROGS_VERSION_PRIVATE, + EXT2FS_LIB_VERSION_PRIVATE, + E2FSPROGS_DATE); + VLOGD("DisplayVersion: build type: "); + if (Booleans::VerboseMode) #if defined(__clang__) && !defined(__NDK_BUILD) - if (Booleans::VerboseMode) printf("clang (manual).\n"); - LOGD("%s: clang %d.%d.%d\n", Display::UsingDispString->compiler_str, __clang_major__, __clang_minor__, __clang_patchlevel__); + LOGD("pmt %s: clang %d.%d.%d\n", + Display::UsingDispString->compiler_str, + __clang_major__, + __clang_minor__, + __clang_patchlevel__); #elif defined(__NDK_BUILD) - if (Booleans::VerboseMode) printf("NDK.\n"); LOGD("\n%s\n", __NDK_CXX_VERSION__); #endif diff --git a/jni/PartitionTool.cpp b/jni/PartitionTool.cpp deleted file mode 100755 index 7a8927f..0000000 --- a/jni/PartitionTool.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* By YZBruh */ - -/** - * Copyright 2024 Partition Manager - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define INC_MAIN_LIBS - -#include - -using namespace PartitionManager; - -static bool -accf(const string fp) -{ - VLOGD("accf : trying to access `%s' with 'access '\n", fp.c_str()); - - return (access(fp.c_str(), F_OK) == 0) ? true : false; -} - -/* check parts */ -void Functions::CheckDevPoint(void) -{ - VLOGD("CheckDevPoint: selecting context...\n"); - string dpoint = (Booleans::UseCustomContext) ? Strings::CustomContext : "/dev/block/by-name"; - - /* true = ab | false = a only */ - Booleans::UsesSlots = (accf(dpoint + "/boot_a")) ? true : false; - - if (Booleans::UsesSlots) - VLOGW("CheckDevPoint: 1 warning generated: A/B status.\n"); - - /* true = logical | false = normal */ - Booleans::UsesLogical = (accf(dpoint + "/super")) ? true : false; - - if (Booleans::UsesLogical) - VLOGW("CheckDevPoint: 1 warning generated: logical partitions status.\n"); -} - -/* end of code */ diff --git a/jni/Tools.cpp b/jni/Tools.cpp deleted file mode 100755 index be8519d..0000000 --- a/jni/Tools.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* By YZBruh */ - -/** - * Copyright 2024 Partition Manager - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define INC_MAIN_LIBS -#define INC_STAT -#define INC_DEBUGERS -#define INC_TOOLS_REQS -#define INC_STRINGKEYS - -#include - -namespace PartitionManager { -namespace Functions { - -/** - * it is meant to calculate the size of the quickly given file. - * its purpose is for rapid processing - */ -static double -CalculateSizeDouble(const string& fp) -{ - VLOGD("CalculateSizeDouble: calculating file size: `%s'\n", fp.c_str()); - - VLOGD("CalculateSizeDouble: reading `%s' with 'ifstream '\n", fp.c_str()); - ifstream target(fp, ios::binary | ios::ate); - - return (!target) ? -1 : static_cast(target.tellg()) / (1024 * 1024); -} - -static long long -CalculateSizeLongLong(const string& fp) -{ - VLOGD("CalculateSizeLongLong: calculating file size: `%s'\n", fp.c_str()); - - VLOGD("CalculateSizeLongLong: reading `%s' with 'ifstream '\n", fp.c_str()); - ifstream target(fp, ios::binary | ios::ate); - - return (!target) ? -1 : static_cast(target.tellg()); -} - -/** - * error that the partition is not found. - * It's for quick action. - */ -static void -PartitionNotFound(const char* p) { LOGE("`%s': %s\n", p, Display::UsingDispString->part_not_found); } - -/* the partitions are meant to quickly find. */ -static void -SearchPartition(const string& fp) -{ - VLOGD("SearchPartition: calling GetState()...\n"); - static int op = GetState(fp, "blk"); - - if (op == 1) - PartitionNotFound(fp.c_str()); - else if (op == -1 && !Booleans::ForceMode) - LOGE("%s\n", Display::UsingDispString->not_block); -} - -} /* namespace Functions */ -} /* namespace PartitionNotFound */ - -using namespace PartitionManager; - -/* to stop use of function type */ -#define PartitionNotFound Functions::PartitionNotFound() - -int Functions::Start(unsigned short progress_code) -{ - /* required variables */ - static fstream sourceF; - static fstream targetF; - static string accessPrefix; - static string opName; - static int BFSIZE = 1; - static char formatterCmd[200]; - static long long copiedData = 0; - - if (Booleans::UseLogical) - accessPrefix = "/dev/block/mapper/" + Strings::TargetPartition; - else - accessPrefix = (Booleans::UseCustomContext) ? (Strings::CustomContext) + ("/") + (Strings::TargetPartition) : ("/dev/block/by-name/") + (Strings::TargetPartition); - - VLOGD("PartitionManager: calling SearchPartition() for searching partition (path); `%s'\n", accessPrefix.c_str()); - Functions::SearchPartition(accessPrefix); - - static long long count = (long long)(CalculateSizeLongLong(accessPrefix) + ((1024 * 1024) * 10)); - - BFSIZE = (int)(CalculateSizeLongLong(accessPrefix) / (10240 * 10240)); - if (BFSIZE < 1) - BFSIZE = 1; - - const int bfsize = BFSIZE; - char buffer[bfsize]; - - VLOGD("PartitionManager: calculating sizes...\n"); - double partition_size = Functions::CalculateSizeDouble(accessPrefix); - double flashfile_size; - - if (!Strings::TargetFlashFile.empty()) - flashfile_size = Functions::CalculateSizeDouble(Strings::TargetFlashFile); - - if (progress_code < 3) - { - if (partition_size != -1) - LOGD("%s: %.2fM\n", Display::UsingDispString->part_disk_sz, partition_size); - else - LOGW("%s\n", Display::UsingDispString->part_disk_sz_fail); - } - - if (progress_code == 1) - { - VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", accessPrefix.c_str()); - sourceF.open(accessPrefix, ios::binary | ios::in); - if (!sourceF.is_open()) - LOGE("%s: %s: %s\n", Display::UsingDispString->not_read, accessPrefix.c_str(), strqerror()); - - /* determine output */ - if (Strings::OutputName == Strings::TargetPartition) - { - opName = Strings::OutputName + ".img"; - VLOGW("PartitionManager: output not speficed. Selecting automaticly.\n"); - LOGW("%s: %s\n", Display::UsingDispString->out_not_spec, opName.c_str()); - } - else - opName = Strings::OutputName; - - VLOGD("Checking output status...\n"); - if (GetState(opName) == 0) - LOGE("`%s': File exits.\n", opName.c_str()); - - VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", opName.c_str()); - targetF.open(opName, ios::binary | ios::out); - if (!targetF.is_open()) - LOGE("%s: %s: %s\n", Display::UsingDispString->not_gen, opName.c_str(), strqerror()); - - VLOGD("PartitionManager: read (partition) and write (output) 'read, write '\n"); - /* start writing */ - while (sourceF.read(buffer, bfsize) && copiedData < count) - { - streamsize readed_data = sourceF.gcount(); - targetF.write(buffer, readed_data); - - if (targetF.fail()) - { - if (Functions::GetState(opName) == 0) - remove(opName.c_str()); - LOGF("%s: %s: %s\n", Display::UsingDispString->not_write, opName.c_str(), strqerror()); - } - - copiedData += readed_data; - } - - /* close files */ - sourceF.close(); - targetF.close(); - - LOGD("%s: %s\n", Display::UsingDispString->success_backup, opName.c_str()); - } - else if (progress_code == 2) - { - if (flashfile_size != -1) - LOGD("%s: %.2fM\n", Display::UsingDispString->flash_file_sz, flashfile_size); - else - LOGW("%s\n", Display::UsingDispString->flash_file_sz_fail); - - if (partition_size != -1 && flashfile_size != -1) - { - if (flashfile_size > partition_size && !Booleans::ForceMode) - LOGE("%s\n", Display::UsingDispString->ffile_more_part); - } - - VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", Strings::TargetFlashFile.c_str()); - sourceF.open(Strings::TargetFlashFile, ios::binary | ios::in); - if (!sourceF.is_open()) - LOGF("%s: %s: %s\n", Display::UsingDispString->not_read, Strings::TargetFlashFile.c_str(), strqerror()); - - VLOGD("PartitionManager: trying to open `%s' with 'open '.\n", accessPrefix.c_str()); - targetF.open(accessPrefix, ios::binary | ios::in | ios::out | ios::trunc); - if (!targetF.is_open()) - LOGF("%s: %s: %s\n", Display::UsingDispString->not_read, accessPrefix.c_str(), strqerror()); - - VLOGD("PartitionManager: read (flash file) and write (partition) 'read, write '\n"); - /* start writing */ - while (sourceF.read(buffer, bfsize) && copiedData < count) - { - streamsize readed_data = sourceF.gcount(); - targetF.write(buffer, readed_data); - - if (targetF.fail()) - LOGF("%s: %s: %s\n", Display::UsingDispString->not_write, accessPrefix.c_str(), strqerror()); - - copiedData += readed_data; - } - - sourceF.close(); - targetF.close(); - - LOGD("%s.\n", Display::UsingDispString->success_flash); - } - else if (progress_code == 3) - { - /* get target partition block size */ - VLOGD("PartitionManager: getting block size `%s' with 'statvfs '\n", accessPrefix.c_str()); - - struct statvfs file_sys_inf; - if (statvfs(accessPrefix.c_str(), &file_sys_inf) != 0) - LOGE("%s\n", Display::UsingDispString->cannot_get_bsz); - - /* generate mke2fs command */ - VLOGD("PartitionManager: generating command...\n"); - sprintf(formatterCmd, "/system/bin/mke2fs -Fq -t %s -b %lu %s &>/data/local/tmp/mke2fs", Strings::TargetFormatFS.c_str(), file_sys_inf.f_bsize, accessPrefix.c_str()); - - LOGD("%s: `%s'. %s: %s\n", Display::UsingDispString->formatting, accessPrefix.c_str(), Display::UsingDispString->fs_str, Strings::TargetFormatFS.c_str()); - - /* run command */ - VLOGD("PartitionManager: executing command: \"%s\"\n", formatterCmd); - if (system(formatterCmd) != 0) - LOGF("%s\n", Display::UsingDispString->format_fail); - - LOGD("%s.\n", Display::UsingDispString->success_format); - } - - return 0; -} - -/* end of code */ diff --git a/jni/e2fsprogs/NOTICE b/jni/e2fsprogs/NOTICE new file mode 100755 index 0000000..da98a3e --- /dev/null +++ b/jni/e2fsprogs/NOTICE @@ -0,0 +1,849 @@ +This package, the EXT2 filesystem utilities, are made available under +the GNU Public License version 2, with the exception of the lib/ext2fs +and lib/e2p libraries, which are made available under the GNU Library +General Public License Version 2, the lib/uuid library which is made +available under a BSD-style license and the lib/et and lib/ss +libraries which are made available under an MIT-style license. Please +see lib/uuid/COPYING for more details for the license for the files +comprising the libuuid library, and the source file headers of the +libet and libss libraries for more information. + +The most recent officially distributed version can be found at +http://e2fsprogs.sourceforge.net. If you need to make a distribution, +that's the one you should use. If there is some reason why you'd like +a more recent version that is still in ALPHA testing (i.e., either +using the "WIP" test distributions or one from the hg or git +repository from the development branch, please contact me +(tytso@mit.edu) before you ship. The release schedules for this +package are flexible, if you give me enough lead time. + + + Theodore Ts'o + 23-June-2007 + +---------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +---------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/jni/e2fsprogs/lib/blkid/cache.c b/jni/e2fsprogs/lib/blkid/cache.c new file mode 100755 index 0000000..80c8089 --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/cache.c @@ -0,0 +1,209 @@ +/* + * cache.c - allocation/initialization/free routines for cache + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include "config.h" +#if HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_PRCTL_H +#include +#else +#define PR_GET_DUMPABLE 3 +#endif +#if (!defined(HAVE_PRCTL) && defined(linux)) +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include "blkidP.h" + +int blkid_debug_mask = 0; + + +static char *safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if defined(HAVE_SECURE_GETENV) + return secure_getenv(arg); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +#if 0 /* ifdef CONFIG_BLKID_DEBUG */ +static blkid_debug_dump_cache(int mask, blkid_cache cache) +{ + struct list_head *p; + + if (!cache) { + printf("cache: NULL\n"); + return; + } + + printf("cache: time = %lu\n", cache->bic_time); + printf("cache: flags = 0x%08X\n", cache->bic_flags); + + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + blkid_debug_dump_dev(dev); + } +} +#endif + +int blkid_get_cache(blkid_cache *ret_cache, const char *filename) +{ + blkid_cache cache; + +#ifdef CONFIG_BLKID_DEBUG + if (!(blkid_debug_mask & DEBUG_INIT)) { + char *dstr = getenv("BLKID_DEBUG"); + + if (dstr) + blkid_debug_mask = strtoul(dstr, 0, 0); + blkid_debug_mask |= DEBUG_INIT; + } +#endif + + DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", + filename ? filename : "default cache")); + + if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache)))) + return -BLKID_ERR_MEM; + + INIT_LIST_HEAD(&cache->bic_devs); + INIT_LIST_HEAD(&cache->bic_tags); + + if (filename && !strlen(filename)) + filename = 0; + if (!filename) + filename = safe_getenv("BLKID_FILE"); + if (!filename) + filename = BLKID_CACHE_FILE; + cache->bic_filename = blkid_strdup(filename); + + blkid_read_cache(cache); + + *ret_cache = cache; + return 0; +} + +void blkid_put_cache(blkid_cache cache) +{ + if (!cache) + return; + + (void) blkid_flush_cache(cache); + + DBG(DEBUG_CACHE, printf("freeing cache struct\n")); + + /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */ + + while (!list_empty(&cache->bic_devs)) { + blkid_dev dev = list_entry(cache->bic_devs.next, + struct blkid_struct_dev, + bid_devs); + blkid_free_dev(dev); + } + + while (!list_empty(&cache->bic_tags)) { + blkid_tag tag = list_entry(cache->bic_tags.next, + struct blkid_struct_tag, + bit_tags); + + while (!list_empty(&tag->bit_names)) { + blkid_tag bad = list_entry(tag->bit_names.next, + struct blkid_struct_tag, + bit_names); + + DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", + bad->bit_name, bad->bit_val)); + blkid_free_tag(bad); + } + blkid_free_tag(tag); + } + free(cache->bic_filename); + + free(cache); +} + +void blkid_gc_cache(blkid_cache cache) +{ + struct list_head *p, *pnext; + struct stat st; + + if (!cache) + return; + + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (stat(dev->bid_name, &st) < 0) { + DBG(DEBUG_CACHE, + printf("freeing %s\n", dev->bid_name)); + blkid_free_dev(dev); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } else { + DBG(DEBUG_CACHE, + printf("Device %s exists\n", dev->bid_name)); + } + } +} + + +#ifdef TEST_PROGRAM +int main(int argc, char** argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_debug_mask = DEBUG_ALL; + if ((argc > 2)) { + fprintf(stderr, "Usage: %s [filename] \n", argv[0]); + exit(1); + } + + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { + fprintf(stderr, "error %d parsing cache file %s\n", ret, + argv[1] ? argv[1] : BLKID_CACHE_FILE); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if ((ret = blkid_probe_all(cache) < 0)) + fprintf(stderr, "error probing devices\n"); + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/cache.o b/jni/e2fsprogs/lib/blkid/cache.o new file mode 100755 index 0000000000000000000000000000000000000000..1014bfbe5bfd79d0f9766c7d6b976798063dcc92 GIT binary patch literal 3640 zcmbtWO=w(I6h800)J{5SlD5XSY10WBFogJ;#99k>@!BM{t-(cU7m7H(%)I=N$qzFx zB{hNr*>q=nvVr)+Y3)JByO zkJu~XjR&zmz?s-jaW#2wbN>7?a#C2al0S!Y!~052bU)ZnU8N@HevD!h=M1{a`-MKP z>EnSuPl5iyLSmx{yiX{9<%yN(TDR)De#i3%9^MPyTWp7UdoY#|ALB)=MSKg%jcxH+ z25M(5ZzA59nSab@X6_PrV=^B$>=dzPJIY2k<|w`J#oUd_=?(}WnoISh^?Z9e6C0gr(fGwPp}(O2p$FJK#a3u=J5@X@BuxfSQ; zeE)LQGJ-nv(<82R&@1RU(KGeWN{7E{t@f*0naIUH^s!k8=b%HLMV)gA=M?jW6C$s? zUdCBD)^;nX6=P-ezUZ44r?UPU6*!0O#>Q#Rjp`%b*V&6Y8z=fYd+ELj9qWVqeZ0YW z)&2d6GjGmcMvs}|Z0CpGyEKrzaA|0ePI`Xo8bYK zGj^|ihMExsi}C3dGCn(D9BW7r&PPWCN^~5KX`r#^VnbW=ZS%`ItIlXh^jvJD-+mQ5 zNAik1YCQ91jV5^LA0cIa4>UT;p1IbLZ~}9p;rTMMa17uzf7D3SiRlurA@}$-(0IqF z87MX+uo3~WE<##yjyn3Qx|`Y}WH}_)_}shT4FWZTykK6$!@_hEe_u;eB7R`F%aA&L z?GTG_D?@Tt@OR>G3;d-Jo2XCVu^srgKn`m0i#h^31iq@dzUc}UyWxWo_*w-1cLe@# z1YQ>rPdozuAi~ap2>dp1&chEPPeh{sfc+T3=f2-95BUiEc?7-=oc%tO{UG`l*gFyY zB=7@TpQw&G4xHr};^*E|vM48v?^htkJ95r--mBqv<-8??uZ8&Pv;I?vuka@lXTP|b zHF=@o_$Jk)8$1@~HwRPkKBeJYJ0(LJeo%oJuWI-q4Zo@3{J~UG)bJJsVk~PozA-gv zmUZGd)o&jwGa7!h#>W3Y5%^6FZ`JsV5qP&1kl3%PH6v#=T#rX__JA)<3IhXy8B(~q z@0k#;?!m1Pu70<^3E`@LDKnn)liuWve}i)Fh?gAod~fPHiSJ8tB5|C}4#eMCJ9lG}$BwjpieGQ?tB+s32zxs1`Yuy@vFw<$ zdt|=<@9--6LAJ~`Q%Cj%%MYQ~CA6e&C>aZXVH~+BA2P0fpQM^z$AmFQ0dicFKSJt$ zaX8$!>Wig%+mTqv4XsEZ>@U2&fZ#d)K0Lap{rX*Gy*j@dc^}Wi_4q~le}y+`qV}nA z20As@X!JaMAgK&<`93nH-)W|*{cF6?MCDIGUtqFZ{)_biV@?t||GZc2SNZRP^RRE; RvLX|`CY2l`e+$C<{{wCZ5g`Bo literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/dev.c b/jni/e2fsprogs/lib/blkid/dev.c new file mode 100755 index 0000000..1d62dd8 --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/dev.c @@ -0,0 +1,254 @@ +/* + * dev.c - allocation/initialization/free routines for dev + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "blkidP.h" + +blkid_dev blkid_new_dev(void) +{ + blkid_dev dev; + + if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev)))) + return NULL; + + INIT_LIST_HEAD(&dev->bid_devs); + INIT_LIST_HEAD(&dev->bid_tags); + + return dev; +} + +void blkid_free_dev(blkid_dev dev) +{ + if (!dev) + return; + + DBG(DEBUG_DEV, + printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type ? + dev->bid_type : "(null)")); + DBG(DEBUG_DEV, blkid_debug_dump_dev(dev)); + + list_del(&dev->bid_devs); + while (!list_empty(&dev->bid_tags)) { + blkid_tag tag = list_entry(dev->bid_tags.next, + struct blkid_struct_tag, + bit_tags); + blkid_free_tag(tag); + } + free(dev->bid_name); + free(dev); +} + +/* + * Given a blkid device, return its name + */ +extern const char *blkid_dev_devname(blkid_dev dev) +{ + return dev->bid_name; +} + +#ifdef CONFIG_BLKID_DEBUG +void blkid_debug_dump_dev(blkid_dev dev) +{ + struct list_head *p; + + if (!dev) { + printf(" dev: NULL\n"); + return; + } + + printf(" dev: name = %s\n", dev->bid_name); + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno); + printf(" dev: TIME=\"%ld\"\n", (long)dev->bid_time); + printf(" dev: PRI=\"%d\"\n", dev->bid_pri); + printf(" dev: flags = 0x%08X\n", dev->bid_flags); + + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + if (tag) + printf(" tag: %s=\"%s\"\n", tag->bit_name, + tag->bit_val); + else + printf(" tag: NULL\n"); + } + printf("\n"); +} +#endif + +/* + * dev iteration routines for the public libblkid interface. + * + * These routines do not expose the list.h implementation, which are a + * contamination of the namespace, and which force us to reveal far, far + * too much of our internal implementation. I'm not convinced I want + * to keep list.h in the long term, anyway. It's fine for kernel + * programming, but performance is not the #1 priority for this + * library, and I really don't like the tradeoff of type-safety for + * performance for this application. [tytso:20030125.2007EST] + */ + +/* + * This series of functions iterate over all devices in a blkid cache + */ +#define DEV_ITERATE_MAGIC 0x01a5284c + +struct blkid_struct_dev_iterate { + int magic; + blkid_cache cache; + char *search_type; + char *search_value; + struct list_head *p; +}; + +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) +{ + blkid_dev_iterate iter; + + iter = malloc(sizeof(struct blkid_struct_dev_iterate)); + if (iter) { + iter->magic = DEV_ITERATE_MAGIC; + iter->cache = cache; + iter->p = cache->bic_devs.next; + iter->search_type = 0; + iter->search_value = 0; + } + return (iter); +} + +extern int blkid_dev_set_search(blkid_dev_iterate iter, + char *search_type, char *search_value) +{ + char *new_type, *new_value; + + if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type || + !search_value) + return -1; + new_type = malloc(strlen(search_type)+1); + new_value = malloc(strlen(search_value)+1); + if (!new_type || !new_value) { + free(new_type); + free(new_value); + return -1; + } + strcpy(new_type, search_type); + strcpy(new_value, search_value); + free(iter->search_type); + free(iter->search_value); + iter->search_type = new_type; + iter->search_value = new_value; + return 0; +} + +/* + * Return 0 on success, -1 on error + */ +extern int blkid_dev_next(blkid_dev_iterate iter, + blkid_dev *ret_dev) +{ + blkid_dev dev; + + *ret_dev = 0; + if (!iter || iter->magic != DEV_ITERATE_MAGIC) + return -1; + while (iter->p != &iter->cache->bic_devs) { + dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); + iter->p = iter->p->next; + if (iter->search_type && + !blkid_dev_has_tag(dev, iter->search_type, + iter->search_value)) + continue; + *ret_dev = dev; + return 0; + } + return -1; +} + +extern void blkid_dev_iterate_end(blkid_dev_iterate iter) +{ + if (!iter || iter->magic != DEV_ITERATE_MAGIC) + return; + iter->magic = 0; + free(iter); +} + +#ifdef TEST_PROGRAM +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif + +void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog); + fprintf(stderr, "\tList all devices and exit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + blkid_dev_iterate iter; + blkid_cache cache = NULL; + blkid_dev dev; + int c, ret; + char *tmp; + char *file = NULL; + char *search_type = NULL; + char *search_value = NULL; + + while ((c = getopt (argc, argv, "m:f:")) != EOF) + switch (c) { + case 'f': + file = optarg; + break; + case 'm': + blkid_debug_mask = strtoul (optarg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Invalid debug mask: %s\n", + optarg); + exit(1); + } + break; + case '?': + usage(argv[0]); + } + if (argc >= optind+2) { + search_type = argv[optind]; + search_value = argv[optind+1]; + optind += 2; + } + if (argc != optind) + usage(argv[0]); + + if ((ret = blkid_get_cache(&cache, file)) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + + iter = blkid_dev_iterate_begin(cache); + if (search_type) + blkid_dev_set_search(iter, search_type, search_value); + while (blkid_dev_next(iter, &dev) == 0) { + printf("Device: %s\n", blkid_dev_devname(dev)); + } + blkid_dev_iterate_end(iter); + + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/dev.o b/jni/e2fsprogs/lib/blkid/dev.o new file mode 100755 index 0000000000000000000000000000000000000000..cd2910464f4fb1f92048886e9206918413a84419 GIT binary patch literal 3720 zcmbtXQD~c06h42FZmCVXtm~XOT_P5#;6ghb6!hVrty*M=OocrRk~I0(mL};)er9VY z7DSjZVTC^IMJ+xx;N!&h$wB+zgM!XzjOa{lbgSZK6poR&;9Oq z&-u=|=l|1v`0B;i0+vO3So96GRvIOminMH7nKt!;+4zX=*O#qweS%iwwDQ2}UwMG- zwMvj`D@0$z*HGgq)gH&pb~R|%_V5|8sMfT5sK$GGKYW2!6{pwZG}rwekIz-%llhgS zcCEgAp$r|X_kzivOg$BFs@R_u9VdkkEo&+k_6V`gV2xDHYb@Lg|IlAS9M0wMM&lIw zp_AU4V=~VC|B6jLtktermRV}B34u+{r}<GoR4p$i+wi;f3F4L!7dg$N#okf%J!aQ7$m3P}l&yLs zOe=#M+p*0T_>REg`cjBidFK2o;I?77AI_!ei*vBNe$)4(?@#;I_rELtd4E^@vSz}) za|~todp5@?V{b(2qHNUWTWIBc*0+A{!R#CP*Jz!*8fm@H!M~~*bC2WRFh7re;vQKEN5zjT2Z8!oME+K97JO)u1sy z1DpApr}_xkU3@z6f9-)IFpOk@{{G5TCeAmED{v881b*^{8Hw~P7Opl!|_>Tr|`hVC3-;sOb zeDQnO92ez2{PlcF7(L*NONC7O@Y}M^`EdPQuK95NTz=)lbzkrJaNXB`_;B67{6on@ z>(u?I<7iy>UDn6f?*q!smE5G0zveDc$t`BCEzxvtelD9VIPWF1&UIN`Ejo@`CW=lj zop7B+S9ZVw7t2IuA)j{&CO+pn#kA`rr=6L(0=v&S1xhAW$gGp2L}9^o60g7c?%9%? z&deJgOOBf?Iq70%)&OVIrKFplF(vWRljO`MuNKpJ$KXR+fe{vOz*?14$WlI?%PnLm z<4rh_$WQ`8-Sjl(r998W*~B^i8l&OG#Hd&H|NVUe_aUv><}2FgEzik)=}q5~&SQfy z|C`#D1Gl8VWqIgL&v`J#)&!YvhCSns1mq<@2Ld<$es}{IQ~dS#UgF~a9Bo7E*YgM1 z)wW4| +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif +#include + +#include "blkidP.h" + +/* + * Find a dev struct in the cache by device name, if available. + * + * If there is no entry with the specified device name, and the create + * flag is set, then create an empty device entry. + */ +blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) +{ + blkid_dev dev = NULL, tmp; + struct list_head *p, *pnext; + + if (!cache || !devname) + return NULL; + + list_for_each(p, &cache->bic_devs) { + tmp = list_entry(p, struct blkid_struct_dev, bid_devs); + if (strcmp(tmp->bid_name, devname)) + continue; + + DBG(DEBUG_DEVNAME, + printf("found devname %s in cache\n", tmp->bid_name)); + dev = tmp; + break; + } + + if (!dev && (flags & BLKID_DEV_CREATE)) { + if (access(devname, F_OK) < 0) + return NULL; + dev = blkid_new_dev(); + if (!dev) + return NULL; + dev->bid_time = INT_MIN; + dev->bid_name = blkid_strdup(devname); + dev->bid_cache = cache; + list_add_tail(&dev->bid_devs, &cache->bic_devs); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } + + if (flags & BLKID_DEV_VERIFY) { + dev = blkid_verify(cache, dev); + if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) + return dev; + /* + * If the device is verified, then search the blkid + * cache for any entries that match on the type, uuid, + * and label, and verify them; if a cache entry can + * not be verified, then it's stale and so we remove + * it. + */ + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev dev2; + dev2 = list_entry(p, struct blkid_struct_dev, bid_devs); + if (dev2->bid_flags & BLKID_BID_FL_VERIFIED) + continue; + if (!dev->bid_type || !dev2->bid_type || + strcmp(dev->bid_type, dev2->bid_type)) + continue; + if (dev->bid_label && dev2->bid_label && + strcmp(dev->bid_label, dev2->bid_label)) + continue; + if (dev->bid_uuid && dev2->bid_uuid && + strcmp(dev->bid_uuid, dev2->bid_uuid)) + continue; + if ((dev->bid_label && !dev2->bid_label) || + (!dev->bid_label && dev2->bid_label) || + (dev->bid_uuid && !dev2->bid_uuid) || + (!dev->bid_uuid && dev2->bid_uuid)) + continue; + dev2 = blkid_verify(cache, dev2); + if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED)) + blkid_free_dev(dev2); + } + } + return dev; +} + +/* Directories where we will try to search for device names */ +static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL }; + +static int is_dm_leaf(const char *devname) +{ + struct dirent *de, *d_de; + DIR *dir, *d_dir; + char path[300]; + int ret = 1; + + if ((dir = opendir("/sys/block")) == NULL) + return 0; + while ((de = readdir(dir)) != NULL) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || + !strcmp(de->d_name, devname) || + strncmp(de->d_name, "dm-", 3) || + strlen(de->d_name) > sizeof(path)-32) + continue; + sprintf(path, "/sys/block/%s/slaves", de->d_name); + if ((d_dir = opendir(path)) == NULL) + continue; + while ((d_de = readdir(d_dir)) != NULL) { + if (!strcmp(d_de->d_name, devname)) { + ret = 0; + break; + } + } + closedir(d_dir); + if (!ret) + break; + } + closedir(dir); + return ret; +} + +/* + * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs + * provides the real DM device names in /sys/block//dm/name + */ +static char *get_dm_name(const char *ptname) +{ + FILE *f; + size_t sz; + char path[300], name[256], *res = NULL; + + snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname); + if ((f = fopen(path, "r")) == NULL) + return NULL; + + /* read "\n" from sysfs */ + if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { + name[sz - 1] = '\0'; + snprintf(path, sizeof(path), "/dev/mapper/%s", name); + res = blkid_strdup(path); + } + fclose(f); + return res; +} + +/* + * Probe a single block device to add to the device cache. + */ +static void probe_one(blkid_cache cache, const char *ptname, + dev_t devno, int pri, int only_if_new) +{ + blkid_dev dev = NULL; + struct list_head *p, *pnext; + const char **dir; + char *devname = NULL; + + /* See if we already have this device number in the cache. */ + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev tmp = list_entry(p, struct blkid_struct_dev, + bid_devs); + if (tmp->bid_devno == devno) { + if (only_if_new && !access(tmp->bid_name, F_OK)) + return; + dev = blkid_verify(cache, tmp); + if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) + break; + dev = 0; + } + } + if (dev && dev->bid_devno == devno) + goto set_pri; + + /* Try to translate private device-mapper dm- names + * to standard /dev/mapper/. + */ + if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) { + devname = get_dm_name(ptname); + if (!devname) + blkid__scan_dir("/dev/mapper", devno, 0, &devname); + if (devname) + goto get_dev; + } + + /* + * Take a quick look at /dev/ptname for the device number. We check + * all of the likely device directories. If we don't find it, or if + * the stat information doesn't check out, use blkid_devno_to_devname() + * to find it via an exhaustive search for the device major/minor. + */ + for (dir = dirlist; *dir; dir++) { + struct stat st; + char device[256]; + + sprintf(device, "%s/%s", *dir, ptname); + if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && + dev->bid_devno == devno) + goto set_pri; + + if (stat(device, &st) == 0 && + blkidP_is_disk_device(st.st_mode) && + st.st_rdev == devno) { + devname = blkid_strdup(device); + goto get_dev; + } + } + /* Do a short-cut scan of /dev/mapper first */ + if (!devname) + devname = get_dm_name(ptname); + if (!devname) + blkid__scan_dir("/dev/mapper", devno, 0, &devname); + if (!devname) { + devname = blkid_devno_to_devname(devno); + if (!devname) + return; + } +get_dev: + dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); + free(devname); +set_pri: + if (dev) { + if (pri) + dev->bid_pri = pri; + else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) { + dev->bid_pri = BLKID_PRI_DM; + if (is_dm_leaf(ptname)) + dev->bid_pri += 5; + } else if (!strncmp(ptname, "md", 2)) + dev->bid_pri = BLKID_PRI_MD; + } + return; +} + +#define PROC_PARTITIONS "/proc/partitions" +#define VG_DIR "/proc/lvm/VGs" + +/* + * This function initializes the UUID cache with devices from the LVM + * proc hierarchy. We currently depend on the names of the LVM + * hierarchy giving us the device structure in /dev. (XXX is this a + * safe thing to do?) + */ +#ifdef VG_DIR +static dev_t lvm_get_devno(const char *lvm_device) +{ + FILE *lvf; + char buf[1024]; + int ma, mi; + dev_t ret = 0; + + DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); + if ((lvf = fopen(lvm_device, "r")) == NULL) { + DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, + strerror(errno))); + return 0; + } + + while (fgets(buf, sizeof(buf), lvf)) { + if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { + ret = makedev(ma, mi); + break; + } + } + fclose(lvf); + + return ret; +} + +static void lvm_probe_all(blkid_cache cache, int only_if_new) +{ + DIR *vg_list; + struct dirent *vg_iter; + int vg_len = strlen(VG_DIR); + dev_t dev; + + if ((vg_list = opendir(VG_DIR)) == NULL) + return; + + DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); + + while ((vg_iter = readdir(vg_list)) != NULL) { + DIR *lv_list; + char *vdirname; + char *vg_name; + struct dirent *lv_iter; + + vg_name = vg_iter->d_name; + if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) + continue; + vdirname = malloc(vg_len + strlen(vg_name) + 8); + if (!vdirname) + goto exit; + sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); + + lv_list = opendir(vdirname); + free(vdirname); + if (lv_list == NULL) + continue; + + while ((lv_iter = readdir(lv_list)) != NULL) { + char *lv_name, *lvm_device; + + lv_name = lv_iter->d_name; + if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) + continue; + + lvm_device = malloc(vg_len + strlen(vg_name) + + strlen(lv_name) + 8); + if (!lvm_device) { + closedir(lv_list); + goto exit; + } + sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, + lv_name); + dev = lvm_get_devno(lvm_device); + sprintf(lvm_device, "%s/%s", vg_name, lv_name); + DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", + lvm_device, + (unsigned int) dev)); + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, + only_if_new); + free(lvm_device); + } + closedir(lv_list); + } +exit: + closedir(vg_list); +} +#endif + +#define PROC_EVMS_VOLUMES "/proc/evms/volumes" + +static int +evms_probe_all(blkid_cache cache, int only_if_new) +{ + char line[100]; + int ma, mi, sz, num = 0; + FILE *procpt; + char device[110]; + + procpt = fopen(PROC_EVMS_VOLUMES, "r"); + if (!procpt) + return 0; + while (fgets(line, sizeof(line), procpt)) { + if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", + &ma, &mi, &sz, device) != 4) + continue; + + DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", + device, ma, mi)); + + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, + only_if_new); + num++; + } + fclose(procpt); + return num; +} + +/* + * Read the device data for all available block devices in the system. + */ +static int probe_all(blkid_cache cache, int only_if_new) +{ + FILE *proc; + char line[1024]; + char ptname0[129], ptname1[129], *ptname = 0; + char *ptnames[2]; + dev_t devs[2]; + int ma, mi; + unsigned long long sz; + int lens[2] = { 0, 0 }; + int which = 0, last = 0; + struct list_head *p, *pnext; + + ptnames[0] = ptname0; + ptnames[1] = ptname1; + + if (!cache) + return -BLKID_ERR_PARAM; + + if (cache->bic_flags & BLKID_BIC_FL_PROBED && + time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) + return 0; + + blkid_read_cache(cache); + evms_probe_all(cache, only_if_new); +#ifdef VG_DIR + lvm_probe_all(cache, only_if_new); +#endif + + proc = fopen(PROC_PARTITIONS, "r"); + if (!proc) + return -BLKID_ERR_PROC; + + while (fgets(line, sizeof(line), proc)) { + last = which; + which ^= 1; + ptname = ptnames[which]; + + if (sscanf(line, " %d %d %llu %128[^\n ]", + &ma, &mi, &sz, ptname) != 4) + continue; + devs[which] = makedev(ma, mi); + + DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); + + /* Skip whole disk devs unless they have no partitions. + * If base name of device has changed, also + * check previous dev to see if it didn't have a partn. + * heuristic: partition name ends in a digit, & partition + * names contain whole device name as substring. + * + * Skip extended partitions. + * heuristic: size is 1 + * + * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs + */ + + lens[which] = strlen(ptname); + + /* ends in a digit, clearly a partition, so check */ + if (isdigit(ptname[lens[which] - 1])) { + DBG(DEBUG_DEVNAME, + printf("partition dev %s, devno 0x%04X\n", + ptname, (unsigned int) devs[which])); + + if (sz > 1) + probe_one(cache, ptname, devs[which], 0, + only_if_new); + lens[which] = 0; /* mark as checked */ + } + + /* + * If last was a whole disk and we just found a partition + * on it, remove the whole-disk dev from the cache if + * it exists. + */ + if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) { + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev tmp; + + /* find blkid dev for the whole-disk devno */ + tmp = list_entry(p, struct blkid_struct_dev, + bid_devs); + if (tmp->bid_devno == devs[last]) { + DBG(DEBUG_DEVNAME, + printf("freeing %s\n", + tmp->bid_name)); + blkid_free_dev(tmp); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + break; + } + } + lens[last] = 0; + } + /* + * If last was not checked because it looked like a whole-disk + * dev, and the device's base name has changed, + * check last as well. + */ + if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) { + DBG(DEBUG_DEVNAME, + printf("whole dev %s, devno 0x%04X\n", + ptnames[last], (unsigned int) devs[last])); + probe_one(cache, ptnames[last], devs[last], 0, + only_if_new); + lens[last] = 0; + } + } + + /* Handle the last device if it wasn't partitioned */ + if (lens[which]) + probe_one(cache, ptname, devs[which], 0, only_if_new); + + fclose(proc); + blkid_flush_cache(cache); + return 0; +} + +int blkid_probe_all(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n")); + ret = probe_all(cache, 0); + cache->bic_time = time(0); + cache->bic_flags |= BLKID_BIC_FL_PROBED; + DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n")); + return ret; +} + +int blkid_probe_all_new(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n")); + ret = probe_all(cache, 1); + DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n")); + return ret; +} + + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_debug_mask = DEBUG_ALL; + if (argc != 1) { + fprintf(stderr, "Usage: %s\n" + "Probe all devices and exit\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if (blkid_probe_all(cache) < 0) + printf("%s: error probing devices\n", argv[0]); + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/devname.o b/jni/e2fsprogs/lib/blkid/devname.o new file mode 100755 index 0000000000000000000000000000000000000000..d964c073357c118e65bd27a8a8ce1ff419b9d01e GIT binary patch literal 12432 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 +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include "blkidP.h" + +#if defined(__GNUC__) && __GNUC__ >= 8 +/* gcc incorrectly thinks the destination string is not being null-terminated */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif + +char *blkid_strndup(const char *s, int length) +{ + char *ret; + + if (!s) + return NULL; + + if (!length) + length = strlen(s); + + ret = malloc(length + 1); + if (ret) { + strncpy(ret, s, length); + ret[length] = '\0'; + } + return ret; +} + +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif + +char *blkid_strdup(const char *s) +{ + return blkid_strndup(s, 0); +} + +/* + * This function adds an entry to the directory list + */ +static void add_to_dirlist(const char *name, struct dir_list **list) +{ + struct dir_list *dp; + + dp = malloc(sizeof(struct dir_list)); + if (!dp) + return; + dp->name = blkid_strdup(name); + if (!dp->name) { + free(dp); + return; + } + dp->next = *list; + *list = dp; +} + +/* + * This function frees a directory list + */ +static void free_dirlist(struct dir_list **list) +{ + struct dir_list *dp, *next; + + for (dp = *list; dp; dp = next) { + next = dp->next; + free(dp->name); + free(dp); + } + *list = NULL; +} + +void blkid__scan_dir(const char *dirname, dev_t devno, struct dir_list **list, + char **devname) +{ + DIR *dir; + struct dirent *dp; + char path[1024]; + int dirlen; + struct stat st; + + if ((dir = opendir(dirname)) == NULL) + return; + dirlen = strlen(dirname) + 2; + while ((dp = readdir(dir)) != 0) { + if (dirlen + strlen(dp->d_name) >= sizeof(path)) + continue; + + if (dp->d_name[0] == '.' && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) + continue; + + sprintf(path, "%s/%s", dirname, dp->d_name); + if (stat(path, &st) < 0) + continue; + + if (blkidP_is_disk_device(st.st_mode) && st.st_rdev == devno) { + *devname = blkid_strdup(path); + DBG(DEBUG_DEVNO, + printf("found 0x%llx at %s (%p)\n", (long long)devno, + path, *devname)); + break; + } + if (list && S_ISDIR(st.st_mode) && !lstat(path, &st) && + S_ISDIR(st.st_mode)) + add_to_dirlist(path, list); + } + closedir(dir); + return; +} + +/* Directories where we will try to search for device numbers */ +static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL }; + +/* + * This function finds the pathname to a block device with a given + * device number. It returns a pointer to allocated memory to the + * pathname on success, and NULL on failure. + */ +char *blkid_devno_to_devname(dev_t devno) +{ + struct dir_list *list = NULL, *new_list = NULL; + char *devname = NULL; + const char **dir; + + /* + * Add the starting directories to search in reverse order of + * importance, since we are using a stack... + */ + for (dir = devdirs; *dir; dir++) + add_to_dirlist(*dir, &list); + + while (list) { + struct dir_list *current = list; + + list = list->next; + DBG(DEBUG_DEVNO, printf("directory %s\n", current->name)); + blkid__scan_dir(current->name, devno, &new_list, &devname); + free(current->name); + free(current); + if (devname) + break; + /* + * If we're done checking at this level, descend to + * the next level of subdirectories. (breadth-first) + */ + if (list == NULL) { + list = new_list; + new_list = NULL; + } + } + free_dirlist(&list); + free_dirlist(&new_list); + + if (!devname) { + DBG(DEBUG_DEVNO, + printf("blkid: couldn't find devno 0x%04lx\n", + (unsigned long) devno)); + } else { + DBG(DEBUG_DEVNO, + printf("found devno 0x%04llx as %s\n", (long long)devno, devname)); + } + + + return devname; +} + +#ifdef TEST_PROGRAM +int main(int argc, char** argv) +{ + char *devname, *tmp; + int major, minor; + dev_t devno; + const char *errmsg = "Couldn't parse %s: %s\n"; + + blkid_debug_mask = DEBUG_ALL; + if ((argc != 2) && (argc != 3)) { + fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n" + "Resolve a device number to a device name\n", + argv[0], argv[0]); + exit(1); + } + if (argc == 2) { + devno = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "device number", argv[1]); + exit(1); + } + } else { + major = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "major number", argv[1]); + exit(1); + } + minor = strtoul(argv[2], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "minor number", argv[2]); + exit(1); + } + devno = makedev(major, minor); + } + printf("Looking for device 0x%04llx\n", (long long)devno); + devname = blkid_devno_to_devname(devno); + free(devname); + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/devno.o b/jni/e2fsprogs/lib/blkid/devno.o new file mode 100755 index 0000000000000000000000000000000000000000..e03d5bd19829be23b4e411337f3f6472f01c606b GIT binary patch literal 4256 zcmbtWU2Icj7=BOB1|5`b{K=oJC5{9k7KUh;(Rg%IxDZ7nW*16V+A~?`+R;`r9KoGV61foA;HFg*y};;h1ceJOxB!F33nd-i9KsdEi`J~E&-?wfhqE;?@mqSn?|Z)I z{eQo6_Q`8+yzVm$(!-$dsj<^2(bTfW+7e5P0$|pz(e3KEuUO4dzOcSIx+8wH*6u6svvk zbum>+i=od9Ze?B7@mGpC7rg5DkHtB}QZ*@G>sxty3i_taVEJOMt9;4qDzjdenaXV} z52`pL${yo>KjobZGOnrI2a;=oyF|v}T$n(Ps8TR-wvX~G!#VRCblPupK8z8)%l<#C z)z&b_zt8IR&(KlBCvkzjZS^8AyO^i<%$ZfP0y_YX%K2UBx(L4+H(|4s^NAcl{>&zl zK8Sq8v_00xaTLshWwb?QE&G)_ST6Wf z%+TRqwrYicxmAyYWoETKL-vN_;{BvznT8(bu7G~_=_~l8^U8bFC_jh%RmXoWh&uPt z?GpDPdP>+_XB{oAxv;+0r~2Spqi4Ccv#166CVpZ6xi1{_1@b2PcNO&OdNaS1#;}`WBq6v=tr|yy+(QV;|hAL) zDuRVR=7qj!Ilt(f-z*rC`v>bpAJe3yQi$jN_RfKJX-oJ5=#<18K8-%^(;Ys?;KD)P z(mwg-0zu2=`b{aiF13QRYpLfV9xV+Pnh*CZTIQV>kP<0RF2$eKe^=LQKQp zJoxZ;S>YmPU@zlmP%EBtgw*^LX6Em2k${Lvotf~|JGzBG^Ks^xF8x{#{fN=9tMT;$ zU#z$Fd9}cC`#j?$_AB709=fKd0q9=TXFNY>g0uRC_#8Lu*Lp=?0vlAg?hVn0!1my` zke-1i_{App3r+CeCiq)T@LNsr8Q>h(izXHrqPH>g9p?5Aiu%sCEBi{~t2G&Oe-pm0!%Cd{UHt2c&wb>^@lF+k<9foy zzvIH!xbT2#HRj{HTp#@|d~F>iI^n|Cx$v7V+?`Lyg}e3pRh`)GdY7I7g>$_4*3`%Q z3g>v;_#Ky?m31~z$%VW1~b;{j!_u)ve84BkB^91 zBp@EmMyWd<-o=k+`LUB9Jusi*GnVSXwtFnRL#6tEP5(ezweDkj1_N^YlB%0N^lXXW zS&ZpE)jUfruBtxQxMxfJrDDv|1U0W!pRfVdyi0-eQr`pp?syu;+5S!?SD(};b3+}F z3+=z2JCwXP2O%XN^2lrZ8eRhVh5R37hcWibiFnH@wY>J9i^#rsi)ktQ`aXjqhW1;} zp90luMG@0`O5Tm}+ROb$VeWSX^9FSM9s%t?b9j7--$L>KpyDqG7K!+|q*`9b?}L7? SZ5A0*4K<|>*$wVBul&EY;+7Nu literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/getsize.c b/jni/e2fsprogs/lib/blkid/getsize.c new file mode 100755 index 0000000..7a6e6fd --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/getsize.c @@ -0,0 +1,217 @@ +/* + * getsize.c --- get the size of a partition. + * + * Copyright (C) 1995, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include "blkidP.h" + +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_LINUX_FD_H +#include +#endif +#ifdef HAVE_SYS_DISKLABEL_H +#include +#endif +#ifdef HAVE_SYS_DISK_H +#include +#endif +#ifdef __linux__ +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif + + +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) +#define BLKGETSIZE _IO(0x12,96) /* return device size */ +#endif + +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#endif + +#ifdef APPLE_DARWIN +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 +#endif /* APPLE_DARWIN */ + +static int valid_offset(int fd, blkid_loff_t offset) +{ + char ch; + + if (blkid_llseek(fd, offset, 0) < 0) + return 0; + if (read(fd, &ch, 1) < 1) + return 0; + return 1; +} + +/* + * Returns the number of bytes in a partition + */ +blkid_loff_t blkid_get_dev_size(int fd) +{ + unsigned long long size64 __BLKID_ATTR((unused)); + blkid_loff_t high, low; + +#if defined DKIOCGETBLOCKCOUNT && defined DKIOCGETBLOCKSIZE /* For Apple Darwin */ + unsigned int size; + + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0 && + ioctl(fd, DKIOCGETBLOCKSIZE, &size) >= 0) { + if (sizeof(blkid_loff_t) < sizeof(unsigned long long) && + (size64 * size) > 0xFFFFFFFF) + return 0; /* EFBIG */ + return (blkid_loff_t)size64 * size; + } +#endif + +#ifdef BLKGETSIZE64 + { + int valid_blkgetsize64 = 1; +#ifdef __linux__ + struct utsname ut; + + if ((uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] < '6') && (ut.release[3] == '.'))) + valid_blkgetsize64 = 0; +#endif + if (valid_blkgetsize64 && + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { + if (sizeof(blkid_loff_t) < sizeof(unsigned long long) && + (size64 > 0xFFFFFFFF)) + return 0; /* EFBIG */ + return size64; + } + } +#endif /* BLKGETSIZE64 */ + +#ifdef BLKGETSIZE + { + unsigned long size; + + if (ioctl(fd, BLKGETSIZE, &size) >= 0) + return (blkid_loff_t)size << 9; + } +#endif + +/* tested on FreeBSD 6.1-RELEASE i386 */ +#ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0) + return (off_t)size64; +#endif /* DIOCGMEDIASIZE */ + +#ifdef FDGETPRM + { + struct floppy_struct this_floppy; + + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) + return (blkid_loff_t)this_floppy.size << 9; + } +#endif +#if defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) + { + int part = -1; + struct disklabel lab; + struct partition *pp; + char ch; + struct stat st; + + /* + * This code works for FreeBSD 4.11 i386, except for the full + * device (such as /dev/ad0). It doesn't work properly for + * newer FreeBSD though. FreeBSD >= 5.0 should be covered by + * the DIOCGMEDIASIZE above however. + * + * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw, + * character) devices, so we need to check for S_ISCHR, too. + */ + if (fstat(fd, &st) >= 0 && + blkidP_is_disk_device(st.st_mode)) + part = st.st_rdev & 7; + + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { + pp = &lab.d_partitions[part]; + if (pp->p_size) + return pp->p_size << 9; + } + } +#endif /* defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) */ + { +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + struct stat64 st; + if (fstat64(fd, &st) == 0) +#else + struct stat st; + if (fstat(fd, &st) == 0) +#endif + if (S_ISREG(st.st_mode)) + return st.st_size; + } + + /* + * OK, we couldn't figure it out by using a specialized ioctl, + * which is generally the best way. So do binary search to + * find the size of the partition. + */ + low = 0; + for (high = 1024; valid_offset(fd, high); high *= 2) + low = high; + while (low < high - 1) { + const blkid_loff_t mid = (low + high) / 2; + + if (valid_offset(fd, mid)) + low = mid; + else + high = mid; + } + return low + 1; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + long long bytes; + int fd; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n" + "Determine the size of a device\n", argv[0]); + return 1; + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) + perror(argv[0]); + + bytes = blkid_get_dev_size(fd); + printf("Device %s has %lld 1k blocks.\n", argv[1], + (unsigned long long)bytes >> 10); + + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/getsize.o b/jni/e2fsprogs/lib/blkid/getsize.o new file mode 100755 index 0000000000000000000000000000000000000000..15f475e73a312008266b15e626b9fb98f2d93e5d GIT binary patch literal 2088 zcmbtVO=uHa6h1SP+Nn)z@gKA%Y8O6vj;;7pL2xuyD@ehhAiP&&Os79IKQrsCOBbOwuH=_OlMivTv5w}CtK7}#K&kFSBuS&3$ z-_vtBC`psahY^^jd^xapFka@kZDoA+Va}5dT@KC`sx`gfoZ?@4N&Rr<9q|ru z-X%R9lsuEk*?^0COMfP~yEu0y0IbIo67O+6a+;PdR@dqy4|v_h^?HfoZ$=-gYbw)f ztLgMxOIc%!9v&#i?LV=0Kkv&z-9jGg17)>z@g4F1uT)krEYoXGApS=kd{w1}|E}?w zS{z60`awv)Rh!=2E!IPc<}_2UmzJ>kRA*O2opN}vCMNTG{>2;=N3DY_)y-|CQ>Dv!OiUMQjWl>$tc$K;7}2C}(~FF%9tAeX^B$eC4q8`<51{e=9d3ch?3p3J@* zvg@!mva25WdQIFfa;O&eeo$t43!!{@Z0`i-%2G~%>4U z_|cNi2SK{9Mq1_d!3NYCcQbta^bbHAnK{>_ zb6;~ia$Cmb`yTmkudf}6#H+QEXuwt~^Vt=Ue}Tst@+-a!aT)(uy(qI<@VvwLI33rz z&GZE>6rc-{#g4op-T>laR!*mNHSilXaGLFWabh)aKjO4j;XSBTk?l9ROn8F>e_R9q zTm$#e{oI)_M`%{JqLy3qPg_F@?grd=uVGM&7Pnd>wpy%kOlo^f;bK`(vhWd=rP-^JB z!NVGZq5fnzX29txIY{c9zoqP$?@pG<0PP8~kZ;L{SHzt1n zbjK9KJ&sA9cRAXeOVlsUZDzkrXSFkk;IeEy;@ d@}n6Gf6@OH#N4?Nf_8qXoxET=>hW{?e+T4zKx_a2 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/llseek.c b/jni/e2fsprogs/lib/blkid/llseek.c new file mode 100755 index 0000000..5929864 --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/llseek.c @@ -0,0 +1,147 @@ +/* + * llseek.c -- stub calling the llseek system call + * + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif + +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#ifdef __MSDOS__ +#include +#endif + +#include "blkidP.h" + +#ifdef __linux__ + +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + +#define my_llseek lseek64 + +#elif defined(HAVE_LLSEEK) +#include + +#ifndef HAVE_LLSEEK_PROTOTYPE +extern long long llseek(int fd, long long offset, int origin); +#endif + +#define my_llseek llseek + +#else /* ! HAVE_LLSEEK */ + +#if SIZEOF_LONG == SIZEOF_LONG_LONG + +#define llseek lseek + +#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */ + +#include + +#ifndef __NR__llseek +#define __NR__llseek 140 +#endif + +#ifndef __i386__ +static int _llseek(unsigned int, unsigned long, unsigned long, + blkid_loff_t *, unsigned int); + +static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high, + unsigned long, offset_low, blkid_loff_t *, result, + unsigned int, origin) +#endif + +static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin) +{ + blkid_loff_t result; + int retval; + +#ifndef __i386__ + retval = _llseek(fd, ((unsigned long long) offset) >> 32, + ((unsigned long long)offset) & 0xffffffff, + &result, origin); +#else + retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32, + ((unsigned long long)offset) & 0xffffffff, + &result, origin); +#endif + return (retval == -1 ? (blkid_loff_t) retval : result); +} + +#endif /* __alpha__ || __ia64__ */ + +#endif /* HAVE_LLSEEK */ + +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence) +{ + blkid_loff_t result; + static int do_compat = 0; + + if ((sizeof(off_t) >= sizeof(blkid_loff_t)) || + (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1)))) + return lseek(fd, (off_t) offset, whence); + + if (do_compat) { + errno = EOVERFLOW; + return -1; + } + + result = my_llseek(fd, offset, whence); + if (result == -1 && errno == ENOSYS) { + /* + * Just in case this code runs on top of an old kernel + * which does not support the llseek system call + */ + do_compat++; + errno = EOVERFLOW; + } + return result; +} + +#else /* !linux */ + +#ifndef EOVERFLOW +#ifdef EXT2_ET_INVALID_ARGUMENT +#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT +#else +#define EOVERFLOW 112 +#endif +#endif + +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin) +{ +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + return lseek64 (fd, offset, origin); +#else + if ((sizeof(off_t) < sizeof(blkid_loff_t)) && + (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) { + errno = EOVERFLOW; + return -1; + } + return lseek(fd, (off_t) offset, origin); +#endif +} + +#endif /* linux */ + + diff --git a/jni/e2fsprogs/lib/blkid/llseek.o b/jni/e2fsprogs/lib/blkid/llseek.o new file mode 100755 index 0000000000000000000000000000000000000000..e93eb75a8cba86bb4c709a9d781d340ecc49965b GIT binary patch literal 1280 zcmbtTJx?1!5S_Du0I>i?0wM8X3KuED%7zqF(J3N8fhZEu5uMKV@*$tk$ag{nM*<0@ zNfo5DAX{H`K!ef*34Q@7Q&?o?n32zmQ?b(Rn|W_$c6WAf_ru~`!m>by1*g#T zgaz13G;KRFZRo|whdNv}YKfD^J{%m^(`UCY;qP5PoFCU6v~9HQa}594sJ%bI*n^9t za}5R0_17l0bT!zh_!GGql~XfZet^;1`3Tn6acd-%hS$gqGyj%wwlBMo8XGuD9Coav z(%FSRxcSZc|KKwU9q{L&ot}i);W*%1girZFpXj{EQGcX2@uUnpBY0^&F=3SLPUKrop{m+*Rj9W^P=!jlto;!3UTLG~cwV4& zNfj#&@|!N|`53wWtNEqn$slwKC3q~R*PYd>Th_o83ZR0p8oGJJFJ;0^QBBh{ zMNvPOiOis2baLle({&kXxG1AypZ&X`bU3@ + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_MKDEV_H +#include +#endif +#ifdef __linux__ +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#include "blkidP.h" +#include "uuid/uuid.h" +#include "probe.h" + +static int figure_label_len(const unsigned char *label, int len) +{ + const unsigned char *end = label + len - 1; + + while (end >= label && (*end == ' ' || *end == 0)) + --end; + if (end >= label) + return end - label + 1; + return 0; +} + +static unsigned char *get_buffer(struct blkid_probe *pr, + blkid_loff_t off, size_t len) +{ + ssize_t ret_read; + unsigned char *newbuf; + + if (off + len <= SB_BUFFER_SIZE) { + if (!pr->sbbuf) { + pr->sbbuf = malloc(SB_BUFFER_SIZE); + if (!pr->sbbuf) + return NULL; + if (lseek(pr->fd, 0, SEEK_SET) < 0) + return NULL; + ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE); + if (ret_read < 0) + ret_read = 0; + pr->sb_valid = ret_read; + } + if (off+len > pr->sb_valid) + return NULL; + return pr->sbbuf + off; + } else { + if (len > pr->buf_max) { + newbuf = realloc(pr->buf, len); + if (newbuf == NULL) + return NULL; + pr->buf = newbuf; + pr->buf_max = len; + } + if (blkid_llseek(pr->fd, off, SEEK_SET) < 0) + return NULL; + ret_read = read(pr->fd, pr->buf, len); + if (ret_read != (ssize_t) len) + return NULL; + return pr->buf; + } +} + + +/* + * This is a special case code to check for an MDRAID device. We do + * this special since it requires checking for a superblock at the end + * of the device. + */ +static int check_mdraid(int fd, unsigned char *ret_uuid) +{ + struct mdp_superblock_s *md; + blkid_loff_t offset; + char buf[4096]; + + if (fd < 0) + return -BLKID_ERR_PARAM; + + offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; + + if (blkid_llseek(fd, offset, 0) < 0 || + read(fd, buf, 4096) != 4096) + return -BLKID_ERR_IO; + /* Check for magic number */ + if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4)) + return -BLKID_ERR_PARAM; + + if (!ret_uuid) + return 0; + *ret_uuid = 0; + + /* The MD UUID is not contiguous in the superblock, make it so */ + md = (struct mdp_superblock_s *)buf; + if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { + memcpy(ret_uuid, &md->set_uuid0, 4); + memcpy(ret_uuid + 4, &md->set_uuid1, 12); + } + return 0; +} + +static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag) +{ + char str[37]; + + if (!uuid_is_null(uuid)) { + uuid_unparse(uuid, str); + blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str)); + } +} + +static void get_ext2_info(blkid_dev dev, struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es = (struct ext2_super_block *) buf; + const char *label = 0; + + DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", + blkid_le32(es->s_feature_compat), + blkid_le32(es->s_feature_incompat), + blkid_le32(es->s_feature_ro_compat))); + + if (es->s_volume_name[0]) + label = es->s_volume_name; + blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); + + set_uuid(dev, es->s_uuid, 0); + + if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !uuid_is_null(es->s_journal_uuid)) + set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL"); + + if (strcmp(id->bim_type, "ext2") && + ((blkid_le32(es->s_feature_incompat) & + EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) + blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); +} + +/* + * Check to see if a filesystem is in /proc/filesystems. + * Returns 1 if found, 0 if not + */ +static int fs_proc_check(const char *fs_name) +{ + FILE *f; + char buf[80], *cp, *t; + + f = fopen("/proc/filesystems", "r"); + if (!f) + return (0); + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + cp = buf; + if (!isspace(*cp)) { + while (*cp && !isspace(*cp)) + cp++; + } + while (*cp && isspace(*cp)) + cp++; + if ((t = strchr(cp, '\n')) != NULL) + *t = 0; + if ((t = strchr(cp, '\t')) != NULL) + *t = 0; + if ((t = strchr(cp, ' ')) != NULL) + *t = 0; + if (!strcmp(fs_name, cp)) { + fclose(f); + return (1); + } + } + fclose(f); + return (0); +} + +/* + * Check to see if a filesystem is available as a module + * Returns 1 if found, 0 if not + */ +static int check_for_modules(const char *fs_name) +{ +#ifdef __linux__ + struct utsname uts; + FILE *f; + char buf[1024], *cp; + int namesz; + + if (uname(&uts)) + return (0); + snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); + + f = fopen(buf, "r"); + if (!f) + return (0); + + namesz = strlen(fs_name); + + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + if ((cp = strchr(buf, ':')) != NULL) + *cp = 0; + else + continue; + if ((cp = strrchr(buf, '/')) != NULL) + cp++; + else + cp = buf; + if (!strncmp(cp, fs_name, namesz) && + (!strcmp(cp + namesz, ".ko") || + !strcmp(cp + namesz, ".ko.gz"))) { + fclose(f); + return (1); + } + } + fclose(f); +#endif + return (0); +} + +static int linux_version_code(void) +{ +#ifdef __linux__ + struct utsname ut; + static int version_code = -1; + int major, minor, rev; + char *endptr; + const char *cp; + + if (version_code > 0) + return version_code; + + if (uname(&ut)) + return 0; + cp = ut.release; + + major = strtol(cp, &endptr, 10); + if (cp == endptr || *endptr != '.') + return 0; + cp = endptr + 1; + minor = strtol(cp, &endptr, 10); + if (cp == endptr || *endptr != '.') + return 0; + cp = endptr + 1; + rev = strtol(cp, &endptr, 10); + if (cp == endptr) + return 0; + version_code = (((major * 256) + minor) * 256) + rev; + return version_code; +#else + return 0; +#endif +} + +#define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29) + +static int system_supports_ext2(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext2") || check_for_modules("ext2")); + return ret; +} + +static int system_supports_ext4(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext4") || check_for_modules("ext4")); + return ret; +} + +static int system_supports_ext4dev(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); + return ret; +} + +static int probe_ext4dev(struct blkid_probe *probe, + struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es; + es = (struct ext2_super_block *)buf; + + /* Distinguish from jbd */ + if (blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + + /* + * If the filesystem does not have a journal and ext2 and ext4 + * is not present, then force this to be detected as an + * ext4dev filesystem. + */ + if (!(blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !system_supports_ext2() && !system_supports_ext4() && + system_supports_ext4dev() && + linux_version_code() >= EXT4_SUPPORTS_EXT2) + goto force_ext4dev; + + /* + * If the filesystem is marked as OK for use by in-development + * filesystem code, but ext4dev is not supported, and ext4 is, + * then don't call ourselves ext4dev, since we should be + * detected as ext4 in that case. + * + * If the filesystem is marked as in use by production + * filesystem, then it can only be used by ext4 and NOT by + * ext4dev, so always disclaim we are ext4dev in that case. + */ + if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { + if (!system_supports_ext4dev() && system_supports_ext4()) + return -BLKID_ERR_PARAM; + } else + return -BLKID_ERR_PARAM; + +force_ext4dev: + get_ext2_info(probe->dev, id, buf); + return 0; +} + +static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es; + es = (struct ext2_super_block *)buf; + + /* Distinguish from jbd */ + if (blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + + /* + * If the filesystem does not have a journal and ext2 is not + * present, then force this to be detected as an ext2 + * filesystem. + */ + if (!(blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !system_supports_ext2() && system_supports_ext4() && + linux_version_code() >= EXT4_SUPPORTS_EXT2) + goto force_ext4; + + /* Ext4 has at least one feature which ext3 doesn't understand */ + if (!(blkid_le32(es->s_feature_ro_compat) & + EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && + !(blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + +force_ext4: + /* + * If the filesystem is a OK for use by in-development + * filesystem code, and ext4dev is supported or ext4 is not + * supported, then don't call ourselves ext4, so we can redo + * the detection and mark the filesystem as ext4dev. + * + * If the filesystem is marked as in use by production + * filesystem, then it can only be used by ext4 and NOT by + * ext4dev. + */ + if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { + if (system_supports_ext4dev() || !system_supports_ext4()) + return -BLKID_ERR_PARAM; + } + get_ext2_info(probe->dev, id, buf); + return 0; +} + +static int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es; + es = (struct ext2_super_block *)buf; + + /* ext3 requires journal */ + if (!(blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL)) + return -BLKID_ERR_PARAM; + + /* Any features which ext3 doesn't understand */ + if ((blkid_le32(es->s_feature_ro_compat) & + EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || + (blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + + get_ext2_info(probe->dev, id, buf); + return 0; +} + +static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es; + + es = (struct ext2_super_block *)buf; + + /* Distinguish between ext3 and ext2 */ + if ((blkid_le32(es->s_feature_compat) & + EXT3_FEATURE_COMPAT_HAS_JOURNAL)) + return -BLKID_ERR_PARAM; + + /* Any features which ext2 doesn't understand */ + if ((blkid_le32(es->s_feature_ro_compat) & + EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || + (blkid_le32(es->s_feature_incompat) & + EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + + /* + * If ext2 is not present, but ext4 or ext4dev are, then + * disclaim we are ext2 + */ + if (!system_supports_ext2() && + (system_supports_ext4() || system_supports_ext4dev()) && + linux_version_code() >= EXT4_SUPPORTS_EXT2) + return -BLKID_ERR_PARAM; + + get_ext2_info(probe->dev, id, buf); + return 0; +} + +static int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id, + unsigned char *buf) +{ + struct ext2_super_block *es = (struct ext2_super_block *) buf; + + if (!(blkid_le32(es->s_feature_incompat) & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) + return -BLKID_ERR_PARAM; + + get_ext2_info(probe->dev, id, buf); + + return 0; +} + +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIR 0x10 +#define FAT_ATTR_LONG_NAME 0x0f +#define FAT_ATTR_MASK 0x3f +#define FAT_ENTRY_FREE 0xe5 + +static const char *no_name = "NO NAME "; + +static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (dir[i].name[0] == 0x00) + break; + + if ((dir[i].name[0] == FAT_ENTRY_FREE) || + (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) || + ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) + continue; + + if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == + FAT_ATTR_VOLUME_ID) { + return dir[i].name; + } + } + return 0; +} + +/* FAT label extraction from the root directory taken from Kay + * Sievers's volume_id library */ +static int probe_fat(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct vfat_super_block *vs = (struct vfat_super_block *) buf; + struct msdos_super_block *ms = (struct msdos_super_block *) buf; + struct vfat_dir_entry *dir; + char serno[10]; + const unsigned char *label = 0, *vol_label = 0, *tmp; + unsigned char *vol_serno; + int label_len = 0, maxloop = 100; + __u16 sector_size, dir_entries, reserved; + __u32 sect_count, fat_size, dir_size, cluster_count, fat_length; + __u32 buf_size, start_data_sect, next, root_start, root_dir_entries; + + /* sector size check */ + tmp = (unsigned char *)&ms->ms_sector_size; + sector_size = tmp[0] + (tmp[1] << 8); + if (sector_size != 0x200 && sector_size != 0x400 && + sector_size != 0x800 && sector_size != 0x1000) + return 1; + + tmp = (unsigned char *)&ms->ms_dir_entries; + dir_entries = tmp[0] + (tmp[1] << 8); + reserved = blkid_le16(ms->ms_reserved); + tmp = (unsigned char *)&ms->ms_sectors; + sect_count = tmp[0] + (tmp[1] << 8); + if (sect_count == 0) + sect_count = blkid_le32(ms->ms_total_sect); + + fat_length = blkid_le16(ms->ms_fat_length); + if (fat_length == 0) + fat_length = blkid_le32(vs->vs_fat32_length); + + fat_size = fat_length * ms->ms_fats; + dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + + (sector_size-1)) / sector_size; + + cluster_count = sect_count - (reserved + fat_size + dir_size); + if (ms->ms_cluster_size == 0) + return 1; + cluster_count /= ms->ms_cluster_size; + + if (cluster_count > FAT32_MAX) + return 1; + + if (ms->ms_fat_length) { + /* the label may be an attribute in the root directory */ + root_start = (reserved + fat_size) * sector_size; + root_dir_entries = vs->vs_dir_entries[0] + + (vs->vs_dir_entries[1] << 8); + + buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); + dir = (struct vfat_dir_entry *) get_buffer(probe, root_start, + buf_size); + if (dir) + vol_label = search_fat_label(dir, root_dir_entries); + + if (!vol_label || !memcmp(vol_label, no_name, 11)) + vol_label = ms->ms_label; + vol_serno = ms->ms_serno; + + blkid_set_tag(probe->dev, "SEC_TYPE", "msdos", + sizeof("msdos")); + } else { + /* Search the FAT32 root dir for the label attribute */ + buf_size = vs->vs_cluster_size * sector_size; + start_data_sect = reserved + fat_size; + + next = blkid_le32(vs->vs_root_cluster); + while (next && --maxloop) { + __u32 next_sect_off; + __u64 next_off, fat_entry_off; + int count; + + next_sect_off = (next - 2) * vs->vs_cluster_size; + next_off = (__u64) (start_data_sect + next_sect_off) * + sector_size; + + dir = (struct vfat_dir_entry *) + get_buffer(probe, next_off, buf_size); + if (dir == NULL) + break; + + count = buf_size / sizeof(struct vfat_dir_entry); + + vol_label = search_fat_label(dir, count); + if (vol_label) + break; + + /* get FAT entry */ + fat_entry_off = + ((unsigned int) reserved * + (unsigned int) sector_size) + + (next * sizeof(__u32)); + buf = get_buffer(probe, fat_entry_off, buf_size); + if (buf == NULL) + break; + + /* set next cluster */ + next = blkid_le32(*((__u32 *) buf) & 0x0fffffff); + } + + if (!vol_label || !memcmp(vol_label, no_name, 11)) + vol_label = vs->vs_label; + vol_serno = vs->vs_serno; + } + + if (vol_label && memcmp(vol_label, no_name, 11)) { + if ((label_len = figure_label_len(vol_label, 11))) + label = vol_label; + } + + /* We can't just print them as %04X, because they are unaligned */ + sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2], + vol_serno[1], vol_serno[0]); + + blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len); + blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1); + + return 0; +} + +/* + * The FAT filesystem could be without a magic string in superblock + * (e.g. old floppies). This heuristic for FAT detection is inspired + * by http://vrfy.org/projects/volume_id/ and Linux kernel. + * [7-Jul-2005, Karel Zak ] + */ +static int probe_fat_nomagic(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct msdos_super_block *ms; + + ms = (struct msdos_super_block *)buf; + + /* heads check */ + if (ms->ms_heads == 0) + return 1; + + /* cluster size check*/ + if (ms->ms_cluster_size == 0 || + (ms->ms_cluster_size & (ms->ms_cluster_size-1))) + return 1; + + /* media check */ + if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0) + return 1; + + /* fat counts(Linux kernel expects at least 1 FAT table) */ + if (!ms->ms_fats) + return 1; + + /* + * OS/2 and apparently DFSee will place a FAT12/16-like + * pseudo-superblock in the first 512 bytes of non-FAT + * filesystems --- at least JFS and HPFS, and possibly others. + * So we explicitly check for those filesystems at the + * FAT12/16 filesystem magic field identifier, and if they are + * present, we rule this out as a FAT filesystem, despite the + * FAT-like pseudo-header. + */ + if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) || + (memcmp(ms->ms_magic, "HPFS ", 8) == 0)) + return 1; + + return probe_fat(probe, id, buf); +} + +static int probe_ntfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct ntfs_super_block *ns; + struct master_file_table_record *mft; + struct file_attribute *attr; + char uuid_str[17], label_str[129], *cp; + int bytes_per_sector, sectors_per_cluster; + int mft_record_size, attr_off, attr_len; + unsigned int i, attr_type, val_len; + int val_off; + __u64 nr_clusters; + blkid_loff_t off; + unsigned char *buf_mft, *val; + + ns = (struct ntfs_super_block *) buf; + + bytes_per_sector = ns->bios_parameter_block[0] + + (ns->bios_parameter_block[1] << 8); + sectors_per_cluster = ns->bios_parameter_block[2]; + + if ((bytes_per_sector < 512) || (sectors_per_cluster == 0)) + return 1; + + if (ns->cluster_per_mft_record < 0) + mft_record_size = 1 << (0-ns->cluster_per_mft_record); + else + mft_record_size = ns->cluster_per_mft_record * + sectors_per_cluster * bytes_per_sector; + nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster; + + if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) || + (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters)) + return 1; + + off = blkid_le64(ns->mft_mirror_cluster_location) * + bytes_per_sector * sectors_per_cluster; + + buf_mft = get_buffer(probe, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector * + sectors_per_cluster; + + buf_mft = get_buffer(probe, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + off += MFT_RECORD_VOLUME * mft_record_size; + + buf_mft = get_buffer(probe, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + mft = (struct master_file_table_record *) buf_mft; + + attr_off = blkid_le16(mft->attrs_offset); + label_str[0] = 0; + + while (1) { + attr = (struct file_attribute *) (buf_mft + attr_off); + attr_len = blkid_le16(attr->len); + attr_type = blkid_le32(attr->type); + val_off = blkid_le16(attr->value_offset); + val_len = blkid_le32(attr->value_len); + + attr_off += attr_len; + + if ((attr_off > mft_record_size) || + (attr_len == 0)) + break; + + if (attr_type == MFT_RECORD_ATTR_END) + break; + + if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) { + if (val_len > sizeof(label_str)) + val_len = sizeof(label_str)-1; + + for (i=0, cp=label_str; i < val_len; i+=2,cp++) { + val = ((__u8 *) attr) + val_off + i; + *cp = val[0]; + if (val[1]) + *cp = '?'; + } + *cp = 0; + } + } + + sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial)); + blkid_set_tag(probe->dev, "UUID", uuid_str, 0); + if (label_str[0]) + blkid_set_tag(probe->dev, "LABEL", label_str, 0); + return 0; +} + + +static int probe_xfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct xfs_super_block *xs; + const char *label = 0; + + xs = (struct xfs_super_block *)buf; + + if (strlen(xs->xs_fname)) + label = xs->xs_fname; + blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname)); + set_uuid(probe->dev, xs->xs_uuid, 0); + return 0; +} + +static int probe_reiserfs(struct blkid_probe *probe, + struct blkid_magic *id, unsigned char *buf) +{ + struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; + unsigned int blocksize; + const char *label = 0; + + blocksize = blkid_le16(rs->rs_blocksize); + + /* The blocksize must be at least 1k */ + if ((blocksize >> 10) == 0) + return -BLKID_ERR_PARAM; + + /* If the superblock is inside the journal, we have the wrong one */ + if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) + return -BLKID_ERR_BIG; + + /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ + if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') { + if (strlen(rs->rs_label)) + label = rs->rs_label; + set_uuid(probe->dev, rs->rs_uuid, 0); + } + blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label)); + + return 0; +} + +static int probe_reiserfs4(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf; + const unsigned char *label = 0; + + if (strlen((char *) rs4->rs4_label)) + label = rs4->rs4_label; + set_uuid(probe->dev, rs4->rs4_uuid, 0); + blkid_set_tag(probe->dev, "LABEL", (const char *) label, + sizeof(rs4->rs4_label)); + + return 0; +} + +static int probe_jfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct jfs_super_block *js; + const char *label = 0; + + js = (struct jfs_super_block *)buf; + + if (blkid_le32(js->js_bsize) != (1U << blkid_le16(js->js_l2bsize))) + return 1; + + if (blkid_le32(js->js_pbsize) != (1U << blkid_le16(js->js_l2pbsize))) + return 1; + + if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) != + blkid_le16(js->js_l2bfactor)) + return 1; + + if (strlen((char *) js->js_label)) + label = (char *) js->js_label; + blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label)); + set_uuid(probe->dev, js->js_uuid, 0); + return 0; +} + +static int probe_zfs(struct blkid_probe *probe __BLKID_ATTR((unused)), + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf __BLKID_ATTR((unused))) +{ +#if 0 + char *vdev_label; + const char *pool_name = 0; + + /* read nvpair data for pool name, pool GUID (complex) */ + blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name)); + set_uuid(probe->dev, pool_guid, 0); +#endif + return 0; +} + +static int probe_luks(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + char uuid[41]; + + /* 168 is the offset to the 40 character uuid: + * http://luks.endorphin.org/LUKS-on-disk-format.pdf */ + strncpy(uuid, (char *) buf+168, 40); + uuid[40] = 0; + blkid_set_tag(probe->dev, "UUID", uuid, 40); + return 0; +} + +static int probe_romfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct romfs_super_block *ros; + const char *label = 0; + + ros = (struct romfs_super_block *)buf; + + if (strlen((char *) ros->ros_volume)) + label = (char *) ros->ros_volume; + blkid_set_tag(probe->dev, "LABEL", label, 0); + return 0; +} + +static int probe_cramfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct cramfs_super_block *csb; + const char *label = 0; + + csb = (struct cramfs_super_block *)buf; + + if (strlen((char *) csb->name)) + label = (char *) csb->name; + blkid_set_tag(probe->dev, "LABEL", label, 0); + return 0; +} + +static int probe_swap0(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf __BLKID_ATTR((unused))) +{ + blkid_set_tag(probe->dev, "UUID", 0, 0); + blkid_set_tag(probe->dev, "LABEL", 0, 0); + return 0; +} + +static int probe_swap1(struct blkid_probe *probe, + struct blkid_magic *id, + unsigned char *buf __BLKID_ATTR((unused))) +{ + struct swap_id_block *sws; + + probe_swap0(probe, id, buf); + /* + * Version 1 swap headers are always located at offset of 1024 + * bytes, although the swap signature itself is located at the + * end of the page (which may vary depending on hardware + * pagesize). + */ + sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024); + if (!sws) + return 1; + + /* check for wrong version or zeroed pagecount, for sanity */ + if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) && + (sws->sws_version != 1 || sws->sws_lastpage == 0)) + return 1; + + /* arbitrary sanity check.. is there any garbage down there? */ + if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { + if (sws->sws_volume[0]) + blkid_set_tag(probe->dev, "LABEL", sws->sws_volume, + sizeof(sws->sws_volume)); + if (sws->sws_uuid[0]) + set_uuid(probe->dev, sws->sws_uuid, 0); + } + return 0; +} + +static int probe_iso9660(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct iso_volume_descriptor *iso; + const unsigned char *label; + + iso = (struct iso_volume_descriptor *) buf; + label = iso->volume_id; + + blkid_set_tag(probe->dev, "LABEL", (const char *) label, + figure_label_len(label, 32)); + return 0; +} + + +static const char +*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", + "NSR03", "TEA01", 0 }; + +static int probe_udf(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf __BLKID_ATTR((unused))) +{ + int j, bs; + struct iso_volume_descriptor *isosb; + const char ** m; + + /* determine the block size by scanning in 2K increments + (block sizes larger than 2K will be null padded) */ + for (bs = 1; bs < 16; bs++) { + isosb = (struct iso_volume_descriptor *) + get_buffer(probe, (blkid_loff_t) bs*2048+32768, + sizeof(*isosb)); + if (!isosb) + return 1; + if (isosb->vd_id[0]) + break; + } + + /* Scan up to another 64 blocks looking for additional VSD's */ + for (j = 1; j < 64; j++) { + if (j > 1) { + isosb = (struct iso_volume_descriptor *) + get_buffer(probe, j*bs*2048+32768, + sizeof(*isosb)); + if (!isosb) + return 1; + } + /* If we find NSR0x then call it udf: + NSR01 for UDF 1.00 + NSR02 for UDF 1.50 + NSR03 for UDF 2.00 */ + if (!memcmp(isosb->vd_id, "NSR0", 4)) + return probe_iso9660(probe, id, buf); + for (m = udf_magic; *m; m++) + if (!memcmp(*m, isosb->vd_id, 5)) + break; + if (*m == 0) + return 1; + } + return 1; +} + +static int probe_ocfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct ocfs_volume_header ovh; + struct ocfs_volume_label ovl; + __u32 major; + + memcpy(&ovh, buf, sizeof(ovh)); + memcpy(&ovl, buf+512, sizeof(ovl)); + + major = ocfsmajor(ovh); + if (major == 1) + blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); + else if (major >= 9) + blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); + + blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl)); + blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); + set_uuid(probe->dev, ovl.vol_id, 0); + return 0; +} + +static int probe_ocfs2(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct ocfs2_super_block *osb; + + osb = (struct ocfs2_super_block *)buf; + + blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label)); + set_uuid(probe->dev, osb->s_uuid, 0); + return 0; +} + +static int probe_oracleasm(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct oracle_asm_disk_label *dl; + + dl = (struct oracle_asm_disk_label *)buf; + + blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); + return 0; +} + +static int probe_gfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct gfs2_sb *sbd; + const char *label = 0; + + sbd = (struct gfs2_sb *)buf; + + if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS && + blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI) + { + blkid_set_tag(probe->dev, "UUID", 0, 0); + + if (strlen(sbd->sb_locktable)) + label = sbd->sb_locktable; + blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable)); + return 0; + } + return 1; +} + +static int probe_gfs2(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct gfs2_sb *sbd; + const char *label = 0; + + sbd = (struct gfs2_sb *)buf; + + if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS && + blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI) + { + blkid_set_tag(probe->dev, "UUID", 0, 0); + + if (strlen(sbd->sb_locktable)) + label = sbd->sb_locktable; + blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable)); + return 0; + } + return 1; +} + +static void unicode_16be_to_utf8(unsigned char *str, int out_len, + const unsigned char *buf, int in_len) +{ + int i, j; + unsigned int c; + + for (i = j = 0; i + 2 <= in_len; i += 2) { + c = (buf[i] << 8) | buf[i+1]; + if (c == 0) { + str[j] = '\0'; + break; + } else if (c < 0x80) { + if (j+1 >= out_len) + break; + str[j++] = (unsigned char) c; + } else if (c < 0x800) { + if (j+2 >= out_len) + break; + str[j++] = (unsigned char) (0xc0 | (c >> 6)); + str[j++] = (unsigned char) (0x80 | (c & 0x3f)); + } else { + if (j+3 >= out_len) + break; + str[j++] = (unsigned char) (0xe0 | (c >> 12)); + str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f)); + str[j++] = (unsigned char) (0x80 | (c & 0x3f)); + } + } + str[j] = '\0'; +} + +static void unicode_16le_to_utf8(unsigned char *str, int out_len, + const unsigned char *buf, int in_len) +{ + int i, j; + unsigned int c; + + for (i = j = 0; i + 2 <= in_len; i += 2) { + c = (buf[i+1] << 8) | buf[i]; + if (c == 0) { + str[j] = '\0'; + break; + } else if (c < 0x80) { + if (j+1 >= out_len) + break; + str[j++] = (unsigned char) c; + } else if (c < 0x800) { + if (j+2 >= out_len) + break; + str[j++] = (unsigned char) (0xc0 | (c >> 6)); + str[j++] = (unsigned char) (0x80 | (c & 0x3f)); + } else { + if (j+3 >= out_len) + break; + str[j++] = (unsigned char) (0xe0 | (c >> 12)); + str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f)); + str[j++] = (unsigned char) (0x80 | (c & 0x3f)); + } + } + str[j] = '\0'; +} + +static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)), + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct hfs_mdb *hfs = (struct hfs_mdb *)buf; + char uuid_str[17]; + __u64 uuid; + + if ((memcmp(hfs->embed_sig, "H+", 2) == 0) || + (memcmp(hfs->embed_sig, "HX", 2) == 0)) + return 1; /* Not hfs, but an embedded HFS+ */ + + memcpy(&uuid, hfs->finder_info.id, 8); + uuid = blkid_le64(uuid); + if (uuid) { + sprintf(uuid_str, "%016llX", uuid); + blkid_set_tag(probe->dev, "UUID", uuid_str, 0); + } + blkid_set_tag(probe->dev, "LABEL", (char *)hfs->label, hfs->label_len); + return 0; +} + + +#define HFSPLUS_SECTOR_SIZE 512 + +static int probe_hfsplus(struct blkid_probe *probe, + struct blkid_magic *id, + unsigned char *buf) +{ + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; + struct hfsplus_bnode_descriptor *descr; + struct hfsplus_bheader_record *bnode; + struct hfsplus_catalog_key *key; + struct hfsplus_vol_header *hfsplus; + struct hfs_mdb *sbd = (struct hfs_mdb *) buf; + unsigned int alloc_block_size; + unsigned int alloc_first_block; + unsigned int embed_first_block; + unsigned int off = 0; + unsigned int blocksize; + unsigned int cat_block; + unsigned int ext_block_start; + unsigned int ext_block_count; + unsigned int record_count; + unsigned int leaf_node_head; + unsigned int leaf_node_count; + unsigned int leaf_node_size; + unsigned int leaf_block; + unsigned int label_len; + __u64 leaf_off, uuid; + char uuid_str[17], label[512]; + int ext; + + /* Check for a HFS+ volume embedded in a HFS volume */ + if (memcmp(sbd->signature, "BD", 2) == 0) { + if ((memcmp(sbd->embed_sig, "H+", 2) != 0) && + (memcmp(sbd->embed_sig, "HX", 2) != 0)) + /* This must be an HFS volume, so fail */ + return 1; + + alloc_block_size = blkid_be32(sbd->al_blk_size); + alloc_first_block = blkid_be16(sbd->al_bl_st); + embed_first_block = blkid_be16(sbd->embed_startblock); + off = (alloc_first_block * 512) + + (embed_first_block * alloc_block_size); + buf = get_buffer(probe, off + (id->bim_kboff * 1024), + sizeof(*sbd)); + if (!buf) + return 1; + + hfsplus = (struct hfsplus_vol_header *) buf; + } + + hfsplus = (struct hfsplus_vol_header *) buf; + + if ((memcmp(hfsplus->signature, "H+", 2) != 0) && + (memcmp(hfsplus->signature, "HX", 2) != 0)) + return 1; + + memcpy(&uuid, hfsplus->finder_info.id, 8); + uuid = blkid_le64(uuid); + if (uuid) { + sprintf(uuid_str, "%016llX", uuid); + blkid_set_tag(probe->dev, "UUID", uuid_str, 0); + } + + blocksize = blkid_be32(hfsplus->blocksize); + if (blocksize < HFSPLUS_SECTOR_SIZE) + return 1; + + memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); + cat_block = blkid_be32(extents[0].start_block); + + buf = get_buffer(probe, off + ((__u64) cat_block * blocksize), 0x2000); + if (!buf) + return 0; + + bnode = (struct hfsplus_bheader_record *) + &buf[sizeof(struct hfsplus_bnode_descriptor)]; + + leaf_node_head = blkid_be32(bnode->leaf_head); + leaf_node_size = blkid_be16(bnode->node_size); + leaf_node_count = blkid_be32(bnode->leaf_count); + if (leaf_node_count == 0) + return 0; + + leaf_block = (leaf_node_head * leaf_node_size) / blocksize; + + /* get physical location */ + for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { + ext_block_start = blkid_be32(extents[ext].start_block); + ext_block_count = blkid_be32(extents[ext].block_count); + if (ext_block_count == 0) + return 0; + + /* this is our extent */ + if (leaf_block < ext_block_count) + break; + + leaf_block -= ext_block_count; + } + if (ext == HFSPLUS_EXTENT_COUNT) + return 0; + + leaf_off = (__u64) (ext_block_start + leaf_block) * blocksize; + + buf = get_buffer(probe, off + leaf_off, leaf_node_size); + if (!buf) + return 0; + + descr = (struct hfsplus_bnode_descriptor *) buf; + record_count = blkid_be16(descr->num_recs); + if (record_count == 0) + return 0; + + if (descr->type != HFS_NODE_LEAF) + return 0; + + key = (struct hfsplus_catalog_key *) + &buf[sizeof(struct hfsplus_bnode_descriptor)]; + + if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID) + return 0; + + label_len = blkid_be16(key->unicode_len) * 2; + unicode_16be_to_utf8((unsigned char *)label, sizeof(label), + key->unicode, label_len); + blkid_set_tag(probe->dev, "LABEL", label, 0); + return 0; +} + +#define LVM2_LABEL_SIZE 512 +static unsigned int lvm2_calc_crc(const void *buf, unsigned int size) +{ + static const unsigned int crctab[] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + unsigned int i, crc = 0xf597a6cf; + const __u8 *data = (const __u8 *) buf; + + for (i = 0; i < size; i++) { + crc ^= *data++; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + } + return crc; +} + +static int probe_lvm2(struct blkid_probe *probe, + struct blkid_magic *id, + unsigned char *buf) +{ + int sector = (id->bim_kboff) << 1; + struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf; + char *p, *q, uuid[40]; + unsigned int i, b; + + /* buf is at 0k or 1k offset; find label inside */ + if (memcmp(buf, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *)buf; + } else if (memcmp(buf + 512, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *)(buf + 512); + sector++; + } else { + return 1; + } + + if (blkid_le64(label->sector_xl) != (unsigned) sector) { + DBG(DEBUG_PROBE, + printf("LVM2: label for sector %llu found at sector %d\n", + blkid_le64(label->sector_xl), sector)); + return 1; + } + + if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE - + ((char *)&label->offset_xl - (char *)label)) != + blkid_le32(label->crc_xl)) { + DBG(DEBUG_PROBE, + printf("LVM2: label checksum incorrect at sector %d\n", + sector)); + return 1; + } + + for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i < LVM2_ID_LEN; + i++, b <<= 1) { + if (b & 0x4444440) + *p++ = '-'; + *p++ = *q++; + } + + blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6); + + return 0; +} + +static int probe_btrfs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct btrfs_super_block *bs; + const char *label = 0; + + bs = (struct btrfs_super_block *)buf; + + if (strlen(bs->label)) + label = bs->label; + blkid_set_tag(probe->dev, "LABEL", label, sizeof(bs->label)); + set_uuid(probe->dev, bs->fsid, 0); + return 0; +} + +static int probe_f2fs(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct f2fs_super_block *bs; + + bs = (struct f2fs_super_block *)buf; + set_uuid(probe->dev, bs->uuid, 0); + return 0; +} + +static uint64_t exfat_block_to_offset(const struct exfat_super_block *sb, + uint64_t block) +{ + return block << sb->block_bits; +} + +static uint64_t exfat_cluster_to_block(const struct exfat_super_block *sb, + uint32_t cluster) +{ + return sb->cluster_block_start + + ((uint64_t)(cluster - EXFAT_FIRST_DATA_CLUSTER) << sb->bpc_bits); +} + +static uint64_t exfat_cluster_to_offset(const struct exfat_super_block *sb, + uint32_t cluster) +{ + return exfat_block_to_offset(sb, exfat_cluster_to_block(sb, cluster)); +} + +static uint32_t exfat_next_cluster(struct blkid_probe *probe, + const struct exfat_super_block *sb, + uint32_t cluster) +{ + uint32_t *next; + uint64_t offset; + + offset = exfat_block_to_offset(sb, sb->fat_block_start) + + (uint64_t) cluster * sizeof (cluster); + next = (uint32_t *)get_buffer(probe, offset, sizeof (uint32_t)); + + return next ? *next : 0; +} + +static struct exfat_entry_label *find_exfat_entry_label( + struct blkid_probe *probe, const struct exfat_super_block *sb) +{ + uint32_t cluster = sb->rootdir_cluster; + uint64_t offset = exfat_cluster_to_offset(sb, cluster); + uint8_t *entry; + const size_t max_iter = 10000; + size_t i = 0; + + for (; i < max_iter; ++i) { + entry = (uint8_t *)get_buffer(probe, offset, EXFAT_ENTRY_SIZE); + if (!entry) + return NULL; + if (entry[0] == EXFAT_ENTRY_EOD) + return NULL; + if (entry[0] == EXFAT_ENTRY_LABEL) + return (struct exfat_entry_label*) entry; + + offset += EXFAT_ENTRY_SIZE; + if (offset % CLUSTER_SIZE(sb) == 0) { + cluster = exfat_next_cluster(probe, sb, cluster); + if (cluster < EXFAT_FIRST_DATA_CLUSTER) + return NULL; + if (cluster > EXFAT_LAST_DATA_CLUSTER) + return NULL; + offset = exfat_cluster_to_offset(sb, cluster); + } + } + + return NULL; +} + +static int probe_exfat(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + struct exfat_super_block *sb; + struct exfat_entry_label *label; + char uuid[40]; + + sb = (struct exfat_super_block *)buf; + if (!sb || CLUSTER_SIZE(sb) == 0) { + DBG(DEBUG_PROBE, printf("bad exfat superblock.\n")); + return errno ? - errno : 1; + } + + label = find_exfat_entry_label(probe, sb); + if (label) { + unsigned char utf8_label[128]; + unicode_16le_to_utf8(utf8_label, sizeof(utf8_label), label->name, label->length * 2); + blkid_set_tag(probe->dev, "LABEL", (char *) utf8_label, 0); + } else { + blkid_set_tag(probe->dev, "LABEL", "disk", 4); + } + + memset(uuid, 0, sizeof (uuid)); + snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX", + sb->volume_serial[3], sb->volume_serial[2], + sb->volume_serial[1], sb->volume_serial[0]); + blkid_set_tag(probe->dev, "UUID", uuid, strlen(uuid)); + + return 0; +} + +/* + * Various filesystem magics that we can check for. Note that kboff and + * sboff are in kilobytes and bytes respectively. All magics are in + * byte strings so we don't worry about endian issues. + */ +static struct blkid_magic type_array[] = { +/* type kboff sboff len magic probe */ + { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, + { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs }, + { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, + { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev }, + { "ext4", 1, 0x38, 2, "\123\357", probe_ext4 }, + { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, + { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, + { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, + { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, + { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, + { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4 }, + { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2 }, + { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs }, + { "vfat", 0, 0x52, 5, "MSWIN", probe_fat }, + { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat }, + { "vfat", 0, 0x36, 5, "MSDOS", probe_fat }, + { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat }, + { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat }, + { "vfat", 0, 0, 1, "\353", probe_fat_nomagic }, + { "vfat", 0, 0, 1, "\351", probe_fat_nomagic }, + { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic }, + { "minix", 1, 0x10, 2, "\177\023", 0 }, + { "minix", 1, 0x10, 2, "\217\023", 0 }, + { "minix", 1, 0x10, 2, "\150\044", 0 }, + { "minix", 1, 0x10, 2, "\170\044", 0 }, + { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, + { "xfs", 0, 0, 4, "XFSB", probe_xfs }, + { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, + { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, + { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, + { "qnx4", 0, 4, 6, "QNX4FS", 0 }, + { "udf", 32, 1, 5, "BEA01", probe_udf }, + { "udf", 32, 1, 5, "BOOT2", probe_udf }, + { "udf", 32, 1, 5, "CD001", probe_udf }, + { "udf", 32, 1, 5, "CDW02", probe_udf }, + { "udf", 32, 1, 5, "NSR02", probe_udf }, + { "udf", 32, 1, 5, "NSR03", probe_udf }, + { "udf", 32, 1, 5, "TEA01", probe_udf }, + { "iso9660", 32, 1, 5, "CD001", probe_iso9660 }, + { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 }, + { "jfs", 32, 0, 4, "JFS1", probe_jfs }, + /* 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 }, + { "hfs", 1, 0, 2, "BD", probe_hfs }, + { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, + { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, + { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, + { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, + { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, + { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1 }, + { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, + { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, + { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1 }, + { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, + { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, + { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1 }, + { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, + { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, + { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1 }, + { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, + { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, + { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1 }, + { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1 }, + { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, + { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, + { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, + { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, + { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, + { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks }, + { "squashfs", 0, 0, 4, "sqsh", 0 }, + { "squashfs", 0, 0, 4, "hsqs", 0 }, + { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 }, + { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs }, + { "f2fs", 1, 0, 4, "\x10\x20\xf5\xf2", probe_f2fs }, + { "exfat", 0, 3, 8, "EXFAT ", probe_exfat }, + { NULL, 0, 0, 0, NULL, NULL } +}; + +/* + * Verify that the data in dev is consistent with what is on the actual + * block device (using the devname field only). Normally this will be + * called when finding items in the cache, but for long running processes + * is also desirable to revalidate an item before use. + * + * If we are unable to revalidate the data, we return the old data and + * do not set the BLKID_BID_FL_VERIFIED flag on it. + */ +blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) +{ + struct blkid_magic *id; + struct blkid_probe probe; + blkid_tag_iterate iter; + unsigned char *buf; + const char *type, *value; + struct stat st; + time_t now; + double diff; + int idx; + + if (!dev) + return NULL; + + now = time(0); + diff = difftime(now, dev->bid_time); + + if (stat(dev->bid_name, &st) < 0) { + DBG(DEBUG_PROBE, + printf("blkid_verify: error %s (%d) while " + "trying to stat %s\n", strerror(errno), errno, + dev->bid_name)); + open_err: + if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) { + /* We don't have read permission, just return cache data. */ + DBG(DEBUG_PROBE, printf("returning unverified data for %s\n", + dev->bid_name)); + return dev; + } + blkid_free_dev(dev); + return NULL; + } + + if ((now >= dev->bid_time) && + (st.st_mtime <= dev->bid_time) && + ((diff < BLKID_PROBE_MIN) || + (dev->bid_flags & BLKID_BID_FL_VERIFIED && + diff < BLKID_PROBE_INTERVAL))) + return dev; + + DBG(DEBUG_PROBE, + printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t" + "time since last check %lu)\n", + dev->bid_name, (unsigned long)dev->bid_time, + (unsigned long)st.st_mtime, (unsigned long)diff)); + + if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) { + DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while " + "opening %s\n", strerror(errno), errno, + dev->bid_name)); + goto open_err; + } + + probe.cache = cache; + probe.dev = dev; + probe.sbbuf = 0; + probe.buf = 0; + probe.buf_max = 0; + + /* + * Iterate over the type array. If we already know the type, + * then try that first. If it doesn't work, then blow away + * the type information, and try again. + * + */ +try_again: + type = 0; + if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { + uuid_t uuid; + + if (check_mdraid(probe.fd, uuid) == 0) { + set_uuid(dev, uuid, 0); + type = "mdraid"; + goto found_type; + } + } + for (id = type_array; id->bim_type; id++) { + if (dev->bid_type && + strcmp(id->bim_type, dev->bid_type)) + continue; + + idx = id->bim_kboff + (id->bim_sboff >> 10); + buf = get_buffer(&probe, (__u64) idx << 10, 1024); + if (!buf) + continue; + + if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff), + id->bim_len)) + continue; + + if ((id->bim_probe == NULL) || + (id->bim_probe(&probe, id, buf) == 0)) { + type = id->bim_type; + goto found_type; + } + } + + if (!id->bim_type && dev->bid_type) { + /* + * Zap the device filesystem information and try again + */ + DBG(DEBUG_PROBE, + printf("previous fs type %s not valid, " + "trying full probe\n", dev->bid_type)); + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) + blkid_set_tag(dev, type, 0, 0); + blkid_tag_iterate_end(iter); + goto try_again; + } + + if (!dev->bid_type) { + blkid_free_dev(dev); + dev = 0; + goto found_type; + } + +found_type: + if (dev && type) { + dev->bid_devno = st.st_rdev; + dev->bid_time = time(0); + dev->bid_flags |= BLKID_BID_FL_VERIFIED; + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + + blkid_set_tag(dev, "TYPE", type, 0); + + DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", + dev->bid_name, (long long)st.st_rdev, type)); + } + + free(probe.sbbuf); + free(probe.buf); + if (probe.fd >= 0) + close(probe.fd); + + return dev; +} + +int blkid_known_fstype(const char *fstype) +{ + struct blkid_magic *id; + + for (id = type_array; id->bim_type; id++) { + if (strcmp(fstype, id->bim_type) == 0) + return 1; + } + return 0; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_dev dev; + blkid_cache cache; + int ret; + + if (argc != 2) { + fprintf(stderr, "Usage: %s device\n" + "Probe a single device to determine type\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); + if (!dev) { + printf("%s: %s has an unsupported type\n", argv[0], argv[1]); + return (1); + } + printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)"); + if (dev->bid_label) + printf("LABEL='%s'\n", dev->bid_label); + if (dev->bid_uuid) + printf("UUID='%s'\n", dev->bid_uuid); + + blkid_free_dev(dev); + return (0); +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/probe.o b/jni/e2fsprogs/lib/blkid/probe.o new file mode 100755 index 0000000000000000000000000000000000000000..29b31a5ab030ce4cc1e5bd7f25542e1e43343960 GIT binary patch literal 46912 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 |^v6^=fX`_EhWrXT% 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 a8#lXY)19XtrcbPcl=)>GZ@|BM|NjGzvn~Sw literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/read.c b/jni/e2fsprogs/lib/blkid/read.c new file mode 100755 index 0000000..b894856 --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/read.c @@ -0,0 +1,494 @@ +/* + * read.c - read the blkid cache from disk, to avoid scanning all devices + * + * Copyright (C) 2001, 2003 Theodore Y. Ts'o + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#define _XOPEN_SOURCE 600 /* for inclusion of strtoull */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "blkidP.h" +#include "uuid/uuid.h" + +#ifdef HAVE_STRTOULL +#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */ +#else +/* FIXME: need to support real strtoull here */ +#define STRTOULL strtoul +#endif + +#if HAVE_STDLIB_H +#include +#endif + +#ifdef TEST_PROGRAM +#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev)) +static void debug_dump_dev(blkid_dev dev); +#endif + +/* + * File format: + * + * ...]>device_name + * + * The following tags are required for each entry: + * unique (within this file) ID number of this device + * (ascii time_t) time this entry was last read from disk + * (detected) type of filesystem/data for this partition + * + * The following tags may be present, depending on the device contents + * (user supplied) label (volume name, etc) + * (generated) universally unique identifier (serial no) + */ + +static char *skip_over_blank(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + char ch; + + while ((ch = *cp)) { + /* If we see a backslash, skip the next character */ + if (ch == '\\') { + cp++; + if (*cp == '\0') + break; + cp++; + continue; + } + if (isspace(ch) || ch == '<' || ch == '>') + break; + cp++; + } + return cp; +} + +static char *strip_line(char *line) +{ + char *p; + + line = skip_over_blank(line); + + p = line + strlen(line) - 1; + + while (*line) { + if (isspace(*p)) + *p-- = '\0'; + else + break; + } + + return line; +} + +#if 0 +static char *parse_word(char **buf) +{ + char *word, *next; + + word = *buf; + if (*word == '\0') + return NULL; + + word = skip_over_blank(word); + next = skip_over_word(word); + if (*next) { + char *end = next - 1; + if (*end == '"' || *end == '\'') + *end = '\0'; + *next++ = '\0'; + } + *buf = next; + + if (*word == '"' || *word == '\'') + word++; + return word; +} +#endif + +/* + * Start parsing a new line from the cache. + * + * line starts with " continue parsing line + * line starts with " skip line + * line starts with other, return -BLKID_ERR_CACHE -> error + */ +static int parse_start(char **cp) +{ + char *p; + + p = strip_line(*cp); + + /* Skip comment or blank lines. We can't just NUL the first '#' char, + * in case it is inside quotes, or escaped. + */ + if (*p == '\0' || *p == '#') + return 0; + + if (!strncmp(p, "", 9)) { + DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp)); + *cp += 9; + return 0; + } + + return -BLKID_ERR_CACHE; +} + +/* + * Allocate a new device struct with device name filled in. Will handle + * finding the device on lines of the form: + * devname + * devnamebar + */ +static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) +{ + char *start, *tmp, *end, *name; + int ret; + + if ((ret = parse_start(cp)) <= 0) + return ret; + + start = tmp = strchr(*cp, '>'); + if (!start) { + DBG(DEBUG_READ, + printf("blkid: short line parsing dev: %s\n", *cp)); + return -BLKID_ERR_CACHE; + } + start = skip_over_blank(start + 1); + end = skip_over_word(start); + + DBG(DEBUG_READ, printf("device should be %.*s\n", + (int)(end - start), start)); + + if (**cp == '>') + *cp = end; + else + (*cp)++; + + *tmp = '\0'; + + if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { + DBG(DEBUG_READ, + printf("blkid: missing ending: %s\n", end)); + } else if (tmp) + *tmp = '\0'; + + if (end - start <= 1) { + DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp)); + return -BLKID_ERR_CACHE; + } + + name = blkid_strndup(start, end-start); + if (name == NULL) + return -BLKID_ERR_MEM; + + DBG(DEBUG_READ, printf("found dev %s\n", name)); + + if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) { + free(name); + return -BLKID_ERR_MEM; + } + + free(name); + return 1; +} + +/* + * Extract a tag of the form NAME="value" from the line. + */ +static int parse_token(char **name, char **value, char **cp) +{ + char *end; + + if (!name || !value || !cp) + return -BLKID_ERR_PARAM; + + if (!(*value = strchr(*cp, '='))) + return 0; + + **value = '\0'; + *name = strip_line(*cp); + *value = skip_over_blank(*value + 1); + + if (**value == '"') { + end = strchr(*value + 1, '"'); + if (!end) { + DBG(DEBUG_READ, + printf("unbalanced quotes at: %s\n", *value)); + *cp = *value; + return -BLKID_ERR_CACHE; + } + (*value)++; + *end = '\0'; + end++; + } else { + end = skip_over_word(*value); + if (*end) { + *end = '\0'; + end++; + } + } + *cp = end; + + return 1; +} + +/* + * Extract a tag of the form value from the line. + */ +/* +static int parse_xml(char **name, char **value, char **cp) +{ + char *end; + + if (!name || !value || !cp) + return -BLKID_ERR_PARAM; + + *name = strip_line(*cp); + + if ((*name)[0] != '<' || (*name)[1] == '/') + return 0; + + FIXME: finish this. +} +*/ + +/* + * Extract a tag from the line. + * + * Return 1 if a valid tag was found. + * Return 0 if no tag found. + * Return -ve error code. + */ +static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) +{ + char *name; + char *value; + int ret; + + if (!cache || !dev) + return -BLKID_ERR_PARAM; + + if ((ret = parse_token(&name, &value, cp)) <= 0 /* && + (ret = parse_xml(&name, &value, cp)) <= 0 */) + return ret; + + /* Some tags are stored directly in the device struct */ + if (!strcmp(name, "DEVNO")) + dev->bid_devno = STRTOULL(value, 0, 0); + else if (!strcmp(name, "PRI")) + dev->bid_pri = strtol(value, 0, 0); + else if (!strcmp(name, "TIME")) + dev->bid_time = STRTOULL(value, 0, 0); + else + ret = blkid_set_tag(dev, name, value, strlen(value)); + + DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); + + return ret < 0 ? ret : 1; +} + +/* + * Parse a single line of data, and return a newly allocated dev struct. + * Add the new device to the cache struct, if one was read. + * + * Lines are of the form /dev/foo + * + * Returns -ve value on error. + * Returns 0 otherwise. + * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL + * (e.g. comment lines, unknown XML content, etc). + */ +static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) +{ + blkid_dev dev; + int ret; + + if (!cache || !dev_p) + return -BLKID_ERR_PARAM; + + *dev_p = NULL; + + DBG(DEBUG_READ, printf("line: %s\n", cp)); + + if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) + return ret; + + dev = *dev_p; + + while ((ret = parse_tag(cache, dev, &cp)) > 0) { + ; + } + + if (dev->bid_type == NULL) { + DBG(DEBUG_READ, + printf("blkid: device %s has no TYPE\n",dev->bid_name)); + blkid_free_dev(dev); + } + + DBG(DEBUG_READ, blkid_debug_dump_dev(dev)); + + return ret; +} + +/* + * Parse the specified filename, and return the data in the supplied or + * a newly allocated cache struct. If the file doesn't exist, return a + * new empty cache struct. + */ +void blkid_read_cache(blkid_cache cache) +{ + FILE *file; + char buf[4096]; + int fd, lineno = 0; + struct stat st; + + if (!cache) + return; + + /* + * If the file doesn't exist, then we just return an empty + * struct so that the cache can be populated. + */ + if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) + return; + if (fstat(fd, &st) < 0) + goto errout; + if ((st.st_mtime == cache->bic_ftime) || + (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { + DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", + cache->bic_filename)); + goto errout; + } + + DBG(DEBUG_CACHE, printf("reading cache file %s\n", + cache->bic_filename)); + + file = fdopen(fd, "r"); + if (!file) + goto errout; + + while (fgets(buf, sizeof(buf), file)) { + blkid_dev dev; + unsigned int end; + + lineno++; + if (buf[0] == 0) + continue; + end = strlen(buf) - 1; + /* Continue reading next line if it ends with a backslash */ + while (buf[end] == '\\' && end < sizeof(buf) - 2 && + fgets(buf + end, sizeof(buf) - end, file)) { + end = strlen(buf) - 1; + lineno++; + } + + if (blkid_parse_line(cache, &dev, buf) < 0) { + DBG(DEBUG_READ, + printf("blkid: bad format on line %d\n", lineno)); + continue; + } + } + fclose(file); + + /* + * Initially we do not need to write out the cache file. + */ + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + cache->bic_ftime = st.st_mtime; + + return; +errout: + close(fd); + return; +} + +#ifdef TEST_PROGRAM +static void debug_dump_dev(blkid_dev dev) +{ + struct list_head *p; + + if (!dev) { + printf(" dev: NULL\n"); + return; + } + + printf(" dev: name = %s\n", dev->bid_name); + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno); + printf(" dev: TIME=\"%lld\"\n", (long long)dev->bid_time); + printf(" dev: PRI=\"%d\"\n", dev->bid_pri); + printf(" dev: flags = 0x%08X\n", dev->bid_flags); + + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + if (tag) + printf(" tag: %s=\"%s\"\n", tag->bit_name, + tag->bit_val); + else + printf(" tag: NULL\n"); + } + printf("\n"); +} + +int main(int argc, char**argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_debug_mask = DEBUG_ALL; + if (argc > 2) { + fprintf(stderr, "Usage: %s [filename]\n" + "Test parsing of the cache (filename)\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) + fprintf(stderr, "error %d reading cache file %s\n", ret, + argv[1] ? argv[1] : BLKID_CACHE_FILE); + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/read.o b/jni/e2fsprogs/lib/blkid/read.o new file mode 100755 index 0000000000000000000000000000000000000000..4bff33f37ca78e96007217fceec5a2bbe6dd1283 GIT binary patch literal 6656 zcmbtYZERat8Gh}XHclJTt{=2p*E;Q5DG8d}bQ@}(e889@MYN-f>x{+@C;dB+-4-oa3ASIQU5E9CSrXmV*GJZG|q($_HEiE$7bMATV zn>%~^!HMj1?sMMn_dV~q&UcPH{zxzo5FG*ewUnO}6`9ylUPsL`Dr-QwJpSA1kJd_I z*^yMSHab^yoVj$n%;kW|Dk&7-kW6S*w9qH=E6CmSZG3WTqXlBJJzAJ|!YvSYG5e-u zx+VX4(wxC3`(`vV|C*$@r}zNyMeyd@qlIShH*bcVK;7-E$Z_(i+)!&Y(8&F z{eL-iEsK!R7+CY7KG(_l_nHH1ZqH+n_8Q#+-L*fzhcb-*b`KujF`_T@ajybt?L zOc2xgNl7h0*WI4D{|5VSD~;8~JhXtm6R{3Gw|zrrD`H~v(zIC$H8$?Fi?*OPQmBp8 zN8no?|9yJK>3YBD1m>2 zpRpghyKF-i&*~HQjBF!ow(HvRc>6SbN*UiK>D#L5<@SK_?egS~{HxB6{FL)d{?F8f z9IdbuxuTujuqzE3ft}ZDCrth29J!L)D2416Dde`4ZAk~*czlJv0mpeuEmAh)FCd6?yWVmb4K@KtcmD_0I+?ECHIcrZAw#?Z4WKl0$ zp-0asd@?-9nR{j|KV=ztkh2Kecy6I*N%N$>G=h${GrvkVk2A!WXHgrhQ^+>;&}aSM z2p*G5?CruCBW-$;F+?0JZ5DgPm52T+)&w5Lp7u?dJRX@YPTD-qGLNgLm+{OR)jWD@ zl)BU=tx*`U=~cvb>NT00M}2>ex!CK=`Cd2Yk5cdC*YnU{>QRjWx3^@snI3s%!S+ex z*G?%!D)29g(gIjq^M*ejR=Z{J#(k4L79vziYwzWwc+?qNJAH?NnV5`<*j`9$n8SOcIMh}YF=T$x#fBQ7s9puA7%^~N%C>DR>uFDwWV)D5w z;O0|oJ{Q5$#2&cE?QN`q%6am{Y_?o$Q863++o zLmJlNyP8Y(AUrpKKCAT!tPVVj;K6;?76czZONawyFOPfbrd{TEZ!F@jU>!D}Lp`jO zjM(=D;vwRDSSOOXtuZJ55U@Ys-M~{j-)^65eGi*}%#um*t z&W@jt@isB9&{K%Jy`uack&uJE@n`#c;&O1WyZC~19C_;Km*t6LkIC`JzH~&SXCO9o zs`1%)Vyu67sIm1xq&0E?HE9OyG$ZiMV-on*j=;A1urvX|`;Zw2QEbxD(AZhOz421b zE301)IlF`P;l|Dex%H2~i|ppMODeZGcQiynyZ)8n%Qe9p_2DQ8l@9OcW}x0l*R6EU zTY>s;w@XNQ7hN*B;L?qh=+1&}q)hjYrMtnoqhX)Y1+UhJ_j&aG)6ykfI{M<;_q6MX z+E-6~7)Gw^vrG5-N;)=PjlfDbuMmVh9%y24Svhgn_K{Ev2q41y@|cciuhRL?K7tVFI2%lsDk5nUq$)HtKeU&g7;Lx8MaDs z*n^Eq_-GaS%T@57Rl)yQ1?L&Bq_+b&$2Qo7-xsCPZCAv3wsoZKVk2tEQ$NN=jXzwEK`B#j*fM*Ur{Z$X{rN86B^$s9^qb*s=VGZcGnrw5<#$=6ss?~||i3m!RM`BNTzmq-3JpL~tQJ3je}&v@i`<=^z+ zUi)ioU#7p_dbrnv-{-Ms#^M@JTLyB&;u=rI|KyRg+au?K?aL}>jossq84i`B_$7wWlBAFlV|j1SlQFz3Vd zK3oqwI8?9RhX;JP-iO^jT<<;Y11d-Fy(u5P-k)+};Bl$k1>y9(nZW zllMb)&uQz(7#vB)PN^iUPWB88kHskm`~&?%aZBmyGJxw`ysztIA~vY|iFmBHt0&ge z7Z*lB`p3pbVtD^9+wqOzM6Xp8ALkYe(mR1t3(pRy|HAB zRIPa2eKxYs&HVrOeGK`vEq8^WyuDPuYxA$0zDKzq8^rAKRWga%RX6_8;T^X9mY^oA zh($|?yV#0<8gbmT#_{;_yxHSj`u#Bq<)#o(;hc6||p8HDi`_NugA +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include "blkidP.h" + +/* + * Find a tagname (e.g. LABEL or UUID) on a specific device. + */ +char *blkid_get_tag_value(blkid_cache cache, const char *tagname, + const char *devname) +{ + blkid_tag found; + blkid_dev dev; + blkid_cache c = cache; + char *ret = NULL; + + DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname)); + + if (!devname) + return NULL; + + if (!cache) { + if (blkid_get_cache(&c, NULL) < 0) + return NULL; + } + + if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) && + (found = blkid_find_tag_dev(dev, tagname))) + ret = blkid_strdup(found->bit_val); + + if (!cache) + blkid_put_cache(c); + + return ret; +} + +/* + * Locate a device name from a token (NAME=value string), or (name, value) + * pair. In the case of a token, value is ignored. If the "token" is not + * of the form "NAME=value" and there is no value given, then it is assumed + * to be the actual devname and a copy is returned. + */ +char *blkid_get_devname(blkid_cache cache, const char *token, + const char *value) +{ + blkid_dev dev; + blkid_cache c = cache; + char *t = 0, *v = 0; + char *ret = NULL; + + if (!token) + return NULL; + + if (!cache) { + if (blkid_get_cache(&c, NULL) < 0) + return NULL; + } + + DBG(DEBUG_RESOLVE, + printf("looking for %s%s%s %s\n", token, value ? "=" : "", + value ? value : "", cache ? "in cache" : "from disk")); + + if (!value) { + if (!strchr(token, '=')) { + ret = blkid_strdup(token); + goto out; + } + blkid_parse_tag_string(token, &t, &v); + if (!t || !v) + goto out; + token = t; + value = v; + } + + dev = blkid_find_dev_with_tag(c, token, value); + if (!dev) + goto out; + + ret = blkid_strdup(blkid_dev_devname(dev)); + +out: + free(t); + free(v); + if (!cache) { + blkid_put_cache(c); + } + return (ret); +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + char *value; + blkid_cache cache; + + blkid_debug_mask = DEBUG_ALL; + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage:\t%s tagname=value\n" + "\t%s tagname devname\n" + "Find which device holds a given token or\n" + "Find what the value of a tag is in a device\n", + argv[0], argv[0]); + exit(1); + } + if (blkid_get_cache(&cache, "/dev/null") < 0) { + fprintf(stderr, "Couldn't get blkid cache\n"); + exit(1); + } + + if (argv[2]) { + value = blkid_get_tag_value(cache, argv[1], argv[2]); + printf("%s has tag %s=%s\n", argv[2], argv[1], + value ? value : ""); + } else { + value = blkid_get_devname(cache, argv[1], NULL); + printf("%s has tag %s\n", value ? value : "", argv[1]); + } + blkid_put_cache(cache); + return value ? 0 : 1; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/resolve.o b/jni/e2fsprogs/lib/blkid/resolve.o new file mode 100755 index 0000000000000000000000000000000000000000..cac8a5d19a419e56652654f25b442614120b2f4d GIT binary patch literal 2464 zcmbuAKWGzC7{I^lRby>!tF8Y~8_|L;9#%x^ARM&SA|g@{#G%(~a!rD18k1|Se?TEi zUBrNECGC`mgM;EC>ex{iH{~i08Fdiuh7!N;-S_P4nM^*oeDD3f|KCe4567-tY|}K5 zOM|ztd6E=hDz>>d#nyxlv}}xMpEvHe*EV#mT+!qHN@>9V-UmTdxBPkxf`$%3z0VAm z0N!BS{tu0%hXVGxjIuQpdTZ*{>gMg%0nAcoplXd>+n}X1A(y z-2Hf0`#1fzlMS9Jw#+O1Xtp$0j74(GTrnmwva92ax6XB}hVvA2g+$iQrH(E*g<@td zcXVjj7&3;@u@@g&+Pw+T9t>!Qy5ca1=L3QQcqB)=uZ?#d>3!a|+}^g<6~8v#4d1>3 zoJ5sLdR#ZK0JNKucDku`#i!U%STz6mjkq0tHJWL4X!{2rq&!VHT_{D0t{%a0vXS)| z&wG?O9_vZUnJ^N9!ZhPOE%=2N{8J159y!(Hp`<0|iSisi&GO!C!Ed+VFI(`RE%+7W zv<_k8%Bu+SAr^cG?@25vyhGs?h3{1OJB4>D{H(aIfAdZ$e3xRMSGXE~N#Wg!{hGq* z?&SKRaCP2wg{$%D2ThCSvpd{|pZt}L@_vP@{T^oDZ5T)WwvR@*$7h(%-pVAcl;c`S zXMs;MnOxFx?UX=9!O7Z&>nyrpB<5ykotz6rw~$B|*cuPX`8*i8IoB~RUA=y)=-P=} ztjybmq9bCVStgfKGhjmNPR31>nmN@$i5KkbyaQosCvD9X>{*9R$P1s`CgI{0lAm|2 zgq=uBAF>F~GX=+if>WH!E;vR446Mqvr%~RWB{`Th&d|pY3@#d{<&6GA(u+uM;&1XR zWPtBonnaF(|Fz=(Jo?5l*iRo TF)S#Wn?m>uUva@Cn)&|$7{F(A literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/save.c b/jni/e2fsprogs/lib/blkid/save.c new file mode 100755 index 0000000..6f4499c --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/save.c @@ -0,0 +1,213 @@ +/* + * save.c - write the cache struct to disk + * + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#include "blkidP.h" + +#ifdef _WIN32 +#include "windows.h" +#endif + +static int save_dev(blkid_dev dev, FILE *file) +{ + struct list_head *p; + + if (!dev || dev->bid_name[0] != '/') + return 0; + + DBG(DEBUG_SAVE, + printf("device %s, type %s\n", dev->bid_name, dev->bid_type ? + dev->bid_type : "(null)")); + + fprintf(file, + "bid_devno, (long) dev->bid_time); + if (dev->bid_pri) + fprintf(file, " PRI=\"%d\"", dev->bid_pri); + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); + } + fprintf(file, ">%s\n", dev->bid_name); + + return 0; +} + +/* + * Write out the cache struct to the cache file on disk. + */ +int blkid_flush_cache(blkid_cache cache) +{ + struct list_head *p; + char *tmp = NULL; + const char *opened = NULL; + const char *filename; + FILE *file = NULL; + int fd, ret = 0; + struct stat st; + + if (!cache) + return -BLKID_ERR_PARAM; + + if (list_empty(&cache->bic_devs) || + !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { + DBG(DEBUG_SAVE, printf("skipping cache file write\n")); + return 0; + } + + filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; + + /* If we can't write to the cache file, then don't even try */ + if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || + (ret == 0 && access(filename, W_OK) < 0)) { + DBG(DEBUG_SAVE, + printf("can't write to cache file %s\n", filename)); + return 0; + } + + /* + * Try and create a temporary file in the same directory so + * that in case of error we don't overwrite the cache file. + * If the cache file doesn't yet exist, it isn't a regular + * file (e.g. /dev/null or a socket), or we couldn't create + * a temporary file then we open it directly. + */ + if (ret == 0 && S_ISREG(st.st_mode)) { + tmp = malloc(strlen(filename) + 8); + if (tmp) { + mode_t save_umask = umask(022); + sprintf(tmp, "%s-XXXXXX", filename); + fd = mkstemp(tmp); + umask(save_umask); + if (fd >= 0) { + file = fdopen(fd, "w"); + opened = tmp; + } +#ifndef _WIN32 + fchmod(fd, 0644); +#else + chmod(tmp, 0644); +#endif + } + } + + if (!file) { + file = fopen(filename, "w"); + opened = filename; + } + + DBG(DEBUG_SAVE, + printf("writing cache file %s (really %s)\n", + filename, opened)); + + if (!file) { + ret = errno; + goto errout; + } + + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (!dev->bid_type) + continue; + if ((ret = save_dev(dev, file)) < 0) + break; + } + + if (ret >= 0) { + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + ret = 1; + } + + fclose(file); + if (opened != filename) { + if (ret < 0) { + (void) unlink(opened); + DBG(DEBUG_SAVE, + printf("unlinked temp cache %s\n", opened)); + } else { + char *backup; + + backup = malloc(strlen(filename) + 5); + if (backup) { + sprintf(backup, "%s.old", filename); + unlink(backup); +#if defined(__GNUC__) && __GNUC__ >= 5 +/* explicit (void) cast is not enough with glibc and _FORTIFY_SOURCE */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" +#endif + (void) link(filename, backup); +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic pop +#endif + free(backup); + } + if (rename(opened, filename) < 0) + (void) unlink(opened); + DBG(DEBUG_SAVE, + printf("moved temp cache %s\n", opened)); + } + } + +errout: + free(tmp); + return ret; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_debug_mask = DEBUG_ALL; + if (argc > 2) { + fprintf(stderr, "Usage: %s [filename]\n" + "Test loading/saving a cache (filename)\n", argv[0]); + exit(1); + } + + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if ((ret = blkid_probe_all(cache)) < 0) { + fprintf(stderr, "error (%d) probing devices\n", ret); + exit(1); + } + cache->bic_filename = blkid_strdup(argv[1]); + + if ((ret = blkid_flush_cache(cache)) < 0) { + fprintf(stderr, "error (%d) saving cache\n", ret); + exit(1); + } + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/save.o b/jni/e2fsprogs/lib/blkid/save.o new file mode 100755 index 0000000000000000000000000000000000000000..c06080935b9c216ad597fce93cf57dd280b78953 GIT binary patch literal 4248 zcmbuCUu+ab7{I^11-U|Lk5c4sdq+c)^1#yaM5ct7A`hSE|k=XvKqGU zs;&0jQVagJVS8J(qQ>kBz#X*NTnQALD%0WW_t-8Y{{i6IJ%Ige4Ew<@ed-E?UZnnA zl>3Hsh_~qT_W^FZa@e0!VSXi!2LY}I6_}ttjnAq2d_`@s%j%##TY?F6^;#MIsDb?g zjZ;4e`c$wE&K*^t-?163b|{V?q<0jGr%A5Jb;y@bm@m=lm6eX%++MV?wz(;|T|YOw z!m&fTqz4f(Z>wEVhwS^Rll@Amh3qub_y_x(IjB#+N-1jhDNg*!zvcRau0F|PoLR0!oGKW*eztbZ zgMzUwwX(S?r6GHga--D!Sq|_xBAZ(S^K)zT`QT=Kewf>;L;V`En`r-aTodKv43F(| zuAf7${l|-o8!Ia1#924Z(}8;KZDGl8qWvWsPK8p zI8Jh5oX^cuvlI8)D)f03?kUB|Qw`hR+z=yu(w*gP!5lvZ?VC8pWIS`yxcsBsGoQ&n z+*?e4I#yk{cw!RI)5JYB_RC^7JP>|S+#lnd6zkf?8(VP9kx>;qd+OxEG_bQb+X%S# zDJRld*+6>w!Qi)Wt_V(^Xg}|#oHWu|iP?eePOY}@HJ-MhVEIzvpE3x}*dUPbIS@E;bZtfaj1>V87mP;q$P|_G5Nf?oy-ZxL2Jlxh< zXz$#YF0@7ZkG@zXNTlQ0wFu_!mcTaZ(fy3GsP1V9Mez=%c9io7E*iP+ng}ZOVO?0@LY@lGH>`kv7Co4CRR}D@3ydu1 zG<5*~*gCMye8jq*^GmcoEX+rz2`bL)Esq&k&L1(3H@v6(!TPH_6yOUaO_Kk@ubs$6 zE@Y*{K3wzR^g?)+o$q}3TRwc;hvRvCru|oa_}4zX*N1=T!(%=??!)i+@asPOJs(~~ zPGvoABzy#U3y$w#R%qUJlKoQ>Z<2Ua;_|#>oQruka~+FwF|XhS$HKQGCDDe;XGuS#6b*FA}g7?avV&P9B- za$7adMSKK*B-xSk@be zTR(Fy)+P9iWJj!(RBVqOx-Y2w>#-xaxUy+ovYq4n$`<~dbj-jh&V@gM_jB&GQ}Eas z;C3!~>jIeZaU+KBdC>AkI<8qp z!2&Ij%VdnK1*R3ZAf8AVrU{u*(?S)9#f*GDn}bwt%*aA2$tu&zr?GcF6E{cUd^SCj z9R)3$vkdK(6L0K7Gl@|!$MPdtD+MW0C(=37;PV>8u~a^uF(7YbsbXI=u~hoJIUGyG z6T=3i@&-Nw8Rp +#include +#include +#include + +#include "blkidP.h" + +static blkid_tag blkid_new_tag(void) +{ + blkid_tag tag; + + if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag)))) + return NULL; + + INIT_LIST_HEAD(&tag->bit_tags); + INIT_LIST_HEAD(&tag->bit_names); + + return tag; +} + +#ifdef CONFIG_BLKID_DEBUG +void blkid_debug_dump_tag(blkid_tag tag) +{ + if (!tag) { + printf(" tag: NULL\n"); + return; + } + + printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val); +} +#endif + +void blkid_free_tag(blkid_tag tag) +{ + if (!tag) + return; + + DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name, + tag->bit_val ? tag->bit_val : "(NULL)")); + DBG(DEBUG_TAG, blkid_debug_dump_tag(tag)); + + list_del(&tag->bit_tags); /* list of tags for this device */ + list_del(&tag->bit_names); /* list of tags with this type */ + + free(tag->bit_name); + free(tag->bit_val); + + free(tag); +} + +/* + * Find the desired tag on a device. If value is NULL, then the + * first such tag is returned, otherwise return only exact tag if found. + */ +blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) +{ + struct list_head *p; + + if (!dev || !type) + return NULL; + + list_for_each(p, &dev->bid_tags) { + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, + bit_tags); + + if (!strcmp(tmp->bit_name, type)) + return tmp; + } + return NULL; +} + +extern int blkid_dev_has_tag(blkid_dev dev, const char *type, + const char *value) +{ + blkid_tag tag; + + if (!dev || !type) + return -1; + + tag = blkid_find_tag_dev(dev, type); + if (!value) + return (tag != NULL); + if (!tag || strcmp(tag->bit_val, value)) + return 0; + return 1; +} + +/* + * Find the desired tag type in the cache. + * We return the head tag for this tag type. + */ +static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) +{ + blkid_tag head = NULL, tmp; + struct list_head *p; + + if (!cache || !type) + return NULL; + + list_for_each(p, &cache->bic_tags) { + tmp = list_entry(p, struct blkid_struct_tag, bit_tags); + if (!strcmp(tmp->bit_name, type)) { + DBG(DEBUG_TAG, + printf(" found cache tag head %s\n", type)); + head = tmp; + break; + } + } + return head; +} + +/* + * Set a tag on an existing device. + * + * If value is NULL, then delete the tagsfrom the device. + */ +int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength) +{ + blkid_tag t = 0, head = 0; + char *val = 0; + char **dev_var = 0; + + if (!dev || !name) + return -BLKID_ERR_PARAM; + + if (!(val = blkid_strndup(value, vlength)) && value) + return -BLKID_ERR_MEM; + + /* + * Certain common tags are linked directly to the device struct + * We need to know what they are before we do anything else because + * the function name parameter might get freed later on. + */ + if (!strcmp(name, "TYPE")) + dev_var = &dev->bid_type; + else if (!strcmp(name, "LABEL")) + dev_var = &dev->bid_label; + else if (!strcmp(name, "UUID")) + dev_var = &dev->bid_uuid; + + t = blkid_find_tag_dev(dev, name); + if (!value) { + if (t) + blkid_free_tag(t); + } else if (t) { + if (!strcmp(t->bit_val, val)) { + /* Same thing, exit */ + free(val); + return 0; + } + free(t->bit_val); + t->bit_val = val; + } else { + /* Existing tag not present, add to device */ + if (!(t = blkid_new_tag())) + goto errout; + t->bit_name = blkid_strdup(name); + t->bit_val = val; + t->bit_dev = dev; + + list_add_tail(&t->bit_tags, &dev->bid_tags); + + if (dev->bid_cache) { + head = blkid_find_head_cache(dev->bid_cache, + t->bit_name); + if (!head) { + head = blkid_new_tag(); + if (!head) + goto errout; + + DBG(DEBUG_TAG, + printf(" creating new cache tag head %s\n", name)); + head->bit_name = blkid_strdup(name); + if (!head->bit_name) + goto errout; + list_add_tail(&head->bit_tags, + &dev->bid_cache->bic_tags); + } + list_add_tail(&t->bit_names, &head->bit_names); + } + } + + /* Link common tags directly to the device struct */ + if (dev_var) + *dev_var = val; + + if (dev->bid_cache) + dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; + return 0; + +errout: + if (t) + blkid_free_tag(t); + else free(val); + if (head) + blkid_free_tag(head); + return -BLKID_ERR_MEM; +} + + +/* + * Parse a "NAME=value" string. This is slightly different than + * parse_token, because that will end an unquoted value at a space, while + * this will assume that an unquoted value is the rest of the token (e.g. + * if we are passed an already quoted string from the command-line we don't + * have to both quote and escape quote so that the quotes make it to + * us). + * + * Returns 0 on success, and -1 on failure. + */ +int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) +{ + char *name, *value, *cp; + + DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token)); + + if (!token || !(cp = strchr(token, '='))) + return -1; + + name = blkid_strdup(token); + if (!name) + return -1; + value = name + (cp - token); + *value++ = '\0'; + if (*value == '"' || *value == '\'') { + char c = *value++; + if (!(cp = strrchr(value, c))) + goto errout; /* missing closing quote */ + *cp = '\0'; + } + value = blkid_strdup(value); + if (!value) + goto errout; + + *ret_type = name; + *ret_val = value; + + return 0; + +errout: + free(name); + return -1; +} + +/* + * Tag iteration routines for the public libblkid interface. + * + * These routines do not expose the list.h implementation, which are a + * contamination of the namespace, and which force us to reveal far, far + * too much of our internal implementation. I'm not convinced I want + * to keep list.h in the long term, anyway. It's fine for kernel + * programming, but performance is not the #1 priority for this + * library, and I really don't like the tradeoff of type-safety for + * performance for this application. [tytso:20030125.2007EST] + */ + +/* + * This series of functions iterate over all tags in a device + */ +#define TAG_ITERATE_MAGIC 0x01a5284c + +struct blkid_struct_tag_iterate { + int magic; + blkid_dev dev; + struct list_head *p; +}; + +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev) +{ + blkid_tag_iterate iter; + + iter = malloc(sizeof(struct blkid_struct_tag_iterate)); + if (iter) { + iter->magic = TAG_ITERATE_MAGIC; + iter->dev = dev; + iter->p = dev->bid_tags.next; + } + return (iter); +} + +/* + * Return 0 on success, -1 on error + */ +extern int blkid_tag_next(blkid_tag_iterate iter, + const char **type, const char **value) +{ + blkid_tag tag; + + *type = 0; + *value = 0; + if (!iter || iter->magic != TAG_ITERATE_MAGIC || + iter->p == &iter->dev->bid_tags) + return -1; + tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags); + *type = tag->bit_name; + *value = tag->bit_val; + iter->p = iter->p->next; + return 0; +} + +extern void blkid_tag_iterate_end(blkid_tag_iterate iter) +{ + if (!iter || iter->magic != TAG_ITERATE_MAGIC) + return; + iter->magic = 0; + free(iter); +} + +/* + * This function returns a device which matches a particular + * type/value pair. If there is more than one device that matches the + * search specification, it returns the one with the highest priority + * value. This allows us to give preference to EVMS or LVM devices. + */ +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, + const char *type, + const char *value) +{ + blkid_tag head; + blkid_dev dev; + int pri; + struct list_head *p; + int probe_new = 0; + + if (!cache || !type || !value) + return NULL; + + blkid_read_cache(cache); + + DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); + +try_again: + pri = -1; + dev = 0; + head = blkid_find_head_cache(cache, type); + + if (head) { + list_for_each(p, &head->bit_names) { + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, + bit_names); + + if (!strcmp(tmp->bit_val, value) && + (tmp->bit_dev->bid_pri > pri) && + !access(tmp->bit_dev->bid_name, F_OK)) { + dev = tmp->bit_dev; + pri = dev->bid_pri; + } + } + } + if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { + dev = blkid_verify(cache, dev); + if (!dev || (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))) + goto try_again; + } + + if (!dev && !probe_new) { + if (blkid_probe_all_new(cache) < 0) + return NULL; + probe_new++; + goto try_again; + } + + if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { + if (blkid_probe_all(cache) < 0) + return NULL; + goto try_again; + } + return dev; +} + +#ifdef TEST_PROGRAM +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif + +void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device " + "[type value]\n", + prog); + fprintf(stderr, "\tList all tags for a device and exit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + blkid_tag_iterate iter; + blkid_cache cache = NULL; + blkid_dev dev; + int c, ret, found; + int flags = BLKID_DEV_FIND; + char *tmp; + char *file = NULL; + char *devname = NULL; + char *search_type = NULL; + char *search_value = NULL; + const char *type, *value; + + while ((c = getopt (argc, argv, "m:f:")) != EOF) + switch (c) { + case 'f': + file = optarg; + break; + case 'm': + blkid_debug_mask = strtoul (optarg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Invalid debug mask: %s\n", + optarg); + exit(1); + } + break; + case '?': + usage(argv[0]); + } + if (argc > optind) + devname = argv[optind++]; + if (argc > optind) + search_type = argv[optind++]; + if (argc > optind) + search_value = argv[optind++]; + if (!devname || (argc != optind)) + usage(argv[0]); + + if ((ret = blkid_get_cache(&cache, file)) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + + dev = blkid_get_dev(cache, devname, flags); + if (!dev) { + fprintf(stderr, "%s: Can not find device in blkid cache\n", + devname); + exit(1); + } + if (search_type) { + found = blkid_dev_has_tag(dev, search_type, search_value); + printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev), + search_type, search_value ? search_value : "NULL", + found ? "FOUND" : "NOT FOUND"); + return(!found); + } + printf("Device %s...\n", blkid_dev_devname(dev)); + + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) { + printf("\tTag %s has value %s\n", type, value); + } + blkid_tag_iterate_end(iter); + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/jni/e2fsprogs/lib/blkid/tag.o b/jni/e2fsprogs/lib/blkid/tag.o new file mode 100755 index 0000000000000000000000000000000000000000..3b6039f8e1f79491e23dcd392a9016ca2a78c607 GIT binary patch literal 7136 zcmbtYU2L0I89tw#G)|kQ|E#5Jot6r@{CG*}phbYb(zFCAKv%V*NZlOQcIwc?$r5kt zXeEp?q!hSlv`TQ%jbsDKM!hJgXte}dPyj^&q_wKpE(UU{UAQV2Oya_p7R>XU?>+YM zH-{o|rudxmoaelM=RNQF*6$u0JRWcyWtyYjP>q>El^WX77`uAtsxt)`XwHDqkvfWH#v8&t93b!Tm4f&U2Eb89oQ5stSqY8xnQ`myg^m-!B{1))Gf*`Z*Z$KV&j|B;mR&x zTn}|Z<~mi?oON!s0Bk>O4mq6<-GDk}@Ur-+;KMRx(dId&p498`ArF}$$Ta*AY^2wRsxgBTk=s3?$ z@2&=%<}W*HYeT#?-{aUr%>Kw?2bT%5K=z zvYv{)JWuACsbh0iJ!S1&W5r0iAFlYU)wer?$chYAoLY)~EYhJljK( z8~P4+buKy8RPo^84gV9dL~81p`IuX$f|TyQ`+b7@Ip%RHUw{Qk-O z!MRE3EAotW?zTfW#-UD`cS^p3-;}S5>P`vg#rKd7ujMCH(bNKR%^S~p^#FQxyl69O@B_qG&qXfudi5B7 z)F4Nn!4qz=hVPG7@uKh8uWOTzgU@c9>nY0Md2k)R7FYc?T4au|DXgI8gaWy{wAVPuv(IwhuPoVR^F0uDi!)-UiE&O zp7X6=##!CR9#i8Y?XuV03!Im}BgBE3`(eJ{PkrmeF*SJP%f|-Q>C<2BS1K_Y&z$dh zJ~cTtGM?$_I~47UqK4{*|5wn>`OZn@T;A>M>WZ&Q2Gtjkb*Jki&@>NcrQ0o!=ho$2?+Uw?ysQ5s@3!!If*AC74;gvEP_QdJ zE_p6>g*Pt@&mov!eS zhJ88V>G)WB11B1aw?Y^4Qnw{fZ*O3sTidfB_*oBcoKt^eKm98UuQz~6fA>V)p6!9I z@Pua%^=#xi+Nb!_-@P%}?d1aMzHS2^-V<=K@L$>+(ATEkueG8Cl?byIA8PwPjMLu$ z{?mDgvCcE}e-!-YItYl7X9{tEh5 zd=_T%2ef_^RN=1?`~$)Dy~5h1Rpew=!Ea)JE4|C$Q}1;=vTWvl#4v8fA6^B&3Y>EO zC80}W&Q@4OuZuPE&xXiSiuuGg13vM6_()^Z_XqvQ1!5J%+0yslVk9ktH^oFCr7Tay62N)@OM^`)5iA&jsDv4iCDN@ z2?s6Q_Uo*L+vhm33Vz+fw|OS$-ySJ3w8zHpS-5Ra$--^D6$`idy%Jc;$2U^FosxS? z-1ck9!nfDicyBD+wlgdDmU4Dj{GV93&A(^iw*4Ww&y<6IldHE;xwph^{yhs1*V#%9 zNV59<%2{}i#edJj_gMHLNhHeIYvGqI{9_jWxQyGum(oJ+I&;jU-IFmPT%n1rXK&^hnsr*4Z%f`>glBwrabTTy> zk7iRBv$D#C45!h=_}Ew~lU4CVA~iLorm~ZX^dvjod&)3NJ~ts-G0AX7=9mE~ZzP+V zjAv7^bE)$q8NX#}bYvmf z^o(TA3k?4V8dFkPYX(PS>G+g|=ok=wVI-Tj@yV2yEpbVuW5bj2v6M)iOvRJ2L_Co; zfEJT(pu^ZMT-)zdCTaYFpK1)}F`iHfuLCifP*FIOjh{pR;u!mV$>?YJbAUg6FlRg& z&&J8>!*t)pXs?%)|Htodk#|yho1{$OAGX>4DS7G56#mJ)xqTi}Vp9I{3Jb=4s~ zkTP5cpTvlmTSvS>?`E%mM~q`RW6DbztpESoyHHO32RwTHHz|7UH;jwMe$#(LFn=Vo zvfq9aTJ67M$>h3eKk)f&aHH4EPXZt&*V(}8s_b`t3&wv#{2Dg5ieE?!Pm4mvk57x) ZZ{DsyVBM!ei+)QU$svh9#SrrE{|^%7x2ymF literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/blkid/version.c b/jni/e2fsprogs/lib/blkid/version.c new file mode 100755 index 0000000..bf12d9c --- /dev/null +++ b/jni/e2fsprogs/lib/blkid/version.c @@ -0,0 +1,50 @@ +/* + * version.c --- Return the version of the blkid library + * + * Copyright (C) 2004 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include "config.h" +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include +#include "version.h" + +static const char *lib_version = E2FSPROGS_VERSION; +static const char *lib_date = E2FSPROGS_DATE; + +int blkid_parse_version_string(const char *ver_string) +{ + const char *cp; + int version = 0; + + for (cp = ver_string; *cp; cp++) { + if (*cp == '.') + continue; + if (!isdigit(*cp)) + break; + version = (version * 10) + (*cp - '0'); + } + return version; +} + +int blkid_get_library_version(const char **ver_string, + const char **date_string) +{ + if (ver_string) + *ver_string = lib_version; + if (date_string) + *date_string = lib_date; + + return blkid_parse_version_string(lib_version); +} diff --git a/jni/e2fsprogs/lib/blkid/version.o b/jni/e2fsprogs/lib/blkid/version.o new file mode 100755 index 0000000000000000000000000000000000000000..1162daef0cd4790cdf9f8d39e91403d9fd50d413 GIT binary patch literal 2240 zcmbtUO=uHQ5S~q1o6;DI|5!CS^w5G`np$fG537w@K|E9iK_%U$YZ{uQHCeQ^6$=4R z9$M(Zi`s)igBK5q#EXgtJqbndR;i$n;>nviggEm$ldhY1a$w)g`{tXOH?wc|?x}O9 zJ(>n08oYwdouB}38#ir3nFjcgS$PjDT<~{g8x)pv(ci@uC}EzR#TKLF z(~M(dUg&l1eFeB-0$e1lm3e@?T>y*207nQ95WdYQoYm%re0Q4L)-hKnays9^4WHKB zQp8%-oQ<$RHNRIXd)6?fJaaOSXIpsdjee;Nz{(nO*Ae%@+z`bhxA2qeQw`q_#6CRU zM>yv!V0+s!b|XiQ`qc7e+^;o3>6;fy#U`Uv1b9JwAHY2JSz1S|L*w4Pb^M5lpJK4* z5{`4RJaZyn!5Pwd)p%V?SnuuA`$AVHQ+8L@Htj_08icz}TO(aP-93i^Vo5U{58bpf z*~COT6z0Sy(%%8biyWcmkG2mlA;}KZ&MJP!54v!?gMaa54u@QP!H>K68_@uU zi!XSD@ix?31$1coRI)c;PBiX;9pb`1bw=eHmaGB3l7hmQCdd5ncx@}F_pvNXs zDJyM5B0HLhCu|r=jweQ=am$V-6C)WjGacm*321WPgq7N`O&QX(QCTj^N znzb{DbX7gZzc_zq5 zQDNM+PwCy<=zpqtjQ7^bQRFNC+2!NcT1Dxm6Xw401~cdf?-Wj3g~&~qQAIY4k9??Q z##>O+`tM!ouzd{7xP)h9^erT!bls8kO=PFd#q zK_`ed!&U8POzH^z0~2=(z}g)@!0|2`tP0WPaKp14@BFqXWQ~b)v~h^^FVHPC>dkM7 g=Qqeinjd}d5-;<6fS9{Bg$y$|#^)eK{}FfmABtuCBLDyZ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/crypto_mode.c b/jni/e2fsprogs/lib/e2p/crypto_mode.c new file mode 100755 index 0000000..4933016 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/crypto_mode.c @@ -0,0 +1,74 @@ +/* + * crypto_mode.c --- convert between encryption modes and strings + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "e2p.h" + +struct mode { + int num; + const char *string; +}; + +static struct mode mode_list[] = { + { EXT4_ENCRYPTION_MODE_INVALID, "Invalid"}, + { EXT4_ENCRYPTION_MODE_AES_256_XTS, "AES-256-XTS"}, + { EXT4_ENCRYPTION_MODE_AES_256_GCM, "AES-256-GCM"}, + { EXT4_ENCRYPTION_MODE_AES_256_CBC, "AES-256-CBC"}, + { 0, 0 }, +}; + +const char *e2p_encmode2string(int num) +{ + struct mode *p; + static char buf[20]; + + for (p = mode_list; p->string; p++) { + if (num == p->num) + return p->string; + } + sprintf(buf, "ENC_MODE_%d", num); + return buf; +} + +/* + * Returns the hash algorithm, or -1 on error + */ +int e2p_string2encmode(char *string) +{ + struct mode *p; + char *eptr; + int num; + + for (p = mode_list; p->string; p++) { + if (!strcasecmp(string, p->string)) { + return p->num; + } + } + if (strncasecmp(string, "ENC_MODE_", 9)) + return -1; + + if (string[9] == 0) + return -1; + num = strtol(string+9, &eptr, 10); + if (num > 255 || num < 0) + return -1; + if (*eptr) + return -1; + return num; +} + diff --git a/jni/e2fsprogs/lib/e2p/crypto_mode.o b/jni/e2fsprogs/lib/e2p/crypto_mode.o new file mode 100755 index 0000000000000000000000000000000000000000..f5e97898ace3e106ad15b75d08a62ab6cd5fba0b GIT binary patch literal 2848 zcmbtVO>7%g5T5lW#L$q0G(e?79UzfPMV7=gQ4p7HoX{fC617F*wsq`H8`Xc@LdEfhH z-n`j)yB{pQ`Fg~%K*WNtVSgqlKz(4}c9rSE$aZTJ%9TW{76sUfT2O8b zz#hgKYYe!1(SCRDWCZTfyqfT8e_S1LK z7q{NRr(CyH{H^EE#`z}=+ub8y@~dom&DQ$DHs)5oZ+pMAZ3}a>w_7-`*s*4q<1ptq z+?`{^_L>dEEXzI z-xtuXA}>1WzFOtjvi1zG!6cM_Pe6IW+PFwD8aAB5J$5j!ooLH`_e-f8&a2Rz)8ik( z7>y$;SBl@YcOR{h59UEWm0hpaT2E|aja030uP#AOmqfZ|0JbqVr%M+S-ubr{m%Pa| zgf_g9yOGSSrQyudrK$Mr+|)alFNOBm#QD%pEF=I@nPl$j_zk~UTFd9gXXc$5XCAOe zlvwXy1nc$*>-b;{CJ;Hs_~)b-ho;XBK0ESRfO`x1c`^v&@#SaC}=VV`8ATac5Kh zP{2W)U|WkXeh-zgzpvn=ZO|?|FZ`_k`GOeB_<# zP9HO0cH|n0eL}3P5q5V4DOYcWj7vU(k26kjMmtnB zrZxPihD#0UmqO=yir3^`3Vwodx{D-&pXy9up0(g}Jjd^&l75V@-=;+amwo}K=x35n z;NJ`&n@{^*W~~%}lgekaeh!V5QVB{yF_kR&sceDFoMs343^=)b;5%n8yggM4lBw(9 z#|xgHOHr^m(${iVdqB?0d#g|?;A*hSDfrjC)nYR1D|W{*&T$}Byj2MD9>sK0;NWVI zTtR&+tF$^oIvFHkBJIr5aGHi!Xo%A=gL~wOK&~@5ow(^tb4C82qQ2|(jjwZ)|7(Qj zwg^$85vJb>T6AeZ`N44L>%iei%Y?Zh!Uli3mf4^BmHI*YPx>v!n0bZ~ZXUVk9988i zHtFy1p)C&cUnY_!vcEvzqR}h=WiH4SCQ|-%B=ML08;H^VaeQ>S!uc=gAlh7xP}BV* z%@W9I!kGRPUohd2uCc$4k!^B6WXzHi;=zd3CH literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/encoding.c b/jni/e2fsprogs/lib/e2p/encoding.c new file mode 100755 index 0000000..24266fc --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/encoding.c @@ -0,0 +1,118 @@ +/* + * encoding.c --- convert between encoding magic numbers and strings + * + * Copyright (C) 2018 Collabora Ltd. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "e2p.h" + +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof(array[0])) + +static const struct { + const char *name; + __u16 encoding_magic; + __u16 default_flags; + +} ext4_encoding_map[] = { + { + .encoding_magic = EXT4_ENC_UTF8_12_1, + .name = "utf8-12.1", + .default_flags = 0, + }, + { + .encoding_magic = EXT4_ENC_UTF8_12_1, + .name = "utf8", + .default_flags = 0, + }, +}; + +static const struct enc_flags { + __u16 flag; + const char *param; +} encoding_flags[] = { + { EXT4_ENC_STRICT_MODE_FL, "strict" }, +}; + +/* Return a positive number < 0xff indicating the encoding magic number + * or a negative value indicating error. */ +int e2p_str2encoding(const char *string) +{ + unsigned int i; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (!strcmp(string, ext4_encoding_map[i].name)) + return ext4_encoding_map[i].encoding_magic; + + return -EINVAL; +} + +/* Return the name of an encoding or NULL */ +const char *e2p_encoding2str(int encoding) +{ + unsigned int i; + static char buf[32]; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (ext4_encoding_map[i].encoding_magic == encoding) + return ext4_encoding_map[i].name; + sprintf(buf, "UNKNOWN_ENCODING_%d", encoding); + return buf; +} + +int e2p_get_encoding_flags(int encoding) +{ + unsigned int i; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (ext4_encoding_map[i].encoding_magic == encoding) + return ext4_encoding_map[i].default_flags; + + return 0; +} + +int e2p_str2encoding_flags(int encoding, char *param, __u16 *flags) +{ + char *f = strtok(param, "-"); + const struct enc_flags *fl; + unsigned int i, neg = 0; + + if (encoding != EXT4_ENC_UTF8_12_1) + return -EINVAL; + while (f) { + neg = 0; + if (!strncmp("no", f, 2)) { + neg = 1; + f += 2; + } + + for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) { + fl = &encoding_flags[i]; + if (!strcmp(fl->param, f)) { + if (neg) + *flags &= ~fl->flag; + else + *flags |= fl->flag; + + goto next_flag; + } + } + return -EINVAL; + next_flag: + f = strtok(NULL, "-"); + } + return 0; +} diff --git a/jni/e2fsprogs/lib/e2p/encoding.o b/jni/e2fsprogs/lib/e2p/encoding.o new file mode 100755 index 0000000000000000000000000000000000000000..99d5f5263eb4d1b3d5e045ad09706ea37d6bcd16 GIT binary patch literal 3776 zcmbVOO=w(I6h3cWVqSil|7f-9q&7kb%`+2Ih`VPeH4#e+CB+EBbTXNwLz0;|nM%_J zI*={|T_o5=7gb_)F>&Q0;AEphHVQ5pg)RhT6wwLdA}Bb6gz=pF&PndP%xpX`@80{J z@BG|z&%1AKU%2>+&oDs5fY0G*B`83;@o4U-sRJjFS=xc!gIm7MgH>41HA1n}0^4Zc znQw8nt$Nt^nJ_`?T%%JYtp3lH?=65e%Ybzw7Av5uyN&_p#AeU5`b2NF)xT@CIm?+H zf3_Zd2*;|0wmio9y;OQ4<4d=bo^%^Kq3pq}^P8B{`d4P?k)GQ|(4Q@JaBdytx#e+P zDeh)4l(mfdxzmQb2jc1ZTbO@l)n90p+{iEGhH)sj2WXG`Tf^Uat`3Tr8d|#aeEc>NwvzH{a*DmS|fs-@QiUVZJX*zLj`g&N9^wYwXsOd{fRC z>o?3<&M${&RSI$)O#{!^+&sX#ZmjyVADRBbFD+2qFhi98;hxm_o3Nc(#k$qPTN~ik zP0nakVq!0hS+GTWFCqVDTuYtKL;5?a54M)-iC#!w&Lby}9PFp{JocEf(`!=;`wwdP zj4JFI_g18OL#aa}_n>B#P| zH?>;+p!Fu{bEf}OxR*1N&Yl4+>k#TqCyV9*Yz87!reu}BIaG9Ql5cE24>F2xe@?!d4eu!qSP_OcS= z=4CKeo;6N2`Jo4qlZ@Y|ain=*tm&E74}Blh`0h0M2gaJ=ryoJ_9OhBum+>}^c%7)a z#yomCkk{&arx|*2nx-{MiZ(dX>_{B*O{2;0a3IB~{Kz3(1N)^)S`&Q7;4`X_$8pNf zKu;pwJlVq0fX4&|!Cz8%&EZ<=NJLZfLu-;275B)$i@Hx!^DlUV;vdBooJJGs^rf2D zD*kaClSjdh_Q=0#-QYn1K1QTntD8E1#NNQ4zDF?}W4`cIA0YNk75-DqpHO+ZmnA|F zVEk9cRX-s19{wuDy;=nyLY$-n{pi(D&5n4N2X}~!atd)h&V&me^E1h~*Uz_A_z$b_ z|E|I>RN;4XU1(o;zZ^;rD)5)=G_!Xsn>A1x><=Lg>ImWp7d7O0@J$?kA(EJESCigTyw6AUgQSNJg zbbL$mqxa8Q)3uX)WM2b}d-pZOxOZQ!7rcYG4o@;5u>?QEINhlvg3J187Y4c~IAw*5 zcyM`-=RLT*uXjASysuyi4kIc+k7Z9?pMj;tWGtSVVYkt1p_ycOAqv8?BVd#N@Dz^A3pDmj+vn&p zM2{EgF-VU9x=5(BkRQNh&kcKktM~thKhTt0rOe4BU*-58rA$0a^`#-q`(<(1YSQD} z`^6$#!i3LekYk4rxw)E9K~wqioMhr{9La|#4BTVDTOqM$bGV6 +#include +#include + +#include "e2p.h" + +static const char *err_string[] = { + "", + "UNKNOWN", /* 1 */ + "EIO", /* 2 */ + "ENOMEM", /* 3 */ + "EFSBADCRC", /* 4 */ + "EFSCORRUPTED", /* 5 */ + "ENOSPC", /* 6 */ + "ENOKEY", /* 7 */ + "EROFS", /* 8 */ + "EFBIG", /* 9 */ + "EEXIST", /* 10 */ + "ERANGE", /* 11 */ + "EOVERFLOW", /* 12 */ + "EBUSY", /* 13 */ + "ENOTDIR", /* 14 */ + "ENOTEMPTY", /* 15 */ + "ESHUTDOWN", /* 16 */ + "EFAULT", /* 17 */ +}; + +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof(array[0])) + +/* Return the name of an encoding or NULL */ +const char *e2p_errcode2str(unsigned int err) +{ + static char buf[32]; + + if (err < ARRAY_SIZE(err_string)) + return err_string[err]; + + sprintf(buf, "UNKNOWN_ERRCODE_%u", err); + return buf; +} + + diff --git a/jni/e2fsprogs/lib/e2p/errcode.o b/jni/e2fsprogs/lib/e2p/errcode.o new file mode 100755 index 0000000000000000000000000000000000000000..c2171b38774b7615b3e16dfc263861ae43f34093 GIT binary patch literal 2608 zcmd6p&uddz6vxj?)CQ;4;xA+zZ4^ZjeKgg9GK(Q?a@z#kyz-Ka3c@o@U$u-)O7fJd zgUWOxZfr#t3jRP`v>S0D*o`oZe}Nl!%FJ%u>B_n&dd}@R=JqurxS9j+o^w9;d+xpO zzI#J1tAW0VWr3Il&!CYB1$ein5hrz+gmtL=^a5TkUX08wPQlEBRLA^m%A1d6;r%WP z3OLRt%HKv~`(pspF$-p5=f@Uir#cpXz`lprheJ){GxJXid_?{9PK+_X`Cm)&Bk5?2 z2UFg{;>F%MoNMNw>P-*JT4G z+gdwdAF{2?1M=y%&P?m}_Ir`Lt0E^_J32FM@a8oOzTzg3uY&iVnsrAZvI0NXWF`Lv zxdp4g=;@G%|BDJ1Aj6AyIdU~_bV6-*X!VSO?ZB-R<4ftUG<;_cBLBl zc7LvTupX4kzXSGp$j2(D!cu$q>?qVHuqzmarSbjK-e|2f?o$z7MuH?YXmanDGWsoDZd6Mwxg5hhFKU)~D|-5VG0wNL-^?uh4o|s1&R$%2{nxRB zSh#+k3#O%zz05E88V1eQf0AGH2~SAtr(a>Im-RnJMv^XkOv`ZHZ4+Y5_=~4;iG|O@ zzbxGHjr#q@n5OiDOk~0)TDspPrEg;z{m~&y>bB9y`wJ;y&}{$O`9R4&(R + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include "e2p.h" +#include +#include + +struct feature { + int compat; + unsigned int mask; + const char *string; +}; + +static struct feature feature_list[] = { + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC, + "dir_prealloc" }, + { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL, + "has_journal" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES, + "imagic_inodes" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR, + "ext_attr" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, + "dir_index" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE, + "resize_inode" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG, + "lazy_bg" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP, + "snapshot_bitmap" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_SPARSE_SUPER2, + "sparse_super2" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_FAST_COMMIT, + "fast_commit" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_STABLE_INODES, + "stable_inodes" }, + + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, + "sparse_super" }, + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, + "large_file" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE, + "huge_file" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, + "uninit_bg" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, + "uninit_groups" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK, + "dir_nlink" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE, + "extra_isize" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_QUOTA, + "quota" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_BIGALLOC, + "bigalloc"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM, + "metadata_csum"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_REPLICA, + "replica" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_READONLY, + "read-only" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_PROJECT, + "project"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS, + "shared_blocks"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_VERITY, + "verity"}, + + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, + "compression" }, + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, + "filetype" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, + "needs_recovery" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, + "journal_dev" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, + "extent" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, + "extents" }, + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, + "meta_bg" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT, + "64bit" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP, + "mmp" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG, + "flex_bg"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE, + "ea_inode"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA, + "dirdata"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CSUM_SEED, + "metadata_csum_seed"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR, + "large_dir"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA, + "inline_data"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT, + "encrypt"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD, + "casefold"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD, + "fname_encoding"}, + { 0, 0, 0 }, +}; + +static struct feature jrnl_feature_list[] = { + { E2P_FEATURE_COMPAT, JBD2_FEATURE_COMPAT_CHECKSUM, + "journal_checksum" }, + + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_REVOKE, + "journal_incompat_revoke" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_64BIT, + "journal_64bit" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT, + "journal_async_commit" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V2, + "journal_checksum_v2" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V3, + "journal_checksum_v3" }, + { 0, 0, 0 }, +}; + +void e2p_feature_to_string(int compat, unsigned int mask, char *buf, + size_t buf_len) +{ + struct feature *f; + char fchar; + int fnum; + + for (f = feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) { + strncpy(buf, f->string, buf_len); + buf[buf_len - 1] = 0; + return; + } + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); +} + +const char *e2p_feature2string(int compat, unsigned int mask) +{ + static char buf[20]; + + e2p_feature_to_string(compat, mask, buf, sizeof(buf) / sizeof(buf[0])); + return buf; +} + +int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} + +const char *e2p_jrnl_feature2string(int compat, unsigned int mask) +{ + struct feature *f; + static char buf[20]; + char fchar; + int fnum; + + for (f = jrnl_feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) + return f->string; + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); + return buf; +} + +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = jrnl_feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + while (*cp && !isspace(*cp) && *cp != ',') + cp++; + return cp; +} + +/* + * Edit a feature set array as requested by the user. The ok_array, + * if set, allows the application to limit what features the user is + * allowed to set or clear using this function. If clear_ok_array is set, + * then use it tell whether or not it is OK to clear a filesystem feature. + */ +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err) +{ + char *cp, *buf, *next; + int neg; + unsigned int mask; + int compat_type; + int rc = 0; + + if (!clear_ok_array) + clear_ok_array = ok_array; + + if (type_err) + *type_err = 0; + if (mask_err) + *mask_err = 0; + + buf = malloc(strlen(str)+1); + if (!buf) + return 1; + strcpy(buf, str); + for (cp = buf; cp && *cp; cp = next ? next+1 : 0) { + neg = 0; + cp = skip_over_blanks(cp); + next = skip_over_word(cp); + + if (*next == 0) + next = 0; + else + *next = 0; + + if ((strcasecmp(cp, "none") == 0) || + (strcasecmp(cp, "clear") == 0)) { + compat_array[0] = 0; + compat_array[1] = 0; + compat_array[2] = 0; + continue; + } + + switch (*cp) { + case '-': + case '^': + neg++; + /* fallthrough */ + case '+': + cp++; + break; + } + if (e2p_string2feature(cp, &compat_type, &mask)) { + rc = 1; + break; + } + if (neg) { + if (clear_ok_array && + !(clear_ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = (compat_type | + E2P_FEATURE_NEGATE_FLAG); + if (mask_err) + *mask_err = mask; + break; + } + compat_array[compat_type] &= ~mask; + } else { + if (ok_array && !(ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = compat_type; + if (mask_err) + *mask_err = mask; + break; + } + compat_array[compat_type] |= mask; + } + } + free(buf); + return rc; +} + +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) +{ + return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + int compat, compat2, i; + unsigned int mask, mask2; + const char *str; + struct feature *f; + + for (i = 0; i < 2; i++) { + if (i == 0) { + f = feature_list; + printf("Feature list:\n"); + } else { + printf("\nJournal feature list:\n"); + f = jrnl_feature_list; + } + for (; f->string; f++) { + if (i == 0) { + e2p_string2feature((char *)f->string, &compat, + &mask); + str = e2p_feature2string(compat, mask); + } else { + e2p_jrnl_string2feature((char *)f->string, + &compat, &mask); + str = e2p_jrnl_feature2string(compat, mask); + } + + printf("\tCompat = %d, Mask = %u, %s\n", + compat, mask, f->string); + if (strcmp(f->string, str)) { + if (e2p_string2feature((char *) str, &compat2, + &mask2) || + (compat2 != compat) || + (mask2 != mask)) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + } + } + exit(0); +} +#endif diff --git a/jni/e2fsprogs/lib/e2p/feature.o b/jni/e2fsprogs/lib/e2p/feature.o new file mode 100755 index 0000000000000000000000000000000000000000..496fbd79a1fdfebbef61ae2b451704b460f96551 GIT binary patch literal 9624 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 + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#endif + +#include "e2p.h" + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOFOLLOW) + +int fgetflags (const char * name, unsigned long * flags) +{ +#if HAVE_STAT_FLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS) + struct stat buf; + + if (stat (name, &buf) == -1) + return -1; + + *flags = 0; +#ifdef UF_IMMUTABLE + if (buf.st_flags & UF_IMMUTABLE) + *flags |= EXT2_IMMUTABLE_FL; +#endif +#ifdef UF_APPEND + if (buf.st_flags & UF_APPEND) + *flags |= EXT2_APPEND_FL; +#endif +#ifdef UF_NODUMP + if (buf.st_flags & UF_NODUMP) + *flags |= EXT2_NODUMP_FL; +#endif + + return 0; +#elif APPLE_DARWIN && HAVE_EXT2_IOCTLS + int f, save_errno = 0; + + f = -1; + save_errno = syscall(SYS_fsctl, name, EXT2_IOC_GETFLAGS, &f, 0); + *flags = f; + return (save_errno); +#elif HAVE_EXT2_IOCTLS + struct stat buf; + int fd, r, f, save_errno = 0; + + if (!stat(name, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + errno = EOPNOTSUPP; + return -1; + } + fd = open(name, OPEN_FLAGS); + if (fd == -1) { + if (errno == ELOOP || errno == ENXIO) + errno = EOPNOTSUPP; + return -1; + } + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + close(fd); + errno = EOPNOTSUPP; + return -1; + } + r = ioctl(fd, EXT2_IOC_GETFLAGS, &f); + if (r == -1) { + if (errno == ENOTTY) + errno = EOPNOTSUPP; + save_errno = errno; + } + *flags = f; + close(fd); + if (save_errno) + errno = save_errno; + return r; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} diff --git a/jni/e2fsprogs/lib/e2p/fgetflags.o b/jni/e2fsprogs/lib/e2p/fgetflags.o new file mode 100755 index 0000000000000000000000000000000000000000..7d0f2ccd9e81c3f3b00306cca3ebdb1c0bcc09a6 GIT binary patch literal 2040 zcmbW1O=uHA6oB7mTbr6#Yg=ul+N4mSB3+vLLyjx>Q&4({6{Mgc#_bO#S+iLrwM7HH zc<^Arqe==M?5zjEU$t(Bkv)$W$8Gf{_L)I3ntZ~JSZt^M6VxuQlIn;T<|gAmjzYO=AHhBB(Y(F1T9 zeGWMn^jh%P&_Hlp&sP+fZ(}F)Ji23yY@ARj5d^3Op)~MuH&R_dd-AD3IdKU|T7 zq2>&u&u)mN0xjDhAlrm|9bD`*YyhMLR?J*97T020 z90T`br=~nhfU-WOjD{mHiR%$Y0kB2@*ZOvp+3?x^_knj^>Q^Nk!DS!(`pI>?ruzuH z;Lm~Ao(h2uyunB(f6jPUhyE%fM>_Z@k^#v-%OBY(?BcAl(K#PJ<-BJaEEen( zj!TBUm`N=aAel5QD`$fF#K^&lnYJ^aDuFEI;8Z1h`C>q&NamQ z;Y)ne?Tu`S>FpS{c~Z+fAl(VoU)+uOztA^AD(*@|`DM|&l^b`*Y>3CP3nuGbX}j#! zj$8K*w|A?@InZ0COcMDEJcokU`A2yD#W~52YAoyp&m(ikMg&C;<2+%SyzKu05I5Jo literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/fgetproject.c b/jni/e2fsprogs/lib/e2p/fgetproject.c new file mode 100755 index 0000000..12320b5 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/fgetproject.c @@ -0,0 +1,63 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fgetproject(const char *name, unsigned long *project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == 0) + *project = fsx.fsx_projid; + save_errno = errno; + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/jni/e2fsprogs/lib/e2p/fgetproject.o b/jni/e2fsprogs/lib/e2p/fgetproject.o new file mode 100755 index 0000000000000000000000000000000000000000..67ae6441530c96863ba89943f6d39b949f8580c3 GIT binary patch literal 1480 zcmbW1O=uHQ5P)a1iKY_TP*jB4Y=t28;9{ggk1J`lh$sXFJ(z7wU(;%`8#aqZThI^? zK`#NX$`(8%H*aoE3b}aHi#G*5*Xmu&tn4(!gn@6F76Z{F-aTfcrKAW0xZ zf{!p52@3F19@v^^YA}PIhgIoYcQ4fFCZ(DqE1iRCtn;b0=sL3Ak)V>g4335FZ=7Vz zttZoNI0T6UfLpl6@i07}ueTIeLEFK(U-GL|MgCy@PD0I#kugS2yI%kw!+09kTld_s1S>R8c6$z*#M^UPGYru5IOe2v$#z=0+ud7l;5lla zW&Jy3^BE(z^oUudUDH@ftf~oh6%$19A(5V@K-!N<3lRmDaeT_70AES3&2DZ)7NhS1 zZ-W6hqHJ!=!p|SvVT!toJP3adCr!%`7{e8hjPreu2gm#$d*sL%KY?W4m*3kzvUB)| zv-*S7Dg4Y7zBYx&dC~pku zr&=tZQEgVXLCuCWtdgI*%Gqik&Uj6 P2zL1T_)qhM)TH=-&AOMu literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/fgetversion.c b/jni/e2fsprogs/lib/e2p/fgetversion.c new file mode 100755 index 0000000..f3a5b4c --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/fgetversion.c @@ -0,0 +1,74 @@ +/* + * fgetversion.c - Get a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_SYS_IOCTL_H +#include +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fgetversion(const char *name, unsigned long *version) +{ + unsigned int ver = -1; + int rc = -1; +#if HAVE_EXT2_IOCTLS +# if !APPLE_DARWIN + int fd, save_errno = 0; + + fd = open(name, OPEN_FLAGS); + if (fd == -1) + return -1; + + rc = ioctl(fd, EXT2_IOC_GETVERSION, &ver); + if (rc == -1) + save_errno = errno; + close(fd); + if (rc == -1) + errno = save_errno; +# else /* APPLE_DARWIN */ + rc = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0); +# endif /* !APPLE_DARWIN */ +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; +#endif /* ! HAVE_EXT2_IOCTLS */ + if (rc == 0) + *version = ver; + + return rc; +} diff --git a/jni/e2fsprogs/lib/e2p/fgetversion.o b/jni/e2fsprogs/lib/e2p/fgetversion.o new file mode 100755 index 0000000000000000000000000000000000000000..fffba91a2f1ba2b28ffd0695bb1ca617d7106882 GIT binary patch literal 1520 zcmb7^KWGzi6vyA?Qj^-ygjTIkYbsQTgFlQ^=y+n)QbZ-{;B>_F*H}#Mj) za~GlRp!C&l633E;7axM`JAm6b-x1QhZ=|ZEG;PcIbqi{N25b4_q2`m& z5RZf5`8WsFARRH8huaEj`y-eWgK#W{H6YBVyw3m^Nb64+-tVN*%xKUIo^g!ULvg)f zZnsu1ZQ@>QJG%K53Z=YNoPNZe%8G4GXXjX!&EdpksnCJ;GzZ$+No_Kbh77Xfg8wBy zKWZ!_rc!SsZ=#WJiL|jW3O~M!gaPg@@+kb-?>DSNqzA7Dq?fM+Jld20I3S05_!N>c zrGBt}WM}Xv_o|B60Dg1;pC7=_iK3Hu0WlGiTT(dQW81=g0Z{&Mn*wZznD}9Ze^9uZ ze?ssf%D6eu` zpAqmyn}h)#Lx)j^5bN#~LuASR5Rcfiokm(>Mkj{X;;^fN)7=u1cP!tZ1Tw18eHOD~ zp~rAcHG$jTv{@XKOwC*D2m9pS5Uis&klhq|17p?X`XyV$px^#e;{4@4Nk?Za^^)7j Ry5~j&8)E*r@Z|dG{{iJ4oVfr1 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/fsetflags.c b/jni/e2fsprogs/lib/e2p/fsetflags.c new file mode 100755 index 0000000..d865d24 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/fsetflags.c @@ -0,0 +1,118 @@ +/* + * fsetflags.c - Set a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#endif + +#include "e2p.h" + +/* + * Deal with lame glibc's that define this function without actually + * implementing it. Can you say "attractive nuisance", boys and girls? + * I knew you could! + */ +#ifdef __linux__ +#undef HAVE_CHFLAGS +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOFOLLOW) + +int fsetflags (const char * name, unsigned long flags) +{ +#if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS) + unsigned long bsd_flags = 0; + +#ifdef UF_IMMUTABLE + if (flags & EXT2_IMMUTABLE_FL) + bsd_flags |= UF_IMMUTABLE; +#endif +#ifdef UF_APPEND + if (flags & EXT2_APPEND_FL) + bsd_flags |= UF_APPEND; +#endif +#ifdef UF_NODUMP + if (flags & EXT2_NODUMP_FL) + bsd_flags |= UF_NODUMP; +#endif + + return chflags (name, bsd_flags); +#elif APPLE_DARWIN && HAVE_EXT2_IOCTLS + int f = (int) flags; + return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0); +#elif HAVE_EXT2_IOCTLS + struct stat buf; + int fd, r, f, save_errno = 0; + + if (!stat(name, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + errno = EOPNOTSUPP; + return -1; + } + fd = open(name, OPEN_FLAGS); + if (fd == -1) { + if (errno == ELOOP || errno == ENXIO) + errno = EOPNOTSUPP; + return -1; + } + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + close(fd); + errno = EOPNOTSUPP; + return -1; + } + f = (int) flags; + r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); + if (r == -1) { + if (errno == ENOTTY) + errno = EOPNOTSUPP; + save_errno = errno; + } + close(fd); + if (save_errno) + errno = save_errno; + return r; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} diff --git a/jni/e2fsprogs/lib/e2p/fsetflags.o b/jni/e2fsprogs/lib/e2p/fsetflags.o new file mode 100755 index 0000000000000000000000000000000000000000..93502b1c29c5b164ea3d83f67092109d011c2fe0 GIT binary patch literal 2040 zcmbW1%}*0S6u{qhL5i)2fPw*OO)xPrY$$5dn@i#ciH1YPg9oi^T|Q#lwcCv;Vw40A z9z58@gBMLnJiv{c?G1zffEQ0_il@DL>xJNZ(-}J5?p~Z^XWstieb3ImzH#SfNKrrx z1-?S-O;CVpcT3ips6#Jm9;)h(gVo5^!EUHrQDcpb_3_4G1ZovE-Pq4S8C5^%A-IY@ zhulkgEqr2VAbeggR1}zRW2f{2x?_xN+{jug3{VTh+Q8;+ta=~q$)^J4)C^Q?(y0$a z%^gOc-Hga1niP zu0L%2xeR6ZB-BWEX6Ic>Q8t_P3}QWl&3g8wUa)%1;M^$|>A2W;szv1BM$nf6S6H7> zc6)&3=Jp`R-ZGBysJ|pvcGJ~^)!SQmrsW+q{Sz`-Bfl7bZra6VD<4lJwS<<$U^M!h z3n(vApu8McMx!yn`e20fJ#+}y`*xJs=(+ySp-)}vcO@Fb*FO0Di|hC;4-j_2-$TDW z6+#_&osmxdit(-v{S`)zb?{Ln1CoE1Ke99Uh+1W%3jusGfS(TFvjKcMfX9*37{&hf zG(|SgbD21v?a?Sny!VI#yqCDF|0RG|1NffAk8_!pAv%8?lux87vUx<}a@<*oMSH>^|MPD>d%R6Ylx`3)?@iLVhPXfc74LNWAX{R3 zJBDqZ)DjO!XF~lKXCwYE^o@{;w-aOhu;|{(gS%rk#FO|4ChJYN9d>KSt9zH*d)1R1 p=q*zwiTnkgL&2~95#E1MC)rVtg}vYfWZu|_pu}O4Crpc<{XZ7V)<*yU literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/fsetproject.c b/jni/e2fsprogs/lib/e2p/fsetproject.c new file mode 100755 index 0000000..5df7090 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/fsetproject.c @@ -0,0 +1,69 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#include +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fsetproject(const char *name, unsigned long project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == -1) { + save_errno = errno; + goto errout; + } + fsx.fsx_projid = project; + r = ioctl (fd, FS_IOC_FSSETXATTR, &fsx); + if (r == -1) + save_errno = errno; +errout: + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/jni/e2fsprogs/lib/e2p/fsetproject.o b/jni/e2fsprogs/lib/e2p/fsetproject.o new file mode 100755 index 0000000000000000000000000000000000000000..291bc7e8d7e16573fec4afd84d51a63c49ceb90f GIT binary patch literal 1592 zcmbW1J#5oZ5XaAP0x62xDguO5niMGm3_KCkp`%e+s89t`1X3BOn;Q265<7A%D6|qp zkyw}_F|dHr&E2x$On|bmvao@GDJv2~mZ;o0&+bd&2#J%NcmBQm-#g!XdC!+tu16#Z ze3Rfk9KZP#perByisvdYfsscw=}T`fcG$~F^@g189@J9Z5A9jEA*)>ps`+csurT~} zBbRcW+?pGYLG}RP4z6)J4lj~UJMA*`8#wnYheMjojCK;u_*{P+AVI zkwl$STkBGMCk-viAw?;N(_ix+da8jQ(otTgecz2sFi(v9&J?tWcczq99H8ZKtcPm$ zbZyn`?JXT*59%Lf^($z_g0VICShp%WrZJaYU|F_+3CO1V14z&EAnm85nM4{cB0I-< z0u#dGlf8Rh#PkB-DY@yLl0 zeg;WW$nVvU>=Hiyw~8X%<4}HK3|}0>Gd$@G_Uk0~X;>9F?p0uAflmY!;Elk=_@=_6U!eS<#`NNZ(dBtwKo`b1)59#kTCi298flG-e*KtMrqF z%r3hk)c?Qk77B$cAxKl^@MS>y4z^*y=tL14K3NKn^3M~0#WOx=q$Q>dVrcSaJDk(r z67u&r_`e~e9K*d>;f0>XIng){?#6kX^qCm95e7qIZ*w+qHjr&|y@I}Ie*HeXiB8z} fuk!x;-$^>^v9I^JiEManMBwoC@gDSyhA{nKm*S`T literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/fsetversion.c b/jni/e2fsprogs/lib/e2p/fsetversion.c new file mode 100755 index 0000000..5f844b5 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/fsetversion.c @@ -0,0 +1,71 @@ +/* + * fsetversion.c - Set a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_SYS_IOCTL_H +#include +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fsetversion (const char * name, unsigned long version) +{ +#if HAVE_EXT2_IOCTLS +#if !APPLE_DARWIN + int fd, r, ver, save_errno = 0; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + ver = (int) version; + r = ioctl (fd, EXT2_IOC_SETVERSION, &ver); + if (r == -1) + save_errno = errno; + close (fd); + if (save_errno) + errno = save_errno; + return r; +#else + int ver = (int)version; + return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0); +#endif +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/jni/e2fsprogs/lib/e2p/fsetversion.o b/jni/e2fsprogs/lib/e2p/fsetversion.o new file mode 100755 index 0000000000000000000000000000000000000000..f9c15d0c155efef1f6790e19ea9783db56fa0622 GIT binary patch literal 1480 zcmbW1J8u&~5XWbI4t9tYTL}=P5S+q7p|SZ3zDYp-7oBi-%nZ|6Vzn!A_RZ{LV82Fe(G zfo@MxfHy|hH$&Hiag1yk?0a+D*l#wVQZ>>?zmss>nt*!Mu#On)=9Z!AVfg#Q8K?&{ zW<5Rz*-rrXaE?=Pcr~@xNY~Qn2TAkz&sC@dNvI!U-15P@9AkTJ?KEnq+uE;EOF83U z)&rc2a*>8uFoAIl7KxD`#GuV%$e|rexoBRBsWz-ybNkvp?xS*GSU(_Nu$}e!r@||3 zy3TxdiD&r|CQji)#$M!r?VM+`i8L%=|7=JBzEQg}X|5*bQXeB9qLEr6ZLUtjub(nt zMDqZ76#lk`4I2;{z`G$CpLs2QgJ2eVz14*&oF literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/getflags.c b/jni/e2fsprogs/lib/e2p/getflags.c new file mode 100755 index 0000000..6708cd6 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/getflags.c @@ -0,0 +1,71 @@ +/* + * getflags.c - Get a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#endif + +#include "e2p.h" + +int getflags (int fd, unsigned long * flags) +{ +#if HAVE_STAT_FLAGS + struct stat buf; + + if (fstat (fd, &buf) == -1) + return -1; + + *flags = 0; +#ifdef UF_IMMUTABLE + if (buf.st_flags & UF_IMMUTABLE) + *flags |= EXT2_IMMUTABLE_FL; +#endif +#ifdef UF_APPEND + if (buf.st_flags & UF_APPEND) + *flags |= EXT2_APPEND_FL; +#endif +#ifdef UF_NODUMP + if (buf.st_flags & UF_NODUMP) + *flags |= EXT2_NODUMP_FL; +#endif + + return 0; +#else +#if HAVE_EXT2_IOCTLS + struct stat buf; + int r, f; + + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) + goto notsupp; + r = ioctl(fd, EXT2_IOC_GETFLAGS, &f); + *flags = f; + + return r; +notsupp: +#endif /* HAVE_EXT2_IOCTLS */ +#endif + errno = EOPNOTSUPP; + return -1; +} diff --git a/jni/e2fsprogs/lib/e2p/getflags.o b/jni/e2fsprogs/lib/e2p/getflags.o new file mode 100755 index 0000000000000000000000000000000000000000..9a97a076e532f3225a6051b8ab6ea7af0e0d3dd6 GIT binary patch literal 1368 zcmbu8y>HV{5Ww#_0bEEwhzhC{Ag!9A13ZyRNEt1@8X<&41RIhui4!UuM{%sG5F{dn zktI?G7EsuT#L$gotCYWhg$)Eu85m$ILsahB@4ecIJM|>{?)~1~y}Nhzt6O((D};a$ z0-xbc2=uD2A|EMFN0ynXy_o(Lik4wlmbXl&v01a1vpJfjIjgCf@ckQiiB$KI#^LWl)MgBn zDZJ&8X4j<8LFzE6TJaYuUz=KnG(KrJsr2xlyNO>LL zGm-*`JSQ+usB7w&mO))}+XY&zRja1$Lb>4@E>ujnY#EgX=(_1Rb`3UbMb`pq*Ibis z+KA$)cZ4mS&`_dagzpAtyj+<= + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif + +#include "e2p.h" + +int getversion (int fd, unsigned long * version) +{ +#if HAVE_EXT2_IOCTLS + int r, ver; + + r = ioctl (fd, EXT2_IOC_GETVERSION, &ver); + *version = ver; + return r; +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/jni/e2fsprogs/lib/e2p/getversion.o b/jni/e2fsprogs/lib/e2p/getversion.o new file mode 100755 index 0000000000000000000000000000000000000000..8c668b5e3c65b6eb295d53fc8e284ae473ce0160 GIT binary patch literal 1160 zcmbu7y-Q<35Wr`Xcq$1hf`_1Yi5SG@mc-%^Y#wrYDUK@wHrIsb^BKi_=*uGBDJa-j z34v>sw03qTT_FF!U31+X@hUAXQv{t^cVAv!V&%Zj%>HI(KW6uM<;!Y-G0?)`20AlM z0aAgEZ%EgGVa$AN!0+~9;HrHJgQ?3uATq0P{#D1%~7b`g->et zVWTzApw%2TYVE`2E37ZqgPA{I<;+4hwr@M7?P4L8T;xf-6m%jlg};SCE*Bj9qso#+4u%uAeDsp0Z(|2 z^eQ)v)xkb1{8FEB&lgkJrPOI+{*D_eL-$!t@$I{XYKa-$7%FNb{ojT#PW>iJqIm>; zO7%D7jFM2^J{wo7Wn~S)IUJg~N$6a9Cm!FQyM!@fU4H@R6&xgn)E%YIugOPr`rW^( dHq!T`I_j~m*ZdnY|K5n8NeZPdb?1%z^-t>oW)c7Z literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/hashstr.c b/jni/e2fsprogs/lib/e2p/hashstr.c new file mode 100755 index 0000000..a73758c --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/hashstr.c @@ -0,0 +1,72 @@ +/* + * feature.c --- convert between features and strings + * + * Copyright (C) 1999 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include "e2p.h" + +struct hash { + int num; + const char *string; +}; + +static struct hash hash_list[] = { + { EXT2_HASH_LEGACY, "legacy" }, + { EXT2_HASH_HALF_MD4, "half_md4" }, + { EXT2_HASH_TEA, "tea" }, + { 0, 0 }, +}; + +const char *e2p_hash2string(int num) +{ + struct hash *p; + static char buf[20]; + + for (p = hash_list; p->string; p++) { + if (num == p->num) + return p->string; + } + sprintf(buf, "HASHALG_%d", num); + return buf; +} + +/* + * Returns the hash algorithm, or -1 on error + */ +int e2p_string2hash(char *string) +{ + struct hash *p; + char *eptr; + int num; + + for (p = hash_list; p->string; p++) { + if (!strcasecmp(string, p->string)) { + return p->num; + } + } + if (strncasecmp(string, "HASHALG_", 8)) + return -1; + + if (string[8] == 0) + return -1; + num = strtol(string+8, &eptr, 10); + if (num > 255 || num < 0) + return -1; + if (*eptr) + return -1; + return num; +} + diff --git a/jni/e2fsprogs/lib/e2p/hashstr.o b/jni/e2fsprogs/lib/e2p/hashstr.o new file mode 100755 index 0000000000000000000000000000000000000000..c2bbd3e98a7734f3035daa4c7aa66ee8f5a758cd GIT binary patch literal 2768 zcmbVNO>7%Q6n^VXh@mD4X@E)roQNO=1WRI4RK#WT1NEUoRSW0U#@_s>{=>VVlvE;8 z5GPc{f@_h5D&a^-Tq-q@I23Z=!hv$AkWf*$84e(B&cQP8jo)*|W9Pz?cHWzBzW3(a znc3No-@5d6%(6htg1d0i6BJ-~=p=Sk=)&X3Y#qY==2mR4xdWBzQgT0z)VKwe`Vbsr zo$>mRdmJBhk7r_Vhx)Z8Z~srkUbNhUxb^6@?*ZP`d9|HnV-$HEY@uE2?^f&SuP_&< z-o>YKWUKnSQy63ai@NO|Q!eFIcf3Y(YjF>?Rqol|gO+WfMtiS`{i>a8bTp2z#*uD~ zRoiRS5wlP?)xHOCUg;qo>aHCo_fw*gFw%&%NF(JUSLupb+rLnL6=0t7_SxYx@e-sN3)o&T)Xc4&qJw{cmL5uwR45>w5h&SfhSM zX{GvIa}UrM<)9AAsUCX!&8?+9TqCtsI9Hb;r^{kpz1~iG;c9x}(naruEJz5sV9n25 zhjl-<>gBWZ5CuL!Cg&H{CO-_y;YP7AId{RCb1q;x+><5nW+GEp)5H@6TTfPY*4 zMs4VQ`@a;i7f&E=!CznX44)hpcg0D*6K^%eHEO{D>!)@w2znv zep0>{|54%ir5N^u>OW?n04s=$Y3rl*39(P{kv-Lu=ui`1cxt~8n?8mA>M8h}r{FT@ zSv&{&TgZApY2YQSLq_~Z+M#MAj)|}1Hy9_rz8c#aU&lXTd;<9+9Fx1lv8j_TIx>T4%hx7P^MMkCSxyEVbdkS;{(4?{r8?_JK1^qw^VG~!^BOfNYUZ$5kqDGJhu!H-XI5VN z|NE~o)$WsC<-_}rF~-~7L5W6~e%5Kwr3US1BVnKocUl@I%EH9~L=x?W%395|jT9ADZH{d>6-bllcX^i$OpAGrS;aCX#--WhGzq|ArXN zpTbAC%dCG!2QlX5==i4?GmpY1=hL`uX8s}$3a0aJa=wmHY;r$m%%tx!ux=EP_ZRpk l2L0Br#Oo*TMe9fRh~&%qeT$emH$u>0@Q4MI8^*`X{|{e5Ew2Co literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/iod.c b/jni/e2fsprogs/lib/e2p/iod.c new file mode 100755 index 0000000..6a030dd --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/iod.c @@ -0,0 +1,76 @@ +/* + * iod.c - Iterate a function on each entry of a directory + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#include "e2p.h" +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +int iterate_on_dir (const char * dir_name, + int (*func) (const char *, struct dirent *, void *), + void * private) +{ + DIR * dir; + struct dirent *de, *dep; + int max_len = -1, len, ret = 0; + +#if HAVE_PATHCONF && defined(_PC_NAME_MAX) + max_len = pathconf(dir_name, _PC_NAME_MAX); +#endif + if (max_len == -1) { +#ifdef _POSIX_NAME_MAX + max_len = _POSIX_NAME_MAX; +#else +#ifdef NAME_MAX + max_len = NAME_MAX; +#else + max_len = 256; +#endif /* NAME_MAX */ +#endif /* _POSIX_NAME_MAX */ + } + max_len += sizeof(struct dirent); + + de = malloc(max_len+1); + if (!de) + return -1; + memset(de, 0, max_len+1); + + dir = opendir (dir_name); + if (dir == NULL) { + free(de); + return -1; + } + while ((dep = readdir (dir))) { +#ifdef HAVE_RECLEN_DIRENT + len = dep->d_reclen; + if (len > max_len) + len = max_len; +#else + len = sizeof(struct dirent); +#endif + memcpy(de, dep, len); + if ((*func)(dir_name, de, private)) + ret++; + } + free(de); + closedir(dir); + return ret; +} diff --git a/jni/e2fsprogs/lib/e2p/iod.o b/jni/e2fsprogs/lib/e2p/iod.o new file mode 100755 index 0000000000000000000000000000000000000000..2d198731373994b3327f6f13e70394b98fdc549e GIT binary patch literal 1888 zcmbu9L1+_E5Qb;7i6$DGwh<##n}|Kss*8~x3JNZ0wV-$?dJ>wf$<~G@*^n%fTBVU9 z^x~nY7eP&nhxQ(N_sC~;={o_$F+CkL``-uLF8H*fZB7RK+~ zbV(9$li(X1%s2&zcn*Bkc2)3UWOGsazBlh#-@7g?m*sGMWpS{+Di7AZQ0lirP-zCB zQkG-&=TMqN*=tLN5#m-zt#~~UT>-d<`yJnwN|VINw?d_gS934(IG+dlEZH{#&(v3x zqZ)*U6;vB*0ADGd_FCHtZ(KpYikxzDjSDq3IXpr-s>9ZYP#?lLrY8+?p649qp}bX$ zvEu{KD9iB0t}UQ8yl2!oD~M+Zs+He#4#_wBiJgP?rZroSd21N|D_E*fp0&lPI@M4^ zzA8`ELAtiH2{6j?Qa}1E>=(^z&1Q(##p|#FYK6{8>*cN3#@_t+I`)5gQ;zLGBCTZ~ zMIP(3e_X-^EzHP*P0{<-VBLd$R_)&pZ z1@0I4FdYDm@*mrG?PpxzVxAd+_XzRSXEG12x4iv~o=N29K*{TAO)>SN2};7qWb~{F zxKz+hFmie}nabnMHVQg9d0k7=m@@UeX6i8`8>6X`HB4Q(b@%?of~h5DA*Y!$2_rkr za_cj(>AaTFVLGqtkkQgxW;`U40fHMLu`t%mb-(j%JeGwqVf7UOQPd+{y1wCKPTy^$6U|( SOJwbPBZ3Hn{N7VJPWr#uL+1 + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "e2p.h" +#include "ext2fs/kernel-jbd.h" + +#ifdef WORDS_BIGENDIAN +#define e2p_be32(x) (x) +#else +static __u32 e2p_swab32(__u32 val) +{ + return ((val>>24) | ((val>>8)&0xFF00) | + ((val<<8)&0xFF0000) | (val<<24)); +} + +#define e2p_be32(x) e2p_swab32(x) +#endif + +/* + * This function is copied from kernel-jbd.h's function + * jbd2_journal_get_num_fc_blks() to avoid inter-library dependencies. + */ +static inline int get_num_fc_blks(journal_superblock_t *jsb) +{ + int num_fc_blocks = e2p_be32(jsb->s_num_fc_blks); + + return num_fc_blocks ? num_fc_blocks : JBD2_DEFAULT_FAST_COMMIT_BLOCKS; +} + +static const char *journal_checksum_type_str(__u8 type) +{ + switch (type) { + case JBD2_CRC32C_CHKSUM: + return "crc32c"; + default: + return "unknown"; + } +} + +void e2p_list_journal_super(FILE *f, char *journal_sb_buf, + int exp_block_size, int flags) +{ + journal_superblock_t *jsb = (journal_superblock_t *) journal_sb_buf; + __u32 *mask_ptr, mask, m; + unsigned int size; + int j, printed = 0; + unsigned int i, nr_users; + int num_fc_blks = 0; + int journal_blks = 0; + + if (flags & E2P_LIST_JOURNAL_FLAG_FC) + num_fc_blks = get_num_fc_blks((journal_superblock_t *)journal_sb_buf); + journal_blks = ntohl(jsb->s_maxlen) - num_fc_blks; + fprintf(f, "%s", "Journal features: "); + for (i=0, mask_ptr=&jsb->s_feature_compat; i <3; i++,mask_ptr++) { + mask = e2p_be32(*mask_ptr); + for (j=0,m=1; j < 32; j++, m<<=1) { + if (mask & m) { + fprintf(f, " %s", e2p_jrnl_feature2string(i, m)); + printed++; + } + } + } + if (printed == 0) + fprintf(f, " (none)"); + fputc('\n', f); + fputs("Total journal size: ", f); + size = (ntohl(jsb->s_blocksize) / 1024) * ntohl(jsb->s_maxlen); + if (size < 8192) + fprintf(f, "%uk\n", size); + else + fprintf(f, "%uM\n", size >> 10); + nr_users = (unsigned int) ntohl(jsb->s_nr_users); + if (exp_block_size != (int) ntohl(jsb->s_blocksize)) + fprintf(f, "Journal block size: %u\n", + (unsigned int)ntohl(jsb->s_blocksize)); + fprintf(f, "Total journal blocks: %u\n", + (unsigned int)(journal_blks + num_fc_blks)); + fprintf(f, "Max transaction length: %u\n", + (unsigned int)journal_blks); + fprintf(f, "Fast commit length: %u\n", + (unsigned int)num_fc_blks); + + if (ntohl(jsb->s_first) != 1) + fprintf(f, "Journal first block: %u\n", + (unsigned int)ntohl(jsb->s_first)); + fprintf(f, "Journal sequence: 0x%08x\n" + "Journal start: %u\n", + (unsigned int)ntohl(jsb->s_sequence), + (unsigned int)ntohl(jsb->s_start)); + if (nr_users != 1) + fprintf(f, "Journal number of users: %u\n", nr_users); + if (jsb->s_feature_compat & e2p_be32(JBD2_FEATURE_COMPAT_CHECKSUM)) + fprintf(f, "%s", "Journal checksum type: crc32\n"); + if ((jsb->s_feature_incompat & + e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V3)) || + (jsb->s_feature_incompat & + e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2))) + fprintf(f, "Journal checksum type: %s\n" + "Journal checksum: 0x%08x\n", + journal_checksum_type_str(jsb->s_checksum_type), + e2p_be32(jsb->s_checksum)); + if ((nr_users > 1) || + !e2p_is_null_uuid(&jsb->s_users[0])) { + for (i=0; i < nr_users && i < JBD2_USERS_MAX; i++) { + printf(i ? " %s\n" + : "Journal users: %s\n", + e2p_uuid2str(&jsb->s_users[i * UUID_SIZE])); + } + } + if (jsb->s_errno != 0) + fprintf(f, "Journal errno: %d\n", + (int) ntohl(jsb->s_errno)); +} diff --git a/jni/e2fsprogs/lib/e2p/ljs.o b/jni/e2fsprogs/lib/e2p/ljs.o new file mode 100755 index 0000000000000000000000000000000000000000..b6939dc290c2255d20945e01f94792de392d1e5e GIT binary patch literal 5248 zcmbtY?QdIW6+hQEZEY`2lfKZhB()2Th=cH&1Xzpq;f8c;x;ITpCLz|wb)1_fjbq35 zHA~l41i2pu>_dY3VIVQm!3U@R0KU?sbPAv$0otU2CfHC2Ah`$$koe$;hH%bv&v9;_ z#GiPk_<5e+`JLZ6&$;Kmbl-gX`DX%#0Wu8uDeUY7#rg2g+EPmk!pPh%1wPoi5n9BxinUJ58%rfCmV0yuvaXH4PFs@Z`t&}Rvj%B4=? zpvI+2@F3(qvmZv)zI3?;hUIo)oaMpJ%4(^j(hUp4WwW#5*^&P($lWuUKX|#aVqUIb z>~JsuU-USMS~UWj%cy-9Z4`UMgnR1|YZL7%FT%=$sI?E;%6MM#tLqbnam%E8Ju*VE zH@3HrD?8;&b~+2@8f^2<@*A|1UKQX=#PipHVi9(?l&D$8!Z7V=jq@V@soJQz9Q0}# zT38qkhJN|@iaAz`VSQs*-{7rKdwC6Gu3`L;l?xc&`66#JJ~kSwhKe9A5;3r zynL{>xm~f*)+n~}{j_IS>rTrxwLHsfuh2EiVf(8d^J@0WBQ?W(yt;H*ZuLoUqu6t| z@j6wXq`ro5x8d~``AY8o-md${(7zvC2rLXci|IsQY2By$iYO=YI4!;l!^Vx7=>idmh|F-w^g)%z!2Axkaqg z(z6ESf^FaaLG^%_ZxG{BjM!|)$OALf14ih()c=2?`|*IaNo%imJNMNe>i61MEqKau zhkUhH^+Rm0e%QKkaRr}mOZUyh@3u>T&p891bFj3Ixl}3E%a(hHYIy)$+`DD)t|_gn zCb&&_zF>4=nAVijx@oyvHwI7>Jk3G)0I!4l;1KfhFL*0B66`#2IGDWHLs;zciIG@m z>tTErsXZh^J=+*xe_jaJrN-0Q)J)V*>MDjc z3B}=HWPKqyA9eD{Od*+arn8x7+Rj{crYHzmpGg*+Xev89JMH)^lqgy2N0`ndO(}DB zerv(b741x_o_I8RX1?pp+4-=z7o23?kz=VM_}w$b*>O7`%}z#(1v^if`>m-dJ2g`% z&PJWrSEJv+qfz;L&&GS>XYp17XjQ)e#%sf1+&pQtH%Fiwu@j6}vB}|l z%d#=l+}Zk8;D=4-`%TRe+_u0UKS9%JGBbCS=JPF4q26qcM1^-0O=;#m-N-tx&i*Z2KW@>G>+iI$$vWOg<~2%=h5qYllKnK!WVp=@pjZ{<~2?K_TdM8 zIKI=>kbFAX*2K8z3y$w7HFW*7rgMsQ<}@9_9maK?+dkai_HQsQdB#|Ok#WgWaC#}y zAbosi)yGGgj`Z!vnvUS>KAlJEsp(wg2=sA7L-G;)VFMkDTUpNaqUR3h85bSF@f$}C zy>3@D9qFeDO-Jyl20D(W^BvA-Uegi$W&@qqH66NtXuP562)@`r=N(Pw7oH5<*K`E` zSp%J_rt=rp`Mahg_&*!yH1mxn*Xy%m~S6#`WuUUen=pU`W#u{CSN(z;R#F z_=1lzuE+gQ(-~)-k2D>@KW?D&(1-hknO4I*@_21X@1^>{e1%~}3gYPNB*$^S zK1=iIiFm*AD7=~+@9(3%`sqd0>_pN@l0$F27f#Q|&v0S>&*|sr&#nK6QjKo{llwx9 z+7|YsfiRl=!{W_5+#h1&c9gC1CCsWL-eMu_%_mqmgj?#Ppa<8#U;lx7ir>e$Obox(I#sj4LT%IKez|?EylDoA + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#include "e2p.h" +#include "support/quotaio.h" + +static void print_user (unsigned short uid, FILE *f) +{ + struct passwd *pw; + + fprintf(f, "%u ", uid); + pw = getpwuid (uid); + if (pw == NULL) + fprintf(f, "(user unknown)\n"); + else + fprintf(f, "(user %s)\n", pw->pw_name); +} + +static void print_group (unsigned short gid, FILE *f) +{ + struct group *gr; + + fprintf(f, "%u ", gid); + gr = getgrgid (gid); + if (gr == NULL) + fprintf(f, "(group unknown)\n"); + else + fprintf(f, "(group %s)\n", gr->gr_name); +} + +#define MONTH_INT (86400 * 30) +#define WEEK_INT (86400 * 7) +#define DAY_INT (86400) +#define HOUR_INT (60 * 60) +#define MINUTE_INT (60) + +static const char *interval_string(unsigned int secs) +{ + static char buf[256], tmp[80]; + int hr, min, num; + + buf[0] = 0; + + if (secs == 0) + return ""; + + if (secs >= MONTH_INT) { + num = secs / MONTH_INT; + secs -= num*MONTH_INT; + sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); + } + if (secs >= WEEK_INT) { + num = secs / WEEK_INT; + secs -= num*WEEK_INT; + sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", + num, (num>1) ? "s" : ""); + strcat(buf, tmp); + } + if (secs >= DAY_INT) { + num = secs / DAY_INT; + secs -= num*DAY_INT; + sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", + num, (num>1) ? "s" : ""); + strcat(buf, tmp); + } + if (secs > 0) { + hr = secs / HOUR_INT; + secs -= hr*HOUR_INT; + min = secs / MINUTE_INT; + secs -= min*MINUTE_INT; + sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", + hr, min, secs); + strcat(buf, tmp); + } + return buf; +} + +static void print_features(struct ext2_super_block * s, FILE *f) +{ +#ifdef EXT2_DYNAMIC_REV + int i, j, printed=0; + __u32 *mask = &s->s_feature_compat, m; + + fprintf(f, "Filesystem features: "); + for (i=0; i <3; i++,mask++) { + for (j=0,m=1; j < 32; j++, m<<=1) { + if (*mask & m) { + fprintf(f, " %s", e2p_feature2string(i, m)); + printed++; + } + } + } + if (printed == 0) + fprintf(f, " (none)"); + fprintf(f, "\n"); +#endif +} + +static void print_mntopts(struct ext2_super_block * s, FILE *f) +{ +#ifdef EXT2_DYNAMIC_REV + int i, printed=0; + __u32 mask = s->s_default_mount_opts, m; + + fprintf(f, "Default mount options: "); + if (mask & EXT3_DEFM_JMODE) { + fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); + printed++; + } + for (i=0,m=1; i < 32; i++, m<<=1) { + if (m & EXT3_DEFM_JMODE) + continue; + if (mask & m) { + fprintf(f, " %s", e2p_mntopt2string(m)); + printed++; + } + } + if (printed == 0) + fprintf(f, " (none)"); + fprintf(f, "\n"); +#endif +} + +static void print_super_flags(struct ext2_super_block * s, FILE *f) +{ + int flags_found = 0; + + if (s->s_flags == 0) + return; + + fputs("Filesystem flags: ", f); + if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) { + fputs("signed_directory_hash ", f); + flags_found++; + } + if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) { + fputs("unsigned_directory_hash ", f); + flags_found++; + } + if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) { + fputs("test_filesystem ", f); + flags_found++; + } + if (flags_found) + fputs("\n", f); + else + fputs("(none)\n", f); +} + +static __u64 e2p_blocks_count(struct ext2_super_block *super) +{ + return super->s_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_r_blocks_count(struct ext2_super_block *super) +{ + return super->s_r_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_r_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_free_blocks_count(struct ext2_super_block *super) +{ + return super->s_free_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_free_blocks_hi << 32 : 0); +} + +#ifndef EXT2_INODE_SIZE +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) +#endif + +#ifndef EXT2_GOOD_OLD_REV +#define EXT2_GOOD_OLD_REV 0 +#endif + +static const char *checksum_type(__u8 type) +{ + switch (type) { + case EXT2_CRC32C_CHKSUM: + return "crc32c"; + default: + return "unknown"; + } +} + +static const char *quota_prefix[MAXQUOTAS] = { + [USRQUOTA] = "User quota inode:", + [GRPQUOTA] = "Group quota inode:", + [PRJQUOTA] = "Project quota inode:", +}; + +/** + * Convert type of quota to written representation + */ +static const char *quota_type2prefix(enum quota_type qtype) +{ + return quota_prefix[qtype]; +} + +void list_super2(struct ext2_super_block * sb, FILE *f) +{ + int inode_blocks_per_group; + char *str; + time_t tm; + enum quota_type qtype; + + inode_blocks_per_group = (((sb->s_inodes_per_group * + EXT2_INODE_SIZE(sb)) + + EXT2_BLOCK_SIZE(sb) - 1) / + EXT2_BLOCK_SIZE(sb)); + if (sb->s_volume_name[0]) + fprintf(f, "Filesystem volume name: %.*s\n", + EXT2_LEN_STR(sb->s_volume_name)); + else + fprintf(f, "Filesystem volume name: \n"); + if (sb->s_last_mounted[0]) + fprintf(f, "Last mounted on: %.*s\n", + EXT2_LEN_STR(sb->s_last_mounted)); + else + fprintf(f, "Last mounted on: \n"); + fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid)); + fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic); + fprintf(f, "Filesystem revision #: %d", sb->s_rev_level); + if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { + fprintf(f, " (original)\n"); +#ifdef EXT2_DYNAMIC_REV + } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { + fprintf(f, " (dynamic)\n"); +#endif + } else + fprintf(f, " (unknown)\n"); + print_features(sb, f); + print_super_flags(sb, f); + print_mntopts(sb, f); + if (sb->s_mount_opts[0]) + fprintf(f, "Mount options: %.*s\n", + EXT2_LEN_STR(sb->s_mount_opts)); + fprintf(f, "Filesystem state: "); + print_fs_state (f, sb->s_state); + fprintf(f, "\n"); + fprintf(f, "Errors behavior: "); + print_fs_errors(f, sb->s_errors); + fprintf(f, "\n"); + str = e2p_os2string(sb->s_creator_os); + fprintf(f, "Filesystem OS type: %s\n", str); + free(str); + fprintf(f, "Inode count: %u\n", sb->s_inodes_count); + fprintf(f, "Block count: %llu\n", + (unsigned long long) e2p_blocks_count(sb)); + fprintf(f, "Reserved block count: %llu\n", + (unsigned long long) e2p_r_blocks_count(sb)); + if (sb->s_overhead_clusters) + fprintf(f, "Overhead clusters: %u\n", + sb->s_overhead_clusters); + fprintf(f, "Free blocks: %llu\n", + (unsigned long long) e2p_free_blocks_count(sb)); + fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count); + fprintf(f, "First block: %u\n", sb->s_first_data_block); + fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb)); + if (ext2fs_has_feature_bigalloc(sb)) + fprintf(f, "Cluster size: %u\n", + EXT2_CLUSTER_SIZE(sb)); + else + fprintf(f, "Fragment size: %u\n", + EXT2_CLUSTER_SIZE(sb)); + if (ext2fs_has_feature_64bit(sb)) + fprintf(f, "Group descriptor size: %u\n", sb->s_desc_size); + if (sb->s_reserved_gdt_blocks) + fprintf(f, "Reserved GDT blocks: %u\n", + sb->s_reserved_gdt_blocks); + fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group); + if (ext2fs_has_feature_bigalloc(sb)) + fprintf(f, "Clusters per group: %u\n", + sb->s_clusters_per_group); + else + fprintf(f, "Fragments per group: %u\n", + sb->s_clusters_per_group); + fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); + fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); + if (sb->s_raid_stride) + fprintf(f, "RAID stride: %u\n", + sb->s_raid_stride); + if (sb->s_raid_stripe_width) + fprintf(f, "RAID stripe width: %u\n", + sb->s_raid_stripe_width); + if (sb->s_first_meta_bg) + fprintf(f, "First meta block group: %u\n", + sb->s_first_meta_bg); + if (sb->s_log_groups_per_flex) + fprintf(f, "Flex block group size: %u\n", + 1U << sb->s_log_groups_per_flex); + if (sb->s_mkfs_time) { + tm = sb->s_mkfs_time; + fprintf(f, "Filesystem created: %s", ctime(&tm)); + } + tm = sb->s_mtime; + fprintf(f, "Last mount time: %s", + sb->s_mtime ? ctime(&tm) : "n/a\n"); + tm = sb->s_wtime; + fprintf(f, "Last write time: %s", ctime(&tm)); + fprintf(f, "Mount count: %u\n", sb->s_mnt_count); + fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count); + tm = sb->s_lastcheck; + fprintf(f, "Last checked: %s", ctime(&tm)); + fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval, + interval_string(sb->s_checkinterval)); + if (sb->s_checkinterval) + { + time_t next; + + next = sb->s_lastcheck + sb->s_checkinterval; + fprintf(f, "Next check after: %s", ctime(&next)); + } +#define POW2(x) ((__u64) 1 << (x)) + if (sb->s_kbytes_written) { + fprintf(f, "Lifetime writes: "); + if (sb->s_kbytes_written < POW2(13)) + fprintf(f, "%llu kB\n", + (unsigned long long) sb->s_kbytes_written); + else if (sb->s_kbytes_written < POW2(23)) + fprintf(f, "%llu MB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(9)) >> 10); + else if (sb->s_kbytes_written < POW2(33)) + fprintf(f, "%llu GB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(19)) >> 20); + else if (sb->s_kbytes_written < POW2(43)) + fprintf(f, "%llu TB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(29)) >> 30); + else + fprintf(f, "%llu PB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(39)) >> 40); + } + fprintf(f, "Reserved blocks uid: "); + print_user(sb->s_def_resuid, f); + fprintf(f, "Reserved blocks gid: "); + print_group(sb->s_def_resgid, f); + if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { + fprintf(f, "First inode: %d\n", sb->s_first_ino); + fprintf(f, "Inode size: %d\n", sb->s_inode_size); + if (sb->s_min_extra_isize) + fprintf(f, "Required extra isize: %d\n", + sb->s_min_extra_isize); + if (sb->s_want_extra_isize) + fprintf(f, "Desired extra isize: %d\n", + sb->s_want_extra_isize); + } + if (!e2p_is_null_uuid(sb->s_journal_uuid)) + fprintf(f, "Journal UUID: %s\n", + e2p_uuid2str(sb->s_journal_uuid)); + if (sb->s_journal_inum) + fprintf(f, "Journal inode: %u\n", + sb->s_journal_inum); + if (sb->s_journal_dev) + fprintf(f, "Journal device: 0x%04x\n", + sb->s_journal_dev); + if (sb->s_last_orphan) + fprintf(f, "First orphan inode: %u\n", + sb->s_last_orphan); + if (ext2fs_has_feature_dir_index(sb) || + sb->s_def_hash_version) + fprintf(f, "Default directory hash: %s\n", + e2p_hash2string(sb->s_def_hash_version)); + if (!e2p_is_null_uuid(sb->s_hash_seed)) + fprintf(f, "Directory Hash Seed: %s\n", + e2p_uuid2str(sb->s_hash_seed)); + if (sb->s_jnl_backup_type) { + fprintf(f, "Journal backup: "); + switch (sb->s_jnl_backup_type) { + case 1: + fprintf(f, "inode blocks\n"); + break; + default: + fprintf(f, "type %u\n", sb->s_jnl_backup_type); + } + } + if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) { + fprintf(f, "Backup block groups: "); + if (sb->s_backup_bgs[0]) + fprintf(f, "%u ", sb->s_backup_bgs[0]); + if (sb->s_backup_bgs[1]) + fprintf(f, "%u ", sb->s_backup_bgs[1]); + fputc('\n', f); + } + if (sb->s_snapshot_inum) { + fprintf(f, "Snapshot inode: %u\n", + sb->s_snapshot_inum); + fprintf(f, "Snapshot ID: %u\n", + sb->s_snapshot_id); + fprintf(f, "Snapshot reserved blocks: %llu\n", + (unsigned long long) sb->s_snapshot_r_blocks_count); + } + if (sb->s_snapshot_list) + fprintf(f, "Snapshot list head: %u\n", + sb->s_snapshot_list); + if (sb->s_error_count) + fprintf(f, "FS Error count: %u\n", + sb->s_error_count); + if (sb->s_first_error_time) { + tm = sb->s_first_error_time; + fprintf(f, "First error time: %s", ctime(&tm)); + fprintf(f, "First error function: %.*s\n", + EXT2_LEN_STR(sb->s_first_error_func)); + fprintf(f, "First error line #: %u\n", + sb->s_first_error_line); + if (sb->s_first_error_ino) + fprintf(f, "First error inode #: %u\n", + sb->s_first_error_ino); + if (sb->s_first_error_block) + fprintf(f, "First error block #: %llu\n", + (unsigned long long) sb->s_first_error_block); + if (sb->s_first_error_errcode) + fprintf(f, "First error err: %s\n", + e2p_errcode2str(sb->s_first_error_errcode)); + } + if (sb->s_last_error_time) { + tm = sb->s_last_error_time; + fprintf(f, "Last error time: %s", ctime(&tm)); + fprintf(f, "Last error function: %.*s\n", + EXT2_LEN_STR(sb->s_last_error_func)); + fprintf(f, "Last error line #: %u\n", + sb->s_last_error_line); + if (sb->s_last_error_ino) + fprintf(f, "Last error inode #: %u\n", + sb->s_last_error_ino); + if (sb->s_last_error_block) + fprintf(f, "Last error block #: %llu\n", + (unsigned long long) sb->s_last_error_block); + if (sb->s_last_error_errcode) + fprintf(f, "Last error err: %s\n", + e2p_errcode2str(sb->s_last_error_errcode)); + } + if (ext2fs_has_feature_mmp(sb)) { + fprintf(f, "MMP block number: %llu\n", + (unsigned long long) sb->s_mmp_block); + fprintf(f, "MMP update interval: %u\n", + sb->s_mmp_update_interval); + } + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (*quota_sb_inump(sb, qtype) != 0) + fprintf(f, "%-26s%u\n", + quota_type2prefix(qtype), + *quota_sb_inump(sb, qtype)); + } + + if (ext2fs_has_feature_metadata_csum(sb)) { + fprintf(f, "Checksum type: %s\n", + checksum_type(sb->s_checksum_type)); + fprintf(f, "Checksum: 0x%08x\n", + sb->s_checksum); + } + if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt)) + fprintf(f, "Encryption PW Salt: %s\n", + e2p_uuid2str(sb->s_encrypt_pw_salt)); + + if (ext2fs_has_feature_csum_seed(sb)) + fprintf(f, "Checksum seed: 0x%08x\n", + sb->s_checksum_seed); + if (ext2fs_has_feature_casefold(sb)) + fprintf(f, "Character encoding: %s\n", + e2p_encoding2str(sb->s_encoding)); +} + +void list_super (struct ext2_super_block * s) +{ + list_super2(s, stdout); +} + diff --git a/jni/e2fsprogs/lib/e2p/ls.o b/jni/e2fsprogs/lib/e2p/ls.o new file mode 100755 index 0000000000000000000000000000000000000000..3e7b7eeeb905972aeb08dec05da001e7585583bc GIT binary patch literal 25696 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/mntopts.c b/jni/e2fsprogs/lib/e2p/mntopts.c new file mode 100755 index 0000000..7d0ae9c --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/mntopts.c @@ -0,0 +1,150 @@ +/* + * mountopts.c --- convert between default mount options and strings + * + * Copyright (C) 2002 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "e2p.h" + +struct mntopt { + unsigned int mask; + const char *string; +}; + +static struct mntopt mntopt_list[] = { + { EXT2_DEFM_DEBUG, "debug" }, + { EXT2_DEFM_BSDGROUPS, "bsdgroups" }, + { EXT2_DEFM_XATTR_USER, "user_xattr" }, + { EXT2_DEFM_ACL, "acl" }, + { EXT2_DEFM_UID16, "uid16" }, + { EXT3_DEFM_JMODE_DATA, "journal_data" }, + { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" }, + { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" }, + { EXT4_DEFM_NOBARRIER, "nobarrier" }, + { EXT4_DEFM_BLOCK_VALIDITY, "block_validity" }, + { EXT4_DEFM_DISCARD, "discard"}, + { EXT4_DEFM_NODELALLOC, "nodelalloc"}, + { 0, 0 }, +}; + +const char *e2p_mntopt2string(unsigned int mask) +{ + struct mntopt *f; + static char buf[20]; + int fnum; + + for (f = mntopt_list; f->string; f++) { + if (mask == f->mask) + return f->string; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "MNTOPT_%d", fnum); + return buf; +} + +int e2p_string2mntopt(char *string, unsigned int *mask) +{ + struct mntopt *f; + char *eptr; + int num; + + for (f = mntopt_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "MNTOPT_", 7)) + return 1; + + if (string[8] == 0) + return 1; + num = strtol(string+8, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} + +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + while (*cp && !isspace(*cp) && *cp != ',') + cp++; + return cp; +} + +/* + * Edit a mntopt set array as requested by the user. The ok + * parameter, if non-zero, allows the application to limit what + * mntopts the user is allowed to set or clear using this function. + */ +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok) +{ + char *cp, *buf, *next; + int neg; + unsigned int mask; + int rc = 0; + + buf = malloc(strlen(str)+1); + if (!buf) + return 1; + strcpy(buf, str); + cp = buf; + while (cp && *cp) { + neg = 0; + cp = skip_over_blanks(cp); + next = skip_over_word(cp); + if (*next == 0) + next = 0; + else + *next = 0; + switch (*cp) { + case '-': + case '^': + neg++; + /* fallthrough */ + case '+': + cp++; + break; + } + if (e2p_string2mntopt(cp, &mask)) { + rc = 1; + break; + } + if (ok && !(ok & mask)) { + rc = 1; + break; + } + if (mask & EXT3_DEFM_JMODE) + *mntopts &= ~EXT3_DEFM_JMODE; + if (neg) + *mntopts &= ~mask; + else + *mntopts |= mask; + cp = next ? next+1 : 0; + } + free(buf); + return rc; +} diff --git a/jni/e2fsprogs/lib/e2p/mntopts.o b/jni/e2fsprogs/lib/e2p/mntopts.o new file mode 100755 index 0000000000000000000000000000000000000000..8248ecd64d582c43f8d1c955c4e1951f6ce0109b GIT binary patch literal 4896 zcmbtXUu;uV82@g|T-oM;0S+0^@lOVkhD|^;J`^`~@eeLI6HV08KNqO$+S1_M2!#rDaMD+Xrc+kHX(|cQH(EO)CUvIASMUN$!ms%emJgk;TYT$(-Uot&Mbe4*c8@)1q= z49ZuQ(G2XYsw@l6_?m(k)e0~Jxw3tfW{--A<&Z1q z++$Gr^C^F6ua1}3I6v6DhIrWqbX1I2=+t*?ry%+D(5Zt(=x&2<5puqb!8?j%`_OCM zvPK&ze|a0^yWE&MP?WiNV70 z)m7*)@7wszT4zqGj#HshLmj8MH*T1m%^CRu>UcW0q559`hEmN>WzLmjqb2r!On1>t zr3-sPbk-TqIDAe6KP~b~CbwSgTQT=!btz)G+C}Ik=`Ua$JNRRj=6Batu*UYFSN64$ z%C)u){vl^_ePN5|FJM01i5NQV++UX3qUUCous(3VL3gk%_RBuF&wL-zvGa!XF!$eC z@VdUtA2*Ke*X!HBbAQ5r-A)tbi;@q=aXDw#qu{801@-D>zx_{@1`T^pcz$&=>={d2 zP&3tQye}+!3&+cAO!KbP$ga7n8S+4n*|qZeKj69Yq0ZU*>g(ul-bdAse)JuBnb!+b+%xx1)~4j_{Eb;xxaX@eOYQzV5w=?4!(;at<38;3_O0xL z%75ryV|)*=uhH|48nCXaM=S0^gF0%cE9VTXfjkWy;aD~j>f1oe8#tnF7aw%-hg>{j zX{7%eK%+K2bYS@5q2bWhn4VG0jEo(jNH%sPlNw8BX)J4ILgQh}%1}6(ps{$YcP~Ai z8p|ZZiBK$Tg&UYqDibp^W~>o>HWRnZNH{t|$y6kq$;8bJMG~p#Na&exA|8ud$0-)i zM#GsH1Y%|)oWLScG!af7>3+t{WaFu1ckjMHZ(yIquj^=>I7r5G8;q_tKW)L<8d?9I z$AR|XVB7lT?|9x`;yKsm4-U4|FF%u#3yRzz*V7^A-DT7T+1^o++s$ply-M&Qj2`?A$&$(+*cHLQ6kO#C>?bWR zE_8hXlXu?fA?j6e&iQ3IOnb?lbh4~@Dbv(K=h6UI0X#5F>oz-kWsNlfyj;zyNvVZKC?*&Z* z4*X^fVoW&jwGMpPYcp(z&$y;ta#1v}W6-$fdqh{`n}pxz!gmTk z=)&=xrsy#je!K8TUHE|T<1YMh;a_&)Y2n{=;U|PIy6{(oFS+o%@c6Bzs0sCvk}F=v zrEz_}`TR0zT%XI=Y`Bi=d-R+O*Z1hJE__H|by+JDO&_N~25--RWsX}knzT}BE0l<5 zEi(JkAxOlNNBV4-0@2jysF}2vOuT|a_Cl5dk!+T-Bk^=7g;#GVf|u|J0N4*_&FE;F zr%A^=VI~=}QV9wqQ|#tQB^{Hplpc+_7EPs`EeUR`uNcc ze<>DV)n2e$#sj;gzW;adpfBXeHJF-^*ZBQdcan=$XO6KOoI;ofg)ixS7haCBaQ69S zELcbE$r`zoFNni7z}&w+ky|6<1A@78sES|b9mp!~_&WhGwwV4!R&tQ`ub~boFBJbY z2Mp>Khs<(FT3^S{KVVp-5C2ZOAO(HP31Tkh>LcGrjJf+ECZ7tIyjytfl;~HPagfemLtkOCQ2j{yZ$bpQe*A9I`nrBCaPIcaD&rzp MkVTGh#RB^O0ACL8egFUf literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/ostype.c b/jni/e2fsprogs/lib/e2p/ostype.c new file mode 100755 index 0000000..c5fd8ab --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/ostype.c @@ -0,0 +1,79 @@ +/* + * getostype.c - Get the Filesystem OS type + * + * Copyright (C) 2004,2005 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include "e2p.h" +#include +#include + +static const char *os_tab[] = + { "Linux", + "Hurd", + "Masix", + "FreeBSD", + "Lites", + 0 }; + +/* + * Convert an os_type to a string + */ +char *e2p_os2string(int os_type) +{ + const char *os; + char *ret; + + if (os_type >= 0 && os_type <= EXT2_OS_LITES) + os = os_tab[os_type]; + else + os = "(unknown os)"; + + ret = malloc(strlen(os)+1); + if (ret) + strcpy(ret, os); + return ret; +} + +/* + * Convert an os_type to a string + */ +int e2p_string2os(char *str) +{ + const char **cpp; + int i = 0; + + for (cpp = os_tab; *cpp; cpp++, i++) { + if (!strcasecmp(str, *cpp)) + return i; + } + return -1; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + char *s; + int i, os; + + for (i=0; i <= EXT2_OS_LITES; i++) { + s = e2p_os2string(i); + os = e2p_string2os(s); + printf("%d: %s (%d)\n", i, s, os); + free(s); + if (i != os) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + exit(0); +} +#endif + + diff --git a/jni/e2fsprogs/lib/e2p/ostype.o b/jni/e2fsprogs/lib/e2p/ostype.o new file mode 100755 index 0000000000000000000000000000000000000000..9d6d77884e37b0e64767abc682d66b10abbaa411 GIT binary patch literal 2368 zcmbW1O=uHQ5XWbe)B{4kgZPXVT|3RrEpL%=^9n%)IyZz1%!8 zG91t}kfy;aSRV-mh;C7Q&y7MDm6alVSe*(itlojbT(M(uz8GJ;tF0Wv96QJlHN(}g z2IpwJP<*l&0+rs2-ZpU;19D><+=L7SfV#4)?CE33L8a>z=eGEc?3EX*&mDBxz0NAU2sD zg;R!;%)xNhGzZTP;e=~C0Ev`gjdfl#vrf{sI(rB7UVVV8ZD*_9I0M>ryVe%&fG%Wv zn9q_OYU+uF_icY1cvKgd4tMm#n&9gffNq?M(mb|5>DCmr`wZeb_*tnn8-&0H{MsWM z`90(sW|Gz;4%(o?1wZqgb-i%1K~OF;PdxSPMn32923D<`hn~B29k4fownf>OcW%h~ z@h9JcrJhM{!toB()bB-3`6aK|L!0R3oLVs2dby6c#tSNR3zZK%gL zQf-&mBfhOl0j3q+r0{w6{p)(HxIo$r@=B(ncy}C%|^xe8$uhprgz+ zE~Cw-$=Xib8+z*)HCzL_M)f}Gj#3w)t{0QqG)KX`IPA*laa((b9L7dnEVcJ~Ard-@`c9^&gYO zV~E#gu&-7BJufuJI;u}d;-&rzWK=4GKeavJ`iE7BKI5vTcR + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include "e2p.h" + +#include + +unsigned long long parse_num_blocks2(const char *arg, int log_block_size) +{ + char *p; + unsigned long long num; + + num = strtoull(arg, &p, 0); + + if (p[0] && p[1]) + return 0; + + switch (*p) { /* Using fall-through logic */ + case 'T': case 't': + num <<= 10; + /* fallthrough */ + case 'G': case 'g': + num <<= 10; + /* fallthrough */ + case 'M': case 'm': + num <<= 10; + /* fallthrough */ + case 'K': case 'k': + if (log_block_size < 0) + num <<= 10; + else + num >>= log_block_size; + break; + case 's': + if (log_block_size < 0) + num <<= 9; + else + num >>= (1+log_block_size); + break; + case '\0': + break; + default: + return 0; + } + return num; +} + +unsigned long parse_num_blocks(const char *arg, int log_block_size) +{ + return parse_num_blocks2(arg, log_block_size); +} + +#ifdef DEBUG +#include +#include + +main(int argc, char **argv) +{ + unsigned long num; + int log_block_size = 0; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: %s arg [log_block_size]\n", argv[0]); + exit(1); + } + + if (argc == 3) { + char *p; + + log_block_size = strtol(argv[2], &p, 0); + if (*p) { + fprintf(stderr, "Bad log_block_size: %s\n", argv[2]); + exit(1); + } + } + + num = parse_num_blocks(argv[1], log_block_size); + + printf("Parsed number: %lu\n", num); + exit(0); +} +#endif diff --git a/jni/e2fsprogs/lib/e2p/parse_num.o b/jni/e2fsprogs/lib/e2p/parse_num.o new file mode 100755 index 0000000000000000000000000000000000000000..23fa2e1f65fdb97fd416ec14354bf7f6698ae714 GIT binary patch literal 1712 zcmbtTO=wd=5T4CTOo}1YQbnk3a)?rjeOggzFS^pIJxD>RARY`a@oBaBX_D7kZ9%0V zf~SHfp;Ey^auB?TEeIBJsRs{5lzLDSPx0t2IfOX#vYV{0(Tf8wGxN>ulg7t@i91#=Xcw_hmSmlhW~ykSh*r`0e_X+P<75Dk4pDSEj+l0zV zC)bPpQtYSZ8z_5mJ_kQMlV^5`*dKXc@7OhEUWW(vIP-8#-5P#0PqHbVLz`-^E=4M} zh0#3jYozm+)HZHkw_^`F5X( z9l}q}q{Rlz6c5v#_?0-fv7Lr^kI + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 94/01/09 - Creation + */ + +#include "config.h" +#include + +#include "e2p.h" + +void print_fs_errors (FILE * f, unsigned short errors) +{ + switch (errors) + { + case EXT2_ERRORS_CONTINUE: + fprintf (f, "Continue"); + break; + case EXT2_ERRORS_RO: + fprintf (f, "Remount read-only"); + break; + case EXT2_ERRORS_PANIC: + fprintf (f, "Panic"); + break; + default: + fprintf (f, "Unknown (continue)"); + } +} diff --git a/jni/e2fsprogs/lib/e2p/pe.o b/jni/e2fsprogs/lib/e2p/pe.o new file mode 100755 index 0000000000000000000000000000000000000000..4192c9961355d1fee71d50121922b471e039419d GIT binary patch literal 1696 zcmbu9&rcIk5XWcx!xpVTR18T~mIM<#u%W047n4=|!GRbgaPU-?b}LQWx9xV(R!AVx zg9i>Y@!&;IUib?PH~$4M-ZYqa=uwXx8l2hAgXML5a+2Md`MjC$`>{W^A1yqNXc|b< z;0v5)k^<|Wz|pTEXtsyUW;+T8$vD(Z4VF>wN;_&E zBnP0j8q6<3Z3pvV96wB$M_9Kv4$wmR_hIZpNZq**M)P$x@9*Qj?go+M#h-Mh2gq< z(_Sxuwsk{Gr^a9s$td&B|^Qr5@pCTV)k=@joK0gRQe{ew`w}3nbe~-h4qY&xA z+dk>#grlgWTFD2!yx{Y=S`L;^5@q%-;OvWC3?m9( zW}Zeqz%jX1j-`$q%QKfclCLvYbv#8U&3Qx7k$kI<&O1eCobz2pNAkTsI@g%TaldDt zrs3LU%kb=m2S(1RRBYiv)h!AyTc~Gk*LB=F7{c*vK0%3efGf*RuuJ zs@PDqjT{(t&-JV|^vw$SiM(-}ZZmYtV2hKtJd3I_m`*f|X + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include "e2p.h" + +#include + +/* + * We work really hard to calculate this accurately, while avoiding + * an overflow. "Is there a hyphen in anal-retentive?" :-) + */ +unsigned int e2p_percent(int percent, unsigned int base) +{ + unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1); + + if (!percent) + return 0; + if (100 % percent == 0) + return base / (100 / percent); + if (mask & base) + return (base / 100) * percent; + return base * percent / 100; +} + +#ifdef DEBUG +#include +#include + +main(int argc, char **argv) +{ + unsigned int base; + int percent; + char *p; + int log_block_size = 0; + + if (argc != 3) { + fprintf(stderr, "Usage: %s percent base\n", argv[0]); + exit(1); + } + + percent = strtoul(argv[1], &p, 0); + if (p[0] && p[1]) { + fprintf(stderr, "Bad percent: %s\n", argv[1]); + exit(1); + } + + base = strtoul(argv[2], &p, 0); + if (p[0] && p[1]) { + fprintf(stderr, "Bad base: %s\n", argv[2]); + exit(1); + } + + printf("%d percent of %u is %u.\n", percent, base, + e2p_percent(percent, base)); + + exit(0); +} +#endif diff --git a/jni/e2fsprogs/lib/e2p/percent.o b/jni/e2fsprogs/lib/e2p/percent.o new file mode 100755 index 0000000000000000000000000000000000000000..3b646788b27301f857a9404795e33252fc7bfe8c GIT binary patch literal 1128 zcmbVL&o2W}5T5OpZi{L}L|Q?_frJ+o5{b)8C>I=>xVSWHJwHNQ*=__O969EqkdoXba1^k?p^>)W1sFuC%8lC-wA6!FD5&lvZJS|oS`LmN3?H_m*6hd zFR?y~btCzh^-$N1I#1{B8`hDZLjDx>BtCJ8_l7#-G?^p5A!`a#9IBD7-pO6O@704| zdI4+CtZWS)2)njZtqkU8Sf0(`Tp2m0c3cGQq+iRm4?r(s^pM@rYd)Qc-J~h{(`K;} zhmS@xf)2lyDG4RtNAWcu*CTCKeWWFV)BU@C_4n_KSf6CJ;35L2Fh?9Zz^rPyEGiC& z$^Fv4uq}#NrRoT_xUxE4b4+U&m@W29CbmnPwpkV+Y0Lsvb8N?4M}Jf%KfJ*v>6M4! zLpBk)<9~nxilSRUP!6*ZYKmh9jB literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/pf.c b/jni/e2fsprogs/lib/e2p/pf.c new file mode 100755 index 0000000..81e3bb2 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/pf.c @@ -0,0 +1,79 @@ +/* + * pf.c - Print file attributes on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#include + +#include "e2p.h" + +struct flags_name { + unsigned long flag; + const char *short_name; + const char *long_name; +}; + +static struct flags_name flags_array[] = { + { EXT2_SECRM_FL, "s", "Secure_Deletion" }, + { EXT2_UNRM_FL, "u" , "Undelete" }, + { EXT2_SYNC_FL, "S", "Synchronous_Updates" }, + { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" }, + { EXT2_IMMUTABLE_FL, "i", "Immutable" }, + { EXT2_APPEND_FL, "a", "Append_Only" }, + { EXT2_NODUMP_FL, "d", "No_Dump" }, + { EXT2_NOATIME_FL, "A", "No_Atime" }, + { EXT2_COMPR_FL, "c", "Compression_Requested" }, + { EXT4_ENCRYPT_FL, "E", "Encrypted" }, + { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" }, + { EXT2_INDEX_FL, "I", "Indexed_directory" }, + { EXT2_NOTAIL_FL, "t", "No_Tailmerging" }, + { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" }, + { EXT4_EXTENTS_FL, "e", "Extents" }, + { FS_NOCOW_FL, "C", "No_COW" }, + { FS_DAX_FL, "x", "DAX" }, + { EXT4_CASEFOLD_FL, "F", "Casefold" }, + { EXT4_INLINE_DATA_FL, "N", "Inline_Data" }, + { EXT4_PROJINHERIT_FL, "P", "Project_Hierarchy" }, + { EXT4_VERITY_FL, "V", "Verity" }, + { EXT2_NOCOMPR_FL, "m", "Dont_Compress" }, + { 0, NULL, NULL } +}; + +void print_flags (FILE * f, unsigned long flags, unsigned options) +{ + int long_opt = (options & PFOPT_LONG); + struct flags_name *fp; + int first = 1; + + for (fp = flags_array; fp->flag != 0; fp++) { + if (flags & fp->flag) { + if (long_opt) { + if (first) + first = 0; + else + fputs(", ", f); + fputs(fp->long_name, f); + } else + fputs(fp->short_name, f); + } else { + if (!long_opt) + fputs("-", f); + } + } + if (long_opt && first) + fputs("---", f); +} diff --git a/jni/e2fsprogs/lib/e2p/pf.o b/jni/e2fsprogs/lib/e2p/pf.o new file mode 100755 index 0000000000000000000000000000000000000000..fbe3c8f2afec987ac776ca7e1840e30af6812146 GIT binary patch literal 4008 zcmbuBU1%It6vxkGle#sr4e_HXX_^&^rqV1;TO|)76LwQKrL-X*Z6Bo5arY+Kx;wMZ z&emO9Fj|n{2P9CT2ui9I(kB%Jleb`A`q+Xs{t@Zxb8~e0H15v#>SZ#F#tK@5WVY4O5!KYaXv_5*v1!>wNDT z+0lH^vdzfuY2p~a4)7}JMzM%X%(%Uk|J}{aJ>-`$w)4UmL5_`LY+O#=!o8YbiCMqV z_F=q+t*Idez`cuTjU%;3SSKR58Np{Fcyk1gOw^2Uh)Q%O!XBPE>$Fp-K@Lv2R=QFw!61zW{d`eD7E*4p zjPmk+4T_L<9p9400AvfcGnKfcJX%?$oqpPh4dhuo_8_*vf(!0z|TX*}{OO0x#=0hqL-DWFO{p%)2m7sI39N`J(dK{?}RMKf)ISJWg;jO`J0157e zcd@2toSN|NEeZ0+5dIQ#lY8OfKcey1S)bGR8?2`_{ub+!#?P~!(YW}}YWyPW>l(kr zdO_n=)<0-`hV_!hKVp4b^tnGrmacO#?OV)WHJlMvhU#s2KKdL&@#?Sm?;L_ zU*~{w{`6j^bBXi)PVNiXQ%?FCs+?%J?vso7)0o;6UXA9zLq!5xf)l3sX(;|O|HsH^ zsv~%X+X5$))iz9|^c082`gz8~W|7d7TT-shKhyu75KfxIs5PRgAN1b4Q r6UX5u>lc>7L8JY9z=c%yi6qrr@fU6()8|G67kGX-f69?!=>Go!^>kQO literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/ps.c b/jni/e2fsprogs/lib/e2p/ps.c new file mode 100755 index 0000000..757f8a6 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/ps.c @@ -0,0 +1,32 @@ +/* + * ps.c - Print filesystem state + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/12/22 - Creation + */ + +#include "config.h" +#include + +#include "e2p.h" + +void print_fs_state (FILE * f, unsigned short state) +{ + if (state & EXT2_VALID_FS) + fprintf (f, " clean"); + else + fprintf (f, " not clean"); + if (state & EXT2_ERROR_FS) + fprintf (f, " with errors"); +} diff --git a/jni/e2fsprogs/lib/e2p/ps.o b/jni/e2fsprogs/lib/e2p/ps.o new file mode 100755 index 0000000000000000000000000000000000000000..8ad54a68dfcd36697c4bb0fbb2192a0729bdf6cf GIT binary patch literal 1560 zcmbu9&ubG=5XWbe)>H{?s8)okSs{W4`)Ddi4<5GotDuMoLJx&>-M-jpvRif^+E~#; z{{aIYyy(4m!K?p*2;xPlw|di?J%l>5nQ1pK@#KT#JM(!nvy<8P^78ua8#%`TSq^-F zLr*BcoBW~erKShRFmitjK6N*p?e10R>=a<{#{{%@C%pD9z-6p+VyEEkp}sl?(809V zM}{zp>*b6M&7uA7=E62UtMf5m`{D*o?T6rokrDH0!>qYFj-xmM2%3KQ(0!ugq!EQ~ zbzW7~ymVh;!+CZOoabkq>0%i!AUnm}kX{>i7mH^~?{aTPa?8cCyEqQtzj44n^y#CHrb>KJIC=Q zWS>qmqcvsmi#-g}$d9s3A}>JdNM~0#M(POnnA>%hm`j~W_Lo_uj_?)ccAeAAN3qYo zx1eI(^p(*Y22>EWS~^4nPnuRY@7$kBj2}FP`g+_5O&wCH)sq@xqoJ3o*J}0HZ)sRh zQ~)Y5vGE_Ewp*l?RdtEJ=IE=6DbcELe2S`~TiH;v+}MB0UChs1*@J2&hFb@uXW$t6 z7T(kJe}FW*Ja**V$X@nr5Tkm;Jp5#r%ftT4kj@C9G4|yiM(9(GIp!ko*(eKOmHtJG z$jP?H`I+NSvWiHa=oD^Zpv;Np ZM|Vc@g)bqqpN$A+xl!qZT*|fc{{r&ndmI1& literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/setflags.c b/jni/e2fsprogs/lib/e2p/setflags.c new file mode 100755 index 0000000..0f6a3e0 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/setflags.c @@ -0,0 +1,77 @@ +/* + * setflags.c - Set a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_EXT2_IOCTLS +#include +#endif + +#include "e2p.h" + +/* + * Deal with lame glibc's that define this function without actually + * implementing it. Can you say "attractive nuisance", boys and girls? + * I knew you could! + */ +#ifdef __linux__ +#undef HAVE_CHFLAGS +#endif + +int setflags (int fd, unsigned long flags) +{ +#if HAVE_CHFLAGS + unsigned long bsd_flags = 0; + +#ifdef UF_IMMUTABLE + if (flags & EXT2_IMMUTABLE_FL) + bsd_flags |= UF_IMMUTABLE; +#endif +#ifdef UF_APPEND + if (flags & EXT2_APPEND_FL) + bsd_flags |= UF_APPEND; +#endif +#ifdef UF_NODUMP + if (flags & EXT2_NODUMP_FL) + bsd_flags |= UF_NODUMP; +#endif + + return fchflags (fd, bsd_flags); +#else /* ! HAVE_CHFLAGS */ +#if HAVE_EXT2_IOCTLS + struct stat buf; + int f; + + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + errno = EOPNOTSUPP; + return -1; + } + f = (int) flags; + + return ioctl(fd, EXT2_IOC_SETFLAGS, &f); +#else + errno = EOPNOTSUPP; + return -1; +#endif /* HAVE_EXT2_IOCTLS */ +#endif /* HAVE_CHFLAGS */ +} diff --git a/jni/e2fsprogs/lib/e2p/setflags.o b/jni/e2fsprogs/lib/e2p/setflags.o new file mode 100755 index 0000000000000000000000000000000000000000..d4085276a9623bcf32d91ebf3f070ebe3821f4d8 GIT binary patch literal 1360 zcmbu8zi-n(6vyA$0bCkNhzddqkRmcLz^N%h>UdC~6+%cvATc0WCUr_hVk?eS1%gDS zt{obQ6_hdE*hscY`3t(Rfdo@V7&Ca=TS#H?AOlj_jj~P%fQO`!lZ1ro8_i=so1Ks=%`J&})ENt0cWz%&QvdcWnm$4v$7X^Et1NPw> zOU2W06UUbW3ecqdVD2khi(gHA(LTqty?7c&bMW(rv`kIUkjCKe(X@v;XcKrVAd|ct z@YsaE7?9HwJcT3~=^v~g*+sn6UZX{sWB9FOIQc13_>#{IWN?2eHE}$%Fm@w+CZqsY zq&|iIkzI4oE?V5Tt3L3&TPoR(4~2?v`B1U_Lebi&fN9#E=eV%x=KUgY$MtQ#`t-$Z zbmiZ|pn?6yEO=JQ4y$+`c*Xa8>ow+gCCZs~zC^byWU72IvbYn-S6CbQRl-hta+9@? z3U)nPqaNe0ql=8<(jbL* zwSJYC@QKo)3B|wYAfm^;tN4tVT<*{*jbcawrPim9ofX( P$b_8#4{8b;POJY9Fyn$m literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/setversion.c b/jni/e2fsprogs/lib/e2p/setversion.c new file mode 100755 index 0000000..dd4a3f0 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/setversion.c @@ -0,0 +1,40 @@ +/* + * setversion.c - Set a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif + +#include "e2p.h" + +int setversion (int fd, unsigned long version) +{ +#if HAVE_EXT2_IOCTLS + int ver; + + ver = (int) version; + return ioctl (fd, EXT2_IOC_SETVERSION, &ver); +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/jni/e2fsprogs/lib/e2p/setversion.o b/jni/e2fsprogs/lib/e2p/setversion.o new file mode 100755 index 0000000000000000000000000000000000000000..4edca4d5b98f225da19a65e727e01965d3c1a0d1 GIT binary patch literal 1152 zcmbu7JxC)_5P)Zs=qUyj;Y9E!DMT#vk$511yJ8jp3b6>-*o4ix{$PG^^EjdruDD)^ zSlB3*+S#dHAdRh!*xbQgWou~>bY?Se-E3mzz(Rf0{MS{2KWv%TeK|2`H2E!2;M>fFx2kE))*iv}7 z_bhN4S`SBJOWpAI563@J^B4%h^J}Yk5ImRUgp8w``KH4|P0OSm(%!_sBI)z2@0=f5 z6oio)|Mx)jJuXrPMPpYFHt9r%PkoosU P1dlYKRGj(!jr{d*Q7T}w literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/e2p/uuid.c b/jni/e2fsprogs/lib/e2p/uuid.c new file mode 100755 index 0000000..a102092 --- /dev/null +++ b/jni/e2fsprogs/lib/e2p/uuid.c @@ -0,0 +1,85 @@ +/* + * uuid.c -- utility routines for manipulating UUID's. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "e2p.h" + +struct uuid { + __u32 time_low; + __u16 time_mid; + __u16 time_hi_and_version; + __u16 clock_seq; + __u8 node[6]; +}; + +/* Returns 1 if the uuid is the NULL uuid */ +int e2p_is_null_uuid(void *uu) +{ + __u8 *cp; + int i; + + for (i=0, cp = uu; i < 16; i++) + if (*cp++) + return 0; + return 1; +} + +static void e2p_unpack_uuid(void *in, struct uuid *uu) +{ + __u8 *ptr = in; + __u32 tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; + + memcpy(uu->node, ptr, 6); +} + +void e2p_uuid_to_str(void *uu, char *out) +{ + struct uuid uuid; + + e2p_unpack_uuid(uu, &uuid); + sprintf(out, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); +} + +const char *e2p_uuid2str(void *uu) +{ + static char buf[80]; + + if (e2p_is_null_uuid(uu)) + return ""; + e2p_uuid_to_str(uu, buf); + return buf; +} + diff --git a/jni/e2fsprogs/lib/e2p/uuid.o b/jni/e2fsprogs/lib/e2p/uuid.o new file mode 100755 index 0000000000000000000000000000000000000000..27969f76b51e52e258c0122af6d5cac6075cb0a9 GIT binary patch literal 2600 zcmbtUO>7%g5T5nc#7^9_p+6K#aUvyBlr}5djl?1$w6v7wfDo#J)I+tl<7}D;XC3Sf zS`!eF%%KMku@s43fP^BNKslhIwks}`a_a?ENQg@-S8#B80>QyPSY~EDZ?oCtLOa&( z%zX3r-ps5&Irr9^AxQ#365NJuO`rfXUE8weiW>BwXS)LTYdz3xcY#yy(VF!xXkz@~ zdY9%zUWfM|OEAHDGa82K7TP0{_R1B2F~Zw%aH7b)m@xEV4(G3S`?+CQx==?u*=ljk z!CKY3a{9M+MY`Ww3~#i~O4Zd$ys;+78>^LcV-3&p0>H|uoNjzA>vyi5)$MO`y1ib} z?eNEuL*G_(_4+kk{o$sr-q_UD?|;?R@BYx$^?!7AONQ#G1kR}_I4AqS8F?O@;Q_by z@&G^;ue{P)Jhy?h`3!jP1JHbgcdsAl+#Bz_ke&NsBt!g4-J#uREuPtEZ+7-)D52V;Ly0l(m9mEt zDbhMZki)BH!8Be2$mO%<<^B(hVrjNu_9s;(si;_t=wOF|^x*}NK6*(y9*e_a#Evm; z5r3n%Ka}roc5}@EBvnEXGCtB-?DpMSg)_ z@%j6^@tM!xkFPLJb@%(~zQ}SIadvT$u>damcPW62eX#?$=pQIWBcD|)!?r-l73Ss) z6NSlA35?WydSPL9Ds2_gC9CM^DN+=(U>VB!x8EHtS=rosJB-TY!ZeiTi?gOR&FPJq z^mH*hXSjZ|rL?(_&%4Pxf#y8s=;%~Y$$^4Jtn4K6@*MHODP@dar|FfVR}xbfrm|L+ zT$88{+KTwt`L0jGKF1(=kHD+ERKEmlIF=nmZiM-FkQ_96A^qeZBI>~}kzxtc@bOcI zKf&J_>_$$h#10)}{Ac8pBgML4|8iYb0L;bt1wVo~^q%S(%H} literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/et/com_err.c b/jni/e2fsprogs/lib/et/com_err.c new file mode 100755 index 0000000..7294c6d --- /dev/null +++ b/jni/e2fsprogs/lib/et/com_err.c @@ -0,0 +1,105 @@ +/* + * Copyright 1987, 1988 by MIT Student Information Processing Board. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "config.h" +#include +#ifdef HAVE_TERMIOS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include "com_err.h" +#include "error_table.h" +#include "internal.h" + +static void +default_com_err_proc (const char *whoami, errcode_t code, const + char *fmt, va_list args) + COM_ERR_ATTR((format(printf, 3, 0))); + +static void +default_com_err_proc (const char *whoami, errcode_t code, const + char *fmt, va_list args) +{ + int do_cr = 1, fd = fileno(stderr); + + if (whoami) { + fputs(whoami, stderr); + fputs(": ", stderr); + } + if (code) { + fputs(error_message(code), stderr); + fputs(" ", stderr); + } + if (fmt) { + vfprintf (stderr, fmt, args); + } + if (!isatty(fd)) + do_cr = 0; +#ifdef HAVE_TERMIOS_H + else { + struct termios t; + + if ((tcgetattr(fd, &t)) == 0 && + (t.c_oflag & OPOST) && (t.c_oflag & ONLCR)) + do_cr = 0; + } +#endif + if (do_cr) + fputc('\r', stderr); + fputc('\n', stderr); + fflush(stderr); +} + +typedef void (*errf) (const char *, errcode_t, const char *, va_list) + COM_ERR_ATTR((format(printf, 3, 0))); + +errf com_err_hook = default_com_err_proc; + +void com_err_va (const char *whoami, errcode_t code, const char *fmt, + va_list args) +{ + (*com_err_hook) (whoami, code, fmt, args); +} + +void com_err (const char *whoami, + errcode_t code, + const char *fmt, ...) +{ + va_list pvar; + + if (!com_err_hook) + com_err_hook = default_com_err_proc; + va_start(pvar, fmt); + com_err_va (whoami, code, fmt, pvar); + va_end(pvar); +} + +errf set_com_err_hook(errf new_proc) +{ + errf x = com_err_hook; + + if (new_proc) + com_err_hook = new_proc; + else + com_err_hook = default_com_err_proc; + + return x; +} + +errf reset_com_err_hook(void) { + errf x = com_err_hook; + com_err_hook = default_com_err_proc; + return x; +} diff --git a/jni/e2fsprogs/lib/et/com_err.o b/jni/e2fsprogs/lib/et/com_err.o new file mode 100755 index 0000000000000000000000000000000000000000..26ed6c3bc633ef2efa558e4551f0f76a1a327f63 GIT binary patch literal 4112 zcmbtWUuaup6hAk&U9&Z&Sv%dv)+V?}XY}Fz|O6kA{XBN|&wJdE)ayz

op}0S!n}3?2P;jyc$_jgM4|}i*(+8Dooi2qvxVIZvsOQ|AFa7-1iw_>S z_dDP3{6FW*ck}*hhhO(-8VJ(h8m#XG3J`c=osT+f6nv<;cEht=o7qyVS)Tk#2UH7I z(4NSAxb+lXE1h*mdaetR)y2%mYBfwmO6+o$Er z+j9|UUW$}=;mWZK*3lC2Ie_OWm+M$xn^VKl(w(pCIYza*tg=7)Z3W;3(j)#X1RS1h z2y<$=akS*s-~jQW2CBcH<%UE|fmd4UwMAK0X<6@SZRX7)&Lh91$8N9nX*idrVolfb ztGa$gp3929`3lWS_@uc||L3ufm$3E_*1n=czO3gWA*#IvYu8@6U7P7IqTjlIy&3(t z7ayI2YRziOFRZ{a<#vBhF7j6}7x@$Wbq{;D(vgeYZOcXOwB{T?UsyZs&-I=5XVwn; zQ+ljeYGvuUhL~Ctv2DRca@43U8opy1LXL;{D;(8~>TCbC4tYLlg`nf{|{gXqNEp3_l{peh@TALXvuIbI(OIR*r zZE|iE9jX++0`>DtyvURCYiZ09@-j|&m-T3M4fCtd36|I8=&uo{US}Eo3SG>tK`(_M z1dvF@Cys|s8ky`^dLq<&Fx(qHSXT+KrgnM=v@>1WE?*FO5Zl4{93}$&{zYxT*BQ9z zxzMENG+z+6e)!{e6m^rBb&t{7?;jMZo&jHQkQK>iisVQS=+*CE@*MVchR!!#+;qX~ zx#bJu-VeW_*KH`CBORo7=+*BJc!vE>PK&fhdWK$zkNAmkr>{`d1P|9X($K;47))_J z67JMbTGR&#ryY?~3r5(8blCJ5eBVJH$L~5go(6@e#{f8ag{XcpJ6ZIy3%=V0|G))L zx!}}>jp9D-f`8(Mc{w(i=UK>pEE9g&PsT@ zXPwc#;GnDA92wibr z4;WYT{F`w#Pahv7RX@PEs=u3YHO~;^YM$LL{(D^f_q*s1xabcvuIBSL<7z&lRrJ?e z?kC;nM9m65P=_1%9LkBr{UG#h#>MYi;Nrf#S~qL>5%(pGW#guK3c?v96%U)nvO)_%Oi`(w$@N?Xn z|Fv90YaaQ({CN3trFqDtY=Q1_!sKrQ=||~>lv13l|4_WBLs%3anab>Njt%JBM(2+7 ziNycHUy!HxN*GvVK +#include +#include +#include "com_err.h" +#include "error_table.h" + +const char * +com_right(struct et_list *list, long code) +{ + struct et_list *p; + for (p = list; p; p = p->next) { + if (code >= p->table->base && code < p->table->base + p->table->n_msgs) + return p->table->msgs[code - p->table->base]; + } + return NULL; +} + +const char * +com_right_r(struct et_list *list, long code, char *str, size_t len) +{ + struct et_list *p; + for (p = list; p; p = p->next) { + if ((code >= p->table->base) && + (code < p->table->base + p->table->n_msgs)) { + strncpy(str, p->table->msgs[code - p->table->base], len); + str[len-1] = '\0'; + return str; + } + } + return NULL; +} + +struct foobar { + struct et_list etl; + struct error_table tab; +}; + +/* + * We provide this routine for compatibility with Heimdall generated + * foo_err.c files, but we don't use this ourselves for foo_err.c + * files generated by our compile_et. This is so our foo_err.c + * files can be used with older com_err libraries without running + * afoul of dependencies. + */ +void +initialize_error_table_r(struct et_list **list, + const char **messages, + int num_errors, + long base) +{ + struct et_list *et, **end; + struct error_table *tab; + struct foobar *f; + + for (end = list, et = *list; et; end = &et->next, et = et->next) + if (et->table->msgs == messages) + return; + f = malloc(sizeof(*f)); + if (f == NULL) + return; + et = &f->etl; + et->table = tab = &f->tab; + tab->msgs = messages; + tab->n_msgs = num_errors; + tab->base = base; + et->next = NULL; + *end = et; +} + + +void +free_error_table(struct et_list *et) +{ + while(et){ + struct et_list *p = et; + et = et->next; + free(p); + } +} diff --git a/jni/e2fsprogs/lib/et/com_right.o b/jni/e2fsprogs/lib/et/com_right.o new file mode 100755 index 0000000000000000000000000000000000000000..8217af37d57c7550584576c39e92c60642dad70e GIT binary patch literal 2272 zcmbVMO=uKJ6n-^5VZ`B^%R7)LM? z4*^dBkM0s>4;c@8Q8Au2klWteg*~Z^dg;-FdXeeFFn+J5YNqXsmo4aiRp0yGtM|RC z?wdcH_%S8~=^^MTbypfCTH4T^TXJeqKbWm~dR`l(;B_Ab{-7231_g-U<{MV95U0m- z-e(1MtVa{=Cn@^h4;u7SFW)=xj)Ql6^W3vhF>r^u4~62wmxM1VkPkUKT+S;7-X~}C z4SypAN$js{U@q76qSe~bf{*dqMk_$wi>pTVzm_4MH!DW9xkigiMyBx^oHx+(wvU2k zBijh;SxzWDh>z+y5LY!ue4QFYdj5{Jxi#6ZkS4@-_)3$2rZ>=vmfz+6vhL9YeL`RE zWCR^yYxITKo zR`yTz%}0GBv2G9aSya&{J|~;ny7uY*gU@+5PUrc6nkX^%59_JnT=_pgBSf2&71vLbxUpC4N@ZvpFld!ymEV);q1Z~AhA}*(YG!2Hk5+JL7xIIL`_b zcqn@d(_Z{5z$ITvkbMJo;~V^Gm2Vd;zQN8ISMiJwbWoy?Av_hrcdK~<{BZXUNAOj( zJ{!TczS~h;C!6uyQtsDTGF_)&o1SycBQsYn7M+quuvs^Mc{()9x|A>Fy}Vt>Uw5*O z>z3WDXJ05daG0gC=a|P%{(Nx8vvXHeN@qHI$+e3PU2>hTA|yaXyHF_Sx?7n!GEoz9 z!p;`i4qr6CNq=S8Z*YCH`G#$cqDoBhWCTV znC7c6vef=l3gElLN2TwO{y*@)g7=TMV^ZzA9lr3;^=r%bSI@(|Gm*NrFUqx5yuL=7 tcV5LWYd~3DzlQmq_R_zg^q&vKagTMp)_)IJbZ-txsz#5ig4y(n{{oXarFZ}U literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/et/error_message.c b/jni/e2fsprogs/lib/et/error_message.c new file mode 100755 index 0000000..8b9474f --- /dev/null +++ b/jni/e2fsprogs/lib/et/error_message.c @@ -0,0 +1,355 @@ +/* + * $Header$ + * $Source$ + * $Locker$ + * + * Copyright 1987 by the Student Information Processing Board + * of the Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "config.h" +#include +#include +#include +#include +#ifdef HAVE_SYS_PRCTL_H +#include +#else +#define PR_GET_DUMPABLE 3 +#endif +#if (!defined(HAVE_PRCTL) && defined(linux)) +#include +#endif +#ifdef HAVE_SEMAPHORE_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_FCNTL +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#include "com_err.h" +#include "error_table.h" +#include "internal.h" + +#ifdef TLS +#define THREAD_LOCAL static TLS +#else +#define THREAD_LOCAL static +#endif + +THREAD_LOCAL char buffer[25]; + +struct et_list * _et_list = (struct et_list *) NULL; +struct et_list * _et_dynamic_list = (struct et_list *) NULL; + +#ifdef __GNUC__ +#define COMERR_ATTR(x) __attribute__(x) +#else +#define COMERR_ATTR(x) +#endif + +#ifdef HAVE_SEM_INIT +static sem_t _et_lock; +static int _et_lock_initialized; + +static void COMERR_ATTR((constructor)) setup_et_lock(void) +{ + sem_init(&_et_lock, 0, 1); + _et_lock_initialized = 1; +} + +static void COMERR_ATTR((destructor)) fini_et_lock(void) +{ + sem_destroy(&_et_lock); + _et_lock_initialized = 0; +} +#endif + + +int et_list_lock(void) +{ +#ifdef HAVE_SEM_INIT + if (!_et_lock_initialized) + setup_et_lock(); + return sem_wait(&_et_lock); +#else + return 0; +#endif +} + +int et_list_unlock(void) +{ +#ifdef HAVE_SEM_INIT + if (_et_lock_initialized) + return sem_post(&_et_lock); +#endif + return 0; +} + +typedef char *(*gettextf) (const char *); + +static gettextf com_err_gettext = NULL; + +gettextf set_com_err_gettext(gettextf new_proc) +{ + gettextf x = com_err_gettext; + + com_err_gettext = new_proc; + + return x; +} + +#ifdef __GNU__ +#define SYS_ERR_BASE 0x40000000 +#else +#define SYS_ERR_BASE 0 +#endif + +const char * error_message (errcode_t code) +{ + int offset; + struct et_list *et; + errcode_t table_num; + int started = 0; + char *cp; + + offset = (int) (code & ((1<next) { + if ((et->table->base & 0xffffffL) == (table_num & 0xffffffL)) { + /* This is the right table */ + if (et->table->n_msgs <= offset) { + break; + } else { + const char *msg = et->table->msgs[offset]; + et_list_unlock(); + if (com_err_gettext) + return (*com_err_gettext)(msg); + else + return msg; + } + } + } + for (et = _et_dynamic_list; et; et = et->next) { + if ((et->table->base & 0xffffffL) == (table_num & 0xffffffL)) { + /* This is the right table */ + if (et->table->n_msgs <= offset) { + break; + } else { + const char *msg = et->table->msgs[offset]; + et_list_unlock(); + if (com_err_gettext) + return (*com_err_gettext)(msg); + else + return msg; + } + } + } + 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); +} + +/* + * This routine will only return a value if the we are not running as + * a privileged process. + */ +static char *safe_getenv(const char *arg) +{ +#if !defined(_WIN32) + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#endif +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if defined(HAVE_SECURE_GETENV) + return secure_getenv(arg); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +#define DEBUG_INIT 0x8000 +#define DEBUG_ADDREMOVE 0x0001 + +static int debug_mask = 0; +static FILE *debug_f = 0; + +static void init_debug(void) +{ + char *dstr, *fn, *tmp; + + if (debug_mask & DEBUG_INIT) + return; + + dstr = getenv("COMERR_DEBUG"); + if (dstr) { + debug_mask = strtoul(dstr, &tmp, 0); + if (*tmp || errno) + debug_mask = 0; + } + + debug_mask |= DEBUG_INIT; + if (debug_mask == DEBUG_INIT) + return; + + fn = safe_getenv("COMERR_DEBUG_FILE"); + if (fn) + debug_f = fopen(fn, "a"); + if (!debug_f) + debug_f = fopen("/dev/tty", "a"); + if (debug_f) { +#ifdef HAVE_FCNTL + int fd = fileno(debug_f); + + if (fd >= 0) { + int flags = fcntl(fd, F_GETFD); + + if (flags >= 0) + flags = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + if (flags < 0) { + fprintf(debug_f, "Couldn't set FD_CLOEXEC " + "on debug FILE: %s\n", strerror(errno)); + fclose(debug_f); + debug_f = NULL; + debug_mask = DEBUG_INIT; + } + } +#endif + } else + debug_mask = DEBUG_INIT; +} + +/* + * New interface provided by krb5's com_err library + */ +errcode_t add_error_table(const struct error_table * et) +{ + struct et_list *el; + + if (!(el = (struct et_list *) malloc(sizeof(struct et_list)))) + return ENOMEM; + + if (et_list_lock() != 0) { + free(el); + return errno; + } + + el->table = et; + el->next = _et_dynamic_list; + _et_dynamic_list = el; + + init_debug(); + if (debug_mask & DEBUG_ADDREMOVE) + fprintf(debug_f, "add_error_table: %s (0x%p)\n", + error_table_name(et->base), + (const void *) et); + + et_list_unlock(); + return 0; +} + +/* + * New interface provided by krb5's com_err library + */ +errcode_t remove_error_table(const struct error_table * et) +{ + struct et_list *el; + struct et_list *el2 = 0; + + if (et_list_lock() != 0) + return ENOENT; + + el = _et_dynamic_list; + init_debug(); + while (el) { + if (el->table->base == et->base) { + if (el2) /* Not the beginning of the list */ + el2->next = el->next; + else + _et_dynamic_list = el->next; + (void) free(el); + if (debug_mask & DEBUG_ADDREMOVE) + fprintf(debug_f, + "remove_error_table: %s (0x%p)\n", + error_table_name(et->base), + (const void *) et); + et_list_unlock(); + return 0; + } + el2 = el; + el = el->next; + } + if (debug_mask & DEBUG_ADDREMOVE) + fprintf(debug_f, "remove_error_table FAILED: %s (0x%p)\n", + error_table_name(et->base), + (const void *) et); + et_list_unlock(); + return ENOENT; +} + +/* + * Variant of the interface provided by Heimdal's com_err library + */ +void +add_to_error_table(struct et_list *new_table) +{ + add_error_table(new_table->table); +} diff --git a/jni/e2fsprogs/lib/et/error_message.o b/jni/e2fsprogs/lib/et/error_message.o new file mode 100755 index 0000000000000000000000000000000000000000..89db08517dd98225455ffd321d3bffbf90a1c3a6 GIT binary patch literal 8968 zcmchbU2I%O702iL+U+JW`RE5pn-AZBtJfcPdLa^xQlTK_!EN0t4+U*Lgf*_qW9^-}zd3W}oS8G{Uf&lxx^`7Lj*{Z2w^ij%s8SKH(vIq8RMnDX!L4h0 z$Blg?^?aLpuW+|2Em3N$!HJfNt|}Gpj+Po6RVujA67`Qme*T2>-rTX8$+O}McsGUdmG z6~tFWOF5-ZgX{K*y4k-_`vCnQ6CrydWDkBhcf%~?a_;l9qcy=8v?DdtkKc3ASFX`K zjZ|aav#$D@$m{-9(fs7O=V8;qgbMl|WPQ4y=Fm1D9hfaHQ>BIT2lI(Ng=Nu_avuL^ zg6#b*=_t~Dj@oZiyF4e`JTpJPTE_j~{h&SlmwwP5iyx!#gYMzScSHPuF8D|Fn4@T{ zQsbU_{G-n4FMLR0^#ke~+ei#@*z*Hb!MZIbA0c^)mr{Y`Ab-hKZz9&vMs4Z}n^Wtc zI6^<-ht_v{QK@aXFS8moUL=`W+J_wWf806rONkAN(QB`dbq{>;&2+(C(sYgDH}XQ` zt4rrz{2(&te-Lq&E{mL1tFDvor%2BY($ndv?Kv8^gyfn?u5r%)Q6tHHzjma%@r9*p z5nnh1#fPK$NR3*B^Pz2_`}0aYhPJk&Q5|~9wBy3d-G97rY7skn{zE%@v>jh|7TQss zkNmhsel(FE*U66t@&orc!)S-?5#j+lCQig==Zj4yi|?6 zulJ5(ZbAiTebgCwALAQoJo+d`^xhN@cetltM2+Mjx8@txt~Q9cy)|SB+n$wZ$CBt7I3}IWKW4v4H-Fiso}1 zx0tJr!55+l$bsM()j&va}BmdG|r!k)LE%vYMH}um! z=re;h>BHLU+)TD;pZ=YE!(EkpsAxQVD6A&mR!8##u4(m1h+4OnQF)r`iuXTcf;Ade12y@tm2Y z{b)oRC)IfQsE8qY!adyN?FVd-wH3F!iZAHkUj_OC!3Yr*??=UJe&Lo6&f3$!k; zTQLE9p$BJS9nXhnpv()uE>xalcg{n5bH_Yx_&l{tA#Z!Sxd2O}k`#NjauY9fQ=hf~lx3+Fy=W_MuKWVuUmMfrcU)~~eRp)E# zS^_aGmt(oxv{57%6*>2+Q(G6U=$mG_9bC+H> zV!xmt^gtg9wg=?~{lGokP!av8q32x&6X@jPmPZRw>WsEuv{v}rnpf^5j+0`oaJXQCQ{ZhoQQ_SUFYQ!|;Wt|&%;BL|n-pcnnuBm;1ej>|V zy4p(DRmS>={vFKaUTT=Xm>zmxSd@P~L_W%Pw(}MgNDk#YA$pz<;lng$F?+6r@K1#B zABOPnh47IO{*w^?_Yl5`*TLgZ(fNR6A7p-#7rucQN^i(Id?SRXL-^4U{wmF}*m}x2 zyqCsNo-WJKGhCMq78iSMKEm>AN&bFrqk6;Os|=pwHeU2TX>gnilvaz^(>)6G-xDuoGuc%CpSxxA;Ehuv20WV}_X9c4nE| zb`CSQ?L5xhwsVX*=9Om@<~?a}`j%5JZ!j0X=(R!@`u|K9@k{ur5Iv`v+kQVCp(eHgwI&=9?yM|xtt^6Mdo&#%o=*kXU%Qq5)b7Z%ZCkm z>Ud665rdm~tcAJl*EZ(1U+soG?7@2&N+)x%M|c-=*yCx*;F2)-MuQI-`pxwmW^UW_ zvZ2S^-;*JFCPMU_3Xy*+M1CrSp9$g9hJLKux7p_z=CW?WZ(8zWEPuD4ZsxG_)4T?#5(cj~_*e+fF}K(ME#|ggQ-&Th{@*dU z`CfFv(2xDX`x(kKbJ;K9Glm{BpM1>Rwx?joKNP6e*J6nLP3GdS6sQ z{uzU}@W1r%SM~(mod)*|d3i^wA$fjf)4eS$Bb=vG?G|6j_s?3qmG57&xcr|j|2K(# z`R+1f$;4U+$}M2~!TQJHMIcj&0f#QXi&en0Cck0|=?7wb(8;)5el)*sHQ z=Cq%PH|u7Mx)TGLtU{yjXfi%H&>Mhe8a3!Avs!7K24#CP8P$vnO`|_=s-DCB{eD`- zpgoyV{R0UfRcgpjLMTfgA60*EGMi9C>0Y|(PmZy{c;=wud1Hr@iBxapR^K!yQ(3?H z$*=6$l*z`ab09fD#^H0N>K{rEB(wdjsh_kbQW>8;@(;xN)A2!H86RI`8#M<9&S-~I-dN7_K2NsTN?p4iLi+B&!M+Z^Y z_ccF;%QjrL;<5#o&E!U^FP@DwClawPn3)z2u--9?7B@I&xJ>NksZt2R+5 z7(ZspqET-3S)bJSb-OIrKrOInnFNgpAEez#MpTy359d+Nojl)qnb|(%cwXo?i;Nfc z95ujP%P<*l=6;N^{Xa_pYzsP#BIEyHFf?Vn)K4?BH#3RkPsRMUf_oV!^?8G#U&>27 zUhbuqadJOT4KOp;p>LGOcUlAN_4^0OF1CMr`C)w#%BW!fuq85H_HTmp+jB#H8Uv`b N^1i?fym#2+{|P5QrK$h` literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/et/et_name.c b/jni/e2fsprogs/lib/et/et_name.c new file mode 100755 index 0000000..d9a3e87 --- /dev/null +++ b/jni/e2fsprogs/lib/et/et_name.c @@ -0,0 +1,43 @@ +/* + * Copyright 1987 by MIT Student Information Processing Board + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "config.h" +#include "com_err.h" +#include "error_table.h" +#include "internal.h" + +static const char char_set[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; + +static char buf[6]; + +const char * error_table_name(errcode_t num) +{ + int ch; + int i; + char *p; + + /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */ + p = buf; + num >>= ERRCODE_RANGE; + /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */ + num &= 077777777L; + /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */ + for (i = 4; i >= 0; i--) { + ch = (int)((num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1)); + if (ch != 0) + *p++ = char_set[ch-1]; + } + *p = '\0'; + return(buf); +} diff --git a/jni/e2fsprogs/lib/et/et_name.o b/jni/e2fsprogs/lib/et/et_name.o new file mode 100755 index 0000000000000000000000000000000000000000..5bbfd817e5be5736693f3cf2beecd61de8855e0a GIT binary patch literal 1736 zcmbu8&rcIk5XWaJl@$pX5i!94i5$el4F!~vcvzKRDx#nWl9;+J%Ma-f*j=y?emMGd&@^Dv z;2o6Sm;&gPrPvgq2}e*_T!*jU>!6?mZ0Z{1{3&<7R4Lze9W(h zJk~$%*PHo`(C;1*qkae9w{gGyNp+LnzWrKnz???N`;BJ)jRxI9hwK9G7D$JklVqt&uGv~T0TQZJ)QZZSZwrB*Mj@l{w6*->^=7}6#I7R@|C{+fx)4x z*RBuW7`b_CbnNz>@w*d~_ol3PV%naWotuBSkW8gBi%X8{Ew4PvuC8@NI=i~hU+9VU z#sCsYD?Qt~Vmt19Cfyo|8WAHZW(06ldTnhCw8za_Q%wt;L`DzUXIlDdTPr@)QgonA z;7%p{D()u;LB$^YQjop83%Q1s*bd2{LGUnRF#kmWp@5$8h6qY^n3E4dsSfjX5$xqp z1?MhU4X`RgylKS-@cmfe_lo%;V`V*Fe6U)L%x_S*CpqakmrypK5AwGGeX#!ffIi4i zNgl@fWw&5BcG5CDJL`dw$fQzs+JnTL<-}YYN!)e8NM}6T7#tZt=XzFR0piOuu$yJi z#bz8UWrOWF87Jmh@uVF~3*ZTFB*1Vz2RG2Kri6Dg)0SsJ+qBV5OBXGjv_zmSYjnsy z|JPYqAhb`BMG3c*JseA!(d>u?XGj8*7Bs%+-8cFc%8hb~ndKP1$l=omPgac&A--Gw z4x1%Ye?z5gRP9Uce+l!6$>T8EHO@B~NU!G8|CE?|AAM4I;(&avb6VyrGMHk4vZ3OO wGGFcgffTBJ@%*@K4+i_qe^L&V=S=gbT+U}ck4!xq5p2ryqtcV3S*iJd0W2P+O8@`> literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/et/init_et.c b/jni/e2fsprogs/lib/et/init_et.c new file mode 100755 index 0000000..772660d --- /dev/null +++ b/jni/e2fsprogs/lib/et/init_et.c @@ -0,0 +1,53 @@ +/* + * $Header$ + * $Source$ + * $Locker$ + * + * Copyright 1986, 1987, 1988 by MIT Information Systems and + * the MIT Student Information Processing Board. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose is hereby granted, provided that + * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. M.I.T. and the + * M.I.T. S.I.P.B. make no representations about the suitability of + * this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "config.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include "com_err.h" +#include "error_table.h" + +struct foobar { + struct et_list etl; + struct error_table et; +}; + +extern struct et_list * _et_dynamic_list; + +int init_error_table(const char * const *msgs, long base, int count) +{ + struct foobar * new_et; + + if (!base || !count || !msgs) + return 0; + + new_et = (struct foobar *) malloc(sizeof(struct foobar)); + if (!new_et) + return ENOMEM; /* oops */ + new_et->etl.table = &new_et->et; + new_et->et.msgs = msgs; + new_et->et.base = base; + new_et->et.n_msgs= count; + + new_et->etl.next = _et_dynamic_list; + _et_dynamic_list = &new_et->etl; + return 0; +} diff --git a/jni/e2fsprogs/lib/et/init_et.o b/jni/e2fsprogs/lib/et/init_et.o new file mode 100755 index 0000000000000000000000000000000000000000..2e41255f0581d4a40e3a17009d65e502fba1ce41 GIT binary patch literal 1384 zcmbW0&ubGw6vy9W6O%w}gNPAoO@vb7p^FjGfR_=i<{%yldXr_{uI=LffX$+)Ks|^TMLk7t-nxfS-%MuGO|rc>u=~FAnfKnjH?#X>`R4TmAs`2V zcW^M16rijeXv!spEPC!M!1J>N{qgyOaWyi`Uq;LJW;L{WT4%6zbr<_+eo(Y8VA#65R(fdq zb<1;0m8x1%t5{r~_Y6QDuK?LTP3Ce%C?h*5_(x{1&CptIKL0xLDw*iyinKNZ-@gfm zL(E;|N%*@Tx2!;73P0s!ns0NSobrFf$&o3(jO17(Kd&Fz9eiZ3(V*NRye6FH@G#Sn zfR{pFLY|56meAD+eoF8Z^0Dqz-?Vi#FgF6w%s^Y+balrvG~22NpcdsRH^|uJO;X_{?@vten;IW1mN7bxfr|a* zJ+ixENZy(JzUPs#9Fu2}7lod{wdfF-$1uK#k7QB5#W)z_ds#41?kENR%Y4ug846jy l#1~P-_1_Q)WuGjLow1CU+(S0GHzHUU`+sE<9BdjF{}0vLoKXM( literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/alloc.c b/jni/e2fsprogs/lib/ext2fs/alloc.c new file mode 100755 index 0000000..3fd9216 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/alloc.c @@ -0,0 +1,554 @@ +/* + * alloc.c --- allocate new inodes, blocks for ext2fs + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +#undef DEBUG + +#ifdef DEBUG +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) +#else +# define dbg_printf(f, a...) +#endif + +/* + * Clear the uninit block bitmap flag if necessary + */ +void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group) +{ + if (group >= fs->group_desc_count || + !ext2fs_has_group_desc_csum(fs) || + !(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) + return; + + /* uninit block bitmaps are now initialized in read_bitmaps() */ + + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, group); + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); +} + +/* + * Check for uninit inode bitmaps and deal with them appropriately + */ +static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map, + dgrp_t group) +{ + ext2_ino_t i, ino; + + if (group >= fs->group_desc_count || + !ext2fs_has_group_desc_csum(fs) || + !(ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) + return; + + ino = (group * fs->super->s_inodes_per_group) + 1; + for (i=0; i < fs->super->s_inodes_per_group; i++, ino++) + ext2fs_fast_unmark_inode_bitmap2(map, ino); + + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); + /* Mimics what the kernel does */ + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, group); + ext2fs_mark_ib_dirty(fs); + ext2fs_mark_super_dirty(fs); +} + +/* + * Right now, just search forward from the parent directory's block + * group to find the next free inode. + * + * Should have a special policy for directories. + */ +errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, + int mode EXT2FS_ATTR((unused)), + ext2fs_inode_bitmap map, ext2_ino_t *ret) +{ + ext2_ino_t start_inode = 0; + ext2_ino_t i, ino_in_group, upto, first_zero; + errcode_t retval; + dgrp_t group; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!map) + map = fs->inode_map; + if (!map) + return EXT2_ET_NO_INODE_BITMAP; + + if (dir > 0) { + group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super); + start_inode = (group * EXT2_INODES_PER_GROUP(fs->super)) + 1; + } + if (start_inode < EXT2_FIRST_INODE(fs->super)) + start_inode = EXT2_FIRST_INODE(fs->super); + if (start_inode > fs->super->s_inodes_count) + return EXT2_ET_INODE_ALLOC_FAIL; + i = start_inode; + do { + ino_in_group = (i - 1) % EXT2_INODES_PER_GROUP(fs->super); + group = (i - 1) / EXT2_INODES_PER_GROUP(fs->super); + + check_inode_uninit(fs, map, group); + upto = i + (EXT2_INODES_PER_GROUP(fs->super) - ino_in_group); + if (i < start_inode && upto >= start_inode) + upto = start_inode - 1; + if (upto > fs->super->s_inodes_count) + upto = fs->super->s_inodes_count; + + retval = ext2fs_find_first_zero_inode_bitmap2(map, i, upto, + &first_zero); + if (retval == 0) { + i = first_zero; + break; + } + if (retval != ENOENT) + return EXT2_ET_INODE_ALLOC_FAIL; + i = upto + 1; + if (i > fs->super->s_inodes_count) + i = EXT2_FIRST_INODE(fs->super); + } while (i != start_inode); + + if (ext2fs_test_inode_bitmap2(map, i)) + return EXT2_ET_INODE_ALLOC_FAIL; + *ret = i; + return 0; +} + +/* + * Stupid algorithm --- we now just search forward starting from the + * goal. Should put in a smarter one someday.... + */ +errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal, + ext2fs_block_bitmap map, blk64_t *ret, + struct blk_alloc_ctx *ctx) +{ + errcode_t retval; + blk64_t b = 0; + errcode_t (*gab)(ext2_filsys fs, blk64_t goal, blk64_t *ret); + errcode_t (*gab2)(ext2_filsys, blk64_t, blk64_t *, + struct blk_alloc_ctx *); + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!map) { + /* + * In case there are clients out there whose get_alloc_block + * handlers call ext2fs_new_block2 with a NULL block map, + * temporarily swap out the function pointer so that we don't + * end up in an infinite loop. + */ + if (fs->get_alloc_block2) { + gab2 = fs->get_alloc_block2; + fs->get_alloc_block2 = NULL; + retval = gab2(fs, goal, &b, ctx); + fs->get_alloc_block2 = gab2; + goto allocated; + } else if (fs->get_alloc_block) { + gab = fs->get_alloc_block; + fs->get_alloc_block = NULL; + retval = gab(fs, goal, &b); + fs->get_alloc_block = gab; + goto allocated; + } + } + if (!map) + map = fs->block_map; + if (!map) + return EXT2_ET_NO_BLOCK_BITMAP; + if (!goal || (goal >= ext2fs_blocks_count(fs->super))) + goal = fs->super->s_first_data_block; + goal &= ~EXT2FS_CLUSTER_MASK(fs); + + retval = ext2fs_find_first_zero_block_bitmap2(map, + goal, ext2fs_blocks_count(fs->super) - 1, &b); + if ((retval == ENOENT) && (goal != fs->super->s_first_data_block)) + retval = ext2fs_find_first_zero_block_bitmap2(map, + fs->super->s_first_data_block, goal - 1, &b); +allocated: + if (retval == ENOENT) + return EXT2_ET_BLOCK_ALLOC_FAIL; + if (retval) + return retval; + + ext2fs_clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b)); + *ret = b; + return 0; +} + +errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal, + ext2fs_block_bitmap map, blk64_t *ret) +{ + return ext2fs_new_block3(fs, goal, map, ret, NULL); +} + +errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, + ext2fs_block_bitmap map, blk_t *ret) +{ + errcode_t retval; + blk64_t val; + retval = ext2fs_new_block2(fs, goal, map, &val); + if (!retval) + *ret = (blk_t) val; + return retval; +} + +/* + * This function zeros out the allocated block, and updates all of the + * appropriate filesystem records. + */ +errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal, char *block_buf, + blk64_t *ret, struct blk_alloc_ctx *ctx) +{ + errcode_t retval; + blk64_t block; + + if (fs->get_alloc_block2) { + retval = (fs->get_alloc_block2)(fs, goal, &block, ctx); + if (retval) + goto fail; + } else if (fs->get_alloc_block) { + retval = (fs->get_alloc_block)(fs, goal, &block); + if (retval) + goto fail; + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + goto fail; + } + + retval = ext2fs_new_block3(fs, goal, 0, &block, ctx); + if (retval) + goto fail; + } + + if (block_buf) { + memset(block_buf, 0, fs->blocksize); + retval = io_channel_write_blk64(fs->io, block, 1, block_buf); + } else + retval = ext2fs_zero_blocks2(fs, block, 1, NULL, NULL); + if (retval) + goto fail; + + ext2fs_block_alloc_stats2(fs, block, +1); + *ret = block; + +fail: + return retval; +} + +errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal, + char *block_buf, blk64_t *ret) +{ + return ext2fs_alloc_block3(fs, goal, block_buf, ret, NULL); +} + +errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, + char *block_buf, blk_t *ret) +{ + errcode_t retval; + blk64_t ret64, goal64 = goal; + retval = ext2fs_alloc_block3(fs, goal64, block_buf, &ret64, NULL); + if (!retval) + *ret = (blk_t)ret64; + return retval; +} + +errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish, + int num, ext2fs_block_bitmap map, blk64_t *ret) +{ + blk64_t b = start; + int c_ratio; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!map) + map = fs->block_map; + if (!map) + return EXT2_ET_NO_BLOCK_BITMAP; + if (!b) + b = fs->super->s_first_data_block; + if (!finish) + finish = start; + if (!num) + num = 1; + c_ratio = 1 << ext2fs_get_bitmap_granularity(map); + b &= ~(c_ratio - 1); + finish &= ~(c_ratio -1); + do { + if (b + num - 1 >= ext2fs_blocks_count(fs->super)) { + if (finish > start) + return EXT2_ET_BLOCK_ALLOC_FAIL; + b = fs->super->s_first_data_block; + } + if (ext2fs_fast_test_block_bitmap_range2(map, b, num)) { + *ret = b; + return 0; + } + b += c_ratio; + } while (b != finish); + return EXT2_ET_BLOCK_ALLOC_FAIL; +} + +errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish, + int num, ext2fs_block_bitmap map, blk_t *ret) +{ + errcode_t retval; + blk64_t val; + retval = ext2fs_get_free_blocks2(fs, start, finish, num, map, &val); + if(!retval) + *ret = (blk_t) val; + return retval; +} + +void ext2fs_set_alloc_block_callback(ext2_filsys fs, + errcode_t (*func)(ext2_filsys fs, + blk64_t goal, + blk64_t *ret), + errcode_t (**old)(ext2_filsys fs, + blk64_t goal, + blk64_t *ret)) +{ + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS) + return; + + if (old) + *old = fs->get_alloc_block; + + fs->get_alloc_block = func; +} + +blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t lblk) +{ + dgrp_t group; + __u8 log_flex; + struct ext2fs_extent extent; + ext2_extent_handle_t handle = NULL; + errcode_t err; + + /* Make sure data stored in inode->i_block is neither fast symlink nor + * inline data. + */ + if (inode == NULL || ext2fs_is_fast_symlink(inode) || + inode->i_flags & EXT4_INLINE_DATA_FL) + goto no_blocks; + + if (inode->i_flags & EXT4_EXTENTS_FL) { + err = ext2fs_extent_open2(fs, ino, inode, &handle); + if (err) + goto no_blocks; + err = ext2fs_extent_goto2(handle, 0, lblk); + if (err) + goto no_blocks; + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (err) + goto no_blocks; + ext2fs_extent_free(handle); + return extent.e_pblk + (lblk - extent.e_lblk); + } + + /* block mapped file; see if block zero is mapped? */ + if (inode->i_block[0]) + return inode->i_block[0]; + +no_blocks: + ext2fs_extent_free(handle); + log_flex = fs->super->s_log_groups_per_flex; + group = ext2fs_group_of_ino(fs, ino); + if (log_flex) + group = group & ~((1 << (log_flex)) - 1); + return ext2fs_group_first_block2(fs, group); +} + +/* + * Starting at _goal_, scan around the filesystem to find a run of free blocks + * that's at least _len_ blocks long. Possible flags: + * - EXT2_NEWRANGE_EXACT_GOAL: The range of blocks must start at _goal_. + * - EXT2_NEWRANGE_MIN_LENGTH: do not return a allocation shorter than _len_. + * - EXT2_NEWRANGE_ZERO_BLOCKS: Zero blocks pblk to pblk+plen before returning. + * + * The starting block is returned in _pblk_ and the length is returned via + * _plen_. The blocks are not marked in the bitmap; the caller must mark + * however much of the returned run they actually use, hopefully via + * ext2fs_block_alloc_stats_range(). + * + * This function can return a range that is longer than what was requested. + */ +errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk, + blk64_t *plen) +{ + errcode_t retval; + blk64_t start, end, b; + int looped = 0; + blk64_t max_blocks = ext2fs_blocks_count(fs->super); + errcode_t (*nrf)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen); + + dbg_printf("%s: flags=0x%x goal=%llu len=%llu\n", __func__, flags, + goal, len); + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (len == 0 || (flags & ~EXT2_NEWRANGE_ALL_FLAGS)) + return EXT2_ET_INVALID_ARGUMENT; + + if (!map && fs->new_range) { + /* + * In case there are clients out there whose new_range + * handlers call ext2fs_new_range with a NULL block map, + * temporarily swap out the function pointer so that we don't + * end up in an infinite loop. + */ + nrf = fs->new_range; + fs->new_range = NULL; + retval = nrf(fs, flags, goal, len, pblk, plen); + fs->new_range = nrf; + if (retval) + return retval; + start = *pblk; + end = *pblk + *plen; + goto allocated; + } + if (!map) + map = fs->block_map; + if (!map) + return EXT2_ET_NO_BLOCK_BITMAP; + if (!goal || goal >= ext2fs_blocks_count(fs->super)) + goal = fs->super->s_first_data_block; + + start = goal; + while (!looped || start <= goal) { + retval = ext2fs_find_first_zero_block_bitmap2(map, start, + max_blocks - 1, + &start); + if (retval == ENOENT) { + /* + * If there are no free blocks beyond the starting + * point, try scanning the whole filesystem, unless the + * user told us only to allocate from _goal_, or if + * we're already scanning the whole filesystem. + */ + if (flags & EXT2_NEWRANGE_FIXED_GOAL || + start == fs->super->s_first_data_block) + goto fail; + start = fs->super->s_first_data_block; + continue; + } else if (retval) + goto errout; + + if (flags & EXT2_NEWRANGE_FIXED_GOAL && start != goal) + goto fail; + + b = min(start + len - 1, max_blocks - 1); + retval = ext2fs_find_first_set_block_bitmap2(map, start, b, + &end); + if (retval == ENOENT) + end = b + 1; + else if (retval) + goto errout; + + if (!(flags & EXT2_NEWRANGE_MIN_LENGTH) || + (end - start) >= len) { + /* Success! */ + *pblk = start; + *plen = end - start; + dbg_printf("%s: new_range goal=%llu--%llu " + "blk=%llu--%llu %llu\n", + __func__, goal, goal + len - 1, + *pblk, *pblk + *plen - 1, *plen); +allocated: + for (b = start; b < end; + b += fs->super->s_blocks_per_group) + ext2fs_clear_block_uninit(fs, + ext2fs_group_of_blk2(fs, b)); + return 0; + } + + if (flags & EXT2_NEWRANGE_FIXED_GOAL) + goto fail; + start = end; + if (start >= max_blocks) { + if (looped) + goto fail; + looped = 1; + start = fs->super->s_first_data_block; + } + } + +fail: + retval = EXT2_ET_BLOCK_ALLOC_FAIL; +errout: + return retval; +} + +void ext2fs_set_new_range_callback(ext2_filsys fs, + errcode_t (*func)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen), + errcode_t (**old)(ext2_filsys fs, int flags, blk64_t goal, + blk64_t len, blk64_t *pblk, blk64_t *plen)) +{ + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS) + return; + + if (old) + *old = fs->new_range; + + fs->new_range = func; +} + +errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal, + blk_t len, blk64_t *ret) +{ + int newr_flags = EXT2_NEWRANGE_MIN_LENGTH; + errcode_t retval; + blk64_t plen; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (len == 0 || (flags & ~EXT2_ALLOCRANGE_ALL_FLAGS)) + return EXT2_ET_INVALID_ARGUMENT; + + if (flags & EXT2_ALLOCRANGE_FIXED_GOAL) + newr_flags |= EXT2_NEWRANGE_FIXED_GOAL; + + retval = ext2fs_new_range(fs, newr_flags, goal, len, NULL, ret, &plen); + if (retval) + return retval; + + if (plen < len) + return EXT2_ET_BLOCK_ALLOC_FAIL; + + if (flags & EXT2_ALLOCRANGE_ZERO_BLOCKS) { + retval = ext2fs_zero_blocks2(fs, *ret, len, NULL, NULL); + if (retval) + return retval; + } + + ext2fs_block_alloc_stats_range(fs, *ret, len, +1); + return retval; +} diff --git a/jni/e2fsprogs/lib/ext2fs/alloc.o b/jni/e2fsprogs/lib/ext2fs/alloc.o new file mode 100755 index 0000000000000000000000000000000000000000..40afdaf6505d87c6ade303f412a44d5464939d2b GIT binary patch literal 11320 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_sb.c b/jni/e2fsprogs/lib/ext2fs/alloc_sb.c new file mode 100755 index 0000000..8530b40 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/alloc_sb.c @@ -0,0 +1,81 @@ +/* + * alloc_sb.c --- Allocate the superblock and block group descriptors for a + * newly initialized filesystem. Used by mke2fs when initializing a filesystem + * + * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * This function reserves the superblock and block group descriptors + * for a given block group. It currently returns the number of free + * blocks assuming that inode table and allocation bitmaps will be in + * the group. This is not necessarily the case when the flex_bg + * feature is enabled, so callers should take care! It was only + * really intended for use by mke2fs, and even there it's not that + * useful. In the future, when we redo this function for 64-bit block + * numbers, we should probably return the number of blocks used by the + * super block and group descriptors instead. + * + * See also the comment for ext2fs_super_and_bgd_loc() + */ +int ext2fs_reserve_super_and_bgd(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap) +{ + blk64_t super_blk, old_desc_blk, new_desc_blk; + blk_t used_blks; + int old_desc_blocks, num_blocks; + + ext2fs_super_and_bgd_loc2(fs, group, &super_blk, + &old_desc_blk, &new_desc_blk, &used_blks); + + if (ext2fs_has_feature_meta_bg(fs->super)) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; + + if (super_blk || (group == 0)) + ext2fs_mark_block_bitmap2(bmap, super_blk); + if ((group == 0) && (fs->blocksize == 1024) && + EXT2FS_CLUSTER_RATIO(fs) > 1) + ext2fs_mark_block_bitmap2(bmap, 0); + + if (old_desc_blk) { + num_blocks = old_desc_blocks; + if (old_desc_blk + num_blocks >= ext2fs_blocks_count(fs->super)) + num_blocks = ext2fs_blocks_count(fs->super) - + old_desc_blk; + ext2fs_mark_block_bitmap_range2(bmap, old_desc_blk, num_blocks); + } + if (new_desc_blk) + ext2fs_mark_block_bitmap2(bmap, new_desc_blk); + + num_blocks = ext2fs_group_blocks_count(fs, group); + num_blocks -= 2 + fs->inode_blocks_per_group + used_blks; + + return num_blocks ; +} diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_sb.o b/jni/e2fsprogs/lib/ext2fs/alloc_sb.o new file mode 100755 index 0000000000000000000000000000000000000000..250215546d19e846b8b1195b701703c7df46c782 GIT binary patch literal 2064 zcmb7^O-vI(6vyATRJKAI5F>;ZS|bNJxDlcW@w5a`OpFKAgcHlQEFb9?>~0B&Mv{6k z@nRECMil%=z{HzGns~sQ9*lDFq^9_hlyETK+5^EivomE`*@Kg8=k4$R-n{o_XL_se z(s_>{03QOphP^jV0Y3TmY?+!e_|bDWD{Sn{`Brv%gxq2_Tw3Z0uRY1OmKL)L+6vmR z@#87ver6%}%YYn)-d{!y>gDn<+690!nC~cIA~Mm}oi7F<@8_&VF0Y{0j#~Rd_pB)R z?-HHHc!x^M0ISr-T<-wR5_>T_R9ZrfH~{=!2;bU}g)GU#r+Cm&d*Eio_Lza=zFI_{in0#(7*5YpaGb?~lY3tFb2m zwolk{k>06>aUzJ@WDQ>TCbI91a=wzUK`vuoG#{-6-?_&3n7kKo4cgm9?9C7LTVXlx z7yLC?8>uT!aum?snd@7@Zoqp7d~j?H8y|K#_f4;+c@c+j}S9_sN270uY>b_21(Zvs$^<2Cg9UKYADe}IuT#$LTM&hS{@9O{0&oRV%K-e0)8cpo`aTmuckefo7 z^Tx<5;EN-`dE%KzB#!JckLUfrMCQzm2<|b+?=h*n I8Xsr;Uz~P1#{d8T literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_stats.c b/jni/e2fsprogs/lib/ext2fs/alloc_stats.c new file mode 100755 index 0000000..6f98bcc --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/alloc_stats.c @@ -0,0 +1,165 @@ +/* + * alloc_stats.c --- Update allocation statistics for ext2fs + * + * Copyright (C) 2001 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, + int inuse, int isdir) +{ + int group = ext2fs_group_of_ino(fs, ino); + + if (ino > fs->super->s_inodes_count) { +#ifndef OMIT_COM_ERR + com_err("ext2fs_inode_alloc_stats2", 0, + "Illegal inode number: %lu", (unsigned long) ino); +#endif + return; + } + if (inuse > 0) + ext2fs_mark_inode_bitmap2(fs->inode_map, ino); + else + ext2fs_unmark_inode_bitmap2(fs->inode_map, ino); + ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) - inuse); + if (isdir) + ext2fs_bg_used_dirs_count_set(fs, group, ext2fs_bg_used_dirs_count(fs, group) + inuse); + + /* We don't strictly need to be clearing the uninit flag if inuse < 0 + * (i.e. freeing inodes) but it also means something is bad. */ + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); + if (ext2fs_has_group_desc_csum(fs)) { + ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group - + ext2fs_bg_itable_unused(fs, group) + + group * fs->super->s_inodes_per_group + 1; + + if (ino >= first_unused_inode) + ext2fs_bg_itable_unused_set(fs, group, group * fs->super->s_inodes_per_group + fs->super->s_inodes_per_group - ino); + ext2fs_group_desc_csum_set(fs, group); + } + + fs->super->s_free_inodes_count -= inuse; + ext2fs_mark_super_dirty(fs); + ext2fs_mark_ib_dirty(fs); +} + +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse) +{ + ext2fs_inode_alloc_stats2(fs, ino, inuse, 0); +} + +void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse) +{ + int group = ext2fs_group_of_blk2(fs, blk); + + if (blk < fs->super->s_first_data_block || + blk >= ext2fs_blocks_count(fs->super)) { +#ifndef OMIT_COM_ERR + com_err("ext2fs_block_alloc_stats", 0, + "Illegal block number: %lu", (unsigned long) blk); +#endif + return; + } + if (inuse > 0) + ext2fs_mark_block_bitmap2(fs->block_map, blk); + else + ext2fs_unmark_block_bitmap2(fs->block_map, blk); + ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse); + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, group); + + ext2fs_free_blocks_count_add(fs->super, + -inuse * (blk64_t) EXT2FS_CLUSTER_RATIO(fs)); + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); + if (fs->block_alloc_stats) + (fs->block_alloc_stats)(fs, (blk64_t) blk, inuse); +} + +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse) +{ + ext2fs_block_alloc_stats2(fs, blk, inuse); +} + +void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs, + void (*func)(ext2_filsys fs, + blk64_t blk, + int inuse), + void (**old)(ext2_filsys fs, + blk64_t blk, + int inuse)) +{ + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS) + return; + if (old) + *old = fs->block_alloc_stats; + + fs->block_alloc_stats = func; +} + +void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse) +{ +#ifndef OMIT_COM_ERR + if (blk + num > ext2fs_blocks_count(fs->super)) { + com_err("ext2fs_block_alloc_stats_range", 0, + "Illegal block range: %llu (%u) ", + (unsigned long long) blk, num); + return; + } +#endif + if (inuse == 0) + return; + if (inuse > 0) { + ext2fs_mark_block_bitmap_range2(fs->block_map, blk, num); + inuse = 1; + } else { + ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, num); + inuse = -1; + } + while (num) { + int group = ext2fs_group_of_blk2(fs, blk); + blk64_t last_blk = ext2fs_group_last_block2(fs, group); + blk64_t n = num; + + if (blk + num > last_blk) + n = last_blk - blk + 1; + + ext2fs_bg_free_blocks_count_set(fs, group, + ext2fs_bg_free_blocks_count(fs, group) - + inuse*n/EXT2FS_CLUSTER_RATIO(fs)); + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, group); + ext2fs_free_blocks_count_add(fs->super, -inuse * (blk64_t) n); + blk += n; + num -= n; + } + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); + if (fs->block_alloc_stats_range) + (fs->block_alloc_stats_range)(fs, blk, num, inuse); +} + +void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs, + void (*func)(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse), + void (**old)(ext2_filsys fs, blk64_t blk, + blk_t num, int inuse)) +{ + if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS) + return; + if (old) + *old = fs->block_alloc_stats_range; + + fs->block_alloc_stats_range = func; +} diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_stats.o b/jni/e2fsprogs/lib/ext2fs/alloc_stats.o new file mode 100755 index 0000000000000000000000000000000000000000..11baba0d26b532a677572030541b260d0c4f70be GIT binary patch literal 6872 zcmb_gYit}>6~40**SoQC>^$lar`}EL3foFoNeC#aidedC3F$*o6r@O08LxN84|)CQ zKB|<&Y9zM^iT)rWswx^nnjqv2t@snlS_)FZ{6K{tP*7Egg4St4o0>`#A!LhK<~w)p z**%`!0VKFqcJ6%VdC&RootZrM$m5TOEKBjQ)Q?sDj!~sf?XJ%gdYVvMp}CQ?ezSgd zOKIJhfu%({2f%v4%h5kjeV=nzSY>b*6iEJ zp6oczz3Ti4!sz}%T!&lge#59mctHEulvmZJ`l!hg^1KeaW6(PWy@9!{J*Zn-xJ7j> zBu!0|$Q60t7xL=DacRA^dc!t67wOq_4?iW;o!2aL<~3YLO{k_3#P9E-oVHH(cX>77 zHL>pc*`X5naN$kcd1qr@ffrV3J*h5KP`fJXqu}E!mb%!FdQ?%zn58~LFms?b7;^^0;b8 zSFbWpZEy+tl^(SSo~_pEv`h1JCCxmAtlCCgfIikkHq|!t&{8W&qjSyk)s)AdBaRZc z{5*aDJofA^)_5#1ss+VFUDm2S;EUnmGUk*6ty}Y$cnJU8Q{n>YJS;fKHoOMXucBVW zAzJs~Pr)&3i&5L@=CVh7r+Ti-Qe8lUUScOP*?0P>+|oBZ2fGqw1M-X z882k-z=OqQoB`B7inXbC;8O*Acp0_7MK!>F<=8Y2TR2lHFTFkSryu?e>sT2!XT&EA zzpBd1Q|ltn+o%)l*EGk_zuV;R1@FGjGvZ4NIBd=~!Jh&bDWCZ%>!UmA4;q=AJn61oIB{R)!C{wx|#7qXpy=(fW<@usXk;#kRjl)NH`O_^5-~YdagQ@|l`xz~7f4^nL9Tj_ zB;jM5IWIA%Sj*cCPf_zKdR>~oT>fwedN;TA6*}i01NR28uE+NMa?gi$+u*Ue#J2__ zZ+)9$-143env1W(pX4;%lm8m0=RHnG!0D*4o>)67Igfj;CH3VR;?{Zp2+piJ@BeT7Ma-uBeci|3B=!vL6>vT5 z(m8f_u7b05181_{iw*LD1`L9fzTxxpE^%-i6LS>7w{`-pqF{RR3=*6CKbNPvx z>Da*|@q_UrsuN_OVSV+4vd;BdJ?&A|hx^?c#T73XYN+G*(e`^fFNeOf#a5yA=<%Z+ z>W_cWdI_WV6kUfpVyqV$YLCV|HLZs|tH%-g6?(&UHLXVv0~*g`gFr9A{_L#P9!=Ea z5{YU2JAXSNuaFW(fqoD-lt^djfF4P5pc_0H1^b)wy7(qW1}O|ABkLUo*Jg zXTVWB7Q^;O`k+ zp98@E9FYId1MnXN;6uiLzu5vDw+}IBP@mhqss24~<~xAPU31dlyL>qBZ`R*q^oD)< zjAsl^aq+HK8($YVjT+m%R9$z`KP09f5BbIK61mpnP_CQ~ir~O+5(T zDe#j5-zD&02>fn=zbo)=f!`7MZh>z>zi3cg+EY9(37kGydHhP?dl{rF_&|gF+~ZC4 z?{0&0zYZJOUW0Rg8SnGyKVkIyefo^=H#o(W{XH)5UXf2m;8B4;FYuVaFA02~z+V%% z>{nUfvi=_k{9fVbF9Mf+`MbdH6Z)sjzNPi{2)xrgiv0E8Z*Z>vn6WuvaIQb&M|}EU zGx`tt^chbW++Y7Q0{@iA^JRhe3;a!iOJ4n2-~&Q`KR$wKP~4cFc|WrPm;E{~aM`aH z1upw_L*TMs6@klsRRu2l#cOFno@VRlM2AeyjPv_I)`#>oi9#F5!N|TNR4D&r#P(_EW_JELx@P|Uf`Sf-%!lQLiGQp9FcZXuOP6;hsUe0rwf z#=rRFmmk1~VS17cuq>}T@(a*O;}de^KWga@yt=MO7Iz#iPffWTpyBh2p796!@9Z2|2|-WN^OhHHzP7z+5?hzTN;%bAL5|X6)rVA-P~XzILE~ zJSRDicR5i8%+;@3H1_hDMyhN-?lbVaorNKlC_zSIB+N_kUkyg}qgJpz*Y7s${jtd; Rv6X(IZ|YBJ(EF?3{$Iv&Pn!S$ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_tables.c b/jni/e2fsprogs/lib/ext2fs/alloc_tables.c new file mode 100755 index 0000000..e8a1fef --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/alloc_tables.c @@ -0,0 +1,278 @@ +/* + * alloc_tables.c --- Allocate tables for a newly initialized + * filesystem. Used by mke2fs when initializing a filesystem + * + * Copyright (C) 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +/* + * This routine searches for free blocks that can allocate a full + * group of bitmaps or inode tables for a flexbg group. Returns the + * block number with a correct offset were the bitmaps and inode + * tables can be allocated continuously and in order. + */ +static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk, + ext2fs_block_bitmap bmap, int rem_grp, + int elem_size) +{ + int flexbg, flexbg_size, size; + blk64_t last_blk, first_free = 0; + dgrp_t last_grp; + + flexbg_size = 1U << fs->super->s_log_groups_per_flex; + flexbg = group / flexbg_size; + size = rem_grp * elem_size; + + if (size > (int) (fs->super->s_blocks_per_group / 4)) + size = (int) fs->super->s_blocks_per_group / 4; + + /* + * Don't do a long search if the previous block search is still valid, + * but skip minor obstructions such as group descriptor backups. + */ + if (start_blk && start_blk < ext2fs_blocks_count(fs->super) && + ext2fs_get_free_blocks2(fs, start_blk, start_blk + size, elem_size, + bmap, &first_free) == 0) + return first_free; + + start_blk = ext2fs_group_first_block2(fs, flexbg_size * flexbg); + last_grp = group | (flexbg_size - 1); + if (last_grp > fs->group_desc_count-1) + last_grp = fs->group_desc_count-1; + last_blk = ext2fs_group_last_block2(fs, last_grp); + + /* Find the first available block */ + if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, size, + bmap, &first_free) == 0) + return first_free; + + if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, elem_size, + bmap, &first_free) == 0) + return first_free; + + if (ext2fs_get_free_blocks2(fs, 0, last_blk, elem_size, bmap, + &first_free) == 0) + return first_free; + + return first_free; +} + +errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap) +{ + errcode_t retval; + blk64_t group_blk, start_blk, last_blk, new_blk; + dgrp_t last_grp = 0; + int rem_grps = 0, flexbg_size = 0, table_offset = 0; + + group_blk = ext2fs_group_first_block2(fs, group); + last_blk = ext2fs_group_last_block2(fs, group); + + if (!bmap) + bmap = fs->block_map; + + if (ext2fs_has_feature_flex_bg(fs->super) && + fs->super->s_log_groups_per_flex) { + flexbg_size = 1U << fs->super->s_log_groups_per_flex; + last_grp = group | (flexbg_size - 1); + if (last_grp > fs->group_desc_count-1) + last_grp = fs->group_desc_count-1; + rem_grps = last_grp - group + 1; + } + + /* + * Allocate the block and inode bitmaps, if necessary + */ + if (fs->stride && !flexbg_size) { + retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk, + 1, bmap, &start_blk); + if (retval) + return retval; + start_blk += fs->inode_blocks_per_group; + start_blk += ((fs->stride * group) % + (last_blk - start_blk + 1)); + if (start_blk >= last_blk) + start_blk = group_blk; + } else + start_blk = group_blk; + + if (flexbg_size) { + blk64_t prev_block = 0; + + table_offset = flexbg_size; + if (group % flexbg_size) + prev_block = ext2fs_block_bitmap_loc(fs, group - 1) + 1; + else if (last_grp == fs->group_desc_count-1) { + /* + * If we are allocating for the last flex_bg + * keep the metadata tables contiguous + */ + table_offset = last_grp & (flexbg_size - 1); + if (table_offset == 0) + table_offset = flexbg_size; + else + table_offset++; + } + /* FIXME: Take backup group descriptor blocks into account + * if the flexbg allocations will grow to overlap them... */ + start_blk = flexbg_offset(fs, group, prev_block, bmap, + rem_grps, 1); + last_blk = ext2fs_group_last_block2(fs, last_grp); + } + + if (!ext2fs_block_bitmap_loc(fs, group)) { + retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk, + 1, bmap, &new_blk); + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) + retval = ext2fs_get_free_blocks2(fs, group_blk, + last_blk, 1, bmap, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap2(bmap, new_blk); + ext2fs_block_bitmap_loc_set(fs, group, new_blk); + if (flexbg_size) { + dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk); + ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1); + ext2fs_free_blocks_count_add(fs->super, -1); + ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, gr); + } + } + + if (flexbg_size) { + blk64_t prev_block = 0; + if (group % flexbg_size) + prev_block = ext2fs_inode_bitmap_loc(fs, group - 1) + 1; + else + prev_block = ext2fs_block_bitmap_loc(fs, group) + + table_offset; + /* FIXME: Take backup group descriptor blocks into account + * if the flexbg allocations will grow to overlap them... */ + start_blk = flexbg_offset(fs, group, prev_block, bmap, + rem_grps, 1); + last_blk = ext2fs_group_last_block2(fs, last_grp); + } + + if (!ext2fs_inode_bitmap_loc(fs, group)) { + retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk, + 1, bmap, &new_blk); + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) + retval = ext2fs_get_free_blocks2(fs, group_blk, + last_blk, 1, bmap, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap2(bmap, new_blk); + ext2fs_inode_bitmap_loc_set(fs, group, new_blk); + if (flexbg_size) { + dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk); + ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1); + ext2fs_free_blocks_count_add(fs->super, -1); + ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, gr); + } + } + + /* + * Allocate the inode table + */ + if (flexbg_size) { + blk64_t prev_block = 0; + + if (group % flexbg_size) + prev_block = ext2fs_inode_table_loc(fs, group - 1) + + fs->inode_blocks_per_group; + else + prev_block = ext2fs_inode_bitmap_loc(fs, group) + + table_offset; + + /* FIXME: Take backup group descriptor blocks into account + * if the flexbg allocations will grow to overlap them... */ + group_blk = flexbg_offset(fs, group, prev_block, bmap, + rem_grps, fs->inode_blocks_per_group); + last_blk = ext2fs_group_last_block2(fs, last_grp); + } + + if (!ext2fs_inode_table_loc(fs, group)) { + retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk, + fs->inode_blocks_per_group, + bmap, &new_blk); + if (retval) + return retval; + + ext2fs_mark_block_bitmap_range2(bmap, + new_blk, fs->inode_blocks_per_group); + if (flexbg_size) { + blk64_t num, blk; + num = fs->inode_blocks_per_group; + blk = new_blk; + while (num) { + int gr = ext2fs_group_of_blk2(fs, blk); + last_blk = ext2fs_group_last_block2(fs, gr); + blk64_t n = num; + + if (blk + num > last_blk) + n = last_blk - blk + 1; + + ext2fs_bg_free_blocks_count_set(fs, gr, + ext2fs_bg_free_blocks_count(fs, gr) - + n/EXT2FS_CLUSTER_RATIO(fs)); + ext2fs_bg_flags_clear(fs, gr, + EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, gr); + ext2fs_free_blocks_count_add(fs->super, -n); + blk += n; + num -= n; + } + } + ext2fs_inode_table_loc_set(fs, group, new_blk); + } + ext2fs_group_desc_csum_set(fs, group); + return 0; +} + +errcode_t ext2fs_allocate_tables(ext2_filsys fs) +{ + errcode_t retval; + dgrp_t i; + struct ext2fs_numeric_progress_struct progress; + + if (fs->progress_ops && fs->progress_ops->init) + (fs->progress_ops->init)(fs, &progress, NULL, + fs->group_desc_count); + + for (i = 0; i < fs->group_desc_count; i++) { + if (fs->progress_ops && fs->progress_ops->update) + (fs->progress_ops->update)(fs, &progress, i); + retval = ext2fs_allocate_group_table(fs, i, fs->block_map); + if (retval) + return retval; + } + if (fs->progress_ops && fs->progress_ops->close) + (fs->progress_ops->close)(fs, &progress, NULL); + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/alloc_tables.o b/jni/e2fsprogs/lib/ext2fs/alloc_tables.o new file mode 100755 index 0000000000000000000000000000000000000000..0b51baf49ae1bfccdc83b1a096a5bc1db31d603f GIT binary patch literal 6544 zcmd5=U2Ggz6~41$$FqrJC#B$I?Zl1}6x$)&Bo0z5Rb;?P3ACW76p1uW)@ytGBd>qh z-Jn2;NVQP~L_#%4zT@9yHk?2LKPTj*}iE|~aRjAR!wk?gb?!`hWBRBun42fWJn7SA=WcuPY3 z3cjCoA!{ACi!SWwcd^$leqe~(H)_Objak5~hv%Njo0V7?Si89KqIKwZQvHYQ?8%P3CA`_GZi;Zx;C-Moe!#5)UN@nFF4ix$L<@{8HMXd8XBS+fey`!Oj&- ztJBT&c<_14%@9Z61-@h)*TcjrqE9IYBL z=ibaBS=hyD2TNA03(`MsF- z~sRBg`qwx-P%k7V=Bs2yYqm{Wh&y)~@*fot}71*}t#KnQvq9U?07`&}tMiN3?Ke8m=gIaeGv6qadm2)(Fq40glsMDkDJz58;u(1mxp8_^F@r<}awq1$oD&V3&o zg0~2G8$DjGlW*I?`uDJI?S?Jr`n9^^wVUdG#{NS;m9Y?)ly}~w`iixXy2oT6gB*R! z6pr4=g|IIkA)Z;>?T?YOtdsi2$?w8`18?1O&tgv?kHS-S&Oq!^4&OdHKlOdmnQuf+ zjVh-P`EDUuU8fc3kj-WE8y({+ddnm5vt4X0Dz>}GN6LRlE_;+bmtDbrtCl-`b7&qm z_Rn*3rA5QvA13V&b8dZ6$o(Pr!5zDJKBQ|RzlTr*aA|DDC|CWB_s9%)u9#wK74Zn; z%zNaoguYA9Jo>GcqrEXx!@dLI&kFjhwTr_+f56CJ0k&3^FYSkL>gg1J2;a537N})W zfB(rj_QQU}qhmtf*h_cApK%U#?)jkKF!tC?+BrPl1HhP|I*z>gpA&y|$L+==EA^ej<=rwxc3~Y)29d@>of3*r;s)GLjKDM&6zlz_s zD)L{cf)7;ji*LRy{idqmcdFQ#uOk18D)R9vdHt@6o%$;H3UI1p&rVD*HNq(L~vpvTV{&h0#4IG4{eoZD|ReTzZAFED(! zc8X^Y!*Q(3BhB!}GKx!x;e3C&4ByM-vkZTN;Y$qv7{lLXIQ1Sq_Nk*td3{`ic%EQ5 z=O@8%&L{r=L5`rES%z~y->-tBx0mg3KKC*F6TXQ2J;89!=LLpyJ_i`i`AjpM^Ldlu zoX^)8&iQquGhP3#UY9b`h`FV-qywA7{ z=R7PioZIoL;O$B|==ZczCR~Lqqs2F*9JRnz%aQNr1Gv8LdIPw=SHBy;b$=Dnq?3q8 z)6TWDz~8CCRID#C(Lb7s^-o+K-@t}qgGtA!T#NQkjEy-E8caCX`i5c?gM%q&Ta_4F zA4*PKos11Qss31h>gpI@k`cuEM$%*P$rz&HYa`lOBo#^Mk{MF;Bbi995OAW_Uu|X%EzM6C(?p%xY4JqE7Vek?k zbF^gHjh~%#rq?zR7>f@K=*3{l8V{yhiI-Cq(y>Y|+ApH1bP|hresheTse8xQNOl|+472?$HX93M+4yCNHUf7wE`=N_@;$T9%4y+Gdrimk%6fEIVp}@i|Sim zZPx$c@h6-Ub%j-E-&alHb$*B-0r84K?T#?j_R4Fvnmyo$9GJSE%5tPjm|aHv$*^jw zo>HJQPNC?tu6yybz{p0Bi5hje@;eP;<@j|T4VdUTt?Lotm$L@(49b2+=?7>MZA#x| tx-`}CYxo)HZzM#gMQFAsVph~(`u38Cf%U^e*suAsYL() literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/atexit.c b/jni/e2fsprogs/lib/ext2fs/atexit.c new file mode 100755 index 0000000..b3be1d5 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/atexit.c @@ -0,0 +1,116 @@ +/* + * atexit.c --- Clean things up when we exit normally. + * + * Copyright Oracle, 2014 + * Author Darrick J. Wong + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +struct exit_data { + ext2_exit_fn func; + void *data; +}; + +static struct exit_data *items; +static size_t nr_items; + +static void handle_exit(void) +{ + struct exit_data *ed; + + for (ed = items + nr_items - 1; ed >= items; ed--) { + if (ed->func == NULL) + continue; + ed->func(ed->data); + } + + ext2fs_free_mem(&items); + nr_items = 0; +} + +/* + * Schedule a function to be called at (normal) program termination. + * If you want this to be called during a signal exit, you must capture + * the signal and call exit() yourself! + */ +errcode_t ext2fs_add_exit_fn(ext2_exit_fn func, void *data) +{ + struct exit_data *ed, *free_ed = NULL; + size_t x; + errcode_t ret; + + if (func == NULL) + return EXT2_ET_INVALID_ARGUMENT; + + for (x = 0, ed = items; x < nr_items; x++, ed++) { + if (ed->func == func && ed->data == data) + return EXT2_ET_FILE_EXISTS; + if (ed->func == NULL) + free_ed = ed; + } + + if (free_ed) { + free_ed->func = func; + free_ed->data = data; + return 0; + } + + if (nr_items == 0) { + ret = atexit(handle_exit); + if (ret) + return ret; + } + + ret = ext2fs_resize_mem(0, (nr_items + 1) * sizeof(struct exit_data), + &items); + if (ret) + return ret; + + items[nr_items].func = func; + items[nr_items].data = data; + nr_items++; + + return 0; +} + +/* Remove a function from the exit cleanup list. */ +errcode_t ext2fs_remove_exit_fn(ext2_exit_fn func, void *data) +{ + struct exit_data *ed; + size_t x; + + if (func == NULL) + return EXT2_ET_INVALID_ARGUMENT; + + for (x = 0, ed = items; x < nr_items; x++, ed++) { + if (ed->func == NULL) + return 0; + if (ed->func == func && ed->data == data) { + size_t sz = (nr_items - (x + 1)) * + sizeof(struct exit_data); + memmove(ed, ed + 1, sz); + memset(items + nr_items - 1, 0, + sizeof(struct exit_data)); + } + } + + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/atexit.o b/jni/e2fsprogs/lib/ext2fs/atexit.o new file mode 100755 index 0000000000000000000000000000000000000000..06cc371e56264251f27fb40925e9ba6ad633265c GIT binary patch literal 3544 zcmbtXO=w(I6h3cW(oC8$O&hC$*31yINHu*V5hM%6iH#a+kRS?O6erWnODC9_;LK2J z6VZ@Op zzw>|Io0qqrn|wavIHbd&el;~JTW1Te1B<%*XcEtH^d$DD6+jZ8~-FW5lN^hmM zhpHQHs&bR)Q|NlITz>ES>~A0axv>(joW#D?LDeYHYSc+q%iUBpoQ`C*9oQjYQK$X) zz7~4L;N84WRyU!K@nt83w*p^z&EVH5z_WifY)!Ilk>5~XurI?u)~$AuS&g=0wLCi?eDy}tL7s@U@7JV!E zZn+IM+LBfHVsx4{CuSP2{_j;EBSAO9gdr^JD3xwAvw?7QXQ)EF7hAFA={6` z*X_lzP52e~w?pqW>$|66m-|xVsP`Re8uq(ySE#?><5}^Wb2P}lTm5+14e=3+_Tw)S zKilIRnRsFA5OU6a97S!o=eD>XaXIL_U-1lZzi?jEPxCw=*KsFai7y9rGP!~-t{?Yu zxNpBf-kQ}Dx`}4y)A^H$Q+}a1w~$W^k9x!2DBv!0NaUP(nVh9w=Rhn@{lIzzzYU`_ z-Z?c9d!*}970vZkAD9h&&7D+Y1-)MqA37qvWNs3HefbolKC;i+j zJi1Z8u(wYIF!fqE`_Du9n$M{KuJaX-a$jKB{FvaXU->;DK8K+BIVkvk%waqs_yNo@ zV=1^z3U1q-65O^sZShrAMsT(p&QDfww)=pRF`pM)?ds90;A&U#3l?AVaM9u`zG302 z=Zb|Z|MMpJwI+C3aNGa87GLe&v-oQFZ;P*ZO#0H+-zB)6pW{vV(}LS|$q3GM=~O2% zXDvPI&%EGjSMiT6zN)%v@fE*e@m0@Fi?4XX4J0)WiVp~G`!gjt#}$5#k6C)upW~Ju z#iuP??ehDOM=SJ;%Vs}r?hRa@$9W6a_YHXke?IM%{L>}!W)^ZeKVPCWwsR%Qrt_J3 zKV{b5iDHrRh16Wh&lL&mk=bIZ;O7=j1%%XWUeR B +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +/* + * Helper function for making a badblocks list + */ +static errcode_t make_u32_list(int size, int num, __u32 *list, + ext2_u32_list *ret) +{ + ext2_u32_list bb; + errcode_t retval; + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb); + if (retval) + return retval; + memset(bb, 0, sizeof(struct ext2_struct_u32_list)); + bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; + bb->size = size ? size : 10; + bb->num = num; + retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list); + if (retval) { + ext2fs_free_mem(&bb); + return retval; + } + if (list) + memcpy(bb->list, list, bb->size * sizeof(blk_t)); + else + memset(bb->list, 0, bb->size * sizeof(blk_t)); + *ret = bb; + return 0; +} + + +/* + * This procedure creates an empty u32 list. + */ +errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size) +{ + return make_u32_list(size, 0, 0, ret); +} + +/* + * This procedure creates an empty badblocks list. + */ +errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) +{ + return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); +} + + +/* + * This procedure copies a badblocks list + */ +errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest) +{ + errcode_t retval; + + retval = make_u32_list(src->size, src->num, src->list, dest); + if (retval) + return retval; + (*dest)->badblocks_flags = src->badblocks_flags; + return 0; +} + +errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, + ext2_badblocks_list *dest) +{ + return ext2fs_u32_copy((ext2_u32_list) src, + (ext2_u32_list *) dest); +} + +/* + * This procedure frees a badblocks list. + * + * (note: moved to closefs.c) + */ + + +/* + * This procedure adds a block to a badblocks list. + */ +errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) +{ + errcode_t retval; + int i, j; + unsigned long old_size; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb->num >= bb->size) { + old_size = bb->size * sizeof(__u32); + bb->size += 100; + retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32), + &bb->list); + if (retval) { + bb->size -= 100; + return retval; + } + } + + /* + * Add special case code for appending to the end of the list + */ + i = bb->num-1; + if ((bb->num != 0) && (bb->list[i] == blk)) + return 0; + if ((bb->num == 0) || (bb->list[i] < blk)) { + bb->list[bb->num++] = blk; + return 0; + } + + j = bb->num; + for (i=0; i < bb->num; i++) { + if (bb->list[i] == blk) + return 0; + if (bb->list[i] > blk) { + j = i; + break; + } + } + for (i=bb->num; i > j; i--) + bb->list[i] = bb->list[i-1]; + bb->list[j] = blk; + bb->num++; + return 0; +} + +errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); +} + +/* + * This procedure finds a particular block is on a badblocks + * list. + */ +int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) +{ + int low, high, mid; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return -1; + + if (bb->num == 0) + return -1; + + low = 0; + high = bb->num-1; + if (blk == bb->list[low]) + return low; + if (blk == bb->list[high]) + return high; + + while (low < high) { + mid = ((unsigned)low + (unsigned)high)/2; + if (mid == low || mid == high) + break; + if (blk == bb->list[mid]) + return mid; + if (blk < bb->list[mid]) + high = mid; + else + low = mid; + } + return -1; +} + +/* + * This procedure tests to see if a particular block is on a badblocks + * list. + */ +int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) +{ + if (ext2fs_u32_list_find(bb, blk) < 0) + return 0; + else + return 1; +} + +int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); +} + + +/* + * Remove a block from the badblock list + */ +int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk) +{ + int remloc, i; + + if (bb->num == 0) + return -1; + + remloc = ext2fs_u32_list_find(bb, blk); + if (remloc < 0) + return -1; + + for (i = remloc ; i < bb->num-1; i++) + bb->list[i] = bb->list[i+1]; + bb->num--; + return 0; +} + +void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk) +{ + ext2fs_u32_list_del(bb, blk); +} + +errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, + ext2_u32_iterate *ret) +{ + ext2_u32_iterate iter; + errcode_t retval; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter); + if (retval) + return retval; + + iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; + iter->bb = bb; + iter->ptr = 0; + *ret = iter; + return 0; +} + +errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, + ext2_badblocks_iterate *ret) +{ + return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb, + (ext2_u32_iterate *) ret); +} + + +int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) +{ + ext2_u32_list bb; + + if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) + return 0; + + bb = iter->bb; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return 0; + + if (iter->ptr < bb->num) { + *blk = bb->list[iter->ptr++]; + return 1; + } + *blk = 0; + return 0; +} + +int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) +{ + return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, + (__u32 *) blk); +} + + +void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter) +{ + if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) + return; + + iter->bb = 0; + ext2fs_free_mem(&iter); +} + +void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) +{ + ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter); +} + + +int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2) +{ + EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); + EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb1->num != bb2->num) + return 0; + + if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) + return 0; + return 1; +} + +int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) +{ + return ext2fs_u32_list_equal((ext2_u32_list) bb1, + (ext2_u32_list) bb2); +} + +int ext2fs_u32_list_count(ext2_u32_list bb) +{ + return bb->num; +} diff --git a/jni/e2fsprogs/lib/ext2fs/badblocks.o b/jni/e2fsprogs/lib/ext2fs/badblocks.o new file mode 100755 index 0000000000000000000000000000000000000000..78656c2cb8fc7f7a62bd31acb9940f22770fbe85 GIT binary patch literal 6944 zcmb_gU1(g#6`s4RwN{p@AKNr`oO)H_Qpu!?>^Q{_4%tL%D;H6Oaa%u_Y}c!6OVwYz zS{Exe?FRM1xD+g6QWx4FnLxa0NK)F;T`0sLKO~Tc#w~?FTUL!zWXBXYq*VJLw%<4R z%IDplH9>nC(Kp_;&~%&7NQ z&U^WlUNu{4ROQ7+RV+0oiXS#6%8TLHzQ2WIuQe!jW##@nkY5RV zvva+%!hASZxHhwA`NQq1tQvB+7Sn1LOI#^6tMXEFqI_McU&E&zx<32?_k_tdg-%&HZ7yrt4w!=S9mET6(#O7v_%PZ&m^3X8QaufQ$QmOo;PX7hwER1Y~_M|_!MOvm=oOvEy3;f;O{O~toQesd}Tp$ z@A?b7*e}>C(8}E>VeXS~eg$*q!m;J~g*^r2X*ufUibqN>-5UAm%}=6U)5kZII!0}f z|69oaC-mz@j5Qar%?itRd9`qptALy6yBN|a>xcAKXq9^-PuahX>X@fu0BZd6JvjzJ4g2Y8F zla`(S4dz|*Bu3bg*vqeDjZ2YS@#FB;eWMZ8@gwZ>uIYUR+U~b(FEy)T#i|cI9~#o1 zOLf|<@9*QrCiajUS6<@6zK2$-xCLD5#4$ALphk<8%0ot{x_WI6eECes&Lh`I6uY5s z^aJRJSds7YUFgXeE!$fEf6%t2&E4jJr}M~I;X@bnso%rB`3lY}eSW!nxKW>ZsG~%2 z)gA^{*BD~bb>i&ZIng4ja@&?-s`zc{zisisbcSZMoe+(y+{QJyh=JTEz}328F6vt6|FuY%+Fn9NTJw%he1yoMi`M?bc&!@Xv$u>>7>zS9TpDf<3C@@%x@xD-nit9Oul z1|mNtXt)S1nZuk~{xavhy$~zVZWrRbjy|!ug=Asn{5oeEe9>nb;-;;2&t9`HBK7&^ zTHW;7@(KHhxyQZ;d}D0n#lRy@4d~wz*3~(NO^dMvc_GzPTj9}cbU4EyETfKMyxw4CwsSoJ^qCtf2?`j zvB5n{zJ15pe8#Tx*nvFbp6X^^kmI{@?xP0EO~~;*#C@qFIPar|J7 zkypoY>)O)a*7Js}YrYv-M|(vF`nVCdngeK$TB_zCCw5sM?X-s+;JZriO^;8EqmkNo zAovFv=YMt1te1yg+&fYe3O-g)C%n51j+CHc=9boS7k72Vx z{j=iY9EX)GXubTEhF0TW2PcI8be*7Y_S74i+F)4-x_OP`6m{C)k?U>Ny2jqW!80{) zPl-PO-w8Ww@xS;0{;Lnb-xYsyvImVn4}niVd3m$xy2q14;yogf-iyGdF(!UOa9!8H zw_w6rekO(gsYqw+v47`$MHwJp-~Tm+CcXitgHPLycE1v zxcfBT9^FknbNIg$J3H||4%l?9;rXKAw*@zG^-5grTQyzj+Cum9 zf{zKVYYF(b#Li{Gb?pFu1AlAjIVSwEW)RTKx);%BTvr7*_Xl-j+l_e=njSCd-vE~o z0t7rZ^2H@R=4Hu7T$a$|V;0_`k>Fvxbc44=vo*Cn}87gPS_;l)KLOY3f+{=duS*O(jpJhE9%6rbnle>B;A&4SM$R1HpLQA5Yid z(|$IY%4Aa0DxUGjQt>Q|sPWXOpX7wGk*TaPP%}$3ne}V040UZVJ$ZH_tK#X&@o^s= ztUu-JM|%9Z2N)m8`k7SLPoDHok4zX&b(J;WG7y+H&r!s!s*okMzA2V~S z3$2CuXU?Xo%$kh=j!#Tx{rK0u@y#zyWmD-y>n)#hN^a}vxrq`@wAFhWi#2-Nj#^=`P@4c zKfs^;YVWytPjEQ=55GS}ok&U4S?Q9)yC8LBUP}3!q2jqn%>6P;2;(jL5(CyCxOqG! zSi%7E9Nrdm%sIq6gRYpn!`u}w1LOLx68B|Y`wjw4bM5C0Cc825{TBO@B_Pe^hTs%2 zM(dO6c6a`N E0G2>Zt^fc4 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/bb_compat.c b/jni/e2fsprogs/lib/ext2fs/bb_compat.c new file mode 100755 index 0000000..373792a --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/bb_compat.c @@ -0,0 +1,64 @@ +/* + * bb_compat.c --- compatibility badblocks routines + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +errcode_t badblocks_list_create(badblocks_list *ret, int size) +{ + return ext2fs_badblocks_list_create(ret, size); +} + +void badblocks_list_free(badblocks_list bb) +{ + ext2fs_badblocks_list_free(bb); +} + +errcode_t badblocks_list_add(badblocks_list bb, blk_t blk) +{ + return ext2fs_badblocks_list_add(bb, blk); +} + +int badblocks_list_test(badblocks_list bb, blk_t blk) +{ + return ext2fs_badblocks_list_test(bb, blk); +} + +errcode_t badblocks_list_iterate_begin(badblocks_list bb, + badblocks_iterate *ret) +{ + return ext2fs_badblocks_list_iterate_begin(bb, ret); +} + +int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk) +{ + return ext2fs_badblocks_list_iterate(iter, blk); +} + +void badblocks_list_iterate_end(badblocks_iterate iter) +{ + ext2fs_badblocks_list_iterate_end(iter); +} diff --git a/jni/e2fsprogs/lib/ext2fs/bb_inode.c b/jni/e2fsprogs/lib/ext2fs/bb_inode.c new file mode 100755 index 0000000..11f10eb --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/bb_inode.c @@ -0,0 +1,270 @@ +/* + * bb_inode.c --- routines to update the bad block inode. + * + * WARNING: This routine modifies a lot of state in the filesystem; if + * this routine returns an error, the bad block inode may be in an + * inconsistent state. + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct set_badblock_record { + ext2_badblocks_iterate bb_iter; + int bad_block_count; + blk_t *ind_blocks; + int max_ind_blocks; + int ind_blocks_size; + int ind_blocks_ptr; + char *block_buf; + errcode_t err; +}; + +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, + void *priv_data); +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, + void *priv_data); + +/* + * Given a bad blocks bitmap, update the bad blocks inode to reflect + * the map. + */ +errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) +{ + errcode_t retval; + struct set_badblock_record rec; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!fs->block_map) + return EXT2_ET_NO_BLOCK_BITMAP; + + memset(&rec, 0, sizeof(rec)); + rec.max_ind_blocks = 10; + retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t), + &rec.ind_blocks); + if (retval) + return retval; + memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); + retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); + if (retval) + goto cleanup; + memset(rec.block_buf, 0, fs->blocksize); + rec.err = 0; + + /* + * First clear the old bad blocks (while saving the indirect blocks) + */ + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, + BLOCK_FLAG_DEPTH_TRAVERSE, 0, + clear_bad_block_proc, &rec); + if (retval) + goto cleanup; + if (rec.err) { + retval = rec.err; + goto cleanup; + } + + /* + * Now set the bad blocks! + * + * First, mark the bad blocks as used. This prevents a bad + * block from being used as an indirect block for the bad + * block inode (!). + */ + if (bb_list) { + retval = ext2fs_badblocks_list_iterate_begin(bb_list, + &rec.bb_iter); + if (retval) + goto cleanup; + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, + BLOCK_FLAG_APPEND, 0, + set_bad_block_proc, &rec); + ext2fs_badblocks_list_iterate_end(rec.bb_iter); + if (retval) + goto cleanup; + if (rec.err) { + retval = rec.err; + goto cleanup; + } + } + + /* + * Update the bad block inode's mod time and block count + * field. + */ + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); + if (retval) + goto cleanup; + + inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); + if (!inode.i_ctime) + inode.i_ctime = fs->now ? fs->now : time(0); + ext2fs_iblk_set(fs, &inode, rec.bad_block_count); + retval = ext2fs_inode_size_set(fs, &inode, + rec.bad_block_count * fs->blocksize); + if (retval) + goto cleanup; + + retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); + if (retval) + goto cleanup; + +cleanup: + ext2fs_free_mem(&rec.ind_blocks); + ext2fs_free_mem(&rec.block_buf); + return retval; +} + +/* + * Helper function for update_bb_inode() + * + * Clear the bad blocks in the bad block inode, while saving the + * indirect blocks. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int clear_bad_block_proc(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) +{ + struct set_badblock_record *rec = (struct set_badblock_record *) + priv_data; + errcode_t retval; + unsigned long old_size; + + if (!*block_nr) + return 0; + + /* + * If the block number is outrageous, clear it and ignore it. + */ + if (*block_nr >= ext2fs_blocks_count(fs->super) || + *block_nr < fs->super->s_first_data_block) { + *block_nr = 0; + return BLOCK_CHANGED; + } + + if (blockcnt < 0) { + if (rec->ind_blocks_size >= rec->max_ind_blocks) { + old_size = rec->max_ind_blocks * sizeof(blk_t); + rec->max_ind_blocks += 10; + retval = ext2fs_resize_mem(old_size, + rec->max_ind_blocks * sizeof(blk_t), + &rec->ind_blocks); + if (retval) { + rec->max_ind_blocks -= 10; + rec->err = retval; + return BLOCK_ABORT; + } + } + rec->ind_blocks[rec->ind_blocks_size++] = *block_nr; + } + + /* + * Mark the block as unused, and update accounting information + */ + ext2fs_block_alloc_stats2(fs, *block_nr, -1); + + *block_nr = 0; + return BLOCK_CHANGED; +} + + +/* + * Helper function for update_bb_inode() + * + * Set the block list in the bad block inode, using the supplied bitmap. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int set_bad_block_proc(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) +{ + struct set_badblock_record *rec = (struct set_badblock_record *) + priv_data; + errcode_t retval; + blk_t blk; + + if (blockcnt >= 0) { + /* + * Get the next bad block. + */ + if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) + return BLOCK_ABORT; + rec->bad_block_count++; + } else { + /* + * An indirect block; fetch a block from the + * previously used indirect block list. The block + * most be not marked as used; if so, get another one. + * If we run out of reserved indirect blocks, allocate + * a new one. + */ + retry: + if (rec->ind_blocks_ptr < rec->ind_blocks_size) { + blk = rec->ind_blocks[rec->ind_blocks_ptr++]; + if (ext2fs_test_block_bitmap2(fs->block_map, blk)) + goto retry; + } else { + retval = ext2fs_new_block(fs, 0, 0, &blk); + if (retval) { + rec->err = retval; + return BLOCK_ABORT; + } + } + retval = io_channel_write_blk64(fs->io, blk, 1, rec->block_buf); + if (retval) { + rec->err = retval; + return BLOCK_ABORT; + } + } + + /* + * Update block counts + */ + ext2fs_block_alloc_stats2(fs, blk, +1); + + *block_nr = blk; + return BLOCK_CHANGED; +} + + + + + + diff --git a/jni/e2fsprogs/lib/ext2fs/bb_inode.o b/jni/e2fsprogs/lib/ext2fs/bb_inode.o new file mode 100755 index 0000000000000000000000000000000000000000..26fa820af015b833d62a691314444a5a8153b250 GIT binary patch literal 4480 zcmbVOTWl0n82)Ex3tL*j%H2}7HGODn*Z`s-KIi}<6^$37K1gKPZU?%y-PYYjuIidK zhJX(c&<6#wpeC&`(FZR(iAEA06|m) z`Ty^~o-_OM#z!8E7zU|f&}TIBrcfelp0*ZCi|QdcbuRkt47zmAbNxgmPAWX7wf zi_5Dcrd^F0me)D<=7sc?4}Xst_1Df4Jqhjw9l-j4jTGb6FYqp8S6JS8qEC1~c4cP& z6TFvF#tb6L4$o+wAw(a~3^aDn$qCfnau9U=Od z`NSHw&hQ#smBr+hid!KAy+2<1Zkltk<&DDc&Q8l6GwZvI({xnl>yv!1DW3V@F`xBg zh0cT->rz}-=3CyE#g=Lbd~HsrXEl^*J{xuE#^{ZwAhJRIyB4uI<0Y`ds&C zMJ;9S?JD7YY#w=a*dId<*e<^_XJww{T}9rmK1^<91O7KzZbyXf_UjhH)ezvqyWncD zyvinWm9J;ax69-3b$m8?Y;%0Jg?ib@>DIEUbL_?X<_hd{?N~<{Hzlb{m8R0MY zmI+(vMdqrQmPfLOR1XT@igxv{W0p6$|A|qYpQC3@`-iEbfpb(hI=R7^K0{|v`*+T@ zlz+aH+$-p{3VN!7yp5p#I9u*P^7HiNxp?_$_@Hq1f$Km`urK|H8FX#E;h#SxCvpIp z&V`nX^VvTk&nNH44RSlsLnGk6pSjT|-LtBniaeucu@=j{in(*CuiFsyxw)RPr3E*J zb5%j!S*C+!I;p8+DY;{)fs!#;2K#(=+0QZ5v4R>NH2gl-bf0Hk-t#f?x}|SRRPJR? zgirOB_bYf0wG`ZI=A5qnI%+!Hf_V0Jl~r%39E_vx5h~oq_JeT?*>iSza{tCr)aSp~ z2|0^Js-LNx5$?nByX4uCwNr6ChB!oQ^~e?c?WiaBJ{g~qh#@1xcap+C7d zYt@KS1If(J))$;?EJZ|+TGWKmDrtOb_=x2q zK_NkZOFWwdK1)OVB{$J+nm@|Uz1UW{)|DV$6F(e+{|SX!JUc_=9}bbfBLx35glAm{ z{zM2qFNFVt5c!r6{H+lDs}TN+A@buP@}Gyue-t90hdhsF?AQBC@jN2ejL*^V^BS(p zk7+o*sndf$oIHa3D)1_vE12A#p2GcA+u8R)n5_smeQW9QQQ@R*V6N%l&zfpji!r}IuW znRo0SXJRc2#%7OvT8jzK|LC)s-=vTL|kINx(4T-%!MWO@miu(9oXYY%6KQuvfR z$!rkpk(7xPC35*}KG}nL?;y|VAv@KV%w(Ja+jkOqzh{kdQl!C74xnH*QjpKBRy%nI z`S!Pa()q#U@br!k%2KSR_TGeetfKZkiIuWz{{K`$f6AkF14*mAtXlQvg#^TJ7~J!W z1;5OelsX>R2!7f5?qE#GOEqehmwH*+k70wCJo8Xzc@@@dKbVQ{rCt4wU_Ir(n!nL7 z-dE$7fZqyNdg`6eH)DY`(RHbRL +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" +#include "bmap64.h" + +void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap) +{ + ext2fs_free_generic_bmap(bitmap); +} + +void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap) +{ + ext2fs_free_generic_bmap(bitmap); +} + +errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest) +{ + return (ext2fs_copy_generic_bmap(src, dest)); +} +void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map) +{ + ext2fs_set_generic_bmap_padding(map); +} + +errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_inode_bitmap *ret) +{ + __u64 start, end, real_end; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + fs->write_bitmaps = ext2fs_write_bitmaps; + + start = 1; + end = fs->super->s_inodes_count; + real_end = (__u64)EXT2_INODES_PER_GROUP(fs->super) * + fs->group_desc_count; + + /* Are we permitted to use new-style bitmaps? */ + if (fs->flags & EXT2_FLAG_64BITS) + return (ext2fs_alloc_generic_bmap(fs, + EXT2_ET_MAGIC_INODE_BITMAP64, + fs->default_bitmap_type, + start, end, real_end, descr, ret)); + + /* Otherwise, check to see if the file system is small enough + * to use old-style 32-bit bitmaps */ + if ((end > ~0U) || (real_end > ~0U)) + return EXT2_ET_CANT_USE_LEGACY_BITMAPS; + + return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs, + start, end, real_end, + descr, 0, + (ext2fs_generic_bitmap *) ret)); +} + +errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret) +{ + __u64 start, end, real_end; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + fs->write_bitmaps = ext2fs_write_bitmaps; + + start = EXT2FS_B2C(fs, fs->super->s_first_data_block); + end = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1); + real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super) + * (__u64) fs->group_desc_count)-1 + start; + + if (fs->flags & EXT2_FLAG_64BITS) + return (ext2fs_alloc_generic_bmap(fs, + EXT2_ET_MAGIC_BLOCK_BITMAP64, + fs->default_bitmap_type, + start, end, real_end, descr, ret)); + + if ((end > ~0U) || (real_end > ~0U)) + return EXT2_ET_CANT_USE_LEGACY_BITMAPS; + + return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs, + start, end, real_end, + descr, 0, + (ext2fs_generic_bitmap *) ret)); +} + +/* + * ext2fs_allocate_block_bitmap() really allocates a per-cluster + * bitmap for backwards compatibility. This function allocates a + * block bitmap which is truly per-block, even if clusters/bigalloc + * are enabled. mke2fs and e2fsck need this for tracking the + * allocation of the file system metadata blocks. + */ +errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret) +{ + __u64 start, end, real_end; + ext2fs_generic_bitmap bmap; + ext2fs_generic_bitmap_64 bmap64; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + fs->write_bitmaps = ext2fs_write_bitmaps; + + if (!fs->cluster_ratio_bits) + return ext2fs_allocate_block_bitmap(fs, descr, ret); + + if ((fs->flags & EXT2_FLAG_64BITS) == 0) + return EXT2_ET_CANT_USE_LEGACY_BITMAPS; + + start = fs->super->s_first_data_block; + end = ext2fs_blocks_count(fs->super)-1; + real_end = ((__u64) EXT2_BLOCKS_PER_GROUP(fs->super) + * (__u64) fs->group_desc_count)-1 + start; + + retval = ext2fs_alloc_generic_bmap(fs, EXT2_ET_MAGIC_BLOCK_BITMAP64, + fs->default_bitmap_type, start, + end, real_end, descr, &bmap); + if (retval) + return retval; + bmap64 = (ext2fs_generic_bitmap_64) bmap; + bmap64->cluster_bits = 0; + *ret = bmap; + return 0; +} + +int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) bitmap; + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return 0; + + return bmap->cluster_bits; +} + +errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, + ext2_ino_t end, ext2_ino_t *oend) +{ + __u64 tmp_oend; + int retval; + + retval = ext2fs_fudge_generic_bmap_end((ext2fs_generic_bitmap) bitmap, + EXT2_ET_FUDGE_INODE_BITMAP_END, + end, &tmp_oend); + if (oend) + *oend = tmp_oend; + return retval; +} + +errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, + blk_t end, blk_t *oend) +{ + return (ext2fs_fudge_generic_bitmap_end(bitmap, + EXT2_ET_MAGIC_BLOCK_BITMAP, + EXT2_ET_FUDGE_BLOCK_BITMAP_END, + end, oend)); +} + +errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap, + blk64_t end, blk64_t *oend) +{ + return (ext2fs_fudge_generic_bmap_end(bitmap, + EXT2_ET_FUDGE_BLOCK_BITMAP_END, + end, oend)); +} + +void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap) +{ + ext2fs_clear_generic_bmap(bitmap); +} + +void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap) +{ + ext2fs_clear_generic_bmap(bitmap); +} + +errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_inode_bitmap bmap) +{ + return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, + new_end, new_real_end, bmap)); +} + +errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, __u64 new_real_end, + ext2fs_inode_bitmap bmap) +{ + return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end)); +} + +errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_block_bitmap bmap) +{ + return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, + new_end, new_real_end, bmap)); +} + +errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, __u64 new_real_end, + ext2fs_block_bitmap bmap) +{ + return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end)); +} + +errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, + ext2fs_block_bitmap bm2) +{ + return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_BLOCK_BITMAP, + bm1, bm2)); +} + +errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, + ext2fs_inode_bitmap bm2) +{ + return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_INODE_BITMAP, + bm1, bm2)); +} + +errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap, + ext2_ino_t start, unsigned int num, + void *in) +{ + return (ext2fs_set_generic_bitmap_range(bmap, + EXT2_ET_MAGIC_INODE_BITMAP, + start, num, in)); +} + +errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap, + __u64 start, size_t num, + void *in) +{ + return (ext2fs_set_generic_bmap_range(bmap, start, num, in)); +} + +errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap, + ext2_ino_t start, unsigned int num, + void *out) +{ + return (ext2fs_get_generic_bitmap_range(bmap, + EXT2_ET_MAGIC_INODE_BITMAP, + start, num, out)); +} + +errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap, + __u64 start, size_t num, + void *out) +{ + return (ext2fs_get_generic_bmap_range(bmap, start, num, out)); +} + +errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap, + blk_t start, unsigned int num, + void *in) +{ + return (ext2fs_set_generic_bitmap_range(bmap, + EXT2_ET_MAGIC_BLOCK_BITMAP, + start, num, in)); +} + +errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap, + blk64_t start, size_t num, + void *in) +{ + return (ext2fs_set_generic_bmap_range(bmap, start, num, in)); +} + +errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap, + blk_t start, unsigned int num, + void *out) +{ + return (ext2fs_get_generic_bitmap_range(bmap, + EXT2_ET_MAGIC_BLOCK_BITMAP, + start, num, out)); +} + +errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap, + blk64_t start, size_t num, + void *out) +{ + return (ext2fs_get_generic_bmap_range(bmap, start, num, out)); +} diff --git a/jni/e2fsprogs/lib/ext2fs/bitmaps.o b/jni/e2fsprogs/lib/ext2fs/bitmaps.o new file mode 100755 index 0000000000000000000000000000000000000000..d9ab1fbfceb43e27923f9ea1ab5853d362905fd5 GIT binary patch literal 8600 zcmd5>eQaA-6~E6;sk4TpT>>p#7rRm_xl=K1Rah%c=#98rKw-*InJN_Kyx1=v)Nvx) z8O>6(pzM!MAe4%#RE&?L+fa-qQ6VH^sX({>lfwRB6+)9>$oX1bKBN{+Q!Ek8Irp7o zU*EjfL>)!ksqf==e)pVn&pG$p=j?^!olp1-L+~)fFGcl@Q6WwStIwuJ%%j;;m&J?d*Wz^}U8n%_7#?GLWb zOt!8rHjC1%Keie$%+mhCg&Tt_Kl^9EsQ=qlAx^-WTf%@105&@rT>U(}BUkJ&OJ9KX z0OtsD=0B)%OnA?sJ|U)1XZV;Xg~h~;ViVbcxq#=3+m!eHW*+D4KV;?u->84N2r-jB z?Es!}_A_W>8sv!iUV40NsmUxYZ!=3P5Z9kfKD&Ce*(@#m!iFgQ1~}FIbR7C7 z?I-B11?U~>T#SDX>V|ul>2rFQ+;bqiuE=_fTG=f{HbMQM92EI2=pXLcW6*=(9epVT z&3vVQ`>`JUxwUKJ9QK=;_Tbzi#s>EPYx97^xqh)`%hG&T{w>GKRftaD4SHR9P_-H^4WAEz)d%e^H*Tz4WD}!%t zIu;;)i=<-_`y1%6$XCo+&D{HNmQ7y^&Vdj4MW~ILYY?k#W_}53gnO#vgK}1CF<}4k zT%Cb9;2Q4cx0gNM`~Piw*zfVIUI70V@vOe-oE7WrXt7o2guLcxv5c~&r47f zOU-5;>tZj}#k$yNIyjz7;4{|M0>l$*A8Q!%veEqicOQ6vY_yL18HfAjgNP@sRDb9> zJDnLEPK6E~jU0*`g@xjPZy7m^=f5P3Gp)u$4MEWc$S%V1SwtH{9Ssj}|B>&9b)5~t zP)DQq%ew%h%!Ge9HsTF9G;sj$ioO$?zA55uq;HORS!lYTuZ#WjcN-1CF2}b;@wT3qsjgH6_^h{70PZ>KNq7Sd>THogbR*8 zt9|fa1LZS>G#H(dPfj|Jygn)Mk0^-q_!{h!2NnHo#OMLN+#A(Nt;A;@-^YQ3dOC$1U-mtC?t_1B`o}!<{K>;JV!Jg2}<)YC zyuuGUx<3T*qa{e>s0W@<@NM*rx3dcVQ3bC9y*RK=o18~^4G?}*!_N?o{;2u6t>8Np zJr^N9ICT9#AY9k~7U8JB*_kS@QHUE3-7cR)h^ux@h$jx+Zj^A{?f~Ja=Rs$xykZ`4 z=>7z#kLdoi(7r`{r!!SvClve>3VubwRenLi_bB{2+Ha^|#Z3iQ{^TpN3cgp-b6LSv z{<4Cr{9ROhXm_8Yr_%$UQt+_C|Gk1gqTnsGA5cG^T_`@G;1Pv?QNdOH?Jv`;UC0Q{d~UtS;P5!tD|7CKYWg{zl`%ac0%Lxd38p^`CNKc z!}(m|zQOwWTzX&Q^ZB!f`U&$Z=Z}W-Ig`|IK2OeTIG-C=G@Q?eWew-^p@I4g`@`qM z5e?__LD;9Whx;A~z6O9!k>tk1TxqiH+#wc*ip%1Xu( z_H!bVwv$#Q3p$wDn;edx%EaQsqp7Tj#D|B5YBbE~1KBHzBw>V!`sN#-vUmyP zhMTD3hMSPxaFa2(vy&{sr|d-mR0mzzX4rB0#NNPB1N1lA@%b(0-t@tVSDO0V`5i5}xO!cc0RdTW9%h@|yX$QN3rcllF}!`fE!#W~UMy z5l33%`8uiQnYSEmqtxjpnMhnjGTC(2>V^B*5ZZH?ok9QGONe@PrtB z{#9_3o|5#v!U8%T_*Hxso)9xDi1Psd?@W%<aq7eN!nkW0{H-0MX^Zx@F$ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/bitops.c b/jni/e2fsprogs/lib/ext2fs/bitops.c new file mode 100755 index 0000000..ce2acc4 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/bitops.c @@ -0,0 +1,148 @@ +/* + * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined + * routines. + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * C language bitmap functions written by Theodore Ts'o, 9/26/92. + * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian + * systems, as well as non-32 bit systems. + */ + +int ext2fs_set_bit(unsigned int nr,void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR |= mask; + return retval; +} + +int ext2fs_clear_bit(unsigned int nr, void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR &= ~mask; + return retval; +} + +int ext2fs_test_bit(unsigned int nr, const void * addr) +{ + int mask; + const unsigned char *ADDR = (const unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return (mask & *ADDR); +} + +void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, + const char *description) +{ +#ifndef OMIT_COM_ERR + if (description) + com_err(0, errcode, "#%lu for %s", arg, description); + else + com_err(0, errcode, "#%lu", arg); +#endif +} + +/* Bitmap functions that take a 64-bit offset */ + +int ext2fs_set_bit64(__u64 nr, void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR |= mask; + return retval; +} + +int ext2fs_clear_bit64(__u64 nr, void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR &= ~mask; + return retval; +} + +int ext2fs_test_bit64(__u64 nr, const void * addr) +{ + int mask; + const unsigned char *ADDR = (const unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return (mask & *ADDR); +} + +static unsigned int popcount8(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res + (res >> 4)) & 0x0F; +} + +static unsigned int popcount32(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return (res + (res >> 16)) & 0x000000FF; +} + +unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes) +{ + const unsigned char *cp = addr; + const __u32 *p; + unsigned int res = 0; + + while (((((uintptr_t) cp) & 3) != 0) && (nbytes > 0)) { + res += popcount8(*cp++); + nbytes--; + } + p = (const __u32 *) cp; + + while (nbytes > 4) { + res += popcount32(*p++); + nbytes -= 4; + } + cp = (const unsigned char *) p; + + while (nbytes > 0) { + res += popcount8(*cp++); + nbytes--; + } + return res; +} diff --git a/jni/e2fsprogs/lib/ext2fs/bitops.o b/jni/e2fsprogs/lib/ext2fs/bitops.o new file mode 100755 index 0000000000000000000000000000000000000000..3399d9554be71dd59bbd3a1f8c5e8dad75f64863 GIT binary patch literal 3408 zcmcInUr1YL6hHS~Q*RO*HFI5Q?UFJDBkW?VEB5WKx>bjaq89oxvNT?&G@6*)Zf;g4 z$Y8L-v=r8tZ5H;RV^3o+1A7>B5ADOCg>7#e**}&P2J_9pLUzt~&lhj5`n2|wd%y4d zo!>d<`_4Jvm+QMPjlHZY3dp9w*RVH}D8Pfj-q;jF69UMrt-`}%1PZ?fp;8K(m6C>i z#4PxiwTY5uR?3>cS6BQW)NwzAdthZ;KYjm1sTB&PRUQ991Aumu0Lg5i(Jpv2# z_9$?!7&Hs$YyDd-@zay{*&BG0J^}Yx-^*QiSY1-Ls<^j})yOWz@waA-VY68oQQ#}g zMaP}h#P07H+dmL1YLU-XfVJ}g>zIaHx=Zerk#2SA{8sI*D{ie&ap$VsN;xwt`q5D* zM>yC0=FPIE_db?9Ju!cWEeksOS!xi0U z-t=Q#m$80J;N)#{D6y?8uu%Hw(-TzJf{S&0Pl2;i&+mivGTH*H^?uAJod?tj(%BID zK3Ld9pMTYA&yXLqQz2a;YlnsV3QV%yioYFgp&V@$1`e`?e6qDew&<*)-?}YaXWbV1 zaj&c8AX~gHvQ@-2SC@viYMSDl&mp`M_-xZz-U_UY$9%5@@O)pTIH2#s>=C>J@EknC zam+7dK`ARErnip<;V6V_LtMKqn^?1j*s?Ma+kvp#rv4{{NjJ8vPQ-AGvVAu7?;+ga z=k#bJ=SB2;YR~U;-RW!5=}a!#od+5Nq|(XxH==J^x%_NqJ{li1;>I9A8()vgJL8~S ze^xo!5`hlHjx%mkKOBmx>5#zt4#7tlzbyF|L(qle*BMVcc;86NskTqlkDJuVmPp@7 z2!8n)ivnfuGcW7#qUwy}Z{rYroAF7>A9MUYV0-`z1lMg!e_E%~5-}Zz%!sRjL$GG z*5yz@L(kq;6~KPn*{{z_2R!rGn)l%^AQE=1-)6=z<8m(hZpIyZ0GFBn8sjF%Rn!4u zm++Cb$5hdMhi~%x1@lEcAoe5Uog6xef64d_#%0{_>A~`i%#das9!A%eemQ!Dan+@P6gKWc`AXv(ib!wia!`r++%1xH4;}GS}v9FjASh zISU6Yu&umJQaR6C4bxQGO6G(d^%7PtCwXrrbMu7HC9`16XKc&3@am=K^L8?ImEBu2 ziRoN&&H`j*vUwu~M&8cZ$t&2uJx6^ulNE~^lt$%Z&JIX~m$L`d7lcsPlyRnR +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "bmap64.h" + +/* + * Private data for bit array implementation of bitmap ops. + * Currently, this is just a pointer to our big flat hunk of memory, + * exactly equivalent to the old-skool char * bitmap member. + */ + +struct ext2fs_ba_private_struct { + char *bitarray; +}; + +typedef struct ext2fs_ba_private_struct *ext2fs_ba_private; + +static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap_64 bitmap) +{ + ext2fs_ba_private bp; + errcode_t retval; + size_t size; + + /* + * Since we only have the one pointer, we could just shove our + * private data in the void *private field itself, but then + * we'd have to do a fair bit of rewriting if we ever added a + * field. I'm agnostic. + */ + retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp); + if (retval) + return retval; + + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); + + retval = ext2fs_get_mem(size, &bp->bitarray); + if (retval) { + ext2fs_free_mem(&bp); + bp = 0; + return retval; + } + bitmap->private = (void *) bp; + return 0; +} + +static errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)), + ext2fs_generic_bitmap_64 bitmap) +{ + ext2fs_ba_private bp; + errcode_t retval; + size_t size; + + retval = ba_alloc_private_data (bitmap); + if (retval) + return retval; + + bp = (ext2fs_ba_private) bitmap->private; + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); + memset(bp->bitarray, 0, size); + + return 0; +} + +static void ba_free_bmap(ext2fs_generic_bitmap_64 bitmap) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + + if (!bp) + return; + + if (bp->bitarray) { + ext2fs_free_mem (&bp->bitarray); + bp->bitarray = 0; + } + ext2fs_free_mem (&bp); + bp = 0; +} + +static errcode_t ba_copy_bmap(ext2fs_generic_bitmap_64 src, + ext2fs_generic_bitmap_64 dest) +{ + ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private; + ext2fs_ba_private dest_bp; + errcode_t retval; + size_t size; + + retval = ba_alloc_private_data (dest); + if (retval) + return retval; + + dest_bp = (ext2fs_ba_private) dest->private; + + size = (size_t) (((src->real_end - src->start) / 8) + 1); + memcpy (dest_bp->bitarray, src_bp->bitarray, size); + + return 0; +} + +static errcode_t ba_resize_bmap(ext2fs_generic_bitmap_64 bmap, + __u64 new_end, __u64 new_real_end) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private; + errcode_t retval; + size_t size, new_size; + __u64 bitno; + + /* + * If we're expanding the bitmap, make sure all of the new + * parts of the bitmap are zero. + */ + if (new_end > bmap->end) { + bitno = bmap->real_end; + if (bitno > new_end) + bitno = new_end; + for (; bitno > bmap->end; bitno--) + ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray); + } + if (new_real_end == bmap->real_end) { + bmap->end = new_end; + return 0; + } + + size = ((bmap->real_end - bmap->start) / 8) + 1; + new_size = ((new_real_end - bmap->start) / 8) + 1; + + if (size != new_size) { + retval = ext2fs_resize_mem(size, new_size, &bp->bitarray); + if (retval) + return retval; + } + if (new_size > size) + memset(bp->bitarray + size, 0, new_size - size); + + bmap->end = new_end; + bmap->real_end = new_real_end; + return 0; + +} + +static int ba_mark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + blk64_t bitno = (blk64_t) arg; + + return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray); +} + +static int ba_unmark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + blk64_t bitno = (blk64_t) arg; + + return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray); +} + +static int ba_test_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + blk64_t bitno = (blk64_t) arg; + + return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray); +} + +static void ba_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + blk64_t bitno = (blk64_t) arg; + unsigned int i; + + for (i = 0; i < num; i++) + ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray); +} + +static void ba_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + blk64_t bitno = (blk64_t) arg; + unsigned int i; + + for (i = 0; i < num; i++) + ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray); +} + +static int ba_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap, + __u64 start, unsigned int len) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + __u64 start_byte, len_byte = len >> 3; + unsigned int start_bit, len_bit = len % 8; + unsigned int first_bit = 0; + unsigned int last_bit = 0; + int mark_count = 0; + int mark_bit = 0; + int i; + const char *ADDR; + + ADDR = bp->bitarray; + start -= bitmap->start; + start_byte = start >> 3; + start_bit = start % 8; + + if (start_bit != 0) { + /* + * The compared start block number or start inode number + * is not the first bit in a byte. + */ + mark_count = 8 - start_bit; + if (len < 8 - start_bit) { + mark_count = (int)len; + mark_bit = len + start_bit - 1; + } else + mark_bit = 7; + + for (i = mark_count; i > 0; i--, mark_bit--) + first_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the first byte. + * If there is any marked bit, this function returns 0. + */ + if (first_bit & ADDR[start_byte]) + return 0; + else if (len <= 8 - start_bit) + return 1; + + start_byte++; + len_bit = (len - mark_count) % 8; + len_byte = (len - mark_count) >> 3; + } + + /* + * The compared start block number or start inode number is + * the first bit in a byte. + */ + if (len_bit != 0) { + /* + * The compared end block number or end inode number is + * not the last bit in a byte. + */ + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--) + last_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the last byte. + * If there is any marked bit, this function returns 0. + */ + if (last_bit & ADDR[start_byte + len_byte]) + return 0; + else if (len_byte == 0) + return 1; + } + + /* Check whether all bytes are 0 */ + return ext2fs_mem_is_zero(ADDR + start_byte, len_byte); +} + + +static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *in) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + + memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3); + + return 0; +} + +static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *out) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + + memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3); + + return 0; +} + +static void ba_clear_bmap(ext2fs_generic_bitmap_64 bitmap) +{ + ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private; + + memset(bp->bitarray, 0, + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); +} + +#ifdef ENABLE_BMAP_STATS +static void ba_print_stats(ext2fs_generic_bitmap_64 bitmap) +{ + fprintf(stderr, "%16llu Bytes used by bitarray\n", (unsigned long long) + ((bitmap->real_end - bitmap->start) >> 3) + 1 + + sizeof(struct ext2fs_ba_private_struct)); +} +#else +static void ba_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR((unused))) +{ +} +#endif + +/* Find the first zero bit between start and end, inclusive. */ +static errcode_t ba_find_first_zero(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out) +{ + ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private; + unsigned long bitpos = start - bitmap->start; + unsigned long count = end - start + 1; + int byte_found = 0; /* whether a != 0xff byte has been found */ + const unsigned char *pos; + unsigned long max_loop_count, i; + + /* scan bits until we hit a byte boundary */ + while ((bitpos & 0x7) != 0 && count > 0) { + if (!ext2fs_test_bit64(bitpos, bp->bitarray)) { + *out = bitpos + bitmap->start; + return 0; + } + bitpos++; + count--; + } + + if (!count) + return ENOENT; + + pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3); + /* scan bytes until 8-byte (64-bit) aligned */ + while (count >= 8 && (((uintptr_t)pos) & 0x07)) { + if (*pos != 0xff) { + byte_found = 1; + break; + } + pos++; + count -= 8; + bitpos += 8; + } + + if (!byte_found) { + max_loop_count = count >> 6; /* 8-byte blocks */ + i = max_loop_count; + while (i) { + if (*((const __u64 *)pos) != ((__u64)-1)) + break; + pos += 8; + i--; + } + count -= 64 * (max_loop_count - i); + bitpos += 64 * (max_loop_count - i); + + max_loop_count = count >> 3; + i = max_loop_count; + while (i) { + if (*pos != 0xff) { + byte_found = 1; + break; + } + pos++; + i--; + } + count -= 8 * (max_loop_count - i); + bitpos += 8 * (max_loop_count - i); + } + + /* Here either count < 8 or byte_found == 1. */ + while (count-- > 0) { + if (!ext2fs_test_bit64(bitpos, bp->bitarray)) { + *out = bitpos + bitmap->start; + return 0; + } + bitpos++; + } + + return ENOENT; +} + +/* Find the first one bit between start and end, inclusive. */ +static errcode_t ba_find_first_set(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out) +{ + ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private; + unsigned long bitpos = start - bitmap->start; + unsigned long count = end - start + 1; + int byte_found = 0; /* whether a != 0xff byte has been found */ + const unsigned char *pos; + unsigned long max_loop_count, i; + + /* scan bits until we hit a byte boundary */ + while ((bitpos & 0x7) != 0 && count > 0) { + if (ext2fs_test_bit64(bitpos, bp->bitarray)) { + *out = bitpos + bitmap->start; + return 0; + } + bitpos++; + count--; + } + + if (!count) + return ENOENT; + + pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3); + /* scan bytes until 8-byte (64-bit) aligned */ + while (count >= 8 && (((uintptr_t)pos) & 0x07)) { + if (*pos != 0) { + byte_found = 1; + break; + } + pos++; + count -= 8; + bitpos += 8; + } + + if (!byte_found) { + max_loop_count = count >> 6; /* 8-byte blocks */ + i = max_loop_count; + while (i) { + if (*((const __u64 *)pos) != 0) + break; + pos += 8; + i--; + } + count -= 64 * (max_loop_count - i); + bitpos += 64 * (max_loop_count - i); + + max_loop_count = count >> 3; + i = max_loop_count; + while (i) { + if (*pos != 0) { + byte_found = 1; + break; + } + pos++; + i--; + } + count -= 8 * (max_loop_count - i); + bitpos += 8 * (max_loop_count - i); + } + + /* Here either count < 8 or byte_found == 1. */ + while (count-- > 0) { + if (ext2fs_test_bit64(bitpos, bp->bitarray)) { + *out = bitpos + bitmap->start; + return 0; + } + bitpos++; + } + + return ENOENT; +} + +struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = { + .type = EXT2FS_BMAP64_BITARRAY, + .new_bmap = ba_new_bmap, + .free_bmap = ba_free_bmap, + .copy_bmap = ba_copy_bmap, + .resize_bmap = ba_resize_bmap, + .mark_bmap = ba_mark_bmap, + .unmark_bmap = ba_unmark_bmap, + .test_bmap = ba_test_bmap, + .test_clear_bmap_extent = ba_test_clear_bmap_extent, + .mark_bmap_extent = ba_mark_bmap_extent, + .unmark_bmap_extent = ba_unmark_bmap_extent, + .set_bmap_range = ba_set_bmap_range, + .get_bmap_range = ba_get_bmap_range, + .clear_bmap = ba_clear_bmap, + .print_stats = ba_print_stats, + .find_first_zero = ba_find_first_zero, + .find_first_set = ba_find_first_set +}; diff --git a/jni/e2fsprogs/lib/ext2fs/blkmap64_ba.o b/jni/e2fsprogs/lib/ext2fs/blkmap64_ba.o new file mode 100755 index 0000000000000000000000000000000000000000..468abb66a237ef877a95e9e57fcb2e583526fdb1 GIT binary patch literal 9144 zcmd5>U2I%O6`s4-slB$FG)hB$++;U2p-u#@6GCti50}_Y-KwA{1SyC#n~k%sjeoP= z7Q1PMk^7J;d8kXIR{a6D^kKK+1*rvFs?;KblpuskTER=H?39Of0yHTg?MhhY`{tfm z&rWtp3RKESzIW!EGv{y4IWu?t{d*tW7x6r0nx}rDmPZCvYC68$4|F$Bji6lez27gM z^mB`|YI4et73No|;@qmBSXZOY&ef`7zBVXkm3kdKZ`b{aSmAc|NwX~|<{Lo6{)V8q zfcN&*=zG!2QE&W0UG)6(bt}|l-Um%XP*h$}yyyqTc|W!TDx7@_yvTQIB2id8*`9+g zlW+TpKP*is=;Y-V+tsAeLCYc^tnX3k4X#^BJut2V-@NEJhcS5*k9n#{x;bA>5?jK0 zju%gUEe9E)tajR8lUsyr+W+#z=0es_6tuiGsyH=qr0{DWzM!43q2vqpq5oR&%YsJJ z!*_Zue31i>ioT#v;V1ecza}VpcwdB%uk}YqZmHe)gF3E&KbCcT#kcfa2f5He%Um1! ze|wEONL!6QdD+Vxb;bVVl+0tyInwfvdu;PL?}ckRCD*^d=oncX~HvYGZ{Zy7&JwQ7bwL(I+OW{*r`Kl&n(l|yrV*9)K zCh$ZbJTHLf^Wgacb0B}0n#tc4%yibP-P)(@ZTa9`E<0roY|b-_%2mGoDUR-L$2_IhDWFw+d$=$7*v^D)h5M;Rqu%efL4N%y725FDY;5}L(81_VdyM|53%X`fW)^hq zpwqIz2eKx$pJ3Ypbf&$P_JDlNyuD|d&z-QfMtq6B@rj;;4Oy@7W%kSLZql-LKz3-i zW$WK*E9Q-@mr<)8@ET56viUap9rLhJpPk0Wda+UK0G}Y*LeZ5qIj=`%mk-?8jcaUVc{MJ;xep z@wa(<)p%d$ZlTX*^5lI6Z}$w3AP!93FS|!LeCw2Yns!&?$Gl@qMYgC(`1k28D!ikV z@$@684YjzNS+xP@{!dsFOnvatm$S#{iW~{gAm%sn*u?JA-4a7F*cT0+i6YJym_O!z z$2j+JhCln`jdo7vBWe$0U=HiD{zC;*X9G`ti8%7jzVDzeKU8SO-HT`Yl+0@#pcmqm zxpbAe^g$TErI_qg;}>`y{}5{^hyGijuGmY|iy~z)KI@?O_ATJipk_XloaMO=n?BCh zLU-U=uZCdel<2PKz2Kg@MgIhJD&=_|K53wiT+bZm9f2~)A3D-D^e5@ldFp#NayTk> zlWuX}yYQ91(?PD*QJ>wO+?mN2c7XTKj*48wMktSbDGzb1eS-B@DFZpeyG)dOS2up4 z{)y-dv>SEm@&a_?{o@kmIgVmZ>xi7Cj#_ut^a?sPN6K`n=!=qW#ut`uy0+T7;k@`H zx^YkRzQC3!Vt}?V-ky?r|KG%y)|Y!kePRCs{Ac2bvch}UefYMBg!lcMKc{wUAN_}% zdWrF4*?c28^)%M}zjCU_$*HWItvpjcNj_bae9GQHKAm&&sYhy7DPAk&(#M}-F4Z}? zE=Cl zKzWaE_L>@FYAcZSf}iEPV`b3UxaqbZMP90jJl+@!I#;R>{-iWrAawm9UA#nhurU_5 z=z4_i)sSv~iSA5eY`;Z^x}w{AbZp1UqlV6Z(`$?!4GF2=bV#Q5^WCws)zFPL##)7) z)^F|x>2Pl7c0GQrLU)GLwqG*kemQi5bmKxd9nt)TjUE0}q%k(UY;RWR4!d$Y%H_Uu zgLM3%jO`E~9V?gjEhyi&IQ2q1$cIITFfiMznlaUB=zL8#?v)Jrs^1vHFbo+@n-SX1 zYiL`qp`8-i*F*Wsarol0-JGh{ehxcp)YYX*^S%=1*5n)LM=V^&Kd{F&>9zEXQ_{Cd zB56HAUn{s-uk!wExK5d2lab^HUnEchsWg{I>Z@AvUXx#t}Gmx8aaK?lvy zGj2%VBe;%VVEY9Bhl77!@bMMspy~L;`x&vT4F#S}$0OdJmRP%HIq zjf*nY>=^p8cci@LgIN*x-KJc$Ze}5G|o2tm2p09$R!g@CHxg+fAX8?QIh;ItJ`kA-z%@!U= z+`0NpTX@W(uagjT`5&_IxJCbtg>SL&!;)|0^H~eOL-L3CofbZB;kLc+SHasPlwG?H z3C^-zvds=#Bp$ba3PUQ3p5vf7QXweMb$X2D*mFRBAM{ zt9vAItiNv{IlO0g!hCwDmUOB=*^m-xt>Q5!piDMv408S0+nMVc(lIcDd zy#{OP8X6ej6387%>6P8RgU1uyy=ib3WH{YBh(RWq8Brsd50p;yjwEd8;Z!C8*iZ;l z3(Gm|Je=xDbf=R8DQX5cgpN$(qfaB0q8%^9nWC&NwP_AjGa z9UIVO5(PGHLtBrx>{fVuk&j(`?1TzKluvzkVz_m*#gxY|>Hdf3uaG}-w3l&dl}o`7 zB>v5$q?;M)vxS&@vkZjdFSnIQbw`f>61W9DVnGQBJEL-tOo@E_wye(|a~{dG`Ut`) z-?gE2b;##b_$ockdIMa-;!5(@%ON;U=4g~pI?&YSjES#QSX?b7nzNX*%0bw$>nb0&=ahTjAhSMuL;a&SE- h0_i_qh0J>6zu#is5usU6-yTYMTQ-(#ct3X6{~LuCNb>*y literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/blkmap64_rb.c b/jni/e2fsprogs/lib/ext2fs/blkmap64_rb.c new file mode 100755 index 0000000..0df58dc --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/blkmap64_rb.c @@ -0,0 +1,998 @@ +/* + * blkmap64_rb.c --- Simple rb-tree implementation for bitmaps + * + * (C)2010 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_LINUX_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "bmap64.h" +#include "rbtree.h" + +#include + +struct bmap_rb_extent { + struct rb_node node; + __u64 start; + __u64 count; +}; + +struct ext2fs_rb_private { + struct rb_root root; + struct bmap_rb_extent *wcursor; + struct bmap_rb_extent *rcursor; + struct bmap_rb_extent *rcursor_next; +#ifdef ENABLE_BMAP_STATS_OPS + __u64 mark_hit; + __u64 test_hit; +#endif +}; + +inline static struct bmap_rb_extent *node_to_extent(struct rb_node *node) +{ + /* + * This depends on the fact the struct rb_node is at the + * beginning of the bmap_rb_extent structure. We use this + * instead of the ext2fs_rb_entry macro because it causes gcc + * -Wall to generate a huge amount of noise. + */ + return (struct bmap_rb_extent *) node; +} + +static int rb_insert_extent(__u64 start, __u64 count, + struct ext2fs_rb_private *); +static void rb_get_new_extent(struct bmap_rb_extent **, __u64, __u64); + +/* #define DEBUG_RB */ + +#ifdef DEBUG_RB +static void print_tree(struct rb_root *root) +{ + struct rb_node *node = NULL; + struct bmap_rb_extent *ext; + + fprintf(stderr, "\t\t\t=================================\n"); + node = ext2fs_rb_first(root); + for (node = ext2fs_rb_first(root); node != NULL; + node = ext2fs_rb_next(node)) { + ext = node_to_extent(node); + fprintf(stderr, "\t\t\t--> (%llu -> %llu)\n", + (unsigned long long) ext->start, + (unsigned long long) ext->start + ext->count); + } + fprintf(stderr, "\t\t\t=================================\n"); +} + +static void check_tree(struct rb_root *root, const char *msg) +{ + struct rb_node *node; + struct bmap_rb_extent *ext, *old = NULL; + + for (node = ext2fs_rb_first(root); node; + node = ext2fs_rb_next(node)) { + ext = node_to_extent(node); + if (ext->count == 0) { + fprintf(stderr, "Tree Error: count is zero\n"); + fprintf(stderr, "extent: %llu -> %llu (%llu)\n", + (unsigned long long) ext->start, + (unsigned long long) ext->start + ext->count, + (unsigned long long) ext->count); + goto err_out; + } + if (ext->start + ext->count < ext->start) { + fprintf(stderr, + "Tree Error: start or count is crazy\n"); + fprintf(stderr, "extent: %llu -> %llu (%llu)\n", + (unsigned long long) ext->start, + (unsigned long long) ext->start + ext->count, + (unsigned long long) ext->count); + goto err_out; + } + + if (old) { + if (old->start > ext->start) { + fprintf(stderr, "Tree Error: start is crazy\n"); + fprintf(stderr, "extent: %llu -> %llu (%llu)\n", + (unsigned long long) old->start, + (unsigned long long) old->start + old->count, + (unsigned long long) old->count); + fprintf(stderr, + "extent next: %llu -> %llu (%llu)\n", + (unsigned long long) ext->start, + (unsigned long long) ext->start + ext->count, + (unsigned long long) ext->count); + goto err_out; + } + if ((old->start + old->count) >= ext->start) { + fprintf(stderr, + "Tree Error: extent is crazy\n"); + fprintf(stderr, "extent: %llu -> %llu (%llu)\n", + (unsigned long long) old->start, + (unsigned long long) old->start + old->count, + (unsigned long long) old->count); + fprintf(stderr, + "extent next: %llu -> %llu (%llu)\n", + (unsigned long long) ext->start, + (unsigned long long) ext->start + ext->count, + (unsigned long long) ext->count); + goto err_out; + } + } + old = ext; + } + return; + +err_out: + fprintf(stderr, "%s\n", msg); + print_tree(root); + exit(1); +} +#else +#define check_tree(root, msg) do {} while (0) +#define print_tree(root) do {} while (0) +#endif + +static void rb_get_new_extent(struct bmap_rb_extent **ext, __u64 start, + __u64 count) +{ + struct bmap_rb_extent *new_ext; + int retval; + + retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent), + &new_ext); + if (retval) + abort(); + + new_ext->start = start; + new_ext->count = count; + *ext = new_ext; +} + +inline +static void rb_free_extent(struct ext2fs_rb_private *bp, + struct bmap_rb_extent *ext) +{ + if (bp->wcursor == ext) + bp->wcursor = NULL; + if (bp->rcursor == ext) + bp->rcursor = NULL; + if (bp->rcursor_next == ext) + bp->rcursor_next = NULL; + ext2fs_free_mem(&ext); +} + +static errcode_t rb_alloc_private_data (ext2fs_generic_bitmap_64 bitmap) +{ + struct ext2fs_rb_private *bp; + errcode_t retval; + + retval = ext2fs_get_mem(sizeof (struct ext2fs_rb_private), &bp); + if (retval) + return retval; + + bp->root = RB_ROOT; + bp->rcursor = NULL; + bp->rcursor_next = NULL; + bp->wcursor = NULL; + +#ifdef ENABLE_BMAP_STATS_OPS + bp->test_hit = 0; + bp->mark_hit = 0; +#endif + + bitmap->private = (void *) bp; + return 0; +} + +static errcode_t rb_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)), + ext2fs_generic_bitmap_64 bitmap) +{ + errcode_t retval; + + retval = rb_alloc_private_data (bitmap); + if (retval) + return retval; + + return 0; +} + +static void rb_free_tree(struct rb_root *root) +{ + struct bmap_rb_extent *ext; + struct rb_node *node, *next; + + for (node = ext2fs_rb_first(root); node; node = next) { + next = ext2fs_rb_next(node); + ext = node_to_extent(node); + ext2fs_rb_erase(node, root); + ext2fs_free_mem(&ext); + } +} + +static void rb_free_bmap(ext2fs_generic_bitmap_64 bitmap) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bitmap->private; + + rb_free_tree(&bp->root); + ext2fs_free_mem(&bp); + bp = 0; +} + +static errcode_t rb_copy_bmap(ext2fs_generic_bitmap_64 src, + ext2fs_generic_bitmap_64 dest) +{ + struct ext2fs_rb_private *src_bp, *dest_bp; + struct bmap_rb_extent *src_ext, *dest_ext; + struct rb_node *dest_node, *src_node, *dest_last, **n; + errcode_t retval = 0; + + retval = rb_alloc_private_data (dest); + if (retval) + return retval; + + src_bp = (struct ext2fs_rb_private *) src->private; + dest_bp = (struct ext2fs_rb_private *) dest->private; + src_bp->rcursor = NULL; + dest_bp->rcursor = NULL; + + src_node = ext2fs_rb_first(&src_bp->root); + while (src_node) { + src_ext = node_to_extent(src_node); + retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent), + &dest_ext); + if (retval) + break; + + memcpy(dest_ext, src_ext, sizeof(struct bmap_rb_extent)); + + dest_node = &dest_ext->node; + n = &dest_bp->root.rb_node; + + dest_last = NULL; + if (*n) { + dest_last = ext2fs_rb_last(&dest_bp->root); + n = &(dest_last)->rb_right; + } + + ext2fs_rb_link_node(dest_node, dest_last, n); + ext2fs_rb_insert_color(dest_node, &dest_bp->root); + + src_node = ext2fs_rb_next(src_node); + } + + return retval; +} + +static void rb_truncate(__u64 new_max, struct rb_root *root) +{ + struct bmap_rb_extent *ext; + struct rb_node *node; + + node = ext2fs_rb_last(root); + while (node) { + ext = node_to_extent(node); + + if ((ext->start + ext->count - 1) <= new_max) + break; + else if (ext->start > new_max) { + ext2fs_rb_erase(node, root); + ext2fs_free_mem(&ext); + node = ext2fs_rb_last(root); + continue; + } else + ext->count = new_max - ext->start + 1; + } +} + +static errcode_t rb_resize_bmap(ext2fs_generic_bitmap_64 bmap, + __u64 new_end, __u64 new_real_end) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bmap->private; + bp->rcursor = NULL; + bp->wcursor = NULL; + + rb_truncate(((new_end < bmap->end) ? new_end : bmap->end) - bmap->start, + &bp->root); + + bmap->end = new_end; + bmap->real_end = new_real_end; + + if (bmap->end < bmap->real_end) + rb_insert_extent(bmap->end + 1 - bmap->start, + bmap->real_end - bmap->end, bp); + return 0; + +} + +inline static int +rb_test_bit(struct ext2fs_rb_private *bp, __u64 bit) +{ + struct bmap_rb_extent *rcursor, *next_ext = NULL; + struct rb_node *parent = NULL, *next; + struct rb_node **n = &bp->root.rb_node; + struct bmap_rb_extent *ext; + + rcursor = bp->rcursor; + if (!rcursor) + goto search_tree; + + if (bit >= rcursor->start && bit < rcursor->start + rcursor->count) { +#ifdef ENABLE_BMAP_STATS_OPS + bp->test_hit++; +#endif + return 1; + } + + next_ext = bp->rcursor_next; + if (!next_ext) { + next = ext2fs_rb_next(&rcursor->node); + if (next) + next_ext = node_to_extent(next); + bp->rcursor_next = next_ext; + } + if (next_ext) { + if ((bit >= rcursor->start + rcursor->count) && + (bit < next_ext->start)) { +#ifdef BMAP_STATS_OPS + bp->test_hit++; +#endif + return 0; + } + } + bp->rcursor = NULL; + bp->rcursor_next = NULL; + + rcursor = bp->wcursor; + if (!rcursor) + goto search_tree; + + if (bit >= rcursor->start && bit < rcursor->start + rcursor->count) + return 1; + +search_tree: + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (bit < ext->start) + n = &(*n)->rb_left; + else if (bit >= (ext->start + ext->count)) + n = &(*n)->rb_right; + else { + bp->rcursor = ext; + bp->rcursor_next = NULL; + return 1; + } + } + return 0; +} + +static int rb_insert_extent(__u64 start, __u64 count, + struct ext2fs_rb_private *bp) +{ + struct rb_root *root = &bp->root; + struct rb_node *parent = NULL, **n = &root->rb_node; + struct rb_node *new_node, *node, *next; + struct bmap_rb_extent *new_ext; + struct bmap_rb_extent *ext; + int retval = 0; + + if (count == 0) + return 0; + + bp->rcursor_next = NULL; + ext = bp->wcursor; + if (ext) { + if (start >= ext->start && + start <= (ext->start + ext->count)) { +#ifdef ENABLE_BMAP_STATS_OPS + bp->mark_hit++; +#endif + goto got_extent; + } + } + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + + if (start < ext->start) { + n = &(*n)->rb_left; + } else if (start > (ext->start + ext->count)) { + n = &(*n)->rb_right; + } else { +got_extent: + if ((start + count) <= (ext->start + ext->count)) + return 1; + + if ((ext->start + ext->count) == start) + retval = 0; + else + retval = 1; + + count += (start - ext->start); + start = ext->start; + new_ext = ext; + new_node = &ext->node; + + goto skip_insert; + } + } + + rb_get_new_extent(&new_ext, start, count); + + new_node = &new_ext->node; + ext2fs_rb_link_node(new_node, parent, n); + ext2fs_rb_insert_color(new_node, root); + bp->wcursor = new_ext; + + node = ext2fs_rb_prev(new_node); + if (node) { + ext = node_to_extent(node); + if ((ext->start + ext->count) == start) { + start = ext->start; + count += ext->count; + ext2fs_rb_erase(node, root); + rb_free_extent(bp, ext); + } + } + +skip_insert: + /* See if we can merge extent to the right */ + for (node = ext2fs_rb_next(new_node); node != NULL; node = next) { + next = ext2fs_rb_next(node); + ext = node_to_extent(node); + + if ((ext->start + ext->count) <= start) + continue; + + /* No more merging */ + if ((start + count) < ext->start) + break; + + /* ext is embedded in new_ext interval */ + if ((start + count) >= (ext->start + ext->count)) { + ext2fs_rb_erase(node, root); + rb_free_extent(bp, ext); + continue; + } else { + /* merge ext with new_ext */ + count += ((ext->start + ext->count) - + (start + count)); + ext2fs_rb_erase(node, root); + rb_free_extent(bp, ext); + break; + } + } + + new_ext->start = start; + new_ext->count = count; + + return retval; +} + +static int rb_remove_extent(__u64 start, __u64 count, + struct ext2fs_rb_private *bp) +{ + struct rb_root *root = &bp->root; + struct rb_node *parent = NULL, **n = &root->rb_node; + struct rb_node *node; + struct bmap_rb_extent *ext; + __u64 new_start, new_count; + int retval = 0; + + if (ext2fs_rb_empty_root(root)) + return 0; + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (start < ext->start) { + n = &(*n)->rb_left; + continue; + } else if (start >= (ext->start + ext->count)) { + n = &(*n)->rb_right; + continue; + } + + if ((start > ext->start) && + (start + count) < (ext->start + ext->count)) { + /* We have to split extent into two */ + new_start = start + count; + new_count = (ext->start + ext->count) - new_start; + + ext->count = start - ext->start; + + rb_insert_extent(new_start, new_count, bp); + return 1; + } + + if ((start + count) >= (ext->start + ext->count)) { + ext->count = start - ext->start; + retval = 1; + } + + if (0 == ext->count) { + parent = ext2fs_rb_next(&ext->node); + ext2fs_rb_erase(&ext->node, root); + rb_free_extent(bp, ext); + break; + } + + if (start == ext->start) { + ext->start += count; + ext->count -= count; + return 1; + } + } + + /* See if we should delete or truncate extent on the right */ + for (; parent != NULL; parent = node) { + node = ext2fs_rb_next(parent); + ext = node_to_extent(parent); + if ((ext->start + ext->count) <= start) + continue; + + /* No more extents to be removed/truncated */ + if ((start + count) < ext->start) + break; + + /* The entire extent is within the region to be removed */ + if ((start + count) >= (ext->start + ext->count)) { + ext2fs_rb_erase(parent, root); + rb_free_extent(bp, ext); + retval = 1; + continue; + } else { + /* modify the last extent in region to be removed */ + ext->count -= ((start + count) - ext->start); + ext->start = start + count; + retval = 1; + break; + } + } + + return retval; +} + +static int rb_mark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + struct ext2fs_rb_private *bp; + int retval; + + bp = (struct ext2fs_rb_private *) bitmap->private; + arg -= bitmap->start; + + retval = rb_insert_extent(arg, 1, bp); + check_tree(&bp->root, __func__); + return retval; +} + +static int rb_unmark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + struct ext2fs_rb_private *bp; + int retval; + + bp = (struct ext2fs_rb_private *) bitmap->private; + arg -= bitmap->start; + + retval = rb_remove_extent(arg, 1, bp); + check_tree(&bp->root, __func__); + + return retval; +} + +inline +static int rb_test_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bitmap->private; + arg -= bitmap->start; + + return rb_test_bit(bp, arg); +} + +static void rb_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bitmap->private; + arg -= bitmap->start; + + rb_insert_extent(arg, num, bp); + check_tree(&bp->root, __func__); +} + +static void rb_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg, + unsigned int num) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bitmap->private; + arg -= bitmap->start; + + rb_remove_extent(arg, num, bp); + check_tree(&bp->root, __func__); +} + +static int rb_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap, + __u64 start, unsigned int len) +{ + struct rb_node *parent = NULL, **n; + struct rb_node *node, *next; + struct ext2fs_rb_private *bp; + struct bmap_rb_extent *ext; + int retval = 1; + + bp = (struct ext2fs_rb_private *) bitmap->private; + n = &bp->root.rb_node; + start -= bitmap->start; + + if (len == 0 || ext2fs_rb_empty_root(&bp->root)) + return 1; + + /* + * If we find nothing, we should examine whole extent, but + * when we find match, the extent is not clean, thus be return + * false. + */ + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (start < ext->start) { + n = &(*n)->rb_left; + } else if (start >= (ext->start + ext->count)) { + n = &(*n)->rb_right; + } else { + /* + * We found extent int the tree -> extent is not + * clean + */ + return 0; + } + } + + node = parent; + while (node) { + next = ext2fs_rb_next(node); + ext = node_to_extent(node); + node = next; + + if ((ext->start + ext->count) <= start) + continue; + + /* No more merging */ + if ((start + len) <= ext->start) + break; + + retval = 0; + break; + } + return retval; +} + +static errcode_t rb_set_bmap_range(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *in) +{ + struct ext2fs_rb_private *bp; + unsigned char *cp = in; + size_t i; + int first_set = -1; + + bp = (struct ext2fs_rb_private *) bitmap->private; + + for (i = 0; i < num; i++) { + if ((i & 7) == 0) { + unsigned char c = cp[i/8]; + if (c == 0xFF) { + if (first_set == -1) + first_set = i; + i += 7; + continue; + } + if ((c == 0x00) && (first_set == -1)) { + i += 7; + continue; + } + } + if (ext2fs_test_bit(i, in)) { + if (first_set == -1) + first_set = i; + continue; + } + if (first_set == -1) + continue; + + rb_insert_extent(start + first_set - bitmap->start, + i - first_set, bp); + check_tree(&bp->root, __func__); + first_set = -1; + } + if (first_set != -1) { + rb_insert_extent(start + first_set - bitmap->start, + num - first_set, bp); + check_tree(&bp->root, __func__); + } + + return 0; +} + +static errcode_t rb_get_bmap_range(ext2fs_generic_bitmap_64 bitmap, + __u64 start, size_t num, void *out) +{ + + struct rb_node *parent = NULL, *next, **n; + struct ext2fs_rb_private *bp; + struct bmap_rb_extent *ext; + __u64 count, pos; + + bp = (struct ext2fs_rb_private *) bitmap->private; + n = &bp->root.rb_node; + start -= bitmap->start; + + if (ext2fs_rb_empty_root(&bp->root)) + return 0; + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (start < ext->start) { + n = &(*n)->rb_left; + } else if (start >= (ext->start + ext->count)) { + n = &(*n)->rb_right; + } else + break; + } + + memset(out, 0, (num + 7) >> 3); + + for (; parent != NULL; parent = next) { + next = ext2fs_rb_next(parent); + ext = node_to_extent(parent); + + pos = ext->start; + count = ext->count; + if (pos >= start + num) + break; + if (pos < start) { + if (pos + count < start) + continue; + count -= start - pos; + pos = start; + } + if (pos + count > start + num) + count = start + num - pos; + + while (count > 0) { + if ((count >= 8) && + ((pos - start) % 8) == 0) { + int nbytes = count >> 3; + int offset = (pos - start) >> 3; + + memset(((char *) out) + offset, 0xFF, nbytes); + pos += nbytes << 3; + count -= nbytes << 3; + continue; + } + ext2fs_fast_set_bit64((pos - start), out); + pos++; + count--; + } + } + return 0; +} + +static void rb_clear_bmap(ext2fs_generic_bitmap_64 bitmap) +{ + struct ext2fs_rb_private *bp; + + bp = (struct ext2fs_rb_private *) bitmap->private; + + rb_free_tree(&bp->root); + bp->rcursor = NULL; + bp->rcursor_next = NULL; + bp->wcursor = NULL; + check_tree(&bp->root, __func__); +} + +static errcode_t rb_find_first_zero(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out) +{ + struct rb_node *parent = NULL, **n; + struct ext2fs_rb_private *bp; + struct bmap_rb_extent *ext; + + bp = (struct ext2fs_rb_private *) bitmap->private; + n = &bp->root.rb_node; + start -= bitmap->start; + end -= bitmap->start; + + if (start > end) + return EINVAL; + + if (ext2fs_rb_empty_root(&bp->root)) + return ENOENT; + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (start < ext->start) { + n = &(*n)->rb_left; + } else if (start >= (ext->start + ext->count)) { + n = &(*n)->rb_right; + } else if (ext->start + ext->count <= end) { + *out = ext->start + ext->count + bitmap->start; + return 0; + } else + return ENOENT; + } + + *out = start + bitmap->start; + return 0; +} + +static errcode_t rb_find_first_set(ext2fs_generic_bitmap_64 bitmap, + __u64 start, __u64 end, __u64 *out) +{ + struct rb_node *parent = NULL, **n; + struct rb_node *node; + struct ext2fs_rb_private *bp; + struct bmap_rb_extent *ext; + + bp = (struct ext2fs_rb_private *) bitmap->private; + n = &bp->root.rb_node; + start -= bitmap->start; + end -= bitmap->start; + + if (start > end) + return EINVAL; + + if (ext2fs_rb_empty_root(&bp->root)) + return ENOENT; + + while (*n) { + parent = *n; + ext = node_to_extent(parent); + if (start < ext->start) { + n = &(*n)->rb_left; + } else if (start >= (ext->start + ext->count)) { + n = &(*n)->rb_right; + } else { + /* The start bit is set */ + *out = start + bitmap->start; + return 0; + } + } + + node = parent; + ext = node_to_extent(node); + if (ext->start < start) { + node = ext2fs_rb_next(node); + if (node == NULL) + return ENOENT; + ext = node_to_extent(node); + } + if (ext->start <= end) { + *out = ext->start + bitmap->start; + return 0; + } + return ENOENT; +} + +#ifdef ENABLE_BMAP_STATS +static void rb_print_stats(ext2fs_generic_bitmap_64 bitmap) +{ + struct ext2fs_rb_private *bp; + struct rb_node *node = NULL; + struct bmap_rb_extent *ext; + __u64 count = 0; + __u64 max_size = 0; + __u64 min_size = ULONG_MAX; + __u64 size = 0, avg_size = 0; + double eff; +#ifdef ENABLE_BMAP_STATS_OPS + __u64 mark_all, test_all; + double m_hit = 0.0, t_hit = 0.0; +#endif + + bp = (struct ext2fs_rb_private *) bitmap->private; + + for (node = ext2fs_rb_first(&bp->root); node != NULL; + node = ext2fs_rb_next(node)) { + ext = node_to_extent(node); + count++; + if (ext->count > max_size) + max_size = ext->count; + if (ext->count < min_size) + min_size = ext->count; + size += ext->count; + } + + if (count) + avg_size = size / count; + if (min_size == ULONG_MAX) + min_size = 0; + eff = (double)((count * sizeof(struct bmap_rb_extent)) << 3) / + (bitmap->real_end - bitmap->start); +#ifdef ENABLE_BMAP_STATS_OPS + mark_all = bitmap->stats.mark_count + bitmap->stats.mark_ext_count; + test_all = bitmap->stats.test_count + bitmap->stats.test_ext_count; + if (mark_all) + m_hit = ((double)bp->mark_hit / mark_all) * 100; + if (test_all) + t_hit = ((double)bp->test_hit / test_all) * 100; + + fprintf(stderr, "%16llu cache hits on test (%.2f%%)\n" + "%16llu cache hits on mark (%.2f%%)\n", + bp->test_hit, t_hit, bp->mark_hit, m_hit); +#endif + fprintf(stderr, "%16llu extents (%llu bytes)\n", + (unsigned long long) count, (unsigned long long) + ((count * sizeof(struct bmap_rb_extent)) + + sizeof(struct ext2fs_rb_private))); + fprintf(stderr, "%16llu bits minimum size\n", + (unsigned long long) min_size); + fprintf(stderr, "%16llu bits maximum size\n" + "%16llu bits average size\n", + (unsigned long long) max_size, (unsigned long long) avg_size); + fprintf(stderr, "%16llu bits set in bitmap (out of %llu)\n", + (unsigned long long) size, + (unsigned long long) bitmap->real_end - bitmap->start); + fprintf(stderr, + "%16.4lf memory / bitmap bit memory ratio (bitarray = 1)\n", + eff); +} +#else +static void rb_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR((unused))) +{ +} +#endif + +struct ext2_bitmap_ops ext2fs_blkmap64_rbtree = { + .type = EXT2FS_BMAP64_RBTREE, + .new_bmap = rb_new_bmap, + .free_bmap = rb_free_bmap, + .copy_bmap = rb_copy_bmap, + .resize_bmap = rb_resize_bmap, + .mark_bmap = rb_mark_bmap, + .unmark_bmap = rb_unmark_bmap, + .test_bmap = rb_test_bmap, + .test_clear_bmap_extent = rb_test_clear_bmap_extent, + .mark_bmap_extent = rb_mark_bmap_extent, + .unmark_bmap_extent = rb_unmark_bmap_extent, + .set_bmap_range = rb_set_bmap_range, + .get_bmap_range = rb_get_bmap_range, + .clear_bmap = rb_clear_bmap, + .print_stats = rb_print_stats, + .find_first_zero = rb_find_first_zero, + .find_first_set = rb_find_first_set, +}; diff --git a/jni/e2fsprogs/lib/ext2fs/blkmap64_rb.o b/jni/e2fsprogs/lib/ext2fs/blkmap64_rb.o new file mode 100755 index 0000000000000000000000000000000000000000..5e67b5f1fc8c303fbaa1c9ed01c5f44770188ca8 GIT binary patch literal 14600 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 Mysl5a35w_c4__X1^8f$< literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/blknum.c b/jni/e2fsprogs/lib/ext2fs/blknum.c new file mode 100755 index 0000000..04839d8 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/blknum.c @@ -0,0 +1,606 @@ +/* + * blknum.c --- Functions to handle blk64_t and high/low 64-bit block + * number. + * + * Copyright IBM Corporation, 2007 + * Author Jose R. Santos + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#include "ext2fs.h" + +/* + * Return the group # of a block + */ +dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk) +{ + return (blk - fs->super->s_first_data_block) / + fs->super->s_blocks_per_group; +} + +/* + * Return the first block (inclusive) in a group + */ +blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group) +{ + return fs->super->s_first_data_block + + EXT2_GROUPS_TO_BLOCKS(fs->super, group); +} + +/* + * Return the last block (inclusive) in a group + */ +blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group) +{ + return (group == fs->group_desc_count - 1 ? + ext2fs_blocks_count(fs->super) - 1 : + ext2fs_group_first_block2(fs, group) + + (fs->super->s_blocks_per_group - 1)); +} + +/* + * Return the number of blocks in a group + */ +int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group) +{ + int num_blocks; + + if (group == fs->group_desc_count - 1) { + num_blocks = (ext2fs_blocks_count(fs->super) - + fs->super->s_first_data_block) % + fs->super->s_blocks_per_group; + if (!num_blocks) + num_blocks = fs->super->s_blocks_per_group; + } else + num_blocks = fs->super->s_blocks_per_group; + + return num_blocks; +} + +/* + * Return the inode data block count + */ +blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, + struct ext2_inode *inode) +{ + return (inode->i_blocks | + (ext2fs_has_feature_huge_file(fs->super) ? + (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) - + (inode->i_file_acl ? EXT2_CLUSTER_SIZE(fs->super) >> 9 : 0); +} + +/* + * Return the inode i_blocks count + */ +blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, + struct ext2_inode *inode) +{ + return (inode->i_blocks | + (ext2fs_has_feature_huge_file(fs->super) ? + (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)); +} + +/* + * Return the inode i_blocks in stat (512 byte) units + */ +blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs, + struct ext2_inode *inode) +{ + blk64_t ret = inode->i_blocks; + + if (ext2fs_has_feature_huge_file(fs->super)) { + ret += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32; + if (inode->i_flags & EXT4_HUGE_FILE_FL) + ret *= (fs->blocksize / 512); + } + return ret; +} + +/* + * Return the fs block count + */ +blk64_t ext2fs_blocks_count(struct ext2_super_block *super) +{ + return super->s_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_blocks_count_hi << 32 : 0); +} + +/* + * Set the fs block count + */ +void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk) +{ + super->s_blocks_count = blk; + if (ext2fs_has_feature_64bit(super)) + super->s_blocks_count_hi = (__u64) blk >> 32; +} + +/* + * Add to the current fs block count + */ +void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk) +{ + blk64_t tmp; + tmp = ext2fs_blocks_count(super) + blk; + ext2fs_blocks_count_set(super, tmp); +} + +/* + * Return the fs reserved block count + */ +blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super) +{ + return super->s_r_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_r_blocks_count_hi << 32 : 0); +} + +/* + * Set the fs reserved block count + */ +void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk) +{ + super->s_r_blocks_count = blk; + if (ext2fs_has_feature_64bit(super)) + super->s_r_blocks_count_hi = (__u64) blk >> 32; +} + +/* + * Add to the current reserved fs block count + */ +void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk) +{ + blk64_t tmp; + tmp = ext2fs_r_blocks_count(super) + blk; + ext2fs_r_blocks_count_set(super, tmp); +} + +/* + * Return the fs free block count + */ +blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super) +{ + return super->s_free_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_free_blocks_hi << 32 : 0); +} + +/* + * Set the fs free block count + */ +void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk) +{ + super->s_free_blocks_count = blk; + if (ext2fs_has_feature_64bit(super)) + super->s_free_blocks_hi = (__u64) blk >> 32; +} + +/* + * Add to the current free fs block count + */ +void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk) +{ + blk64_t tmp; + tmp = ext2fs_free_blocks_count(super) + blk; + ext2fs_free_blocks_count_set(super, tmp); +} + +/* + * Get a pointer to a block group descriptor. We need the explicit + * pointer to the group desc for code that swaps block group + * descriptors before writing them out, as it wants to make a copy and + * do the swap there. + */ +struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, + struct opaque_ext2_group_desc *gdp, + dgrp_t group) +{ + struct ext2_group_desc *ret_gdp; + errcode_t retval; + static char *buf = 0; + static unsigned bufsize = 0; + blk64_t blk; + int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; + int desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super); + + if (group > fs->group_desc_count) + return NULL; + if (gdp) + return (struct ext2_group_desc *)((char *)gdp + + group * desc_size); + /* + * If fs->group_desc wasn't read in when the file system was + * opened, then read it on demand here. + */ + if (bufsize < fs->blocksize) + ext2fs_free_mem(&buf); + if (!buf) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return NULL; + bufsize = fs->blocksize; + } + blk = ext2fs_descriptor_block_loc2(fs, fs->super->s_first_data_block, + group / desc_per_blk); + retval = io_channel_read_blk(fs->io, blk, 1, buf); + if (retval) + return NULL; + ret_gdp = (struct ext2_group_desc *) + (buf + ((group % desc_per_blk) * desc_size)); +#ifdef WORDS_BIGENDIAN + ext2fs_swap_group_desc2(fs, ret_gdp); +#endif + return ret_gdp; +} + +/* Do the same but as an ext4 group desc for internal use here */ +static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs, + struct opaque_ext2_group_desc *gdp, + dgrp_t group) +{ + return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group); +} + +/* + * Return the block bitmap checksum of a group + */ +__u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + __u32 csum; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + csum = gdp->bg_block_bitmap_csum_lo; + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) + csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16); + return csum; +} + +/* + * Return the block bitmap block of a group + */ +blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_block_bitmap | + (ext2fs_has_feature_64bit(fs->super) ? + (__u64)gdp->bg_block_bitmap_hi << 32 : 0); +} + +/* + * Set the block bitmap block of a group + */ +void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_block_bitmap = blk; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_block_bitmap_hi = (__u64) blk >> 32; +} + +/* + * Return the inode bitmap checksum of a group + */ +__u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + __u32 csum; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + csum = gdp->bg_inode_bitmap_csum_lo; + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) + csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16); + return csum; +} + +/* + * Return the inode bitmap block of a group + */ +blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_inode_bitmap | + (ext2fs_has_feature_64bit(fs->super) ? + (__u64) gdp->bg_inode_bitmap_hi << 32 : 0); +} + +/* + * Set the inode bitmap block of a group + */ +void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_inode_bitmap = blk; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_inode_bitmap_hi = (__u64) blk >> 32; +} + +/* + * Return the inode table block of a group + */ +blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_inode_table | + (ext2fs_has_feature_64bit(fs->super) ? + (__u64) gdp->bg_inode_table_hi << 32 : 0); +} + +/* + * Set the inode table block of a group + */ +void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_inode_table = blk; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_inode_table_hi = (__u64) blk >> 32; +} + +/* + * Return the free blocks count of a group + */ +__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_free_blocks_count | + (ext2fs_has_feature_64bit(fs->super) ? + (__u32) gdp->bg_free_blocks_count_hi << 16 : 0); +} + +/* + * Set the free blocks count of a group + */ +void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_free_blocks_count = n; + + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_free_blocks_count_hi = (__u32) n >> 16; +} + +/* + * Return the free inodes count of a group + */ +__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_free_inodes_count | + (ext2fs_has_feature_64bit(fs->super) ? + (__u32) gdp->bg_free_inodes_count_hi << 16 : 0); +} + +/* + * Set the free inodes count of a group + */ +void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_free_inodes_count = n; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_free_inodes_count_hi = (__u32) n >> 16; +} + +/* + * Return the used dirs count of a group + */ +__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_used_dirs_count | + (ext2fs_has_feature_64bit(fs->super) ? + (__u32) gdp->bg_used_dirs_count_hi << 16 : 0); +} + +/* + * Set the used dirs count of a group + */ +void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_used_dirs_count = n; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_used_dirs_count_hi = (__u32) n >> 16; +} + +/* + * Return the unused inodes count of a group + */ +__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_itable_unused | + (ext2fs_has_feature_64bit(fs->super) ? + (__u32) gdp->bg_itable_unused_hi << 16 : 0); +} + +/* + * Set the unused inodes count of a group + */ +void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_itable_unused = n; + if (ext2fs_has_feature_64bit(fs->super)) + gdp->bg_itable_unused_hi = (__u32) n >> 16; +} + +/* + * Get the flags for this block group + */ +__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_flags; +} + +/* + * Zero out the flags for this block group + */ +void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_flags = 0; + return; +} + +/* + * Get the value of a particular flag for this block group + */ +int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_flags & bg_flag; +} + +/* + * Set a flag or set of flags for this block group + */ +void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_flags |= bg_flags; + return; +} + +/* + * Clear a flag or set of flags for this block group + */ +void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_flags &= ~bg_flags; + return; +} + +/* + * Get the checksum for this block group + */ +__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + return gdp->bg_checksum; +} + +/* + * Set the checksum for this block group to a previously calculated value + */ +void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum) +{ + struct ext4_group_desc *gdp; + + gdp = ext4fs_group_desc(fs, fs->group_desc, group); + gdp->bg_checksum = checksum; + return; +} + +/* + * Get the acl block of a file + */ +blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode) +{ + blk64_t blk = inode->i_file_acl; + + if (fs && ext2fs_has_feature_64bit(fs->super)) + blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32; + return blk; +} + +/* + * Set the acl block of a file + */ +void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode, + blk64_t blk) +{ + inode->i_file_acl = blk; + if (fs && ext2fs_has_feature_64bit(fs->super)) + inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32; +} + +/* + * Set the size of the inode + */ +errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode, + ext2_off64_t size) +{ + if (size < 0) + return EINVAL; + + /* If writing a large inode, set the large_file or large_dir flag */ + if (ext2fs_needs_large_file_feature(size)) { + int dirty_sb = 0; + + if (LINUX_S_ISREG(inode->i_mode)) { + if (!ext2fs_has_feature_large_file(fs->super)) { + ext2fs_set_feature_large_file(fs->super); + dirty_sb = 1; + } + } else if (LINUX_S_ISDIR(inode->i_mode)) { + if (!ext2fs_has_feature_largedir(fs->super)) { + ext2fs_set_feature_largedir(fs->super); + dirty_sb = 1; + } + } else { + /* Only regular files get to be larger than 4GB */ + return EXT2_ET_FILE_TOO_BIG; + } + if (dirty_sb) { + if (fs->super->s_rev_level == EXT2_GOOD_OLD_REV) + ext2fs_update_dynamic_rev(fs); + ext2fs_mark_super_dirty(fs); + } + } + + inode->i_size = size & 0xffffffff; + inode->i_size_high = (size >> 32); + + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/blknum.o b/jni/e2fsprogs/lib/ext2fs/blknum.o new file mode 100755 index 0000000000000000000000000000000000000000..3ffd170f179c9d177e78b3def086a9b5f925a46c GIT binary patch literal 13256 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 +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct block_context { + ext2_filsys fs; + int (*func)(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t bcount, + blk64_t ref_blk, + int ref_offset, + void *priv_data); + e2_blkcnt_t bcount; + int bsize; + int flags; + errcode_t errcode; + char *ind_buf; + char *dind_buf; + char *tind_buf; + void *priv_data; +}; + +#define check_for_ro_violation_return(ctx, ret) \ + do { \ + if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \ + ((ret) & BLOCK_CHANGED)) { \ + (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \ + ret |= BLOCK_ABORT | BLOCK_ERROR; \ + return ret; \ + } \ + } while (0) + +#define check_for_ro_violation_goto(ctx, ret, label) \ + do { \ + if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \ + ((ret) & BLOCK_CHANGED)) { \ + (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \ + ret |= BLOCK_ABORT | BLOCK_ERROR; \ + goto label; \ + } \ + } while (0) + +static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + blk64_t blk64; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) { + blk64 = *ind_block; + ret = (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_IND, ref_block, + ref_offset, ctx->priv_data); + *ind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + if (!*ind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += limit; + return ret; + } + if (*ind_block >= ext2fs_blocks_count(ctx->fs->super) || + *ind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_IND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->ind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { + blk64 = *block_nr; + flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount, + *ind_block, offset, + ctx->priv_data); + *block_nr = blk64; + changed |= flags; + if (flags & BLOCK_ABORT) { + ret |= BLOCK_ABORT; + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { + if (*block_nr == 0) + goto skip_sparse; + blk64 = *block_nr; + flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount, + *ind_block, offset, + ctx->priv_data); + *block_nr = blk64; + changed |= flags; + if (flags & BLOCK_ABORT) { + ret |= BLOCK_ABORT; + break; + } + skip_sparse: + offset += sizeof(blk_t); + } + } + check_for_ro_violation_return(ctx, changed); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) { + blk64 = *ind_block; + ret |= (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_IND, ref_block, + ref_offset, ctx->priv_data); + *ind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + return ret; +} + +static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + blk64_t blk64; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | + BLOCK_FLAG_DATA_ONLY))) { + blk64 = *dind_block; + ret = (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_DIND, ref_block, + ref_offset, ctx->priv_data); + *dind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + if (!*dind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += limit*limit; + return ret; + } + if (*dind_block >= ext2fs_blocks_count(ctx->fs->super) || + *dind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->dind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, block_nr++) { + flags = block_iterate_ind(block_nr, + *dind_block, offset, + ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, block_nr++) { + if (*block_nr == 0) { + ctx->bcount += limit; + continue; + } + flags = block_iterate_ind(block_nr, + *dind_block, offset, + ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } + check_for_ro_violation_return(ctx, changed); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) { + blk64 = *dind_block; + ret |= (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_DIND, ref_block, + ref_offset, ctx->priv_data); + *dind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + return ret; +} + +static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + blk64_t blk64; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | + BLOCK_FLAG_DATA_ONLY))) { + blk64 = *tind_block; + ret = (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_TIND, ref_block, + ref_offset, ctx->priv_data); + *tind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + if (!*tind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += ((unsigned long long) limit)*limit*limit; + return ret; + } + if (*tind_block >= ext2fs_blocks_count(ctx->fs->super) || + *tind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->tind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, block_nr++) { + flags = block_iterate_dind(block_nr, + *tind_block, + offset, ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, block_nr++) { + if (*block_nr == 0) { + ctx->bcount += limit*limit; + continue; + } + flags = block_iterate_dind(block_nr, + *tind_block, + offset, ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } + check_for_ro_violation_return(ctx, changed); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) { + blk64 = *tind_block; + ret |= (*ctx->func)(ctx->fs, &blk64, + BLOCK_COUNT_TIND, ref_block, + ref_offset, ctx->priv_data); + *tind_block = blk64; + } + check_for_ro_violation_return(ctx, ret); + return ret; +} + +errcode_t ext2fs_block_iterate3(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data) +{ + int i; + int r, ret = 0; + struct ext2_inode inode; + errcode_t retval; + struct block_context ctx; + int limit; + blk64_t blk64; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + ctx.errcode = ext2fs_read_inode(fs, ino, &inode); + if (ctx.errcode) + return ctx.errcode; + + /* + * An inode with inline data has no blocks over which to + * iterate, so return an error code indicating this fact. + */ + if (inode.i_flags & EXT4_INLINE_DATA_FL) + return EXT2_ET_INLINE_DATA_CANT_ITERATE; + + /* + * Check to see if we need to limit large files + */ + if (flags & BLOCK_FLAG_NO_LARGE) { + if (!LINUX_S_ISDIR(inode.i_mode) && + (inode.i_size_high != 0)) + return EXT2_ET_FILE_TOO_BIG; + } + + limit = fs->blocksize >> 2; + + ctx.fs = fs; + ctx.func = func; + ctx.priv_data = priv_data; + ctx.flags = flags; + ctx.bcount = 0; + if (block_buf) { + ctx.ind_buf = block_buf; + } else { + retval = ext2fs_get_array(3, fs->blocksize, &ctx.ind_buf); + if (retval) + return retval; + } + ctx.dind_buf = ctx.ind_buf + fs->blocksize; + ctx.tind_buf = ctx.dind_buf + fs->blocksize; + + /* + * Iterate over the HURD translator block (if present) + */ + if ((fs->super->s_creator_os == EXT2_OS_HURD) && + !(flags & BLOCK_FLAG_DATA_ONLY)) { + if (inode.osd1.hurd1.h_i_translator) { + blk64 = inode.osd1.hurd1.h_i_translator; + ret |= (*ctx.func)(fs, &blk64, + BLOCK_COUNT_TRANSLATOR, + 0, 0, priv_data); + inode.osd1.hurd1.h_i_translator = (blk_t) blk64; + if (ret & BLOCK_ABORT) + goto abort_exit; + check_for_ro_violation_goto(&ctx, ret, abort_exit); + } + } + + if (inode.i_flags & EXT4_EXTENTS_FL) { + ext2_extent_handle_t handle; + struct ext2fs_extent extent, next; + e2_blkcnt_t blockcnt = 0; + blk64_t blk, new_blk; + int op = EXT2_EXTENT_ROOT; + int uninit; + unsigned int j; + + ctx.errcode = ext2fs_extent_open2(fs, ino, &inode, &handle); + if (ctx.errcode) + goto abort_exit; + + while (1) { + if (op == EXT2_EXTENT_CURRENT) + ctx.errcode = 0; + else + ctx.errcode = ext2fs_extent_get(handle, op, + &extent); + if (ctx.errcode) { + if (ctx.errcode != EXT2_ET_EXTENT_NO_NEXT) + break; + ctx.errcode = 0; + if (!(flags & BLOCK_FLAG_APPEND)) + break; + next_block_set: + blk = 0; + r = (*ctx.func)(fs, &blk, blockcnt, + 0, 0, priv_data); + ret |= r; + check_for_ro_violation_goto(&ctx, ret, + extent_done); + if (r & BLOCK_CHANGED) { + ctx.errcode = + ext2fs_extent_set_bmap(handle, + (blk64_t) blockcnt++, + (blk64_t) blk, 0); + if (ctx.errcode || (ret & BLOCK_ABORT)) + break; + if (blk) + goto next_block_set; + } + break; + } + + op = EXT2_EXTENT_NEXT; + blk = extent.e_pblk; + if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) { + if (ctx.flags & BLOCK_FLAG_DATA_ONLY) + continue; + if ((!(extent.e_flags & + EXT2_EXTENT_FLAGS_SECOND_VISIT) && + !(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)) || + ((extent.e_flags & + EXT2_EXTENT_FLAGS_SECOND_VISIT) && + (ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE))) { + ret |= (*ctx.func)(fs, &blk, + -1, 0, 0, priv_data); + if (ret & BLOCK_CHANGED) { + extent.e_pblk = blk; + ctx.errcode = + ext2fs_extent_replace(handle, 0, &extent); + if (ctx.errcode) + break; + } + if (ret & BLOCK_ABORT) + break; + } + continue; + } + uninit = 0; + if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) + uninit = EXT2_EXTENT_SET_BMAP_UNINIT; + + /* + * Get the next extent before we start messing + * with the current extent + */ + retval = ext2fs_extent_get(handle, op, &next); + +#if 0 + printf("lblk %llu pblk %llu len %d blockcnt %llu\n", + extent.e_lblk, extent.e_pblk, + extent.e_len, blockcnt); +#endif + if (extent.e_lblk + extent.e_len <= (blk64_t) blockcnt) + continue; + if (extent.e_lblk > (blk64_t) blockcnt) + blockcnt = extent.e_lblk; + j = blockcnt - extent.e_lblk; + blk += j; + for (blockcnt = extent.e_lblk, j = 0; + j < extent.e_len; + blk++, blockcnt++, j++) { + new_blk = blk; + r = (*ctx.func)(fs, &new_blk, blockcnt, + 0, 0, priv_data); + ret |= r; + check_for_ro_violation_goto(&ctx, ret, + extent_done); + if (r & BLOCK_CHANGED) { + ctx.errcode = + ext2fs_extent_set_bmap(handle, + (blk64_t) blockcnt, + new_blk, uninit); + if (ctx.errcode) + goto extent_done; + } + if (ret & BLOCK_ABORT) + goto extent_done; + } + if (retval == 0) { + extent = next; + op = EXT2_EXTENT_CURRENT; + } + } + + extent_done: + ext2fs_extent_free(handle); + ret |= BLOCK_ERROR; /* ctx.errcode is always valid here */ + goto errout; + } + + /* + * Iterate over normal data blocks + */ + for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) { + if (inode.i_block[i] || (flags & BLOCK_FLAG_APPEND)) { + blk64 = inode.i_block[i]; + ret |= (*ctx.func)(fs, &blk64, ctx.bcount, 0, i, + priv_data); + inode.i_block[i] = (blk_t) blk64; + if (ret & BLOCK_ABORT) + goto abort_exit; + } + } + check_for_ro_violation_goto(&ctx, ret, abort_exit); + if (inode.i_block[EXT2_IND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_ind(&inode.i_block[EXT2_IND_BLOCK], + 0, EXT2_IND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } else + ctx.bcount += limit; + if (inode.i_block[EXT2_DIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_dind(&inode.i_block[EXT2_DIND_BLOCK], + 0, EXT2_DIND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } else + ctx.bcount += limit * limit; + if (inode.i_block[EXT2_TIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_tind(&inode.i_block[EXT2_TIND_BLOCK], + 0, EXT2_TIND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } + +abort_exit: + if (ret & BLOCK_CHANGED) { + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) { + ret |= BLOCK_ERROR; + ctx.errcode = retval; + } + } +errout: + if (!block_buf) + ext2fs_free_mem(&ctx.ind_buf); + + return (ret & BLOCK_ERROR) ? ctx.errcode : 0; +} + +/* + * Emulate the old ext2fs_block_iterate function! + */ + +struct xlate64 { + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_blk, + int ref_offset, + void *priv_data); + void *real_private; +}; + +static int xlate64_func(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt, blk64_t ref_blk, + int ref_offset, void *priv_data) +{ + struct xlate64 *xl = (struct xlate64 *) priv_data; + int ret; + blk_t block32 = *blocknr; + + ret = (*xl->func)(fs, &block32, blockcnt, (blk_t) ref_blk, ref_offset, + xl->real_private); + *blocknr = block32; + return ret; +} + +errcode_t ext2fs_block_iterate2(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data) +{ + struct xlate64 xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_block_iterate3(fs, ino, flags, block_buf, + xlate64_func, &xl); +} + + +struct xlate { + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int bcount, + void *priv_data); + void *real_private; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct xlate *xl = (struct xlate *) priv_data; + + return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); +} + +errcode_t ext2fs_block_iterate(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int blockcnt, + void *priv_data), + void *priv_data) +{ + struct xlate xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, + block_buf, xlate_func, &xl); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/block.o b/jni/e2fsprogs/lib/ext2fs/block.o new file mode 100755 index 0000000000000000000000000000000000000000..c43b00d7561e8c856659f8eb1a30619e29c79578 GIT binary patch literal 9904 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/bmap.c b/jni/e2fsprogs/lib/ext2fs/bmap.c new file mode 100755 index 0000000..65c45c5 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/bmap.c @@ -0,0 +1,499 @@ +/* + * bmap.c --- logical to physical block mapping + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS) +#define _BMAP_INLINE_ __inline__ +#else +#define _BMAP_INLINE_ +#endif + +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, int bmap_flags, + blk_t block, blk_t *phys_blk); + +#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) + +static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags, + blk_t ind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + errcode_t retval; + blk_t b; + + if (!ind) { + if (flags & BMAP_SET) + return EXT2_ET_SET_BMAP_NO_IND; + *ret_blk = 0; + return 0; + } + retval = io_channel_read_blk(fs->io, ind, 1, block_buf); + if (retval) + return retval; + + if (flags & BMAP_SET) { + b = *ret_blk; +#ifdef WORDS_BIGENDIAN + b = ext2fs_swab32(b); +#endif + ((blk_t *) block_buf)[nr] = b; + return io_channel_write_blk(fs->io, ind, 1, block_buf); + } + + b = ((blk_t *) block_buf)[nr]; + +#ifdef WORDS_BIGENDIAN + b = ext2fs_swab32(b); +#endif + + if (!b && (flags & BMAP_ALLOC)) { + b = nr ? ext2fs_le32_to_cpu(((blk_t *)block_buf)[nr - 1]) : ind; + retval = ext2fs_alloc_block(fs, b, + block_buf + fs->blocksize, &b); + if (retval) + return retval; + +#ifdef WORDS_BIGENDIAN + ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); +#else + ((blk_t *) block_buf)[nr] = b; +#endif + + retval = io_channel_write_blk(fs->io, ind, 1, block_buf); + if (retval) + return retval; + + (*blocks_alloc)++; + } + + *ret_blk = b; + return 0; +} + +static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags, + blk_t dind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + blk_t b = 0; + errcode_t retval; + blk_t addr_per_block; + + addr_per_block = (blk_t) fs->blocksize >> 2; + + retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, + blocks_alloc, nr / addr_per_block, &b); + if (retval) + return retval; + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, + nr % addr_per_block, ret_blk); + return retval; +} + +static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags, + blk_t tind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + blk_t b = 0; + errcode_t retval; + blk_t addr_per_block; + + addr_per_block = (blk_t) fs->blocksize >> 2; + + retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, + blocks_alloc, nr / addr_per_block, &b); + if (retval) + return retval; + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, + nr % addr_per_block, ret_blk); + return retval; +} + +static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + char *block_buf, int bmap_flags, blk64_t block, + int *ret_flags, int *blocks_alloc, + blk64_t *phys_blk); + +static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + blk64_t lblk, blk64_t *phys_blk) +{ + blk64_t base_block, pblock = 0; + int i; + + if (!ext2fs_has_feature_bigalloc(fs->super)) + return 0; + + base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs); + /* + * Except for the logical block (lblk) that was passed in, search all + * blocks in this logical cluster for a mapping to a physical cluster. + * If any such map exists, calculate the physical block that maps to + * the logical block and return that. + * + * The old code wouldn't even look if (block % cluster_ratio) == 0; + * this is incorrect if we're allocating blocks in reverse order. + */ + for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) { + if (base_block + i == lblk) + continue; + extent_bmap(fs, ino, inode, handle, 0, 0, + base_block + i, 0, 0, &pblock); + if (pblock) + break; + } + if (pblock == 0) + return 0; + *phys_blk = pblock - i + (lblk - base_block); + return 0; +} + +/* Try to map a logical block to an already-allocated physical cluster. */ +errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t lblk, + blk64_t *pblk) +{ + ext2_extent_handle_t handle; + errcode_t retval; + + /* Need bigalloc and extents to be enabled */ + *pblk = 0; + if (!ext2fs_has_feature_bigalloc(fs->super) || + !(inode->i_flags & EXT4_EXTENTS_FL)) + return 0; + + retval = ext2fs_extent_open2(fs, ino, inode, &handle); + if (retval) + goto out; + + retval = implied_cluster_alloc(fs, ino, inode, handle, lblk, pblk); + if (retval) + goto out2; + +out2: + ext2fs_extent_free(handle); +out: + return retval; +} + +static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + char *block_buf, int bmap_flags, blk64_t block, + int *ret_flags, int *blocks_alloc, + blk64_t *phys_blk) +{ + struct blk_alloc_ctx alloc_ctx; + struct ext2fs_extent extent; + unsigned int offset; + errcode_t retval = 0; + blk64_t blk64 = 0; + int alloc = 0; + int set_flags; + + set_flags = bmap_flags & BMAP_UNINIT ? EXT2_EXTENT_SET_BMAP_UNINIT : 0; + + if (bmap_flags & BMAP_SET) { + retval = ext2fs_extent_set_bmap(handle, block, + *phys_blk, set_flags); + return retval; + } + retval = ext2fs_extent_goto(handle, block); + if (retval) { + /* If the extent is not found, return phys_blk = 0 */ + if (retval == EXT2_ET_EXTENT_NOT_FOUND) { + extent.e_lblk = block; + goto got_block; + } + return retval; + } + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval) + return retval; + offset = block - extent.e_lblk; + if (block >= extent.e_lblk && (offset <= extent.e_len)) { + *phys_blk = extent.e_pblk + offset; + if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) + *ret_flags |= BMAP_RET_UNINIT; + } +got_block: + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { + implied_cluster_alloc(fs, ino, inode, handle, block, &blk64); + if (blk64) + goto set_extent; + retval = extent_bmap(fs, ino, inode, handle, block_buf, + 0, block-1, 0, blocks_alloc, &blk64); + if (retval) + blk64 = ext2fs_find_inode_goal(fs, ino, inode, block); + alloc_ctx.ino = ino; + alloc_ctx.inode = inode; + alloc_ctx.lblk = extent.e_lblk; + alloc_ctx.flags = BLOCK_ALLOC_DATA; + retval = ext2fs_alloc_block3(fs, blk64, block_buf, &blk64, + &alloc_ctx); + if (retval) + return retval; + blk64 &= ~EXT2FS_CLUSTER_MASK(fs); + blk64 += EXT2FS_CLUSTER_MASK(fs) & block; + alloc++; + set_extent: + retval = ext2fs_extent_set_bmap(handle, block, + blk64, set_flags); + if (retval) { + ext2fs_block_alloc_stats2(fs, blk64, -1); + return retval; + } + /* Update inode after setting extent */ + retval = ext2fs_read_inode(fs, ino, inode); + if (retval) + return retval; + *blocks_alloc += alloc; + *phys_blk = blk64; + } + return 0; +} + +int ext2fs_file_block_offset_too_big(ext2_filsys fs, + struct ext2_inode *inode, + blk64_t offset) +{ + blk64_t addr_per_block, max_map_block; + + /* Kernel seems to cut us off at 4294967294 blocks */ + if (offset >= (1ULL << 32) - 1) + return 1; + + if (inode->i_flags & EXT4_EXTENTS_FL) + return 0; + + addr_per_block = fs->blocksize >> 2; + max_map_block = addr_per_block; + max_map_block += addr_per_block * addr_per_block; + max_map_block += addr_per_block * addr_per_block * addr_per_block; + max_map_block += 12; + + return offset >= max_map_block; +} + +errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + char *block_buf, int bmap_flags, blk64_t block, + int *ret_flags, blk64_t *phys_blk) +{ + struct ext2_inode inode_buf; + ext2_extent_handle_t handle = 0; + blk_t addr_per_block; + blk_t b, blk32; + blk64_t b64; + char *buf = 0; + errcode_t retval = 0; + int blocks_alloc = 0, inode_dirty = 0; + struct blk_alloc_ctx alloc_ctx = { + .ino = ino, + .inode = inode, + .lblk = 0, + .flags = BLOCK_ALLOC_DATA, + }; + + if (!(bmap_flags & BMAP_SET)) + *phys_blk = 0; + + if (ret_flags) + *ret_flags = 0; + + /* Read inode structure if necessary */ + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + addr_per_block = (blk_t) fs->blocksize >> 2; + + if (ext2fs_file_block_offset_too_big(fs, inode, block)) + return EXT2_ET_FILE_TOO_BIG; + + /* + * If an inode has inline data, that means that it doesn't have + * any blocks and we shouldn't map any blocks for it. + */ + if (inode->i_flags & EXT4_INLINE_DATA_FL) + return EXT2_ET_INLINE_DATA_NO_BLOCK; + + if (!block_buf) { + retval = ext2fs_get_array(2, fs->blocksize, &buf); + if (retval) + return retval; + block_buf = buf; + } + + if (inode->i_flags & EXT4_EXTENTS_FL) { + retval = ext2fs_extent_open2(fs, ino, inode, &handle); + if (retval) + goto done; + retval = extent_bmap(fs, ino, inode, handle, block_buf, + bmap_flags, block, ret_flags, + &blocks_alloc, phys_blk); + goto done; + } + + if (block < EXT2_NDIR_BLOCKS) { + if (bmap_flags & BMAP_SET) { + b = *phys_blk; + inode_bmap(inode, block) = b; + inode_dirty++; + goto done; + } + + *phys_blk = inode_bmap(inode, block); + b = block ? inode_bmap(inode, block - 1) : + ext2fs_find_inode_goal(fs, ino, inode, block); + + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { + b64 = b; + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, + &alloc_ctx); + b = b64; + if (retval) + goto done; + inode_bmap(inode, block) = b; + blocks_alloc++; + *phys_blk = b; + } + goto done; + } + + /* Indirect block */ + block -= EXT2_NDIR_BLOCKS; + blk32 = *phys_blk; + if (block < addr_per_block) { + b = inode_bmap(inode, EXT2_IND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_IND_BLOCK-1); + b64 = b; + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, + &alloc_ctx); + b = b64; + if (retval) + goto done; + inode_bmap(inode, EXT2_IND_BLOCK) = b; + blocks_alloc++; + } + retval = block_ind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, &blk32); + if (retval == 0) + *phys_blk = blk32; + goto done; + } + + /* Doubly indirect block */ + block -= addr_per_block; + if (block < addr_per_block * addr_per_block) { + b = inode_bmap(inode, EXT2_DIND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_IND_BLOCK); + b64 = b; + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, + &alloc_ctx); + b = b64; + if (retval) + goto done; + inode_bmap(inode, EXT2_DIND_BLOCK) = b; + blocks_alloc++; + } + retval = block_dind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, &blk32); + if (retval == 0) + *phys_blk = blk32; + goto done; + } + + /* Triply indirect block */ + block -= addr_per_block * addr_per_block; + b = inode_bmap(inode, EXT2_TIND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_DIND_BLOCK); + b64 = b; + retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, + &alloc_ctx); + b = b64; + if (retval) + goto done; + inode_bmap(inode, EXT2_TIND_BLOCK) = b; + blocks_alloc++; + } + retval = block_tind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, &blk32); + if (retval == 0) + *phys_blk = blk32; +done: + if (*phys_blk && retval == 0 && (bmap_flags & BMAP_ZERO)) + retval = ext2fs_zero_blocks2(fs, *phys_blk, 1, NULL, NULL); + if (buf) + ext2fs_free_mem(&buf); + if (handle) + ext2fs_extent_free(handle); + if ((retval == 0) && (blocks_alloc || inode_dirty)) { + ext2fs_iblk_add_blocks(fs, inode, blocks_alloc); + retval = ext2fs_write_inode(fs, ino, inode); + } + return retval; +} + +errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + char *block_buf, int bmap_flags, blk_t block, + blk_t *phys_blk) +{ + errcode_t ret; + blk64_t ret_blk = *phys_blk; + + ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block, + 0, &ret_blk); + if (ret) + return ret; + if (ret_blk >= ((long long) 1 << 32)) + return EOVERFLOW; + *phys_blk = ret_blk; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/bmap.o b/jni/e2fsprogs/lib/ext2fs/bmap.o new file mode 100755 index 0000000000000000000000000000000000000000..96edf78abc4f8c1416b1e02ae9554b9d68c8a1ae GIT binary patch literal 8064 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 D^gXlk literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/bmove.c b/jni/e2fsprogs/lib/ext2fs/bmove.c new file mode 100755 index 0000000..e2ea405 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/bmove.c @@ -0,0 +1,167 @@ +/* + * bmove.c --- Move blocks around to make way for a particular + * filesystem structure. + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +struct process_block_struct { + ext2_ino_t ino; + struct ext2_inode * inode; + ext2fs_block_bitmap reserve; + ext2fs_block_bitmap alloc_map; + errcode_t error; + char *buf; + int add_dir; + int flags; +}; + +static int process_block(ext2_filsys fs, blk64_t *block_nr, + e2_blkcnt_t blockcnt, blk64_t ref_block, + int ref_offset, void *priv_data) +{ + struct process_block_struct *pb; + errcode_t retval; + int ret; + blk64_t block, orig; + + pb = (struct process_block_struct *) priv_data; + block = orig = *block_nr; + ret = 0; + + /* + * Let's see if this is one which we need to relocate + */ + if (ext2fs_test_block_bitmap2(pb->reserve, block)) { + do { + if (++block >= ext2fs_blocks_count(fs->super)) + block = fs->super->s_first_data_block; + if (block == orig) { + pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; + return BLOCK_ABORT; + } + } while (ext2fs_test_block_bitmap2(pb->reserve, block) || + ext2fs_test_block_bitmap2(pb->alloc_map, block)); + + retval = io_channel_read_blk64(fs->io, orig, 1, pb->buf); + if (retval) { + pb->error = retval; + return BLOCK_ABORT; + } + retval = io_channel_write_blk64(fs->io, block, 1, pb->buf); + if (retval) { + pb->error = retval; + return BLOCK_ABORT; + } + *block_nr = block; + ext2fs_mark_block_bitmap2(pb->alloc_map, block); + ret = BLOCK_CHANGED; + if (pb->flags & EXT2_BMOVE_DEBUG) + printf("ino=%u, blockcnt=%lld, %llu->%llu\n", + (unsigned) pb->ino, blockcnt, + (unsigned long long) orig, + (unsigned long long) block); + } + if (pb->add_dir) { + retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, + block, blockcnt); + if (retval) { + pb->error = retval; + ret |= BLOCK_ABORT; + } + } + return ret; +} + +errcode_t ext2fs_move_blocks(ext2_filsys fs, + ext2fs_block_bitmap reserve, + ext2fs_block_bitmap alloc_map, + int flags) +{ + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + struct process_block_struct pb; + ext2_inode_scan scan; + char *block_buf; + + retval = ext2fs_open_inode_scan(fs, 0, &scan); + if (retval) + return retval; + + pb.reserve = reserve; + pb.error = 0; + pb.alloc_map = alloc_map ? alloc_map : fs->block_map; + pb.flags = flags; + + retval = ext2fs_get_array(4, fs->blocksize, &block_buf); + if (retval) + return retval; + pb.buf = block_buf + fs->blocksize * 3; + + /* + * If GET_DBLIST is set in the flags field, then we should + * gather directory block information while we're doing the + * block move. + */ + if (flags & EXT2_BMOVE_GET_DBLIST) { + if (fs->dblist) { + ext2fs_free_dblist(fs->dblist); + fs->dblist = NULL; + } + retval = ext2fs_init_dblist(fs, 0); + if (retval) + return retval; + } + + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) + return retval; + + while (ino) { + if ((inode.i_links_count == 0) || + !ext2fs_inode_has_valid_blocks2(fs, &inode)) + goto next; + + pb.ino = ino; + pb.inode = &inode; + + pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && + flags & EXT2_BMOVE_GET_DBLIST); + + retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, + process_block, &pb); + if (retval) + return retval; + if (pb.error) + return pb.error; + + next: + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) + goto next; + } + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/brel_ma.c b/jni/e2fsprogs/lib/ext2fs/brel_ma.c new file mode 100755 index 0000000..a12afae --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/brel_ma.c @@ -0,0 +1,199 @@ +/* + * brel_ma.c + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * TODO: rewrite to not use a direct array!!! (Fortunately this + * module isn't really used yet.) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "brel.h" + +static errcode_t bma_put(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_get(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_start_iter(ext2_brel brel); +static errcode_t bma_next(ext2_brel brel, blk64_t *old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_move(ext2_brel brel, blk64_t old, blk64_t new); +static errcode_t bma_delete(ext2_brel brel, blk64_t old); +static errcode_t bma_free(ext2_brel brel); + +struct brel_ma { + __u32 magic; + blk64_t max_block; + struct ext2_block_relocate_entry *entries; +}; + +errcode_t ext2fs_brel_memarray_create(char *name, blk64_t max_block, + ext2_brel *new_brel) +{ + ext2_brel brel = 0; + errcode_t retval; + struct brel_ma *ma = 0; + size_t size; + + *new_brel = 0; + + /* + * Allocate memory structures + */ + retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), + &brel); + if (retval) + goto errout; + memset(brel, 0, sizeof(struct ext2_block_relocation_table)); + + retval = ext2fs_get_mem(strlen(name)+1, &brel->name); + if (retval) + goto errout; + strcpy(brel->name, name); + + retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); + if (retval) + goto errout; + memset(ma, 0, sizeof(struct brel_ma)); + brel->priv_data = ma; + + size = (size_t) (sizeof(struct ext2_block_relocate_entry) * + (max_block+1)); + retval = ext2fs_get_array(max_block+1, + sizeof(struct ext2_block_relocate_entry), &ma->entries); + if (retval) + goto errout; + memset(ma->entries, 0, size); + ma->max_block = max_block; + + /* + * Fill in the brel data structure + */ + brel->put = bma_put; + brel->get = bma_get; + brel->start_iter = bma_start_iter; + brel->next = bma_next; + brel->move = bma_move; + brel->delete = bma_delete; + brel->free = bma_free; + + *new_brel = brel; + return 0; + +errout: + bma_free(brel); + return retval; +} + +static errcode_t bma_put(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + ma->entries[(unsigned)old] = *ent; + return 0; +} + +static errcode_t bma_get(ext2_brel brel, blk64_t old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + *ent = ma->entries[old]; + return 0; +} + +static errcode_t bma_start_iter(ext2_brel brel) +{ + brel->current = 0; + return 0; +} + +static errcode_t bma_next(ext2_brel brel, blk64_t *old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + while (++brel->current < ma->max_block) { + if (ma->entries[(unsigned)brel->current].new == 0) + continue; + *old = brel->current; + *ent = ma->entries[(unsigned)brel->current]; + return 0; + } + *old = 0; + return 0; +} + +static errcode_t bma_move(ext2_brel brel, blk64_t old, blk64_t new) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if ((old > ma->max_block) || (new > ma->max_block)) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + ma->entries[(unsigned)new] = ma->entries[old]; + ma->entries[(unsigned)old].new = 0; + return 0; +} + +static errcode_t bma_delete(ext2_brel brel, blk64_t old) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + ma->entries[(unsigned)old].new = 0; + return 0; +} + +static errcode_t bma_free(ext2_brel brel) +{ + struct brel_ma *ma; + + if (!brel) + return 0; + + ma = brel->priv_data; + + if (ma) { + if (ma->entries) + ext2fs_free_mem(&ma->entries); + ext2fs_free_mem(&ma); + } + if (brel->name) + ext2fs_free_mem(&brel->name); + ext2fs_free_mem(&brel); + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/check_desc.c b/jni/e2fsprogs/lib/ext2fs/check_desc.c new file mode 100755 index 0000000..3e3fa94 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/check_desc.c @@ -0,0 +1,104 @@ +/* + * check_desc.c --- Check the group descriptors of an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * This routine sanity checks the group descriptors + */ +errcode_t ext2fs_check_desc(ext2_filsys fs) +{ + ext2fs_block_bitmap bmap; + errcode_t retval; + dgrp_t i; + blk64_t first_block = fs->super->s_first_data_block; + blk64_t last_block = ext2fs_blocks_count(fs->super)-1; + blk64_t blk, b; + unsigned int j; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (EXT2_DESC_SIZE(fs->super) & (EXT2_DESC_SIZE(fs->super) - 1)) + return EXT2_ET_BAD_DESC_SIZE; + + retval = ext2fs_allocate_subcluster_bitmap(fs, "check_desc map", &bmap); + if (retval) + return retval; + + for (i = 0; i < fs->group_desc_count; i++) + ext2fs_reserve_super_and_bgd(fs, i, bmap); + + for (i = 0; i < fs->group_desc_count; i++) { + if (!ext2fs_has_feature_flex_bg(fs->super)) { + first_block = ext2fs_group_first_block2(fs, i); + last_block = ext2fs_group_last_block2(fs, i); + } + + /* + * Check to make sure the block bitmap for group is sane + */ + blk = ext2fs_block_bitmap_loc(fs, i); + if (blk < first_block || blk > last_block || + ext2fs_test_block_bitmap2(bmap, blk)) { + retval = EXT2_ET_GDESC_BAD_BLOCK_MAP; + goto errout; + } + ext2fs_mark_block_bitmap2(bmap, blk); + + /* + * Check to make sure the inode bitmap for group is sane + */ + blk = ext2fs_inode_bitmap_loc(fs, i); + if (blk < first_block || blk > last_block || + ext2fs_test_block_bitmap2(bmap, blk)) { + retval = EXT2_ET_GDESC_BAD_INODE_MAP; + goto errout; + } + ext2fs_mark_block_bitmap2(bmap, blk); + + /* + * Check to make sure the inode table for group is sane + */ + blk = ext2fs_inode_table_loc(fs, i); + if (blk < first_block || + ((blk + fs->inode_blocks_per_group - 1) > last_block)) { + retval = EXT2_ET_GDESC_BAD_INODE_TABLE; + goto errout; + } + for (j = 0, b = blk; j < fs->inode_blocks_per_group; + j++, b++) { + if (ext2fs_test_block_bitmap2(bmap, b)) { + retval = EXT2_ET_GDESC_BAD_INODE_TABLE; + goto errout; + } + ext2fs_mark_block_bitmap2(bmap, b); + } + } +errout: + ext2fs_free_block_bitmap(bmap); + return retval; +} diff --git a/jni/e2fsprogs/lib/ext2fs/check_desc.o b/jni/e2fsprogs/lib/ext2fs/check_desc.o new file mode 100755 index 0000000000000000000000000000000000000000..4596be7e8a9fd510824b4b41fce73031802733d7 GIT binary patch literal 3328 zcmbtXU1%It6h5^g?_E8#vA3eEu7$_zrLbO) z3~PA$A>t-wRK{X zVOy_lZlLW{Tq`4gCZTwF6W^yOTVJ_YCoZ8I>4xDF+U_=+(IAfXL61Y^dkyU`DeyRP z2wvi>;(m0jaWD4ij6ehH*Vq}uJ;Z%k;qfsn>R~m$S8EvSZ>US$6<(*v@4QY}iwopm z(&_MhkA5a4KTrJ+Kc{GMzi{9EXJMIRR9mXOIA?4xSM>Vc z)pHy8UanTc`p?a0V7uCbd)kAX2IcyIUG4egLBs>((GIz}V3`>`X*p&rXA}XaZzqoCoF2lge2CI85OBeue_9g>f=FP@L;OG4yfhMpyWq zaQ}F5ZUBD$1&*Rf<9aa~X9tEZ40yJ9hFFVH&v6C>bf>Tgc+E5q5{DtQ5B?GL;Q)M! zp&>7BoX7B?_AWjl{Hstt*kY{rx-fe7x33xhe*7zjcl*`hd4~7w!|xz+M2eHu6S01L zMD1mxGXeO`036@*19@%);C}}2ycD3H4#58n;5incpA68SM4Z|f+Vy!;*8jujBZwc8 zaQt+!HtNG8948*Ct!VUdqDJ_A-jwwv3CAPbYINCCBmF^d%KGmlT;8`Xel$scSkj-A zaJ)BKZAQXJS|~tP!eyT85-#(6B;oWPiguizZ+|?Rgv&h35EYm3yXOdRI`xFSvcXs1;f!(mfMRlS0_OVgZ!CXOj|adBx|$<=xdrB z#<4Diq~RJAOdOXJOX{P1r|)fe63>-5A~I7c;;ruR_f5!rOLiv^)^RuBTH^*)AG!Y~ zCtJdVJ~xBgobUtg@GuJK{PVC{-^B{bNo86X@-fC8$#(~dI9+Ruam-)MN4WhlGLo9# z{w +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static int test_root(unsigned int a, unsigned int b) +{ + while (1) { + if (a < b) + return 0; + if (a == b) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + +int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group) +{ + if (group == 0) + return 1; + if (ext2fs_has_feature_sparse_super2(fs->super)) { + if (group == fs->super->s_backup_bgs[0] || + group == fs->super->s_backup_bgs[1]) + return 1; + return 0; + } + if ((group <= 1) || !ext2fs_has_feature_sparse_super(fs->super)) + return 1; + if (!(group & 1)) + return 0; + if (test_root(group, 3) || (test_root(group, 5)) || + test_root(group, 7)) + return 1; + + return 0; +} + +/* + * ext2fs_super_and_bgd_loc2() + * @fs: ext2 fs pointer + * @group given block group + * @ret_super_blk: if !NULL, returns super block location + * @ret_old_desc_blk: if !NULL, returns location of the old block + * group descriptor + * @ret_new_desc_blk: if !NULL, returns location of meta_bg block + * group descriptor + * @ret_used_blks: if !NULL, returns number of blocks used by + * super block and group_descriptors. + * + * Returns errcode_t of 0 + */ +errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs, + dgrp_t group, + blk64_t *ret_super_blk, + blk64_t *ret_old_desc_blk, + blk64_t *ret_new_desc_blk, + blk_t *ret_used_blks) +{ + blk64_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; + unsigned int meta_bg, meta_bg_size; + blk_t numblocks = 0; + blk64_t old_desc_blocks; + int has_super; + + group_block = ext2fs_group_first_block2(fs, group); + if (group_block == 0 && fs->blocksize == 1024) + group_block = 1; /* Deal with 1024 blocksize && bigalloc */ + + if (ext2fs_has_feature_meta_bg(fs->super)) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; + + has_super = ext2fs_bg_has_super(fs, group); + + if (has_super) { + super_blk = group_block; + numblocks++; + } + meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); + meta_bg = group / meta_bg_size; + + if (!ext2fs_has_feature_meta_bg(fs->super) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + old_desc_blk = group_block + 1; + numblocks += old_desc_blocks; + } + } else { + if (((group % meta_bg_size) == 0) || + ((group % meta_bg_size) == 1) || + ((group % meta_bg_size) == (meta_bg_size-1))) { + if (has_super) + has_super = 1; + new_desc_blk = group_block + has_super; + numblocks++; + } + } + + if (ret_super_blk) + *ret_super_blk = super_blk; + if (ret_old_desc_blk) + *ret_old_desc_blk = old_desc_blk; + if (ret_new_desc_blk) + *ret_new_desc_blk = new_desc_blk; + if (ret_used_blks) + *ret_used_blks = numblocks; + + return 0; +} + +/* + * This function returns the location of the superblock, block group + * descriptors for a given block group. It currently returns the + * number of free blocks assuming that inode table and allocation + * bitmaps will be in the group. This is not necessarily the case + * when the flex_bg feature is enabled, so callers should take care! + * It was only really intended for use by mke2fs, and even there it's + * not that useful. + * + * The ext2fs_super_and_bgd_loc2() function is 64-bit block number + * capable and returns the number of blocks used by super block and + * group descriptors. + */ +int ext2fs_super_and_bgd_loc(ext2_filsys fs, + dgrp_t group, + blk_t *ret_super_blk, + blk_t *ret_old_desc_blk, + blk_t *ret_new_desc_blk, + int *ret_meta_bg) +{ + blk64_t ret_super_blk2; + blk64_t ret_old_desc_blk2; + blk64_t ret_new_desc_blk2; + blk_t ret_used_blks; + blk_t numblocks; + unsigned int meta_bg_size; + + ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2, + &ret_old_desc_blk2, + &ret_new_desc_blk2, + &ret_used_blks); + + numblocks = ext2fs_group_blocks_count(fs, group); + + if (ret_super_blk) + *ret_super_blk = (blk_t)ret_super_blk2; + if (ret_old_desc_blk) + *ret_old_desc_blk = (blk_t)ret_old_desc_blk2; + if (ret_new_desc_blk) + *ret_new_desc_blk = (blk_t)ret_new_desc_blk2; + if (ret_meta_bg) { + meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); + *ret_meta_bg = group / meta_bg_size; + } + + numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks; + + return numblocks; +} + +/* + * This function forces out the primary superblock. We need to only + * write out those fields which we have changed, since if the + * filesystem is mounted, it may have changed some of the other + * fields. + * + * It takes as input a superblock which has already been byte swapped + * (if necessary). + * + */ +static errcode_t write_primary_superblock(ext2_filsys fs, + struct ext2_super_block *super) +{ + __u16 *old_super, *new_super; + int check_idx, write_idx, size; + errcode_t retval; + + if (!fs->io->manager->write_byte || !fs->orig_super) { + fallback: + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); + retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE, + super); + io_channel_set_blksize(fs->io, fs->blocksize); + return retval; + } + + old_super = (__u16 *) fs->orig_super; + new_super = (__u16 *) super; + + for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { + if (old_super[check_idx] == new_super[check_idx]) + continue; + write_idx = check_idx; + for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) + if (old_super[check_idx] == new_super[check_idx]) + break; + size = 2 * (check_idx - write_idx); +#if 0 + printf("Writing %d bytes starting at %d\n", + size, write_idx*2); +#endif + retval = io_channel_write_byte(fs->io, + SUPERBLOCK_OFFSET + (2 * write_idx), size, + new_super + write_idx); + if (retval == EXT2_ET_UNIMPLEMENTED) + goto fallback; + if (retval) + return retval; + } + memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); + return 0; +} + + +/* + * Updates the revision to EXT2_DYNAMIC_REV + */ +void ext2fs_update_dynamic_rev(ext2_filsys fs) +{ + struct ext2_super_block *sb = fs->super; + + if (sb->s_rev_level > EXT2_GOOD_OLD_REV) + return; + + sb->s_rev_level = EXT2_DYNAMIC_REV; + sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; + sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; + /* s_uuid is handled by e2fsck already */ + /* other fields should be left alone */ +} + +static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, + blk64_t group_block, + struct ext2_super_block *super_shadow) +{ + errcode_t retval; + dgrp_t sgrp = group; + + if (sgrp > ((1 << 16) - 1)) + sgrp = (1 << 16) - 1; + + super_shadow->s_block_group_nr = ext2fs_cpu_to_le16(sgrp); + + retval = ext2fs_superblock_csum_set(fs, super_shadow); + if (retval) + return retval; + + return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE, + super_shadow); +} + +errcode_t ext2fs_flush(ext2_filsys fs) +{ + return ext2fs_flush2(fs, 0); +} + +errcode_t ext2fs_flush2(ext2_filsys fs, int flags) +{ + dgrp_t i; + errcode_t retval; + unsigned long fs_state; + __u32 feature_incompat; + struct ext2_super_block *super_shadow = 0; + struct opaque_ext2_group_desc *group_shadow = 0; +#ifdef WORDS_BIGENDIAN + struct ext2_group_desc *gdp; + dgrp_t j; +#endif + char *group_ptr; + blk64_t old_desc_blocks; + struct ext2fs_numeric_progress_struct progress; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if ((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0 && + !ext2fs_has_feature_journal_dev(fs->super) && + fs->group_desc == NULL) + return EXT2_ET_NO_GDESC; + + fs_state = fs->super->s_state; + feature_incompat = fs->super->s_feature_incompat; + + fs->super->s_wtime = fs->now ? fs->now : time(NULL); + fs->super->s_block_group_nr = 0; + + /* + * If the write_bitmaps() function is present, call it to + * flush the bitmaps. This is done this way so that a simple + * program that doesn't mess with the bitmaps doesn't need to + * drag in the bitmaps.c code. + * + * Bitmap checksums live in the group descriptor, so the + * bitmaps need to be written before the descriptors. + */ + if (fs->write_bitmaps) { + retval = fs->write_bitmaps(fs); + if (retval) + goto errout; + } + + /* + * Set the state of the FS to be non-valid. (The state has + * already been backed up earlier, and will be restored after + * we write out the backup superblocks.) + */ + fs->super->s_state &= ~EXT2_VALID_FS; + ext2fs_clear_feature_journal_needs_recovery(fs->super); + + /* Byte swap the superblock and the group descriptors if necessary */ +#ifdef WORDS_BIGENDIAN + retval = EXT2_ET_NO_MEMORY; + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); + if (retval) + goto errout; + memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block)); + ext2fs_swap_super(super_shadow); + + if (((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0) && + !ext2fs_has_feature_journal_dev(fs->super)) { + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, + &group_shadow); + if (retval) + goto errout; + memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize * + fs->desc_blocks); + + for (j = 0; j < fs->group_desc_count; j++) { + gdp = ext2fs_group_desc(fs, group_shadow, j); + ext2fs_swap_group_desc2(fs, gdp); + } + } +#else + super_shadow = fs->super; + group_shadow = fs->group_desc; +#endif + + /* + * If this is an external journal device, don't write out the + * block group descriptors or any of the backup superblocks + */ + if (ext2fs_has_feature_journal_dev(fs->super)) + goto write_primary_superblock_only; + + /* + * Write out the master group descriptors, and the backup + * superblocks and group descriptors. + */ + group_ptr = (char *) group_shadow; + if (ext2fs_has_feature_meta_bg(fs->super)) { + old_desc_blocks = fs->super->s_first_meta_bg; + if (old_desc_blocks > fs->desc_blocks) + old_desc_blocks = fs->desc_blocks; + } else + old_desc_blocks = fs->desc_blocks; + + if (fs->progress_ops && fs->progress_ops->init) + (fs->progress_ops->init)(fs, &progress, NULL, + fs->group_desc_count); + + + for (i = 0; i < fs->group_desc_count; i++) { + blk64_t super_blk, old_desc_blk, new_desc_blk; + + if (fs->progress_ops && fs->progress_ops->update) + (fs->progress_ops->update)(fs, &progress, i); + ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk, + &new_desc_blk, 0); + + if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { + retval = write_backup_super(fs, i, super_blk, + super_shadow); + if (retval) + goto errout; + } + if (fs->flags & EXT2_FLAG_SUPER_ONLY) + continue; + if ((old_desc_blk) && + (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { + retval = io_channel_write_blk64(fs->io, + old_desc_blk, old_desc_blocks, group_ptr); + if (retval) + goto errout; + } + if (new_desc_blk) { + int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super); + + retval = io_channel_write_blk64(fs->io, new_desc_blk, + 1, group_ptr + (meta_bg*fs->blocksize)); + if (retval) + goto errout; + } + } + + if (fs->progress_ops && fs->progress_ops->close) + (fs->progress_ops->close)(fs, &progress, NULL); + +write_primary_superblock_only: + /* + * Write out master superblock. This has to be done + * separately, since it is located at a fixed location + * (SUPERBLOCK_OFFSET). We flush all other pending changes + * out to disk first, just to avoid a race condition with an + * insy-tinsy window.... + */ + + fs->super->s_block_group_nr = 0; + fs->super->s_state = fs_state; + fs->super->s_feature_incompat = feature_incompat; +#ifdef WORDS_BIGENDIAN + *super_shadow = *fs->super; + ext2fs_swap_super(super_shadow); +#endif + + retval = ext2fs_superblock_csum_set(fs, super_shadow); + if (retval) + return retval; + + if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) { + retval = io_channel_flush(fs->io); + if (retval) + goto errout; + } + retval = write_primary_superblock(fs, super_shadow); + if (retval) + goto errout; + + fs->flags &= ~EXT2_FLAG_DIRTY; + + if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) { + retval = io_channel_flush(fs->io); + if (retval) + goto errout; + } +errout: + fs->super->s_state = fs_state; +#ifdef WORDS_BIGENDIAN + if (super_shadow) + ext2fs_free_mem(&super_shadow); + if (group_shadow) + ext2fs_free_mem(&group_shadow); +#endif + return retval; +} + +errcode_t ext2fs_close_free(ext2_filsys *fs_ptr) +{ + errcode_t ret; + ext2_filsys fs = *fs_ptr; + + ret = ext2fs_close2(fs, 0); + if (ret) + ext2fs_free(fs); + *fs_ptr = NULL; + return ret; +} + +errcode_t ext2fs_close(ext2_filsys fs) +{ + return ext2fs_close2(fs, 0); +} + +errcode_t ext2fs_close2(ext2_filsys fs, int flags) +{ + errcode_t retval; + int meta_blks; + io_stats stats = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (fs->write_bitmaps) { + retval = fs->write_bitmaps(fs); + if (retval) + return retval; + } + if (fs->super->s_kbytes_written && + fs->io->manager->get_stats) + fs->io->manager->get_stats(fs->io, &stats); + if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) { + fs->super->s_kbytes_written += stats->bytes_written >> 10; + meta_blks = fs->desc_blocks + 1; + if (!(fs->flags & EXT2_FLAG_SUPER_ONLY)) + fs->super->s_kbytes_written += meta_blks / + (fs->blocksize / 1024); + if ((fs->flags & EXT2_FLAG_DIRTY) == 0) + fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY; + } + if (fs->flags & EXT2_FLAG_DIRTY) { + retval = ext2fs_flush2(fs, flags); + if (retval) + return retval; + } + + retval = ext2fs_mmp_stop(fs); + if (retval) + return retval; + + ext2fs_free(fs); + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/closefs.o b/jni/e2fsprogs/lib/ext2fs/closefs.o new file mode 100755 index 0000000000000000000000000000000000000000..04e5686a1325a50d6fcaac75e8b5ff8ba6373755 GIT binary patch literal 8408 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 F{~tS~A4vcJ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/crc16.c b/jni/e2fsprogs/lib/ext2fs/crc16.c new file mode 100755 index 0000000..2fdeb24 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/crc16.c @@ -0,0 +1,74 @@ +/* + * crc16.c + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif +#include + +#include "crc16.h" + +/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */ +static __u16 const crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +/** + * Compute the CRC-16 for the data buffer + * + * @param crc previous CRC value + * @param buffer data pointer + * @param len number of bytes in the buffer + * @return the updated CRC value + */ +crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len) +{ + const unsigned char *cp = buffer; + + while (len--) + /* + * for an unknown reason, PPC treats __u16 as signed + * and keeps doing sign extension on the value. + * Instead, use only the low 16 bits of an unsigned + * int for holding the CRC value to avoid this. + */ + crc = (((crc >> 8) & 0xffU) ^ + crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU; + return crc; +} diff --git a/jni/e2fsprogs/lib/ext2fs/crc16.o b/jni/e2fsprogs/lib/ext2fs/crc16.o new file mode 100755 index 0000000000000000000000000000000000000000..29b87d42fd87a08b9fa0792f47eb0f0a07a914a6 GIT binary patch literal 1864 zcmbu9cX(7q5Wr{d61Wr-3oB-g#fuk?oK!`$gbEc zvG?A4$5?l**u@gD2W$zkfR)(d?sK0xj`)}JeQ#&xw==W*X7|079Dw6^I9L2yR3kk z11kbE0z)9LUE7=d)HyjFnmTk&CDNE;%&aWYa~S}uixHZNXD>_yFrzXs7V_HkIvrhI z16p;SUbjj5t6Bh*6p9d^lYZ`F&*F=+7w^qpf^_wQc%IVmHJQzKV6Q{2dQ-eXIgqJd z5wB7fzAQ6%fUU*#avQT#wJRZJjm0i` z5I>Opg}=%D`2Os77^6DHR;qyEs!g<0F?Ps3c?sKu-${q>&Ax{b>Ra&*?S)^+B0h|L z345ro#aFaD?5Z}3&uKT@Aa~(~tQD`9b9s>603mggxRK^Tjk;CbM)UC&8RpgOW~ftl zi+d=7_sIrc&+f%Lpb|GFWkK#wO%V4Iu zL|jZq;?;5vKaO1kRq8r%EgcWXs4K-)bSz#WXY*O?ay(N`;)k-cV6r+#oK2N5Rh=&` zpu_Pzc^IF<&V_O6RB;-O$1~(aK7pN%r^ti(A#4>eB?KpeP+hQoe&LdEG`66jzOb~y zDRnCJ{p@3}D=wc7*f-! zYmU0ozmgQ z%hNSa+B$#}4c7&ocsLOUC)5y$gzL3Y-w+Qw6Q|A`5sL>yi)>7|wyGu?jD#T+4V8|r ziU;S_S=$ML6N^VR(Rx|L)zOCPU_1!AZdpyN%1wcyYG;%g%FIv-MG0r5-PZqBlXL}t z4^_w>fk>ItZP-S7Y0ogDlZC9qlcBa#PuAobM*2yXt#(u1i|YTP+y8(K^6s-aPg7%? zv(diPk1Ht?DK2E|Ad~N{^G}k_w}JgVV6}-g;_3V(+numOOX@b|`9_wt8nqo@82w~hAtWcp{m5-;E5(= + * Reuse Bob Pearson's slice-by-8 implementation for e2fsprogs. + * + * July 20, 2011 Bob Pearson + * added slice by 8 algorithm to the existing conventional and + * slice by 4 algorithms. + * + * Oct 15, 2000 Matt Domsch + * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks! + * Code was from the public domain, copyright abandoned. Code was + * subsequently included in the kernel, thus was re-licensed under the + * GNU GPL v2. + * + * Oct 12, 2000 Matt Domsch + * Same crc32 function was used in 5 other places in the kernel. + * I made one version, and deleted the others. + * There are various incantations of crc32(). Some use a seed of 0 or ~0. + * Some xor at the end with ~0. The generic crc32() function takes + * seed as an argument, and doesn't xor at the end. Then individual + * users can do whatever they need. + * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0. + * fs/jffs2 uses seed 0, doesn't xor with ~0. + * fs/partitions/efi.c uses seed ~0, xor's with ~0. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ +#include "config.h" +#include +#include +#include +#define min(x, y) ((x) > (y) ? (y) : (x)) +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1) +#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) +#define PTR_ALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a))) +#include "crc32c_defs.h" + +#include "ext2fs.h" +#ifdef WORDS_BIGENDIAN +#define __constant_cpu_to_le32(x) ___constant_swab32((x)) +#define __constant_cpu_to_be32(x) (x) +#define __be32_to_cpu(x) (x) +#define __cpu_to_be32(x) (x) +#define __cpu_to_le32(x) (ext2fs_cpu_to_le32((x))) +#define __le32_to_cpu(x) (ext2fs_le32_to_cpu((x))) +#else +#define __constant_cpu_to_le32(x) (x) +#define __constant_cpu_to_be32(x) ___constant_swab32((x)) +#define __be32_to_cpu(x) (ext2fs_be32_to_cpu((x))) +#define __cpu_to_be32(x) (ext2fs_cpu_to_be32((x))) +#define __cpu_to_le32(x) (x) +#define __le32_to_cpu(x) (x) +#endif + +#if CRC_LE_BITS > 8 +# define tole(x) __constant_cpu_to_le32(x) +#else +# define tole(x) (x) +#endif + +#if CRC_BE_BITS > 8 +# define tobe(x) __constant_cpu_to_be32(x) +#else +# define tobe(x) (x) +#endif + +#include "crc32c_table.h" + +#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 + +#if CRC_LE_BITS < 64 && CRC_BE_BITS < 64 +#define CRC_INLINE inline +#else +#define CRC_INLINE +#endif + +/* implements slicing-by-4 or slicing-by-8 algorithm */ +static CRC_INLINE uint32_t +crc32_body(uint32_t crc, unsigned char const *buf, size_t len, + const uint32_t (*tab)[256]) +{ +# ifndef WORDS_BIGENDIAN +# define DO_CRC(x) (crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8)) +# define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \ + t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255]) +# define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \ + t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255]) +# else +# define DO_CRC(x) (crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)) +# define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \ + t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255]) +# define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \ + t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255]) +# endif + const uint32_t *b; + size_t rem_len; + const uint32_t *t0 = tab[0], *t1 = tab[1], *t2 = tab[2], *t3 = tab[3]; + const uint32_t *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7]; + uint32_t q; + + /* Align it */ + if (unlikely((uintptr_t)buf & 3 && len)) { + do { + DO_CRC(*buf++); + } while ((--len) && ((uintptr_t)buf)&3); + } + +# if CRC_LE_BITS == 32 + rem_len = len & 3; + len = len >> 2; +# else + rem_len = len & 7; + len = len >> 3; +# endif + + b = (const uint32_t *)buf; + for (--b; len; --len) { + q = crc ^ *++b; /* use pre increment for speed */ +# if CRC_LE_BITS == 32 + crc = DO_CRC4; +# else + crc = DO_CRC8; + q = *++b; + crc ^= DO_CRC4; +# endif + } + len = rem_len; + /* And the last few bytes */ + if (len) { + const uint8_t *p = (const uint8_t *)(b + 1) - 1; + do { + DO_CRC(*++p); /* use pre increment for speed */ + } while (--len); + } + return crc; +#undef DO_CRC +#undef DO_CRC4 +#undef DO_CRC8 +} +#endif + +/** + * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p: pointer to buffer over which CRC is run + * @len: length of buffer @p + */ +static inline uint32_t crc32_le_generic(uint32_t crc, unsigned char const *p, + size_t len, const uint32_t (*tab)[256], + uint32_t polynomial EXT2FS_ATTR((unused))) +{ +#if CRC_LE_BITS == 1 + int i; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0); + } +# elif CRC_LE_BITS == 2 + while (len--) { + crc ^= *p++; + crc = (crc >> 2) ^ tab[0][crc & 3]; + crc = (crc >> 2) ^ tab[0][crc & 3]; + crc = (crc >> 2) ^ tab[0][crc & 3]; + crc = (crc >> 2) ^ tab[0][crc & 3]; + } +# elif CRC_LE_BITS == 4 + while (len--) { + crc ^= *p++; + crc = (crc >> 4) ^ tab[0][crc & 15]; + crc = (crc >> 4) ^ tab[0][crc & 15]; + } +# elif CRC_LE_BITS == 8 + /* aka Sarwate algorithm */ + while (len--) { + crc ^= *p++; + crc = (crc >> 8) ^ tab[0][crc & 255]; + } +# else + crc = __cpu_to_le32(crc); + crc = crc32_body(crc, p, len, tab); + crc = __le32_to_cpu(crc); +#endif + return crc; +} + +uint32_t ext2fs_crc32c_le(uint32_t crc, unsigned char const *p, size_t len) +{ + return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE); +} + +/** + * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p: pointer to buffer over which CRC is run + * @len: length of buffer @p + */ +static inline uint32_t crc32_be_generic(uint32_t crc, unsigned char const *p, + size_t len, const uint32_t (*tab)[256], + uint32_t polynomial EXT2FS_ATTR((unused))) +{ +#if CRC_BE_BITS == 1 + int i; + while (len--) { + crc ^= *p++ << 24; + for (i = 0; i < 8; i++) + crc = + (crc << 1) ^ ((crc & 0x80000000) ? polynomial : + 0); + } +# elif CRC_BE_BITS == 2 + while (len--) { + crc ^= *p++ << 24; + crc = (crc << 2) ^ tab[0][crc >> 30]; + crc = (crc << 2) ^ tab[0][crc >> 30]; + crc = (crc << 2) ^ tab[0][crc >> 30]; + crc = (crc << 2) ^ tab[0][crc >> 30]; + } +# elif CRC_BE_BITS == 4 + while (len--) { + crc ^= *p++ << 24; + crc = (crc << 4) ^ tab[0][crc >> 28]; + crc = (crc << 4) ^ tab[0][crc >> 28]; + } +# elif CRC_BE_BITS == 8 + while (len--) { + crc ^= *p++ << 24; + crc = (crc << 8) ^ tab[0][crc >> 24]; + } +# else + crc = __cpu_to_be32(crc); + crc = crc32_body(crc, p, len, tab); + crc = __be32_to_cpu(crc); +# endif + return crc; +} + +uint32_t ext2fs_crc32_be(uint32_t crc, unsigned char const *p, size_t len) +{ + return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE); +} + +#ifdef UNITTEST +static uint8_t test_buf[] = { + 0xd9, 0xd7, 0x6a, 0x13, 0x3a, 0xb1, 0x05, 0x48, + 0xda, 0xad, 0x14, 0xbd, 0x03, 0x3a, 0x58, 0x5e, + 0x6e, 0xd1, 0x56, 0xc9, 0x2e, 0xc4, 0xcb, 0x6b, + 0xe8, 0x77, 0x52, 0x37, 0x4e, 0x0f, 0x55, 0xd2, + 0x12, 0x65, 0x90, 0xc2, 0x41, 0x49, 0x81, 0x01, + 0xf5, 0x01, 0xeb, 0x2d, 0x78, 0x74, 0x23, 0x5d, + 0x84, 0x5c, 0x81, 0x92, 0x21, 0xe9, 0x8d, 0x1d, + 0x89, 0xf2, 0x4a, 0xac, 0xdd, 0xf9, 0xaf, 0xee, + 0x44, 0xe7, 0x6e, 0xed, 0xfb, 0xd8, 0x89, 0x0e, + 0x96, 0x62, 0xcd, 0xa4, 0x4b, 0xa9, 0xe5, 0x45, + 0xb1, 0x29, 0x9b, 0x0f, 0xfc, 0xbd, 0x83, 0xab, + 0xa8, 0x54, 0x96, 0x44, 0x2c, 0x7f, 0xbb, 0xe7, + 0x52, 0x29, 0x08, 0xee, 0x14, 0xc5, 0xc2, 0xec, + 0x5a, 0xeb, 0x40, 0x40, 0xea, 0xd1, 0x3d, 0x15, + 0x73, 0xaa, 0x8c, 0x73, 0xfc, 0xf2, 0x2b, 0x49, + 0x0b, 0x13, 0x96, 0xd9, 0x8e, 0x4b, 0xbc, 0xe0, + 0xf4, 0xd2, 0xe0, 0x2e, 0x7a, 0xf0, 0x5d, 0x1f, + 0xd2, 0x92, 0x97, 0xe0, 0xaa, 0x59, 0xab, 0xc9, + 0x5c, 0xa6, 0x51, 0x1a, 0xe3, 0xd6, 0x06, 0xb9, + 0xae, 0xb8, 0x76, 0x36, 0x79, 0x37, 0x52, 0xf6, + 0x34, 0xaf, 0x27, 0x19, 0xe1, 0xc0, 0x2b, 0xdd, + 0x01, 0x15, 0xcd, 0xce, 0x44, 0xf6, 0x4c, 0x18, + 0x92, 0x69, 0xbe, 0x8a, 0x76, 0x23, 0x52, 0x13, + 0x3f, 0xf9, 0xe0, 0xf5, 0x06, 0x28, 0x7c, 0xc7, + 0xf3, 0x42, 0x0f, 0xdd, 0x40, 0x33, 0xf7, 0x99, + 0xe2, 0xad, 0x26, 0xd9, 0x53, 0x10, 0x72, 0x0c, + 0x4e, 0x43, 0x4c, 0x61, 0xfe, 0xd9, 0xc1, 0x16, + 0xa1, 0x93, 0xca, 0x3c, 0x75, 0x7f, 0x07, 0x7a, + 0x65, 0xb3, 0x53, 0x2a, 0x52, 0x00, 0xa0, 0x62, + 0xe0, 0xa3, 0x1f, 0xad, 0xd7, 0xbb, 0xc0, 0x83, + 0x5d, 0x54, 0x87, 0x5f, 0xc8, 0x2f, 0xc8, 0xbf, + 0x69, 0x04, 0x91, 0xc8, 0xa6, 0x1d, 0x4d, 0x46, + 0x91, 0xfc, 0x26, 0xf4, 0x16, 0xd1, 0xa4, 0xbf, + 0x5c, 0xa2, 0x6c, 0xdd, 0xb4, 0x40, 0xf2, 0x2e, + 0xa2, 0xad, 0xf7, 0xf4, 0xa5, 0x8a, 0x3e, 0x23, + 0x64, 0x08, 0xc8, 0xa1, 0xa0, 0xf0, 0x5d, 0x70, + 0xd2, 0x77, 0xfd, 0xc8, 0x50, 0x83, 0x0f, 0xd6, + 0x2b, 0xe4, 0x1f, 0x52, 0x34, 0x33, 0x68, 0xfd, + 0x92, 0xbe, 0x9f, 0x97, 0x6b, 0x8d, 0x81, 0x91, + 0x0f, 0xef, 0x65, 0xc8, 0x0d, 0x15, 0x01, 0x77, + 0x58, 0xb2, 0xf4, 0x1b, 0x06, 0x7e, 0xf5, 0xca, + 0x15, 0x2e, 0x38, 0xd8, 0x81, 0x1c, 0x1c, 0xa0, + 0xb6, 0x13, 0x6a, 0x2b, 0x71, 0x34, 0x52, 0xd7, + 0x1d, 0xbd, 0x37, 0x59, 0xbc, 0x86, 0x25, 0x2b, + 0xa8, 0x93, 0xce, 0x1a, 0x03, 0x16, 0xfe, 0x01, + 0x57, 0x99, 0x24, 0x25, 0x2c, 0xb3, 0xab, 0x1e, + 0x2d, 0x65, 0x20, 0x89, 0x17, 0x02, 0x0e, 0x0a, + 0xf5, 0x1e, 0xc7, 0xff, 0x1f, 0x61, 0xa9, 0x54, + 0x18, 0xd4, 0xba, 0x50, 0x57, 0x02, 0xa1, 0xab, + 0x22, 0x2e, 0x07, 0xea, 0xa9, 0xa3, 0x83, 0x4f, + 0x27, 0xf5, 0xc5, 0xee, 0x3c, 0x3b, 0x10, 0xad, + 0x32, 0x2b, 0x1c, 0x03, 0xcb, 0xaf, 0x98, 0x83, + 0x54, 0xc3, 0x68, 0x63, 0xd4, 0xe0, 0x0e, 0x3c, + 0x1a, 0x4e, 0xc0, 0x81, 0xd0, 0xe8, 0x6a, 0x62, + 0x6b, 0x3e, 0x6f, 0xc4, 0xc6, 0x33, 0x4e, 0x26, + 0x21, 0xf5, 0x04, 0xdf, 0xfa, 0xce, 0x45, 0xaf, + 0xdc, 0x5e, 0x1b, 0xad, 0x93, 0xca, 0xf5, 0xcf, + 0xd7, 0xee, 0x0c, 0x5c, 0x5e, 0xb4, 0xf0, 0x92, + 0xd2, 0xf2, 0xf0, 0xa9, 0x1e, 0xab, 0x80, 0x68, + 0x46, 0xef, 0xcc, 0x26, 0x0c, 0x5c, 0xdd, 0x4e, + 0x83, 0xb8, 0xb9, 0x53, 0x6e, 0xf8, 0x93, 0x38, + 0x67, 0xa4, 0x41, 0x87, 0x72, 0xe7, 0x7e, 0x86, + 0xc9, 0x49, 0x00, 0x33, 0xb1, 0x38, 0x6c, 0x71, + 0xd7, 0x1d, 0x8e, 0x61, 0x01, 0xb6, 0x57, 0xa9, + 0xf1, 0xac, 0x15, 0xc2, 0x83, 0x77, 0xca, 0x64, + 0xca, 0x7b, 0x6c, 0xa1, 0x10, 0x1b, 0x13, 0xd0, + 0xd3, 0x9e, 0x9e, 0x10, 0x70, 0xc8, 0x1a, 0xbb, + 0x3f, 0x19, 0x86, 0xab, 0x01, 0x0e, 0xea, 0x34, + 0x22, 0xea, 0xe2, 0x15, 0xb7, 0xed, 0x21, 0x21, + 0x75, 0xa5, 0xe7, 0x08, 0xa1, 0x38, 0xe0, 0x91, + 0x05, 0x60, 0xea, 0xa7, 0x50, 0x27, 0x18, 0x07, + 0x9d, 0xe0, 0x18, 0x2b, 0xd4, 0x07, 0x59, 0x00, + 0xe6, 0x45, 0x18, 0x2a, 0x30, 0x6e, 0xf3, 0xb4, + 0xd0, 0xef, 0xa6, 0x5b, 0x71, 0xa2, 0x5a, 0x3b, + 0x89, 0x4c, 0xaf, 0x3f, 0xcb, 0x9f, 0x03, 0xfb, + 0x43, 0x7c, 0x6b, 0xd3, 0x6a, 0xea, 0xce, 0x4a, + 0x5f, 0x64, 0xb5, 0x62, 0xda, 0x5d, 0x27, 0xb7, + 0xb8, 0x11, 0xca, 0x33, 0x30, 0xec, 0x70, 0xf0, + 0x1b, 0x03, 0x50, 0xff, 0x5e, 0xa6, 0x08, 0xde, + 0x37, 0x70, 0xc0, 0x81, 0x55, 0x60, 0x17, 0xa1, + 0x85, 0xae, 0x26, 0x44, 0xe4, 0x67, 0x3c, 0x91, + 0xfd, 0xc4, 0x3d, 0x97, 0x72, 0x23, 0xf3, 0x3c, + 0x8f, 0xe0, 0xe2, 0xf2, 0x09, 0x96, 0x10, 0x67, + 0xb5, 0xfe, 0xff, 0x3d, 0x4a, 0xc8, 0x62, 0x11, + 0xa5, 0x98, 0xc1, 0x2d, 0x40, 0x82, 0x88, 0x8b, + 0xe5, 0xb0, 0x75, 0xbf, 0x2f, 0xa8, 0x6a, 0x55, + 0x49, 0x2e, 0x9c, 0x29, 0xd2, 0x7c, 0xbf, 0xf3, + 0xaa, 0x3a, 0x16, 0x4a, 0xa4, 0x15, 0xf3, 0x48, + 0xde, 0x38, 0x13, 0x44, 0x26, 0x02, 0xe6, 0xe9, + 0xa8, 0x24, 0x89, 0xb5, 0x43, 0x95, 0xe4, 0x4c, + 0xc3, 0xa0, 0xdf, 0xcc, 0x42, 0xf8, 0x8d, 0xb0, + 0x3b, 0xea, 0x10, 0xb7, 0xe1, 0x40, 0x54, 0xb9, + 0xa3, 0x2d, 0xfb, 0xb4, 0x91, 0xc0, 0x3e, 0x94, + 0xf1, 0xa1, 0x3c, 0xbe, 0xef, 0xb8, 0x70, 0x55, + 0x0a, 0x26, 0x93, 0xbf, 0xe6, 0x21, 0x92, 0x32, + 0x3c, 0x39, 0x27, 0x6a, 0x23, 0x48, 0x02, 0x35, + 0x3c, 0xd4, 0xcc, 0x04, 0xc0, 0x4e, 0xa7, 0x02, + 0x63, 0x37, 0xc2, 0xb8, 0x56, 0x1d, 0x57, 0x57, + 0x42, 0x04, 0x8d, 0xee, 0xcf, 0x8b, 0xc9, 0xc3, + 0xba, 0x3b, 0x15, 0xd7, 0xaf, 0xbf, 0x9e, 0xcd, + 0x44, 0xcf, 0xf0, 0x00, 0xb7, 0x3a, 0xfc, 0xa8, + 0x12, 0xab, 0x3a, 0x62, 0x01, 0x21, 0x46, 0xe9, + 0x1e, 0x48, 0x37, 0xfc, 0x13, 0x4d, 0xf6, 0x2a, + 0x72, 0x40, 0x75, 0x38, 0x71, 0xf2, 0x17, 0x20, + 0x2c, 0xdd, 0xc0, 0x49, 0xbc, 0x63, 0x33, 0xea, + 0x06, 0x75, 0x41, 0xe7, 0x5c, 0x1f, 0xfb, 0xf9, + 0x68, 0x83, 0xc2, 0x5a, 0x4a, 0x1e, 0x61, 0x08, + 0x57, 0xf3, 0x00, 0xba, 0x77, 0x92, 0x63, 0xa5, + 0xb7, 0xfe, 0x97, 0x22, 0xda, 0x5e, 0xd3, 0xaf, + 0xbc, 0x89, 0x0d, 0x4c, 0x37, 0xa9, 0x27, 0x4a, + 0x7f, 0xdb, 0x81, 0x39, 0x11, 0x86, 0x12, 0xf9, + 0x10, 0x50, 0xe4, 0xdb, 0x72, 0xf9, 0xae, 0x10, + 0x7c, 0xed, 0x50, 0x5c, 0x61, 0xeb, 0x42, 0x1e, + 0xa4, 0xf4, 0xf0, 0xfa, 0x45, 0x4d, 0x95, 0x2b, + 0xd4, 0x67, 0x4a, 0xe3, 0x8a, 0x15, 0x55, 0x92, + 0x77, 0x64, 0x8c, 0x51, 0x38, 0xf9, 0x26, 0x3e, + 0x68, 0xe2, 0xac, 0xbb, 0x64, 0x77, 0xe2, 0x82, + 0xa4, 0x42, 0x41, 0x38, 0xa0, 0xf0, 0xc9, 0xd8, + 0x6c, 0xe0, 0xef, 0x4c, 0xda, 0xb4, 0x92, 0xef, + 0x1b, 0xe3, 0x9b, 0xc1, 0x44, 0x3c, 0xb9, 0xb7, + 0x39, 0xac, 0x5c, 0x32, 0x39, 0xb4, 0x21, 0x85, + 0x93, 0xbc, 0xf2, 0x51, 0x43, 0xb7, 0xae, 0x1e, + 0x61, 0x9c, 0x38, 0x9c, 0xaa, 0xff, 0xde, 0xfc, + 0xbf, 0x85, 0xef, 0x17, 0x34, 0x36, 0x71, 0x5f, + 0x04, 0x16, 0xa6, 0x9e, 0xfd, 0x3a, 0x03, 0xd8, + 0xbf, 0x71, 0x70, 0x20, 0x8f, 0x7c, 0xfb, 0xff, + 0x61, 0xe0, 0xe2, 0x60, 0xa7, 0xb1, 0xc0, 0xe0, + 0xd9, 0x3f, 0xdc, 0x8d, 0x4a, 0xa4, 0x52, 0x61, + 0xaf, 0x9d, 0xdf, 0x8a, 0x0d, 0x41, 0xc0, 0x25, + 0x68, 0x12, 0x7b, 0xd5, 0xc7, 0xdb, 0x68, 0x70, + 0x2d, 0x7d, 0x95, 0x12, 0x03, 0x23, 0x0c, 0xe8, + 0x14, 0x41, 0x11, 0x28, 0xec, 0x9d, 0xd3, 0x28, + 0x77, 0x7a, 0x3c, 0x93, 0x8e, 0x5c, 0x7e, 0xb3, + 0x42, 0x9a, 0x18, 0x25, 0x93, 0xc8, 0xea, 0x43, + 0x1b, 0xbe, 0xd5, 0x27, 0xf1, 0xd4, 0xe0, 0x1e, + 0xce, 0xc7, 0xc7, 0x2c, 0x25, 0x35, 0x58, 0xb8, + 0x6c, 0xf3, 0xa2, 0xad, 0xe7, 0x58, 0x49, 0x47, + 0xf7, 0xca, 0xde, 0x8b, 0x81, 0xb7, 0x75, 0xf4, + 0x95, 0xa7, 0x5c, 0xc3, 0x2c, 0x0e, 0x1c, 0x52, + 0x9a, 0xc3, 0x2a, 0x00, 0x21, 0xa7, 0x51, 0x6b, + 0xf0, 0x05, 0x87, 0x8c, 0x42, 0x1b, 0xc3, 0x2e, + 0xa3, 0x76, 0x22, 0xd5, 0x7f, 0x56, 0x10, 0xef, + 0x98, 0x85, 0x65, 0x86, 0x71, 0x87, 0xd2, 0x8c, + 0xc0, 0x47, 0x20, 0xe8, 0xb5, 0x1c, 0xe3, 0xdd, + 0x3c, 0x5c, 0x03, 0xbb, 0x0e, 0x97, 0x3b, 0xe1, + 0x56, 0x9a, 0xd5, 0x0a, 0x63, 0xd5, 0x33, 0xaf, + 0x36, 0xca, 0xcf, 0x8f, 0x00, 0x28, 0xa3, 0x45, + 0xb8, 0xcd, 0xde, 0x73, 0xd4, 0xfa, 0x2d, 0x6f, + 0xdb, 0x93, 0xaa, 0xdd, 0x7f, 0xd2, 0x22, 0x9c, + 0x96, 0x48, 0x1e, 0xa8, 0x63, 0xbe, 0xbc, 0x0d, + 0x14, 0x3c, 0x2e, 0x11, 0x1f, 0xd2, 0xf4, 0x57, + 0xb3, 0x47, 0xf8, 0xa6, 0x1b, 0xc3, 0xa7, 0x95, + 0x2d, 0xd4, 0xca, 0xb8, 0x0d, 0xfb, 0x06, 0x85, + 0xda, 0x63, 0xf0, 0x3e, 0x9d, 0x5e, 0xee, 0xce, + 0xed, 0x74, 0x1d, 0x2c, 0x97, 0x3f, 0x71, 0x95, + 0x12, 0x03, 0xc5, 0x92, 0x46, 0x84, 0x1b, 0x07, + 0xe6, 0xb4, 0x1d, 0x3a, 0xf1, 0x89, 0x90, 0x50, + 0x10, 0x29, 0x34, 0xc0, 0x90, 0xbe, 0x4a, 0xa9, + 0x0d, 0xb0, 0x7b, 0xfb, 0x35, 0xee, 0x4e, 0x34, + 0xec, 0x5a, 0x58, 0xbc, 0xb8, 0xda, 0x38, 0x88, + 0x8c, 0x74, 0x1e, 0xc9, 0xab, 0x78, 0x2e, 0x2a, + 0x17, 0x8a, 0x43, 0x3d, 0xa1, 0x2a, 0x41, 0xb5, + 0xd6, 0xe8, 0x5b, 0xc5, 0x4a, 0x1c, 0x3c, 0x9f, + 0x8d, 0x3a, 0x69, 0x88, 0xf8, 0x80, 0xd2, 0x11, + 0xfc, 0x7e, 0x80, 0x8e, 0x7f, 0x85, 0x64, 0x9c, + 0x46, 0x58, 0xc8, 0x48, 0x98, 0x4b, 0xf5, 0x73, + 0x3f, 0x49, 0xce, 0x53, 0x2c, 0xd5, 0xfc, 0x33, + 0xf1, 0x6f, 0xd8, 0xe9, 0x2e, 0x70, 0x2e, 0xdc, + 0xe5, 0x43, 0x80, 0x38, 0xf2, 0x87, 0xed, 0x85, + 0xe4, 0x3e, 0x45, 0x14, 0x20, 0xcf, 0xa0, 0x61, + 0x4f, 0xe8, 0xd7, 0x5b, 0xb3, 0x0d, 0x0e, 0x4e, + 0x4d, 0xce, 0xbe, 0xba, 0xaa, 0x90, 0x09, 0xcb, + 0x4b, 0x5d, 0x08, 0xff, 0x52, 0xd5, 0x23, 0xbc, + 0xad, 0x8d, 0xd3, 0x06, 0x4a, 0xa0, 0x51, 0x56, + 0xa7, 0xd8, 0x33, 0xab, 0xbc, 0xd0, 0xdf, 0x92, + 0x87, 0x20, 0x2d, 0x7b, 0x5e, 0xfa, 0x30, 0xa7, + 0x06, 0x06, 0xe5, 0x4f, 0x2c, 0xb5, 0x61, 0xd7, + 0x54, 0xd3, 0xdf, 0xd0, 0x0a, 0xb0, 0x06, 0xce, + 0xf6, 0x86, 0xb7, 0x8e, 0xaa, 0x7b, 0x78, 0xd5, + 0xb9, 0xeb, 0x07, 0xac, 0x5f, 0xc5, 0xd2, 0x8c, + 0x40, 0xe0, 0x7f, 0x98, 0xd4, 0xe5, 0x4b, 0xca, + 0xfb, 0x47, 0xef, 0xef, 0xb9, 0x4d, 0x6d, 0x8f, + 0x82, 0x68, 0x74, 0x84, 0xe0, 0x0a, 0x93, 0x0f, + 0xb2, 0x01, 0xa9, 0x9f, 0x68, 0x6a, 0xe8, 0xf7, + 0xfb, 0x0b, 0xde, 0x17, 0xe0, 0x30, 0x38, 0x51, + 0xbc, 0x07, 0xb8, 0x2c, 0x91, 0x0f, 0xc1, 0x0e, + 0xa6, 0xf9, 0xf0, 0xd5, 0x48, 0x76, 0x8a, 0xde, + 0x74, 0xe3, 0x30, 0x65, 0x56, 0xb3, 0x5c, 0xe2, + 0x89, 0x8d, 0xda, 0x80, 0xad, 0x0f, 0x22, 0xfb, + 0x24, 0x1d, 0x16, 0xdd, 0x34, 0x4b, 0x90, 0x58, + 0x4e, 0x0c, 0x13, 0x28, 0xcf, 0x1d, 0xa4, 0xaa, + 0xb7, 0xf3, 0xb1, 0x66, 0xad, 0x3b, 0xcf, 0x79, + 0x12, 0x04, 0xd7, 0x79, 0xd9, 0x5f, 0xdf, 0x89, + 0xb2, 0x5b, 0xa7, 0x9a, 0x26, 0x1e, 0x67, 0x46, + 0x7c, 0x66, 0x95, 0x67, 0xe6, 0x45, 0x8b, 0x1f, + 0x65, 0x79, 0x9f, 0x6d, 0x11, 0x81, 0x17, 0x0d, + 0x11, 0xb0, 0x5c, 0xb4, 0xc7, 0x27, 0x87, 0xab, + 0x5d, 0x0a, 0x18, 0xae, 0x4e, 0x06, 0xa3, 0x3d, + 0xc7, 0xb0, 0x22, 0xba, 0x03, 0xa4, 0x0f, 0xe5, + 0x1c, 0x72, 0x2a, 0x04, 0xce, 0x83, 0xe9, 0xf3, + 0xd7, 0xc9, 0x67, 0x6c, 0x1e, 0x6b, 0x3c, 0x9b, + 0x0b, 0x5e, 0x6a, 0xa6, 0x79, 0x0a, 0xf1, 0xbe, + 0xd7, 0xb4, 0x6f, 0x45, 0x1e, 0xfb, 0x78, 0x97, + 0xaf, 0x34, 0x76, 0x95, 0x52, 0xf7, 0x3d, 0x5d, + 0x07, 0x28, 0x57, 0x9c, 0x4a, 0x0f, 0xcf, 0x0b, + 0x1b, 0xc4, 0xc2, 0x72, 0xd7, 0x72, 0x38, 0x9b, + 0xea, 0xeb, 0xee, 0xae, 0x34, 0xc8, 0x01, 0xd7, + 0xa5, 0xe3, 0xce, 0x41, 0xad, 0x02, 0x60, 0x23, + 0x18, 0x36, 0xba, 0x17, 0xfa, 0xcf, 0xe4, 0xda, + 0xdc, 0xfc, 0x82, 0xdc, 0x7c, 0x11, 0xf4, 0xb8, + 0x52, 0x5d, 0xf7, 0x2f, 0xc8, 0xfe, 0x4a, 0xe6, + 0xb9, 0xaf, 0x4b, 0x17, 0x18, 0x91, 0xc2, 0xfe, + 0xd7, 0x3a, 0x77, 0x0c, 0xa0, 0x43, 0x9c, 0x6f, + 0x13, 0x06, 0xbe, 0x6e, 0xe0, 0x1a, 0x3c, 0xf3, + 0xf5, 0xcc, 0x78, 0xfb, 0x5d, 0xd5, 0xda, 0xb7, + 0x58, 0xea, 0x86, 0x42, 0x6b, 0x32, 0xff, 0xb2, + 0xe2, 0xee, 0x03, 0x1f, 0xf4, 0xef, 0xdb, 0x53, + 0x79, 0xd5, 0x4e, 0xaf, 0x60, 0x8e, 0x02, 0xc2, + 0xcc, 0x39, 0x97, 0x7b, 0xfd, 0xa1, 0xf8, 0x7a, + 0x26, 0xe8, 0x55, 0xd6, 0xa4, 0x8b, 0xa0, 0x1b, + 0x2d, 0x63, 0xaa, 0x73, 0x71, 0x6e, 0xbf, 0x8b, + 0x3b, 0xe3, 0x1b, 0x0d, 0xbb, 0x2e, 0x44, 0x09, + 0x64, 0xac, 0xc7, 0x9e, 0xb5, 0xc6, 0x77, 0xb0, + 0x79, 0xb3, 0xaa, 0xfc, 0x67, 0x57, 0x9a, 0x50, + 0x81, 0x37, 0x14, 0x7c, 0xd7, 0xa0, 0xd4, 0x6a, + 0x79, 0x84, 0x51, 0x0e, 0x95, 0x0a, 0x30, 0xa3, + 0x60, 0x55, 0x48, 0x05, 0x16, 0xae, 0x43, 0x90, + 0xdc, 0x8e, 0x09, 0xbe, 0x79, 0xf6, 0x90, 0x74, + 0xf8, 0x20, 0x96, 0x4d, 0xa7, 0xf5, 0x1a, 0x2b, + 0xc7, 0x15, 0x9d, 0x18, 0xf7, 0x94, 0x87, 0xf7, + 0xf4, 0xfb, 0x0d, 0x61, 0xb6, 0xd7, 0xbe, 0x10, + 0x8e, 0x47, 0x3c, 0x10, 0x44, 0x90, 0x52, 0x21, + 0x83, 0xc0, 0xf5, 0x99, 0xaa, 0xbc, 0xf6, 0x55, + 0xae, 0xf5, 0xb2, 0xa4, 0xcd, 0x4d, 0xb9, 0x38, + 0x6c, 0xbc, 0x80, 0xc3, 0xad, 0xf4, 0x46, 0x31, + 0x01, 0x58, 0x2d, 0x88, 0x57, 0xc3, 0x23, 0xd1, + 0x64, 0xc9, 0xa3, 0x21, 0x6b, 0x8b, 0x8a, 0x23, + 0x2c, 0x4f, 0xa9, 0xcd, 0x67, 0xfa, 0x77, 0xad, + 0xa3, 0x16, 0xa2, 0xe5, 0x19, 0x14, 0x70, 0x41, + 0x5b, 0xda, 0x14, 0xde, 0xe3, 0xe5, 0xc1, 0x15, + 0xb4, 0x77, 0xa4, 0x9b, 0xb8, 0xb1, 0x28, 0x51, + 0x30, 0xb4, 0xf1, 0xf3, 0xf8, 0x6d, 0xd0, 0xc3, + 0x8c, 0x4c, 0x76, 0xb0, 0x9a, 0xdf, 0xc8, 0xbe, + 0xf8, 0x4a, 0x61, 0x6e, 0x3e, 0xd6, 0x3c, 0xe8, + 0xde, 0x56, 0xa0, 0x9c, 0x25, 0xbe, 0xce, 0x93, + 0x1f, 0x88, 0xfb, 0x9a, 0x1a, 0xe2, 0xff, 0x88, + 0xad, 0x10, 0xcb, 0x6c, 0xd6, 0xe7, 0x39, 0x0b, + 0xe5, 0x1a, 0x06, 0x05, 0x64, 0x5b, 0x0a, 0xdf, + 0x22, 0x58, 0xd7, 0xfb, 0x88, 0x12, 0xdd, 0xb7, + 0x52, 0x3a, 0xc9, 0xbf, 0x49, 0xdf, 0x8c, 0x87, + 0x9f, 0x84, 0xb5, 0x0a, 0xf6, 0x00, 0x52, 0xae, + 0x67, 0x12, 0x1a, 0x8c, 0x71, 0x15, 0xf5, 0xa1, + 0x13, 0x39, 0xf0, 0x91, 0x7e, 0x88, 0x7c, 0xb3, + 0x95, 0x50, 0x02, 0xa6, 0x63, 0xb5, 0x64, 0xfb, + 0x90, 0x87, 0x61, 0xe2, 0x27, 0xaf, 0x11, 0x0c, + 0x73, 0x83, 0xef, 0xa9, 0x28, 0xfe, 0xc8, 0x85, + 0x1a, 0x3a, 0xde, 0xf2, 0xe5, 0x25, 0x64, 0x6d, + 0xaa, 0x41, 0x4c, 0x80, 0x2e, 0x84, 0xff, 0xc1, + 0xc0, 0x54, 0x0c, 0x29, 0x1b, 0xa3, 0x07, 0x7c, + 0x33, 0x4c, 0x10, 0xf6, 0x6f, 0x79, 0xdf, 0xd3, + 0xf0, 0x24, 0x57, 0xf1, 0x60, 0xe1, 0xf0, 0xbd, + 0xc4, 0x1f, 0xf4, 0x67, 0xd2, 0xd3, 0xcc, 0x6a, + 0x07, 0x72, 0x44, 0x16, 0x85, 0x46, 0xd0, 0x73, + 0x87, 0xa9, 0xc7, 0x2f, 0xd1, 0xf5, 0xec, 0xe3, + 0x28, 0xa3, 0x93, 0x4f, 0xd7, 0x76, 0xc1, 0x3c, + 0x0d, 0x13, 0x33, 0xcf, 0x5b, 0xbd, 0x6a, 0x52, + 0x4e, 0xee, 0xc8, 0x5e, 0xa1, 0x58, 0x4a, 0x08, + 0x81, 0xd9, 0x23, 0xcc, 0xfb, 0x1c, 0xb2, 0xd8, + 0xa3, 0xe4, 0x53, 0xfe, 0xf4, 0x4b, 0x48, 0xc1, + 0x20, 0xa4, 0x97, 0xf8, 0x38, 0xa3, 0x69, 0xc1, + 0x11, 0xf0, 0xa1, 0x3b, 0xa9, 0x9a, 0x12, 0x61, + 0xe8, 0x8d, 0x99, 0x44, 0x3f, 0x94, 0x72, 0x82, + 0x19, 0x96, 0x62, 0xb0, 0xa6, 0x64, 0x05, 0x19, + 0x8f, 0xd6, 0x5d, 0x05, 0xbf, 0x79, 0x9e, 0x9d, + 0xe4, 0x93, 0x4c, 0xad, 0x61, 0x8c, 0x18, 0xda, + 0xb6, 0x2e, 0xb3, 0xca, 0x14, 0x4d, 0x53, 0xa4, + 0x97, 0x27, 0x10, 0x56, 0xa2, 0x67, 0x5a, 0x5a, + 0x5e, 0x13, 0xc0, 0xdb, 0xa7, 0x9f, 0x45, 0x5b, + 0xeb, 0x1a, 0x14, 0x0c, 0x8c, 0x38, 0x5e, 0x77, + 0x9a, 0xec, 0x75, 0x68, 0x93, 0x65, 0x02, 0x9c, + 0xfb, 0x62, 0x60, 0x49, 0xdd, 0xb2, 0x2a, 0x67, + 0x86, 0xe3, 0x8a, 0x7d, 0x8c, 0x46, 0x78, 0x81, + 0x60, 0x69, 0xf2, 0x3f, 0x74, 0x11, 0x35, 0xff, + 0x77, 0xa3, 0x66, 0x20, 0xfc, 0x98, 0x4a, 0x35, + 0x7a, 0x52, 0xe4, 0x90, 0x13, 0x80, 0xb9, 0xa6, + 0x73, 0x7a, 0x7d, 0x66, 0x6e, 0x6b, 0xb6, 0x43, + 0x10, 0xd5, 0x91, 0x2b, 0x66, 0xdd, 0x89, 0x87, + 0xe3, 0x8c, 0x58, 0x53, 0x2f, 0x40, 0x74, 0x45, + 0x1b, 0x77, 0x7a, 0xa4, 0x44, 0x19, 0x78, 0xba, + 0x87, 0x10, 0x41, 0x31, 0x32, 0x5f, 0x87, 0x68, + 0xde, 0x43, 0x4a, 0xef, 0x33, 0xb3, 0x11, 0x83, + 0xa9, 0xc2, 0x6f, 0x8d, 0x34, 0xe2, 0x95, 0x84, + 0x3a, 0x4f, 0x6f, 0x8c, 0x31, 0x1d, 0xb6, 0xf5, + 0x95, 0x0d, 0x01, 0x11, 0x20, 0xdf, 0x72, 0xf3, + 0x3f, 0x9a, 0x33, 0xaa, 0xb1, 0x06, 0x6a, 0x63, + 0x47, 0x91, 0x01, 0xdf, 0xb3, 0x54, 0x36, 0xfd, + 0x06, 0x2d, 0xb8, 0x08, 0xe3, 0xd3, 0x65, 0xac, + 0x66, 0x03, 0xee, 0xa4, 0x63, 0xbd, 0xd4, 0xce, + 0xbd, 0x79, 0xa7, 0x48, 0x38, 0xc5, 0x7d, 0xb5, + 0x71, 0x9a, 0x3c, 0x11, 0x7c, 0x6c, 0xe2, 0x54, + 0x02, 0x5d, 0x42, 0xab, 0x25, 0x93, 0x66, 0x01, + 0x37, 0x78, 0x35, 0x4a, 0x8c, 0x19, 0x4d, 0x00, + 0x75, 0x4f, 0xcc, 0xc0, 0x26, 0x82, 0xc1, 0x35, + 0x8c, 0xc7, 0xc2, 0x59, 0x01, 0x3e, 0x98, 0x22, + 0x88, 0x9c, 0x90, 0x75, 0x05, 0x33, 0x07, 0xb9, + 0x39, 0x81, 0x38, 0x58, 0x10, 0x29, 0xcf, 0xc8, + 0x98, 0xb2, 0x03, 0xd7, 0x5b, 0xb3, 0x18, 0xba, + 0x34, 0x0c, 0x9f, 0xab, 0xd7, 0xed, 0x29, 0x82, + 0x41, 0xe0, 0x20, 0x97, 0x57, 0x92, 0xb2, 0xb8, + 0x10, 0x2d, 0x0b, 0xa2, 0xc5, 0x8f, 0x90, 0x6f, + 0xed, 0x12, 0x56, 0x25, 0xbe, 0xfd, 0x75, 0xf7, + 0xb6, 0xf8, 0x40, 0x67, 0x39, 0x11, 0xfa, 0x15, + 0xae, 0x6a, 0x54, 0x5f, 0x32, 0x2b, 0xf8, 0x48, + 0x55, 0xbe, 0x86, 0x2f, 0x69, 0x48, 0x5b, 0x5d, + 0x4d, 0xb7, 0x35, 0xaa, 0xb6, 0x91, 0x88, 0x19, + 0x96, 0x1c, 0x68, 0xf6, 0x85, 0x9e, 0xb3, 0xb2, + 0xa3, 0x32, 0xd4, 0x52, 0x70, 0xb7, 0x62, 0xe3, + 0x14, 0xb6, 0x78, 0x5f, 0x1b, 0x1d, 0x04, 0x9c, + 0x26, 0x0c, 0x33, 0x94, 0xb1, 0x97, 0x08, 0xdb, + 0x0b, 0x39, 0x29, 0xd4, 0xbc, 0x6d, 0xdf, 0x02, + 0xc6, 0x99, 0xab, 0x99, 0x32, 0xe5, 0xce, 0x51, + 0x4f, 0xae, 0xb8, 0x8b, 0xe0, 0xaf, 0x07, 0xc4, + 0xf9, 0x41, 0x7c, 0x59, 0xa0, 0xac, 0x74, 0x4d, + 0x7e, 0x43, 0x77, 0x9c, 0x06, 0x49, 0x79, 0x8a, + 0x14, 0x73, 0x93, 0xa8, 0x5b, 0x1b, 0x34, 0x29, + 0x78, 0x04, 0x2f, 0xd7, 0x1f, 0x13, 0x90, 0xe0, + 0xdd, 0x3b, 0x42, 0x6b, 0x79, 0x6e, 0x52, 0xc7, + 0x0f, 0x38, 0xda, 0x01, 0x2c, 0x8d, 0xe6, 0x94, + 0x5d, 0x59, 0x27, 0x1d, 0x10, 0x4e, 0x11, 0x36, + 0xfb, 0x53, 0x16, 0x05, 0x25, 0xf2, 0x64, 0xd8, + 0xf9, 0xcd, 0x5c, 0xfe, 0xb4, 0x18, 0x44, 0x80, + 0x10, 0xbc, 0x3d, 0xf3, 0x1d, 0x5a, 0xf0, 0xc1, + 0xc3, 0x55, 0xff, 0x41, 0x3e, 0xe3, 0xef, 0x44, + 0xb2, 0xc0, 0x01, 0x18, 0xa2, 0x49, 0x88, 0x78, + 0x0d, 0x4c, 0xc8, 0x73, 0xcf, 0x30, 0x85, 0x3a, + 0x88, 0x90, 0x01, 0xcf, 0x69, 0x53, 0xa3, 0x18, + 0x3f, 0xd6, 0xe7, 0x94, 0x14, 0xa7, 0xae, 0xcd, + 0x6f, 0x11, 0x72, 0xfe, 0x2b, 0xb0, 0x81, 0x53, + 0xea, 0x67, 0xd6, 0xe4, 0xca, 0x42, 0xa0, 0xf9, + 0xb1, 0xd4, 0xb5, 0x3b, 0xc9, 0xf0, 0x36, 0xc1, + 0x1c, 0xf4, 0xb1, 0xf6, 0x84, 0xd0, 0x86, 0x6c, + 0x76, 0x9a, 0x03, 0xc2, 0xb6, 0x2e, 0x9a, 0x46, + 0xf5, 0x5f, 0x2c, 0x38, 0xac, 0xad, 0x6f, 0x2e, + 0x7a, 0x18, 0x2d, 0x22, 0x95, 0x5e, 0x5e, 0xc9, + 0x7a, 0x0a, 0x56, 0xe1, 0xc7, 0x15, 0xfd, 0xbf, + 0xff, 0xf7, 0x7e, 0x85, 0x20, 0xa9, 0x8a, 0x9c, + 0xa9, 0x7d, 0xe8, 0xed, 0xfc, 0x7f, 0xbb, 0xf0, + 0x05, 0x3f, 0xce, 0x4f, 0x4c, 0xee, 0xa4, 0xa0, + 0xcc, 0x9c, 0x62, 0x1e, 0xd6, 0xd0, 0x30, 0x37, + 0xb8, 0x98, 0x56, 0x1d, 0xaa, 0xd6, 0x5e, 0x73, + 0x12, 0xe4, 0x88, 0x82, 0x48, 0x64, 0x06, 0xd7, + 0x2a, 0x31, 0x50, 0x7b, 0x10, 0x17, 0xb8, 0x4c, + 0x5a, 0x8d, 0xf1, 0xfc, 0xf1, 0x33, 0x3b, 0x98, + 0x42, 0x18, 0x5b, 0x35, 0x78, 0xca, 0x8e, 0x41, + 0x52, 0xae, 0x6d, 0xe1, 0xa2, 0x9d, 0x5b, 0xbd, + 0xf3, 0x5f, 0x49, 0xc1, 0x27, 0x06, 0xc1, 0xaf, + 0xc0, 0xa3, 0x9d, 0xf3, 0x1c, 0x8e, 0x90, 0x8a, + 0xb0, 0x69, 0xb0, 0xc5, 0x11, 0x0c, 0x91, 0x14, + 0x1f, 0x5e, 0x10, 0xe1, 0x1d, 0x14, 0x30, 0x54, + 0x1e, 0x17, 0x3d, 0x31, 0x7b, 0xbf, 0x2f, 0x9d, + 0x6d, 0x63, 0x32, 0xf0, 0x9d, 0x9f, 0x95, 0x3d, + 0x0b, 0xd2, 0x4d, 0x10, 0xe2, 0x3f, 0x67, 0x69, + 0x43, 0x9a, 0x4a, 0x2c, 0x54, 0x71, 0xa8, 0xa0, + 0x9e, 0x9f, 0x10, 0xaf, 0x1b, 0xce, 0x99, 0xe3, + 0x25, 0x32, 0x10, 0x54, 0x80, 0xfe, 0xda, 0x57, + 0xd0, 0xb2, 0x92, 0x7f, 0xbb, 0x5f, 0xe7, 0x4d, + 0x1b, 0x3d, 0x46, 0x4d, 0xe4, 0x4c, 0xd6, 0xaf, + 0x1a, 0x32, 0x12, 0x40, 0xb8, 0x84, 0x8e, 0xe4, + 0x80, 0xce, 0x7e, 0xc1, 0x13, 0x8b, 0xb0, 0xb7, + 0x6f, 0x24, 0xba, 0x85, 0x50, 0x83, 0xc3, 0xcf, + 0x19, 0xb3, 0xf0, 0xc7, 0xee, 0x68, 0xbe, 0x9e, + 0x6d, 0xb9, 0xfb, 0xd5, 0x29, 0xce, 0x82, 0xcd, + 0x69, 0x16, 0x68, 0x6b, 0x6a, 0xf4, 0x02, 0x32, + 0xce, 0x60, 0x37, 0x0c, 0xb9, 0x38, 0x92, 0x9c, + 0x42, 0xa9, 0x0b, 0x53, 0x96, 0xfe, 0x39, 0xc1, + 0x24, 0x65, 0x9b, 0xcd, 0xe7, 0x8d, 0x36, 0x07, + 0x9f, 0x1d, 0x35, 0x8e, 0xdc, 0x4c, 0xb5, 0x68, + 0xc5, 0xfd, 0x44, 0x19, 0xf2, 0x6c, 0x59, 0x1c, + 0xb1, 0x0b, 0x35, 0x48, 0x86, 0x1a, 0x05, 0x22, + 0x03, 0x0c, 0x0c, 0xa2, 0x92, 0x90, 0x35, 0xfb, + 0x37, 0x94, 0xc7, 0x15, 0x84, 0xae, 0xe8, 0x05, + 0xa0, 0xf7, 0x30, 0x11, 0x5c, 0xe4, 0x5d, 0x3e, + 0x12, 0x54, 0x80, 0x54, 0x6b, 0x09, 0x8c, 0xce, + 0x80, 0x5e, 0xa7, 0xc8, 0x6a, 0x0c, 0x56, 0xe1, + 0x18, 0x7d, 0xc9, 0x39, 0xc1, 0xef, 0xe3, 0x25, + 0xa0, 0x8b, 0x2f, 0x60, 0x3a, 0x43, 0x39, 0xa6, + 0x28, 0x28, 0x7b, 0x4c, 0x77, 0xd4, 0x49, 0x61, + 0x46, 0xe9, 0x1b, 0x45, 0xd6, 0xb1, 0x56, 0xe1, + 0x7d, 0x34, 0xcd, 0x06, 0xb6, 0x67, 0x8d, 0x7d, + 0x7a, 0xe2, 0xbe, 0x68, 0x35, 0xa6, 0x78, 0xe5, + 0x47, 0x48, 0xb7, 0xc7, 0xde, 0xcd, 0xc9, 0x05, + 0xb4, 0xe7, 0x50, 0x48, 0xe1, 0x4b, 0xfe, 0x76, + 0x77, 0xc6, 0xf7, 0x5f, 0xcb, 0xc2, 0xa8, 0xd7, + 0xd6, 0x8a, 0xe5, 0x49, 0xd9, 0xca, 0x45, 0xf4, + 0xda, 0xcd, 0x33, 0xd1, 0x59, 0x2d, 0x9e, 0xc1, + 0x5c, 0xe6, 0x01, 0x18, 0xb8, 0xf0, 0x5e, 0xb1, + 0x69, 0x95, 0x2f, 0x02, 0x2a, 0xe7, 0x4a, 0xd7, + 0xd1, 0xc3, 0xd5, 0x6f, 0x15, 0xc8, 0xdc, 0x29, + 0xde, 0xb9, 0x3f, 0x8b, 0xa6, 0xbc, 0xdd, 0x25, + 0x84, 0x35, 0x3c, 0x90, 0x2d, 0xc2, 0x1e, 0x98, + 0x8a, 0x50, 0x09, 0x77, 0x42, 0xe9, 0x35, 0x8a, + 0x7c, 0x97, 0xbf, 0xe8, 0xbf, 0x56, 0xd0, 0x8b, + 0x65, 0xd3, 0xaf, 0x1e, 0x05, 0x94, 0xfa, 0xac, + 0xa8, 0x2b, 0x28, 0xcb, 0x37, 0x3e, 0xe8, 0xbb, + 0x66, 0x3a, 0xed, 0xb2, 0x48, 0x10, 0x0f, 0x3a, + 0x5a, 0xc5, 0xdb, 0x26, 0x0e, 0xaa, 0x5e, 0x69, + 0x15, 0xd6, 0x81, 0xae, 0xbd, 0xe6, 0x03, 0xf1, + 0xf6, 0x37, 0xc8, 0xde, 0x70, 0x1f, 0x64, 0xb9, + 0x5e, 0xbf, 0x2e, 0x4f, 0xb1, 0xea, 0xa0, 0x17, + 0xe6, 0x7c, 0xf9, 0x2f, 0x1e, 0xd8, 0x58, 0xde, + 0xa7, 0xf0, 0x46, 0x52, 0x95, 0xdf, 0xa4, 0x96, + 0xd0, 0xc4, 0x97, 0x2b, 0x95, 0xcd, 0x5e, 0x40, + 0x23, 0x5c, 0x10, 0xee, 0xba, 0x72, 0x9b, 0xcf, + 0x0b, 0xe8, 0x18, 0x3a, 0x70, 0xd2, 0x5e, 0x07, + 0x68, 0x93, 0xef, 0x4a, 0x5b, 0x8d, 0x72, 0x41, + 0x4e, 0xea, 0x33, 0x6a, 0x0a, 0x5e, 0xfb, 0x02, + 0x3f, 0xd4, 0xed, 0x5b, 0xe0, 0x42, 0x84, 0xd4, + 0xaa, 0x85, 0xdc, 0x5b, 0x67, 0xee, 0x71, 0x67, + 0xba, 0x8e, 0xd2, 0xbe, 0x61, 0xdf, 0x5a, 0x26, + 0xb9, 0xf0, 0x77, 0x81, 0x53, 0x24, 0x16, 0xcb, + 0x8c, 0xb8, 0x06, 0x6e, 0x68, 0xda, 0xc8, 0x2d, + 0x17, 0x54, 0xdb, 0x46, 0xcb, 0xfd, 0x1f, 0x3d, + 0x94, 0x81, 0x09, 0x4b, 0xfa, 0xb1, 0x46, 0xd9, + 0x11, 0xa3, 0xb7, 0x31, 0x9c, 0xd2, 0x38, 0xd6, + 0xba, 0x3d, 0xa3, 0x74, 0xd8, 0xf1, 0x24, 0xe8, + 0x9c, 0xcb, 0x1d, 0xf9, 0x4a, 0xf7, 0xc8, 0x4b, + 0xfe, 0x97, 0x7c, 0xa1, 0x02, 0xeb, 0x40, 0xc3, + 0x89, 0x71, 0x01, 0xcd, 0x33, 0x2a, 0xc2, 0x82, + 0xce, 0x62, 0x8d, 0x53, 0x7c, 0xdf, 0xce, 0xd7, + 0xf5, 0xa8, 0x4f, 0xf2, 0xf2, 0x2e, 0xc1, 0xeb, + 0x97, 0x99, 0x37, 0x3c, 0x53, 0xa6, 0xb4, 0x46, + 0x05, 0x64, 0x92, 0x87, 0x08, 0x3c, 0x23, 0x4b, + 0x9d, 0x67, 0x18, 0xf9, 0xe2, 0x0b, 0x1c, 0x39, + 0xd3, 0x87, 0x70, 0xc0, 0xb9, 0x1e, 0x52, 0x0a, + 0x0f, 0x48, 0xe2, 0xe7, 0x51, 0x72, 0x94, 0xf7, + 0xa3, 0xdc, 0xe5, 0x66, 0x33, 0x39, 0x54, 0x06, + 0x55, 0x93, 0x30, 0xf9, 0x5e, 0x76, 0x8f, 0xe0, + 0x59, 0x4d, 0x0d, 0xa7, 0xf5, 0xbe, 0xdb, 0x20, + 0xad, 0x0d, 0x76, 0x88, 0x5f, 0x9c, 0x7c, 0x75, + 0x2f, 0x2a, 0x0b, 0x79, 0x6e, 0xd3, 0xe2, 0x66, + 0xf5, 0x4a, 0x2d, 0x87, 0x87, 0x49, 0x84, 0x17, + 0xa2, 0x62, 0x4c, 0xbb, 0xe4, 0x6e, 0x98, 0x10, + 0xc9, 0xfb, 0x8a, 0x04, 0x68, 0x8d, 0x22, 0x66, + 0xad, 0xea, 0x2a, 0xc9, 0x97, 0x2d, 0x3c, 0xbc, + 0xd0, 0x77, 0x5f, 0xe6, 0xb8, 0x7f, 0xe6, 0xf6, + 0x39, 0xbf, 0x56, 0x0e, 0x26, 0x6d, 0xc5, 0x3e, + 0x53, 0x19, 0xd6, 0xb4, 0x57, 0x36, 0xa3, 0xc6, + 0xd3, 0x3d, 0x66, 0x79, 0x30, 0x5c, 0x14, 0x0c, + 0x0f, 0x3e, 0x96, 0xae, 0x90, 0x97, 0xab, 0x0d, + 0x9f, 0xc3, 0xe7, 0x66, 0x3e, 0xe0, 0x31, 0x43, + 0x4b, 0x01, 0xb3, 0x0e, 0x9e, 0x8c, 0x82, 0x4a, + 0x8c, 0xc7, 0x79, 0x85, 0xdf, 0x75, 0x0d, 0xb4, + 0x2b, 0x03, 0x14, 0xef, 0x72, 0x58, 0xfd, 0x64, + 0xc8, 0xe3, 0x0d, 0x9a, 0x14, 0x6f, 0x76, 0xf9, + 0x46, 0xd1, 0xd2, 0x81, 0xb3, 0x16, 0x6e, 0xc7, + 0x76, 0x82, 0xce, 0xf4, 0xee, 0x33, 0x00, 0xe6, + 0x77, 0xc4, 0xad, 0x4f, 0x06, 0xa7, 0x48, 0x80, + 0x9e, 0x21, 0x66, 0xca, 0x75, 0x69, 0x57, 0xcb, + 0xf0, 0x67, 0x6a, 0xaa, 0x8f, 0x88, 0x14, 0xbd, + 0x65, 0x62, 0xe2, 0xad, 0xcc, 0x22, 0x88, 0x7b, + 0x94, 0xbd, 0x0e, 0xcd, 0xb6, 0x69, 0xa2, 0xcb, + 0x7d, 0x57, 0x5c, 0xb4, 0x92, 0x80, 0x13, 0x99, + 0x84, 0xf3, 0x79, 0x0a, 0x2d, 0x70, 0xa4, 0xe0, + 0xde, 0xc6, 0x32, 0xb0, 0x8a, 0x62, 0xb5, 0xcf, + 0xfa, 0x5e, 0x5a, 0x92, 0x32, 0x7d, 0x34, 0x07, + 0xb5, 0x52, 0x3a, 0xb5, 0x7d, 0x0f, 0xa1, 0xba, + 0x56, 0xd0, 0x07, 0x76, 0x11, 0xf2, 0xc3, 0x33, + 0x9d, 0xbd, 0x12, 0x35, 0x5e, 0xf7, 0x05, 0x88, + 0x76, 0x94, 0xa6, 0xbf, 0xed, 0xb8, 0xa4, 0xa2, + 0x0c, 0xbe, 0x0f, 0x6a, 0xaf, 0xf3, 0x1b, 0x33, + 0x4a, 0xb7, 0x68, 0x3f, 0xbe, 0x95, 0x13, 0x97, + 0x0f, 0x15, 0x17, 0x1b, 0x23, 0xaa, 0x08, 0x78, + 0xa6, 0x5b, 0x08, 0xa2, 0x9d, 0x03, 0xa8, 0xa7, + 0x39, 0xdc, 0xbc, 0x9a, 0x85, 0xf5, 0xe5, 0x55, + 0x59, 0x3c, 0xef, 0xf9, 0x3f, 0x22, 0x8e, 0xf8, + 0xd8, 0x3e, 0x02, 0x0b, 0xd8, 0x78, 0x4b, 0x15, + 0x7f, 0xaa, 0x2c, 0xff, 0xbe, 0x77, 0x33, 0xc7, + 0x6a, 0x12, 0xaa, 0xa4, 0xbe, 0xc0, 0x3b, 0xcb, + 0x13, 0x9d, 0x9c, 0x5a, 0x9f, 0x8a, 0x57, 0x36, + 0x4f, 0x02, 0x5a, 0xf8, 0x1d, 0x97, 0x77, 0x43, + 0xc8, 0xa5, 0xb7, 0x9b, 0x10, 0x98, 0xfd, 0x58, + 0xbf, 0x42, 0xf6, 0xbf, 0xff, 0x6c, 0x40, 0x18, + 0x18, 0xdf, 0xac, 0x57, 0x71, 0xea, 0xcc, 0x8e, + 0xfd, 0xfe, 0x10, 0xfb, 0xb9, 0xfe, 0xbc, 0x9a, + 0x9c, 0x27, 0xe4, 0x10, 0x15, 0x94, 0x41, 0xa1, + 0xcc, 0xf6, 0x25, 0x49, 0x4f, 0x96, 0xc1, 0x8c, + 0x9e, 0x3e, 0x18, 0x29, 0x49, 0x92, 0xe7, 0xfe, + 0x22, 0xff, 0xed, 0x02, 0x16, 0x90, 0xef, 0xac, + 0xec, 0x95, 0x1d, 0x5b, 0x94, 0x9c, 0xf6, 0x7c, + 0x1b, 0x5a, 0x9d, 0xb0, 0x9b, 0x05, 0x36, 0xbf, + 0xef, 0xec, 0x63, 0x35, 0x40, 0x24, 0x45, 0x40, + 0x30, 0x1a, 0x9b, 0x90, 0xc3, 0xc2, 0xf7, 0x37, + 0xfb, 0x08, 0x8e, 0x48, 0x19, 0x48, 0xed, 0xa8, + 0xa8, 0x04, 0x6f, 0xd0, 0x33, 0xe9, 0xb8, 0x8d, + 0xe7, 0x1e, 0x5c, 0x47, 0x74, 0xc0, 0x66, 0x30, + 0x4e, 0xa7, 0x86, 0x73, 0xf1, 0xe5, 0x78, 0xa6, + 0xe0, 0xc1, 0xda, 0x13, 0x72, 0x07, 0x85, 0x34, + 0x63, 0x95, 0x49, 0x30, 0x4b, 0x9d, 0x03, 0xf1, + 0x7a, 0x6b, 0x91, 0xa2, 0x85, 0x41, 0xf9, 0x4a, + 0xd6, 0xff, 0xff, 0x86, 0xf7, 0xf0, 0xce, 0xb9, + 0x07, 0xf1, 0x88, 0x04, 0x33, 0xaa, 0xeb, 0x54, + 0xb2, 0x1c, 0x8e, 0x2e, 0x7b, 0x04, 0xa8, 0xcc, + 0x2c, 0x7a, 0xb3, 0xad, 0x1a, 0x89, 0x38, 0x89, + 0xd7, 0x11, 0x3a, 0x8c, 0xcf, 0xe3, 0xc5, 0xba, + 0xb0, 0xcc, 0xc4, 0xe3, 0x33, 0xf3, 0x18, 0xba, + 0xec, 0x56, 0xd9, 0x1c, 0x40, 0x70, 0x0d, 0x4e, + 0x97, 0x01, 0x23, 0xf3, 0x5a, 0xdc, 0xbf, 0x68, + 0x93, 0xc2, 0x1d, 0x8a, 0x96, 0xb7, 0xac, 0x18, + 0x6f, 0xf7, 0x84, 0x71, 0x0d, 0x3d, 0xf8, 0xba, + 0xdf, 0xb6, 0x89, 0x1d, 0x78, 0x19, 0xf2, 0x59, + 0xe9, 0x15, 0x55, 0x29, 0x73, 0x50, 0x59, 0x14, + 0x02, 0x21, 0x16, 0x8f, 0x0f, 0xdf, 0xa5, 0xf0, +}; + +static struct crc_test { + uint32_t crc; /* random starting crc */ + uint32_t start; /* random offset in buf */ + uint32_t length; /* random length of test */ + uint32_t crc32c_le; /* expected crc32c_le result */ + uint32_t crc32_be; /* expected crc32_be result */ +} test[] = { + {0xffffffff, 0x00000000, 0x00001000, 0x13934bef, 0xd8ddcdc3}, + {0xfe7328ea, 0x00000763, 0x00000717, 0xed2c0d70, 0xc863aef8}, + {0x4c40684e, 0x00000721, 0x0000011e, 0xd7f46ccc, 0x173a11c4}, + {0x6b487f90, 0x00000264, 0x000007bc, 0x759e9939, 0xd6307c56}, + {0x9f5810db, 0x00000afa, 0x00000255, 0x2685197f, 0x2e5c9201}, + {0xb15c4755, 0x00000d5b, 0x000002a4, 0xd8fadcb5, 0xf682c4be}, + {0x06518253, 0x00000ffb, 0x00000004, 0xabee2433, 0x3d8abdf9}, + {0xd9e71c55, 0x00000a2a, 0x00000259, 0x96682af2, 0x47b4d26c}, + {0x0c1ae843, 0x00000ce4, 0x0000031b, 0x7b637c43, 0x62b47e8b}, + {0xec3cd517, 0x000002ff, 0x00000566, 0x5d719a77, 0xff5bc5b7}, + {0x77828e95, 0x0000067f, 0x0000038f, 0x43ee5b6c, 0x1a0cfacd}, + {0xec87b4e3, 0x00000d1c, 0x000002e3, 0x2ddd2eee, 0x275118a7}, + {0x412158bb, 0x00000eee, 0x00000111, 0x67b38ba2, 0xa74ecff5}, + {0x2e52de3e, 0x00000c4a, 0x000003b5, 0xbcc5d61d, 0xbd800707}, + {0x6ddaae8b, 0x00000d99, 0x00000266, 0x8b535544, 0xecbde1a1}, + {0x049b6cb1, 0x000009c5, 0x000000b0, 0xfc22cabc, 0xfb78eb9f}, + {0x77d4b954, 0x0000028a, 0x000007fa, 0x71d00923, 0x8c116f85}, + {0x5e192355, 0x00000ac1, 0x000001fa, 0xb966b81a, 0x5aa17bbe}, + {0x7d80b71d, 0x00000213, 0x000001e0, 0x2bba371a, 0xb5906aa6}, + {0x01f6f1e4, 0x000001d6, 0x00000395, 0xb7e8a647, 0x3ad112b1}, + {0x1dfabb13, 0x00000e14, 0x000001eb, 0x53917fba, 0xbaee0339}, + {0xb00a4449, 0x00000bf6, 0x00000409, 0xedecb577, 0x6f3a3979}, + {0x7ecd3981, 0x0000083f, 0x0000016b, 0xefef62b9, 0xe3e52eed}, + {0xf8f330d2, 0x000004be, 0x00000757, 0x9357c9f3, 0x0835bc1b}, + {0x03c38af2, 0x00000d23, 0x000002dc, 0x360fa8c0, 0x2ca885e6}, + {0x687bb79b, 0x00000f3d, 0x000000c2, 0x448d3be2, 0x79be2f78}, + {0x6710f550, 0x000009e9, 0x00000603, 0xdbfd1998, 0x1d25f627}, + {0x873171d1, 0x00000787, 0x000004d5, 0xab7f1b62, 0xa76a5656}, + {0x373b1314, 0x00000f0f, 0x000000f0, 0x184098ab, 0xba273974}, + {0x90fad9cd, 0x00000ead, 0x00000152, 0x23ce52ff, 0xb7bc958c}, + {0x19676fe7, 0x0000007d, 0x0000070d, 0xf8a76f1e, 0xf882b644}, + {0x89facd45, 0x000005f3, 0x00000473, 0x4331a006, 0xe9dc1396}, + {0x6f173747, 0x00000fc3, 0x0000003c, 0xb012f08e, 0xc6b888ee}, + {0x4b44a106, 0x0000075a, 0x0000008b, 0xf6f7ac38, 0x60cd2b74}, + {0xb620ad06, 0x00000774, 0x0000017e, 0xd34558e6, 0x3a0a615b}, + {0x976f21e9, 0x000008d7, 0x0000034a, 0xe533aa3a, 0xa99e60be}, + {0x687628c0, 0x000006c5, 0x0000061b, 0x3a840b15, 0x9bfcaef2}, + {0xe24ac108, 0x00000cd0, 0x0000032f, 0x51010ae8, 0x20958672}, + {0x361c44a3, 0x00000304, 0x00000719, 0xfd7bd481, 0xd70ff2b2}, + {0xd93ff95e, 0x00000db7, 0x0000008e, 0xcfbbc304, 0xad716acd}, + {0xed752d12, 0x00000883, 0x00000091, 0x65a6c868, 0x95c71c7b}, + {0xb4ff4b54, 0x000003d3, 0x000001c1, 0xf82597e7, 0x44b7f99b}, + {0x111b520f, 0x00000708, 0x000000eb, 0xc3e109f3, 0x71bc01ee}, + {0x62c806f2, 0x00000ba3, 0x0000045c, 0x874d3a72, 0xc539b753}, + {0x40d97470, 0x000005e1, 0x0000058d, 0x87a9684f, 0xea6073a5}, + {0x4312179c, 0x00000056, 0x0000070e, 0x809a00f5, 0x209aea3b}, + {0x13d5f84c, 0x00000a2d, 0x00000104, 0xf3d27578, 0xe087a8b6}, + {0x1f302cb2, 0x00000151, 0x00000014, 0x1e162693, 0x95e4b90e}, + {0xe491db24, 0x00000600, 0x000006f6, 0x7ff09615, 0x77611523}, + {0xf9a98069, 0x000002ba, 0x000002ad, 0x01af7387, 0xea925faa}, + {0xe9c477ad, 0x0000015f, 0x00000778, 0x6facf9a0, 0x1130f736}, + {0x353f32b2, 0x0000087c, 0x00000783, 0x6cc964ea, 0x32459994}, + {0x78e1b24f, 0x00000650, 0x000006a8, 0xb3bb7c27, 0x5a632f78}, + {0x61aa400e, 0x00000049, 0x00000254, 0xb8cd1681, 0xdf2652d5}, + {0xb84b10b0, 0x00000f73, 0x0000008c, 0x406a6450, 0x3619d31b}, + {0x9fa99c9c, 0x00000a7c, 0x000004d7, 0xfb3d21b4, 0xea31c743}, + {0x3fc9ebe3, 0x00000cd9, 0x000000d6, 0x43803f9c, 0x1f76a809}, + {0x529879cd, 0x000002f2, 0x00000595, 0x78b4c6a6, 0x63b9b93f}, + {0x3a933019, 0x00000516, 0x00000266, 0xdcb45436, 0x8f99c98c}, + {0x887b4977, 0x00000227, 0x0000038d, 0xc5f7c3d9, 0xaf5e3091}, + {0x770745de, 0x000008c6, 0x00000739, 0xf69145e8, 0x53d0dce1}, + {0x28be3b47, 0x00000c46, 0x0000032b, 0x764c028f, 0x106d0905}, + {0x5013a050, 0x00000cf6, 0x00000309, 0xea8fe164, 0x62180b57}, + {0x2ec4c9ba, 0x000006e8, 0x0000078d, 0xa35557a9, 0xf44430a4}, + {0xa9f950c9, 0x00000d33, 0x000002cc, 0x41ea8618, 0x587b4eb3}, + {0x5b520229, 0x000007b2, 0x00000484, 0x44569f1f, 0x92406c32}, + {0xd8dcbbfc, 0x0000002f, 0x0000048c, 0xdb88ab8b, 0x13bfe70e}, + {0x25529792, 0x00000d1d, 0x000002e2, 0x20cda404, 0x19d3b4e4}, + {0x9f3f6d71, 0x00000238, 0x0000079a, 0x0720443e, 0x3c107021}, + {0x64121215, 0x000007ff, 0x0000038f, 0x6aacff2c, 0xb82fdc3e}, + {0xfb6cdde0, 0x00000ef8, 0x00000107, 0xbd43a0f1, 0xab0d3c1d}, + {0x221c9d6f, 0x000007b6, 0x0000014f, 0xb67f834b, 0x1371ad05}, + {0x030e1de4, 0x00000836, 0x000004b4, 0x0d67d26a, 0xe2e72df1}, + {0xb56fa6cf, 0x00000c07, 0x000003f8, 0x60601ac1, 0x039de73e}, + {0xb55c89f5, 0x0000098e, 0x000001d4, 0x2400efbe, 0xfe39a2bb}, + {0x5e90b6d5, 0x0000070b, 0x000003ea, 0x3bb5d6ea, 0xf0f794a0}, + {0x2a7045ae, 0x00000961, 0x00000633, 0xfca89e4b, 0xe66ce41c}, + {0x8b374ea9, 0x000006ba, 0x00000780, 0xbce036ed, 0x4cb28ef7}, + {0x8bd90bc9, 0x00000562, 0x00000369, 0xcb26a24b, 0x40236d1d}, + {0x5b1b1762, 0x000000fd, 0x0000051a, 0x33cdda07, 0xc32e420a}, + {0xa4153555, 0x0000058f, 0x000005c7, 0xbe50eeca, 0x83a67f35}, + {0x0be1f931, 0x00000651, 0x00000672, 0x95a25753, 0x88f1aac1}, + {0xb7e78618, 0x00000a7f, 0x000002bb, 0xe06bcc1c, 0x74274f66}, + {0x4a9bc41b, 0x00000e51, 0x000001ae, 0x709e8d2c, 0x54eff534}, + {0xfc359d13, 0x00000440, 0x000002f8, 0x0a58451f, 0x55e9363f}, + {0x5aa48619, 0x000006d1, 0x00000284, 0x928ead83, 0x31041c06}, + {0xa609afa8, 0x0000053e, 0x00000272, 0xb048c141, 0x4704efba}, + {0x3f108afb, 0x00000949, 0x00000150, 0x9a6bb5bc, 0x4e4430c8}, + {0x79bec2d3, 0x000008ed, 0x00000712, 0x32692d57, 0x11d52a7b}, + {0x9429e067, 0x00000bc3, 0x0000043c, 0x5295ceff, 0x04640f4d}, + {0xae58b96a, 0x0000082d, 0x000007d2, 0xc2a681ba, 0xf7ca4a2c}, + {0x95df24be, 0x00000985, 0x000004c1, 0x3a287765, 0x2c4af003}, + {0x5e94976f, 0x00000596, 0x000004ed, 0xff00c489, 0x5ae11687}, + {0xf5e5f1de, 0x00000d31, 0x000002ce, 0x35f28e91, 0x30d47957}, + {0xa2c219cf, 0x00000a3c, 0x00000374, 0x707d21eb, 0x2a14a255}, + {0xf21b6ceb, 0x00000919, 0x00000135, 0x0847fb8b, 0xcb8d3b93}, + {0xaa988728, 0x00000787, 0x00000771, 0x885aeaa4, 0x6531b509}, + {0xaa5dfaac, 0x000003e5, 0x0000051b, 0x52c48ab7, 0xe43cc5e9}, + {0x0a053968, 0x00000d2a, 0x000002d5, 0x7a90256d, 0x8004765c}, + {0x1421dc20, 0x00000eef, 0x00000110, 0x97d6da24, 0x1378f6ff}, + {0xb47c2166, 0x00000a6a, 0x00000209, 0xcfd6cc52, 0x676e14a5}, + {0x77dd1955, 0x000000de, 0x00000266, 0xba74bcaa, 0xc71b429c}, + {0x68a03cc2, 0x0000082f, 0x000007b0, 0x752bd5d8, 0x19ed14aa}, + {0x0226b0a3, 0x00000a5f, 0x000005a0, 0x82de4970, 0xf654d3ed}, + {0x637bf3b1, 0x00000d93, 0x0000026c, 0x5c7115cb, 0x3cccb57e}, + {0x3b120edf, 0x00000c13, 0x000003ec, 0x80d7d20f, 0x92132798}, + {0xe2456780, 0x000002eb, 0x00000641, 0xc0a5d289, 0x6160c87a}, + {0x9b2e7125, 0x00000c0c, 0x000003f3, 0xcc15f57e, 0x6f00f637}, + {0x153033ef, 0x00000787, 0x000006b6, 0x3cde443b, 0xb46caa6e}, + {0x18458b3f, 0x0000066c, 0x00000561, 0x9a2bd8c6, 0xb6c29121}, + {0x4ff9d4b9, 0x00000c8f, 0x0000033a, 0xd0ee6d6d, 0xc81cf380}, + {0xdf84b5d9, 0x00000802, 0x0000029a, 0xdab0d74a, 0xb2464559}, + {0x81ee15df, 0x000003ce, 0x00000725, 0x9942e2de, 0x4ccf571b}, + {0x5c768e04, 0x00000afd, 0x00000160, 0x36110831, 0xae0b305a}, + {0xe5e18094, 0x00000b4b, 0x000000a0, 0xffa3e4a7, 0x6c8a4f09}, + {0xed7263b6, 0x00000d0d, 0x000002f2, 0xb0006a35, 0x7e04af8c}, + {0x5bfde7d7, 0x000006fb, 0x00000554, 0xa4193b76, 0xb3a91d12}, + {0x67f4a743, 0x00000b85, 0x0000047a, 0xf05c8d8f, 0xfb472fdf}, + {0xf13bdf22, 0x00000ff7, 0x00000008, 0x816351eb, 0xf347f235}, + {0x08ecc608, 0x00000d5d, 0x00000098, 0x90492772, 0x0b7f1521}, + {0x296f52ba, 0x000004f9, 0x00000788, 0x5e5a4896, 0x1cc67088}, + {0xbe4624c2, 0x00000427, 0x000004ef, 0xcd267b94, 0x550caefd}, + {0x906f7c7c, 0x00000a05, 0x0000003f, 0x03fcfc33, 0x9ed82a02}, + {0x8f7b323e, 0x00000458, 0x000004c7, 0xcd4969c8, 0x633c38a8}, + {0x88d6593d, 0x00000597, 0x000005b5, 0xf199cd3b, 0x0491452f}, + {0x978a7768, 0x00000268, 0x000001d3, 0xb28c95bd, 0x1a42fe61}, + {0x857a621e, 0x000007a7, 0x000003a8, 0xf4bf84ab, 0xcd0694c6}, + {0xb0e121ef, 0x000005be, 0x00000644, 0x28747c14, 0xf0510c72}, + {0, 0, 0, 0, 0}, +}; + +static int test_crc32c(void) +{ + struct crc_test *t = test; + int failures = 0; + + while (t->length) { + uint32_t be, le; + le = ext2fs_crc32c_le(t->crc, test_buf + t->start, t->length); + be = ext2fs_crc32_be(t->crc, test_buf + t->start, t->length); + if (le != t->crc32c_le) { + printf("Test %d LE fails, %x != %x\n", + (int) (t - test), le, t->crc32c_le); + failures++; + } + if (be != t->crc32_be) { + printf("Test %d BE fails, %x != %x\n", + (int) (t - test), be, t->crc32_be); + failures++; + } + t++; + } + + return failures; +} + +int main(int argc, char *argv[]) +{ + int ret; + + ret = test_crc32c(); + if (!ret) + printf("No failures.\n"); + + return ret; +} +#endif /* UNITTEST */ diff --git a/jni/e2fsprogs/lib/ext2fs/crc32c.o b/jni/e2fsprogs/lib/ext2fs/crc32c.o new file mode 100755 index 0000000000000000000000000000000000000000..b1c07c4c77169b4421a5be3f48a718999e9ef34c GIT binary patch literal 19256 zcmb5VV|XQNv@IOlwr$(CJGO1xwr$(CjSf4uopjRiP49E|J^227cm1h}x8@vkyw9jw zwVqmjqB3GYfPeu1egFa50RGGSHwpmIF7aQsz(1w{0Mz%&uOWbi4=Tj1LkcmW0gh&KWNNC2@5QySK-cLV_dNdE8=s`x%Pp&wXpS?3?FP0D$K2y+=9a|BeF!+?|5wVV!=*|B1m1 zbU=Uru>H0F@#zI#&f)|*&cAC&g90R6eB+k_6yT%;gp#7f1wew(uxS6Ahai-cI{lvS z|JDWluKPXbKRu!UThIT%a{o`y@AyCKp#?g|-@)1cZ_mHDAO#XnnZL3BwLgRx|JM3D z$0_^wk^MV{_+9_o{aA1pUSa2r2c=TgNH#_bg5VoDd%0 zn9&7Z&hZ60qC{_QUM%fb^mP7 zz4!Q_fQ+A(IfjFB$9j5FKz3m~xiqK#D{^|H(Vc^0--^2`B4d6|Sawl{qK~}Ky_$pv zS=Vk%7r|PDbw9n$zmi!Hb)c{o2WEVBsb(p>GP+e^iIHKGp! zSEoD5wNApFtXuj`R&G1ChhPhK=#5skqdqtn3t*Tib42FTuWCgeGYlfqaQ; zYNevcz0iEfNN1JTbu%@Oh7>2!!YTXF3C>{F463l!`!(yI958l@%AZ+2 zq>A$zaz!MSc=hCzE<)3?eW`P^OUB&1!EPMAHz7EI?;H4lX_OcDV_c^W)#JdZrZ@np zu-A_!Iv>x+Z19FjqXq^DHAyK4AO5NOsg6D%+NHi>>?)DYX5tagFfBDx_!qSj&X}5A zBv2Y0@_!n&LueXyuD3;LdS}Gymib{-(jDMdAA(*Sw7gcDE?aqv+kap8~zwbL``!XN;o9OB2kh ztwoLL!Q0|D)ryn!cvRbr=pmYSMP3DvQO<=uDGSIuDjz2ynHyN~Ex~eOb@VshG&Y z8{~HNgt&2eF~SXiVulNhP=B9rL~WeB^A+F&qEqG#5G`0aigQ^uJq#mEX-+0W+c5>B zn&tqlD4V>~eExO+E1Md#NA(Mfj~DiO#s=?74(xK6EM{n|70UczG z$@__BfaZu^NE{v7S49%ygTLz?&aV6`21FC(Y&I6%vc&r!Z=z#iFvs5lA(-IC9Z(u(Tn1H16O8TgQkqg;bn&_FHE-6@x>bI0 zTm3Ouhl8Jj<>}(%gFF^qV@qZu%Wb^G>{&{4v@X8y_37=ceg)S!VWN-86 zXx@yH6^~Ar8$Pit$*1itB^HxWnn%-9RQ9R)tADrjLgZ@(QSyxP6P8VbNV%#P3LPfJ zISbJV8_)J3l$<%O)>zdC#ZE%2hYI7u+(l$Ap8m+hjmHltkCTAA5&kC&Ga9=Ae+&!_ zB50j>c?T+pE5oLIDAi$(a#2pEg+jSXr-oIaQGEavJLR`3u?7)=~xG zJwv)dfeoi}3LKPJ#Y9PK4psGyBWTdysrh47rlDV^Z81XFfA-(k*)Ljwr=8&Bu|8_3 zs>jmJzUH)<;#Ty3_I2_;j_OER8_O*Y2YD826I$%0$RK~q9{|1tlEt03iX4nI+uxyw zFXUea9i?FykTNQMzCd)F zxbqwRky+T1M>>TeZa@PCA}dGK4%LqTZERjUq4dVhi1ZZhr zCE9`On04~Ci65+3ptR>Uf%?nq&|9pb!72J==%&6B$sB2xWQ!8;Md?%(Oky{4ZGa%> zswrE6i%T73qTpHrgHn#V4#j!@7q^o+20X}ZCyqNb*f4xj@oFl!@WEcu-fgjEbmZba zU51qAL=EqtRd4?|l17_Cy%gOaHD3+=-!?cE>F8FBTp;%uTMQw9e#CE>62Z{{=V_>v zutkOqb@k-#gOduo`oAV5!mfJfNk4_xwJ}+QKA~#PG5OXVyJ+*eR@6?3okbj?lI+2d z8I3$oW4d7N>C2PX#s+I+#MLC&LC@P;%246-UQSN@Sf+2D2SsVX0~|ET@Jvjh@Z?23*IlR#{o%*;TjqbsF4@~$ywgKg9PyTe!Xt3QLu z%rLTQE~Ix;jl3o!S8DYd>~z?z7XB81t>(ac29X>3M-xTjhYHS-$rF5jb(YI23#X}E z_O=oyh_~P{9B64%YFP^vpFn_4>3$-HUEHbNGws`x-sD`snEB?{j-FSz_=h>-4VJd4 zTf01Q?=q_jnH$+mY&=pY8WW&6j`T4@@Y(MQ8n}V&=IWnWJ_F^KM@C&PvcYjc%VgQU zbeSTMtsH9ccsoWXp+5G7@(57NtBsg4em`irPoDWkuVQ~SxX?^eY)yUYiCSD?MT4Z- zpp*tbb_>=AksK8L)xU3|U&-8okAcCIm79yj_^!-9qJt@8+Le97~ zpIhsv-_M=QxY7cMS>T`JyJyv!1u~I7h4zm(2g_mfGyE?-(V6kTysxjNd8KorkP8kl zl|bZ$A0!wT8n1*9v%z_SwhDio(5_IsSUah=2xX9w1M{G~iR@WgfQn#NP}iDqTSCL> zW%}9AY^(#r{$}vWYff1hLH$*yrsBPs=9yXu%FR4wFeTpd5V=3fTny1(a8#2UdYrI} zQpS?B6tR6JHtrQn!~y?W?@<|HuO{%kk9MTh-c~_M^#r4OzIIIEo*^uVW5LcJOOYre z2j+Ach>k?Z1VM-HDFUyx9jf*DYrB=P2 zFBU2o*13Uuc-1hpLLFF-|s9up>NFahBkC;0xIOKEqz#bSpB@YbFvC?u~y5Zh6k&E`<;a<-_|7#hGl8U zu{6aL(6lSs@9~uqEgnk897y^P_Mi!pi2_NRTC|ZRB_7e7<~9r|iHxkjEJe>FbLYFF zfalLHzSAVU#6~8iO9H3oyj>mKJx84OaJ0+mr{Efk5Rssux0OM%t-ArNA|wC4`J&n% zwTw5nV?XeNJH~VgC&BHfno}5UG3MflOm!B*P;Y~GvN3K0e&d4LtHi@{d!<8!rJNcx;jjMN zD@C^gh|T&qBZv$i7>T^3v&>2zkwk|l+W|0-jYOVwCjhC<1c)Vf&P|h1l}ux5{tzo9 zI{-4#Y>3?OHW;6UU=y-*CjzU2aEL|C`imvHQUS}$7ZK7vLmJ<1{3O6PayJ>&yc5sg z*8=jPH~=z^mlW@)=r`Fwv?KtFLLpsc?$w8aViz)R%mHt4Ck3zWj}vlu0nPZUcGs#uX%27zG_awH82KI5KpzkSDJ!dM0ne)-kjtS`vWC^aWiw(JQUe`+eYQ z>OFw6y%IcuVjDbPJv;!LB70y*ds5m6$g{80ky_^Oj~}wn(bCU<58F>BRTlE*L|2wE z6}&I9emy8;C=!;ZHB<6&V75y@xwFfe;8Jo}{vH;JpgO3<6BF7TOg?1MQ@aNZ3R1i> z*Ihj4hPHS#e;_FGunL?q&{4akhbElE#!l{vKECYXL z;?qLKETNO=wu~Ypc;@3?w$9k4{y{ zR_A|mkqS8yL09Cj(!3QC0^`=N&ic8}6{AviB7Rx+`6aebJUZ7e=xY*^t<*citZN+|oSP*vrfk|4rOi&%%mJT*x8DYI=%{W@z03jc`SbsDG=czMI46tJ-eR)-+b~CHg!=NMI4N z%%aUjJH_Tji#|O8e8(P$aQrmP25gzd$5t|cux=0t+|@cwN^*cqx=G6k3~&g6fQzHV zx5E{H85v&1E+L(aV;g=EDtj3aN)1gJr@ab^{T4a}rueJ>YCA*@^&KMn$9iUo`d-mp zoCTG&Qvxj+yJ8ZX?7~)LYAUZ*PtqnSS@B;t?RBp_e%hkx?PBgmC!`% zV8+b*YAxm1Z|fbz@RpHQMW9*AC(u`K(#G#YeM@su$X(k_qrG$6mJ8d*xdvCYOmOe1 zt^kpI>vmaSbUWp8f%P4(!Ap_J6kS=>o6zNl_QoBXES7W5>7d&()-6{c{p;^Ms5@7R z9rf=PvH)|0dv@EHB?jdUkZ>IlAH9(SiVImUwU&zPK%fHfPc2U3n(KyscuOd&ja{HO zV$f`5=f>oD{040INpR$oX1yqZQwyM-aXU^(#Px<$s{o3IUUmYSKG06>3&w{2q)Uq9 z5nTeeGc9cD2J7VdDV8V{oS>ixmjEa}0(PLH%{y$c81>|=+P#W7w+jL#AO=oX<#2|} zFFP+ZKk83W3IH~=VeKZ3B@Mc#kKk$^5qopHdluq?&6je|hP&bx7@)f|vW;sB)+{$5 zok1rV{aaot1wfu!o0~^I zF*cS)XSPSG3>ub_QUFgjIBlN}eDwXL7vK||Nc#%8Bj%fcrs9+ivLop<1R;2<_xF zcZ7l>*fzn&SOcVZb++Xk^xuYxq-nrzH1D&)8lLwiV$hej%!b!hl7y1yKQhq;M_jg% z@9Fe*dufK+`LTh0QeZ_<2MfZPcHj4)p*z2CP^rH_2?pPfC4wDJI$%#H5gfu)nLth_{JMuiO zfZDd!>05);JUpOBdXcSp{$KrLS~1)V(_3S?p9Xr+@hAATq>T73T-pcqo6&#{kn$uEj(D5$}(E_*VZY3I5`!U_Fr& zS>{raG%YGdNCB14AxvivNWq?>zUB(&sc0y(CN)gZ3Db>@#dB*XpjT zwk6TmJt=rf8S-) zMD|CtQg*!3KGZqa;!4C}7!me)%aa!aydi)FZ@potn(vde<;U!#U9RJ&>u({%4M^y; zK|^kLjEXQBz`?en3oQ`1dj^(0ins7(#`t!wZ0o!35byzIy=fmau`=24M`0k_D+;Cn z_Ji0Ky6|4jAm``JO#Crsfh8|+jXvqqWh;o;X#fsFw5ecJ`26PALhTRlF7}xugLj8A z_cTF?Nhi44MGQVc$i+Yxg!abF9+5YkV*05E-$S=Cvp8`IQ`y@nKeB$~k}Ge8?ogRN zL{Cso2t?MEpX(9(Qw<%k9zUKg^!Y|XI)8gI6y-|oz!?H-phGgZ&J4x{E>-l|sQbK2 z3!+UIXKmTX2eu0M(Mv(Tun}^iU7m*!{SIiE5jT0I)`goK4jys6&8Zc`XHbIApycFt zeYg)2I?rgTS!sj7ncL)eKt&H8gYj;rDDeNNZNHciG$e3v@sbwIoT!8Io*(8*f`Sh$ zLpE-d=uLl{Eqj4Eg|f_SJc}2n zurpedw9p-nv$dMr8K4-@bM9N$X6`8C8=nXE)QK- z!(aW6(*T>tYkIOvwe?m)yRn720Wvzbkd+IW48PZa*H(Y&OXj+XJ9r@dxlk6akonFbpW> zWcMxzQ2c?l=F#y|;>1z6L@@1*e>q*)+7>lG!X1TLhTx2pqRlK3B*s+c0L%EjCwQA@ zBXu*fKf>Am<{`4l zF;+7tt@g5#C7p^@xH^g9Xh{tB_vwu~Eqf5|vfB|@WUmyp`U({Tc4aHV>&41>E zr4ueKReEH#$XsIs9IRpPfC^w(2x45Gmd0HvMmAr>*$|m`286^QpCHASPf);n*6_y7 zoBw{mz}S5|7fAV33h(&fl8j*;4=7;E|Fy)7f%u2PK3!tjM!|Rm6asOvr=NFz8Ot6c z^rtrVbtEO8st_nH-&D&VV&IH7X|2o8hot_GtQ$956>=>b9zQzs;5HzuOTNa~yQkck zjM|HELesG*$?iyDEay@IN18>^$-^(PLL2#_z7nJS)ep21J65hz@L0%Sabl$FCwK}w zdMn)Y9x#k3#>2SiFxlov%_<^@ zn-mX$$h$iMUhS2^L-wIzRWEFYt&CU(+ZJ}lrUk-ga9(hAI!#2?tQTq(F~nY#N0n3Z ze+*A#;<*wfDeilv1ehZO8{bL;){7Q{4XwVyp!Ver(W#6K{2bAY$2z&p>h#^}-pjSB zlW*xNXgGi>MH(9AH9T@<7zr;VBhJR8_EPMB(dlTfi-A(^e9nMwri!$1Mnz|E9V}h) zYvJ_sFptJO>cbU0L#Qs@*XRDZTSJ#X8QC#LuL(m$LY3!5^!clQavvT^xmWi@i!hN5 zn?PJbsV_ovVt11!5KxWRbr5c$4-atY} zvMv-ZmJldB872U*y%;Lz8wAQW>P>53fMyYVvA{R_b0@qgMW=U#$a45)Jlos?( z&*rjI^QaDi9f_l-_Oj7_@sI5H8-i+?yS~4O7dXl)@ z?kt3kh)pIHY_l4>r*quubB*ALrL4k}0TO;eA+ls1g$!5>Q*F8zmy?Etp@Xiu1$|Ph z;~a1>H=<0U7Xns&)4Xa=C7sB$fn)T>+M}|YUR@3;NIa}^tb&l>j3NpjXq?u~e!UcS z>O&}GRkZ-<(ThB~M=I_igOnoEqcpf|dy0g9;VUM^byXTy4wc+LR9C@q_!Wf5FlhZ^ zaVW@~xqo2sD*eemEalAocI8cg0ZJY|oB7DK?LuKtz3X3Ru1BrrzN@qc! zEq-krrk|uf+ndPcnsEche`_vuxQgmqvxq>h_Gp8RmvgQ+(wSxyJ)h@R|GY2#l4}A_ z)Pccl)q`u9kg2b__Hcp(yp%~N1(hXpPkU_NC1Sv$Z-fIuX@;q|C}3=pNqImi2$zcr z@$mr2xgN`F-vsGVmFz6KAMb#J(FQ}HxE*C2`SPSbME=a>1rQ0wWC1I5CTH)PFXck6 zX#;_c3=*d|PJC|^Ao=RnV;d&@2o3;GPvFCBO5$#r4GgNfY#E3IC;LSwp7bg6)f{Bs zx&^{w^XdUX^69O({R_}0tv-}eChZLsR8JWe5jm0pu2=h3!r+ujDb>}V-ANFAZxPPn#F>b{Cw)r6 ziBCm&EdvHU8cO>_{}guO0ELVZNM8yV$4~L9|3c;AGGGz}qtF@^dhqV@?R4)Y7tkBR zhGY}b`-#YDl;y?fR;Dc@ea$)r&x+K_?2XoB8Ok`TI;Sp)gyP3Sr&GWxa}+9JUwt#j z;x^t0!8hHeID9c_6B8&)sanE-ivL&tAOpB#+A8$fn#_FyYUpW$E3O%si)+x% z^R1zEmY8hf=O66Jx9U|te>q4?j?z)Z|cx~Elvd#kqAJD|o}xGcqNTP1C6*eUf} z8zLUJn9jce>E?;`Y3gc0sNwo7C~xYU%4RVbNovwAiC{v*3ap`ZR+o&Xl^bsml#qYC z6ddo$^%c}hcj?!>w-QH@Htwe;M%GZ%$6B+c2hk%4hF!xxWmM=q7g@|}nZaf+Nu`?)SBH$DbM-{da5o z)qQG$pU3CCCKnah-8bf7(5vKKt&7K{fZHYhYwN~2cEiLomi_zlTQdbuAQSo*O+9=u zz8zoj6V2VN2=zWyWwl&yg_Uo|sAcW_(?uRzURiAVqj}Fh4vEcL<*6=W_~A@wSkVvA zH39Xs&LIvALpqW185+_tbSe;4&k7T*0&=m(qEhm2_u?>H)WS3U*cr^B6Gao}H$~MIS#0$X}^Z zDEVnEi?l;;HMMc=>U~f!HE^Q8;(AVeTX(&Gg>hTbgZpTlU-?2F>hy7(H5}3Y0U6`5 z+w0FYY8L#qF`wBTwVdmdYM8`V-<9@N15;Oz&`{+73s%ZRy;JzWX5QUwYSZrGwcf&} z1KjW|(EL~bKQRY3^Y3%v9WV42MM(%N(s*}Wj#m0g+2?#cBPE2D)D;6`sXDiG{uJQ^ z%vl@0;kp!&+vUDL_Jr|LASh-b4@zjx)fa){7aSQ%sU%_X+awG}F17i+3djP@Z@4XATK89K(GL>;8rHSv&wU zmk{RtvCB$ycG;Y)z%mI^5;*Uod}rsinRyX?7nX#*`M6?3^H=WNENvJZlAg8VK#WT~ zuArE;Op;zr{9g0DFmnxa9*Cjr(TZ0zXL0=ExoZRx+Y}r<9wz$rpw)W=V#ksFOe_^# zn>O>D72R5V`}=^Ru_F4jUJx8x(A|-R0`Yr!Gz#;|(Rr7$vi|JYf>4si2ETovr zf>#X{P(|~_cCJ@Sv5cXLJ6{BJ)n)voo57K$Wz&0B>j3(&2{IgL2g!if(9>EcelYXV zv?>(|!bJ@x2WRuzp|oBYdxn_UMQsE}f_MCjESy(q?xvxckVEr;M^Ozx$%2@kE3jT} zB}@G7{BZ;!OtPWxj+j>;@Y{PJHRX};vlbi9O(`M$`t5D>F?qz82xqeTd<#$@MKwv~o7k5l{MIOxfK|qr4Zd zzAGdWYkugX`ot~aD1qTXH75G4;9WKx_0<7Uz5=TpzUV4 zE0(@`P&y5S_HpIA)gQure)O8YMTPX&z4mPMhCo~P4fDedHYd;=bs~l`>U+47C#OcH3w^CacG(Je^s&&vSkz2bF8t^X?Aw!eRONfgu z5JntS8x4dP;Gx$kJ}S>D1!OqTj*p;|wUU9)p;=jMnrHSF5!@E#KVV8%=(qdOAF5R( z2z+HD-WRjz#{dJbv7Ia$#tZE2QBwQhY(+}v8rfvy4GvWldo&iUQ=%qoBwq;cGpRY4 z#c-Zwd1kMpce_CsnQd{9ZVoI0?-}id>4dXzJ`w`A2uo#)w47B8!@&A@RhCNM!z~C0 z^1CaZtsooGOJAwO{lm!qG3!E~?t)*m=9_Xr8sc$Fu^t^*dum|Af-B#c2{ zlF_b9#fP8GvOMfHo2o3b?0y9fcSC1^>hq|0VO`61j%Jr0q004tW!^GY=)H!Obuc~jDWZ!Wcg|dq%?pzgwNk%h-4ZAD71Jg zsJ|N*(X+)h(L^q`xKZPGxn_9GIEp8(IlWCRc-)BIdFx`m_(#3&`S4a2`^jX(CoTX%)SAU8xEC-5z4ZT{7KgorRVp z9VC-B?GyO59RE!IbRsbQ;eIXp$Aj(6&r1*I$uq3p!7uvx&{svv$eXwJ+~)|$#;V|~ z-qJ&q-5jC5*J2!p(|Sm&+6McX+RhQE(6+Lc)WkR@+_;+%-gJ2>)C|@g&=8D2*=Rcn z*`UodQ{Qe9SC+4VK;{^?OfK$}PF_u@E!OY%ySNrLsMMfhzQLx|WTPe3Xf zO)!xlK_tTrL{xApNSuNXO6)cx`MI3Ycjp(5P9gTcEi??T}#@ zKZ=p1#k#Q`GO|&V$buo;8J59TgQotSWUc{lj-E^(LxHT4*|CgiZn<=nw22)2dF|{m z?~UBr2&Ft%(&glKF!vPw%C9s?J=fHQhr6WpX5&O4jDvWqE6ao?!K<+6N`_E+u(n{a z2fmP8y$=5r44MGh=BgkPL88F-tC9$&S%~m+!??(xG_WWw?toYYZhx#oMgQq}sDjkbHE<}|we!>2pdNu=8u7X~}dd_)_`bx)hV z?(G^&Bw^rSH~g>-}2>G(UZ%vH!++ z6DRP~>g7BgiZl$UNA$LSF(Ze{I0SzQUc*tYofGtZ<;dLB;2DLsh}xqKMH&v&GtDS( zCTh>1R4w`qk^N25?;>?^9PYEF;%5>)UgKeoy=?^em?QK{b*-rp_AKIp3zE0=;Q5)@ z9b53GnCgQqMP%+{UMddMqm)CuFclaP?UPk|CNl8$+nlY4OdaMEk(0A^irrJw+wH}k6-7O^eSU|rN&O`JEbq-I98+F)? zfM9(=w)Fiz9g#TFbCN%4!GBUiM~an~GgDmX-mogltHM$9DG z@=?4%=shMUo+cj&e^#leFygMlQw#WCGE>hODw{$c=2<2ki!QOBp9;WNaKE8DLzS) zK@Qvf^wEkjo)m}AEXXnhKzl=NbSHPGm>WcptHtwK!t{kQbt^P`@9#YVsxk~u#{v4H za@14jrlsJDMy+^)`$w5Z2!1G09dZGi#I+nBcowPpn|f<3c%>5RaWUi#s* zU?h1*50R4H()arUe1S4F$F%gA7uPeYtP<-Tb$B!(&S@Rl0RznUqRtdjW1!P`$W;%f z1U<-rKmPzNW|rRz-Glh$4CyP`sU+`UU`jYv%Ukgtp*JQk67uSl!;CScaGn-iyX($! z6ea=J*-+O0dbu1UyxG|W2^a+^-)7v7YklczxBu?>oVSOPwN&{ znU%(UB9P&g{p>QWMmKsFpFtreB&_A=;MgMELlN?8ihns#F?<4{?f}(?RmBA=jH|*7 zH>L|)Ro={X`VTmuZ|a8iA>r6HmK1i7|A*HjQ&L$*If>BStY~hw%KhiXaW+w?H#Hwf zpuoNb#&aNEWrnU31D)IN8i}fO_OGd%kOcHVd@^W&J=s+ouh%xLiDWA`W#U+TRv{(F zy5CHoxLMccVKn#W9^!Oi2e)#!in)n7Qq=u=m2se-Du=(4W|cb*y?IR{jw5q$E;mta<4VTgXah-Tbx%9n3M?z)x z3@=oM<(iJu&-ePi{R2qCn#Cky&0%ezm!}at1_fEX9KtnT%VfMAP@@Q*frCLD>PIa; zjN@c})+HF=28U1}96&sPOXqb$(I5r=goByfu?RpMA3#$dDa|S(i-|j@J_lmt5lV4q zB*hryhJ=b@vkg-q97VvSDahHMi;SomyaKUb7ER(@Bfd?zSs;u5}^QS9nhUjp^0}|%gn`gd!;FhV{bpq%-q4CRrC80a&sw4vvU_T*KbVvW9WW2iH2-`>kpxuk7h3Ee@c56s7$y_G$R z+0coOWwB*xM4azU@aY3fl7O*KF8SG5GW1()hPCUD*x@~#pd#xN{c!hMo15P*p5lf) zZUi^5$za_g83v4bu@j{$LABJh`XT(rHv5fzo>HVwZnWhxK7gH|_NMIHX0!QemKC(t z5rLef!AH%XNwUOkxm2~WVi5IX(ssN!+GCYJ6!Xbz8>5&{`YwBU%0(z$N{EZ+>fl>L z3(dK8TKcO|+RF%Uw4zx{RWI6o1cm8YWJn6(?!b}7-}Q5|FUBF4kL!ZzK!fAWAP#W5 z@ueewBhi4%V*sFnp_-*{0nNcD!&JO^iZ;Qw@kJDI3~lh)n*Om#lH2t_(FWEZe*6sF(D*?V)>;Y6Ch1?liGjtC{&s$ggy=6b>*W zmODQGqao+hph9^Y9u0jx5MXVDl{);WoK@se?jCNl=W?^lWhn0EWJmBiVFGjNZ*FCx zh}fKEky;C%D*}Jrv=ONdQ>!AXv*ub*w=hMD&vR^T*iXqL(vC_iMpz#sf0tzxv0f zfOTh6z`CV%M-R8oXWexR=SbJQ{rL`LR5u1;N`KC>J%1-`6|TOFMy>~3+|NMXuJ=1^0}Ee|P|KyBDr?|9c&V5+7P-Pz zM0vReKUja}Z5V`t3scbHSdpqSA~S7Mar2j29pKK|Pa(AGG=cMpWkHF}hafjj)!#7pkC*TB}3Cu_9GX{3*U18rUL=%*z*;SJ}x6 zIr8=pqVOY|bp0HK@BYNvk7@+O7--yE(sSogN$F?w<%sb%eO zk5Ex}JXbSI6jF!GOhgmZN>eoXvG9Wl!>)T_`T&u zqKrW<&W1T5cZ(}3Bf(uIInL+xABeAoUgI9T`n%4evgt-Ms`a)l=;kt8Fam-lgdD20 zTnJh}3d4~;I`Z*DlGh+$<8DD+W+}*VmjS3u{KJuw2{gG%G6a?3~>EH*xDo2f`SfYiaJ8a8F$900 zx<-CY_gn9!^xExlyRL4fwK;5KHsfnrEO2#z4@*8g70@i?ng&17l$|{f&-JFq)n=?7 zPN1(WR4c9W6Bj1G9gL)=pIW<9g2B0s!J#@u-7+|xK>R(fTze^SepqJ8{agM3_c#mT zXDpky<(Hr7O~Vhnx!s56A<1V5RkD_G^(JP|Ik@(Ip{zdOV^?~1nVcr`3_pdp;A6d!bY%*({&fAue~W{#L!J5RLm($378-Sgl& zwY*=(WV3K;0^0Ay>2=Iwi~M|*RyADMKeQ}WGKva%UkkDXjmDm(?Mrs-_&i-fnz!Y? zNq)^9CI7W^EyW+-K}07gkckV2eh-r(9Zj{4bI1*Sqzxg`$bwnD%J}QRUt^rfWADv} zF5-Ng+@cE_-H)7&ZYHy9SN#nxuknuGz zfQ4&jMVlIj{t!diJsOfu74*OW(B{7W&+@=mUC%uFWIKX-&OBg*u{qNyGXSxUoi8X7 z2O7%IKrMN6>L{D>!_X6Tan;GI4)Rh9l-Edd_{-VGPQo83GRi4Y2f_6k6cMa_VH#-W z&SVbnt9QzihCul8<8wR@d?i{o2`-*(TK@M0Pqiz7pqp*@rLZ~2S2$AM8dH`_m2L1M z;8rwg)20;=#*MM%aihn~Jm@39A(tV!WZa*5HYI!WTr;;EdgBak5c!0qcNj=#rS`zu z)zG8JZ$_(wKpTfKKbn4Ux=+I0?H9t-twD zlT@38XYe@Rft&;{M(`Z2h2nimR3RL zJzueAkHxgKb-c4X@feOpdzPX6^E8w$8Ed1Bh2gq)0QgS#tU_B2eg%B4!lzl>(Ibvj zWs$R%m*%uN3v98+rg=d}68}WG(5OQeYyxIv>Wo?SuT1zJ2&1-Gah9FDI>mLpU9d(u z#xE!z-*Q81;LwXunT4RV918B@pMJ_MTv)0uF0y>a#m%8=7YEm3_I>gC{HK2$t`P-< z3dAUsC5dU1z??+`S7SaJ($`b+JJivmpWyv+$e+e)%?s-K{D&+3=8^_&@hm-c6nT+k zCJn4DL)bvPROY%Ru+x_`9zGT_x+^=vZIl7Kh(IhV^{93Q5PZTF2Z9+4V;9w(Ouz3e zlzXg&e=uSa+T@S?X^^u@jYJ;W8hfOJKhB9$P~*scXs*eLL=ir@4ZG%=I(Q!y@lnS# z-uz?@$Pdwpm)KQT0B>UuT#*ZR%)s0=0us#?l|_0|$-a;?TkIxt<^Dz7>KrRwR^s-M zd`^%Rk_Lxlx2ECg3zt}^tcgSuLQKb)jDTWQqFDK=Su2}*^6&!0%EHqV$8Sh42w>(+rq&t8cTWFhwAl=-5i zDUscem5ry@Hf`5A&?SWG*OJC=)O#HMypHlRPaj*98Q!_zUgw^FCpNE?>WexGta|YF zefjV63P?%<(F+-0JgNBR^y@5_A$jpW`Wm7=XP8fFG7^dC0< zlxzrzvF7czY*Zj0`)4y^YSpf@n)`Z+CuQq>tOm$#L4;-3z4#}iPDZK<)kXPdSjQyZ zsFn2hc{dR@o)kiJGnS7+Rvc;_+n(pNK)u9?U!QWodYYnxAa5BErBG^fLnaE^^kJ+(&SYof_ksJ66~uf) zq61nvc=};#9soa>i3%cKW`!@yQuY~akj1#GB~DIEi$Mc9zKV74YofzppJ-Lau;v&u z1Z}UB$0m;xv#q$)?IZNSs40S`m)7q8#Cgy$8GZkGlY=X*v^O`~?1*2W26Bt^LCO1t z6F`N2RO|NxOdEQt(q*eux+RjJ24hoB(w5?%nb7~U4=U_x1?)n#7jNH~XuPlO)TAUI zAG6F}@#$OLf0tg6TyTZw@~1zybXLZ)J#*ckyhBcIf6aMlRhyq5G$_d44C@ZCALUH(EnVQb4T@$#&eh*zn7&eFP2_eJ`V;?2h-cA6#$ zSL7W&zo|)a)tj3QWopMCd@P*fsJpvhvBy(wrYZVsm(73ojon#A>Zw|lqsy-i!Z|wr z9%nzaF43QQ`+uLOV5OGR1*PtJQs**%yG%Wy-j`(&w##s4SHa!t_j+x&jGr*nS*S+e zfAW62ZR5r_b7HIaZRu`#DjM#``Q1n$DD2&>E1#Z9_Xk^EOx_sNZz0g&I%C4(fWwCM zv-B@Z9Vsa~#`o#k+4C#Q1zBCEmPE^$teEH{QcchQpH@yCBH_$O_k7A5ep_V*d< ziIOW*PwgmOZ|cD^JMZO{sjT^7 z?FojwYI}ZnH*L4Npq%}|<{;m?^n^<(49Pi(dFcvesYS(^`FRS47J7zy7Qiw=08}sl z0b^AV17nRGqco2^g9?x@0TyLoZ~@USdP=z3M86bHeAY|SIh%$x*uwo?hJP_uA+_nR%?g0~!;lek8k@*G_ zA5;t*H6JL*!tn7wHaTVnkRhl5pa5Zk23VPZ5bQr78yp@$8h921 zSlj``0D=cltKxxdusI4KQ6NwNlMH=83S`a$2p19#P&PBNy-=|mU>eCiQ1Q!Pnia}J zPzS(Fc7y@i|ZlnD|j3AC`7tdO)-alp_rEFYw$IH~?=z0rEuA z#1BAKz||{21dc$(;p(B{EYNV22GaacH6Tg@hqw$>4J%L{;X7zL1j@n0VgAZNQxEg^ z6g2S%Q2rh?aacSvBo`$c8^tH(r&KcN6{Y4R>XoEclrZQe=jZ08<^dUb`6a1(?tY=V z#U+W!*-$m98S!aFiMgo|-N_}1Nja(UIjIaltww3Z@nAEPK>}bFL^=soIv&V}*bUU0 zo|>0hl$i{344Oc)UNVDTaY+%-93Wkp3#NOW20Vob*BP%U~>PHp>vC-90VsxUH%N + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "crc16.h" +#include + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + +void ext2fs_init_csum_seed(ext2_filsys fs) +{ + if (ext2fs_has_feature_csum_seed(fs->super)) + fs->csum_seed = fs->super->s_checksum_seed; + else if (ext2fs_has_feature_metadata_csum(fs->super) || + ext2fs_has_feature_ea_inode(fs->super)) + fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid, + sizeof(fs->super->s_uuid)); +} + +static __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp) +{ + int offset = offsetof(struct mmp_struct, mmp_checksum); + + return ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)mmp, offset); +} + +int ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp) +{ + __u32 calculated; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + calculated = ext2fs_mmp_csum(fs, mmp); + + return ext2fs_le32_to_cpu(mmp->mmp_checksum) == calculated; +} + +errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp) +{ + __u32 crc; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + crc = ext2fs_mmp_csum(fs, mmp); + mmp->mmp_checksum = ext2fs_cpu_to_le32(crc); + + return 0; +} + +int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb) +{ + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + return sb->s_checksum_type == EXT2_CRC32C_CHKSUM; +} + +static __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)), + struct ext2_super_block *sb) +{ + int offset = offsetof(struct ext2_super_block, s_checksum); + + return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset); +} + +/* NOTE: The input to this function MUST be in LE order */ +int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb) +{ + __u32 flag, calculated; + + if (fs->flags & EXT2_FLAG_SWAP_BYTES) + flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; + else + flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) + return 1; + + calculated = ext2fs_superblock_csum(fs, sb); + + return ext2fs_le32_to_cpu(sb->s_checksum) == calculated; +} + +/* NOTE: The input to this function MUST be in LE order */ +errcode_t ext2fs_superblock_csum_set(ext2_filsys fs, + struct ext2_super_block *sb) +{ + __u32 flag, crc; + + if (fs->flags & EXT2_FLAG_SWAP_BYTES) + flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; + else + flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) + return 0; + + crc = ext2fs_superblock_csum(fs, sb); + sb->s_checksum = ext2fs_cpu_to_le32(crc); + + return 0; +} + +static errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, + ext2_ino_t inum EXT2FS_ATTR((unused)), + blk64_t block, + struct ext2_ext_attr_header *hdr, + __u32 *crc) +{ + char *buf = (char *)hdr; + __u32 old_crc = hdr->h_checksum; + + hdr->h_checksum = 0; + block = ext2fs_cpu_to_le64(block); + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&block, + sizeof(block)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, fs->blocksize); + hdr->h_checksum = old_crc; + + return 0; +} + +int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, + blk64_t block, + struct ext2_ext_attr_header *hdr) +{ + __u32 calculated; + errcode_t retval; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated); + if (retval) + return 0; + + return ext2fs_le32_to_cpu(hdr->h_checksum) == calculated; +} + +errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum, + blk64_t block, + struct ext2_ext_attr_header *hdr) +{ + errcode_t retval; + __u32 crc; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc); + if (retval) + return retval; + hdr->h_checksum = ext2fs_cpu_to_le32(crc); + return 0; +} + +static __u16 do_nothing16(__u16 x) +{ + return x; +} + +static __u16 disk_to_host16(__u16 x) +{ + return ext2fs_le16_to_cpu(x); +} + +static errcode_t __get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset, + int need_swab) +{ + struct ext2_dir_entry *dp; + struct ext2_dx_root_info *root; + struct ext2_dx_countlimit *c; + int count_offset, max_sane_entries; + unsigned int rec_len; + __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); + + rec_len = translate(dirent->rec_len); + + if (rec_len == fs->blocksize && translate(dirent->name_len) == 0) + count_offset = 8; + else if (rec_len == 12) { + dp = (struct ext2_dir_entry *)(((char *)dirent) + rec_len); + rec_len = translate(dp->rec_len); + if (rec_len != fs->blocksize - 12) + return EXT2_ET_DB_NOT_FOUND; + root = (struct ext2_dx_root_info *)(((char *)dp + 12)); + if (root->reserved_zero || + root->info_length != sizeof(struct ext2_dx_root_info)) + return EXT2_ET_DB_NOT_FOUND; + count_offset = 32; + } else + return EXT2_ET_DB_NOT_FOUND; + + c = (struct ext2_dx_countlimit *)(((char *)dirent) + count_offset); + max_sane_entries = (fs->blocksize - count_offset) / + sizeof(struct ext2_dx_entry); + if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries || + ext2fs_le16_to_cpu(c->count) > max_sane_entries) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + + if (offset) + *offset = count_offset; + if (cc) + *cc = c; + + return 0; +} + +errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset) +{ + return __get_dx_countlimit(fs, dirent, cc, offset, 0); +} + +void ext2fs_initialize_dirent_tail(ext2_filsys fs, + struct ext2_dir_entry_tail *t) +{ + memset(t, 0, sizeof(struct ext2_dir_entry_tail)); + ext2fs_set_rec_len(fs, sizeof(struct ext2_dir_entry_tail), + (struct ext2_dir_entry *)t); + t->det_reserved_name_len = EXT2_DIR_NAME_LEN_CSUM; +} + +static errcode_t __get_dirent_tail(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dir_entry_tail **tt, + int need_swab) +{ + struct ext2_dir_entry *d; + void *top; + struct ext2_dir_entry_tail *t; + unsigned int rec_len; + errcode_t retval = 0; + __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); + + if (fs->blocksize < 1024) + return EXT2_FILSYS_CORRUPTED; /* Should never happen */ + + d = dirent; + top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); + + while ((void *) d < top) { + rec_len = translate(d->rec_len); + if ((rec_len < 8) || (rec_len & 0x03)) + return EXT2_ET_DIR_CORRUPTED; + d = (struct ext2_dir_entry *)(((char *)d) + rec_len); + } + + if ((char *)d > ((char *)dirent + fs->blocksize)) + return EXT2_ET_DIR_CORRUPTED; + if (d != top) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + + t = (struct ext2_dir_entry_tail *)d; + if (t->det_reserved_zero1 || + translate(t->det_rec_len) != sizeof(struct ext2_dir_entry_tail) || + translate(t->det_reserved_name_len) != EXT2_DIR_NAME_LEN_CSUM) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + + if (tt) + *tt = t; + return retval; +} + +int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) +{ + return __get_dirent_tail(fs, dirent, NULL, 0) != + EXT2_ET_DIR_NO_SPACE_FOR_CSUM; +} + +static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent, __u32 *crc, + int size) +{ + errcode_t retval; + char *buf = (char *)dirent; + __u32 gen; + struct ext2_inode inode; + + retval = ext2fs_read_inode(fs, inum, &inode); + if (retval) + return retval; + + inum = ext2fs_cpu_to_le32(inum); + gen = ext2fs_cpu_to_le32(inode.i_generation); + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, + sizeof(inum)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); + + return 0; +} + +int ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + errcode_t retval; + __u32 calculated; + struct ext2_dir_entry_tail *t; + + retval = __get_dirent_tail(fs, dirent, &t, 1); + if (retval) + return 1; + + /* + * The checksum field is overlaid with the dirent->name field + * so the swapfs.c functions won't change the endianness. + */ + retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated, + (char *)t - (char *)dirent); + if (retval) + return 0; + return ext2fs_le32_to_cpu(t->det_checksum) == calculated; +} + +static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + errcode_t retval; + __u32 crc; + struct ext2_dir_entry_tail *t; + + retval = __get_dirent_tail(fs, dirent, &t, 1); + if (retval) + return retval; + + /* swapfs.c functions don't change the checksum endianness */ + retval = ext2fs_dirent_csum(fs, inum, dirent, &crc, + (char *)t - (char *)dirent); + if (retval) + return retval; + t->det_checksum = ext2fs_cpu_to_le32(crc); + return 0; +} + +errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent, + __u32 *crc, struct ext2_dx_tail **ret_t) +{ + errcode_t retval; + char *buf = (char *)dirent; + int size; + __u32 gen, dummy_csum = 0; + struct ext2_inode inode; + struct ext2_dx_tail *t; + struct ext2_dx_countlimit *c; + int count_offset, limit, count; + + retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); + if (retval) + return retval; + limit = ext2fs_le16_to_cpu(c->limit); + count = ext2fs_le16_to_cpu(c->count); + if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > + fs->blocksize - sizeof(struct ext2_dx_tail)) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + /* htree structs are accessed in LE order */ + t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); + + size = count_offset + (count * sizeof(struct ext2_dx_entry)); + + retval = ext2fs_read_inode(fs, inum, &inode); + if (retval) + return retval; + + inum = ext2fs_cpu_to_le32(inum); + gen = ext2fs_cpu_to_le32(inode.i_generation); + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, + sizeof(inum)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 4); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&dummy_csum, 4); + + if (ret_t) + *ret_t = t; + return 0; +} + +static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + __u32 calculated; + errcode_t retval; + struct ext2_dx_tail *t; + + retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, &t); + if (retval) + return 0; + + return ext2fs_le32_to_cpu(t->dt_checksum) == calculated; +} + +static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + __u32 crc; + errcode_t retval = 0; + struct ext2_dx_tail *t; + + retval = ext2fs_dx_csum(fs, inum, dirent, &crc, &t); + if (retval) + return retval; + t->dt_checksum = ext2fs_cpu_to_le32(crc); + return retval; +} + +int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) + return ext2fs_dirent_csum_verify(fs, inum, dirent); + if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) + return ext2fs_dx_csum_verify(fs, inum, dirent); + + return 0; +} + +errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) + return ext2fs_dirent_csum_set(fs, inum, dirent); + if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) + return ext2fs_dx_csum_set(fs, inum, dirent); + + if (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) + return 0; + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; +} + +#define EXT3_EXTENT_TAIL_OFFSET(hdr) (sizeof(struct ext3_extent_header) + \ + (sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max))) + +static struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h) +{ + return (struct ext3_extent_tail *)(((char *)h) + + EXT3_EXTENT_TAIL_OFFSET(h)); +} + +static errcode_t ext2fs_extent_block_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext3_extent_header *eh, + __u32 *crc) +{ + int size; + __u32 gen; + errcode_t retval; + struct ext2_inode inode; + + size = EXT3_EXTENT_TAIL_OFFSET(eh) + offsetof(struct ext3_extent_tail, + et_checksum); + + retval = ext2fs_read_inode(fs, inum, &inode); + if (retval) + return retval; + inum = ext2fs_cpu_to_le32(inum); + gen = ext2fs_cpu_to_le32(inode.i_generation); + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, + sizeof(inum)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)eh, size); + + return 0; +} + +int ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext3_extent_header *eh) +{ + errcode_t retval; + __u32 provided, calculated; + struct ext3_extent_tail *t = get_extent_tail(eh); + + /* + * The extent tree structures are accessed in LE order, so we must + * swap the checksum bytes here. + */ + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + provided = ext2fs_le32_to_cpu(t->et_checksum); + retval = ext2fs_extent_block_csum(fs, inum, eh, &calculated); + if (retval) + return 0; + + return provided == calculated; +} + +errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext3_extent_header *eh) +{ + errcode_t retval; + __u32 crc; + struct ext3_extent_tail *t = get_extent_tail(eh); + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + /* + * The extent tree structures are accessed in LE order, so we must + * swap the checksum bytes here. + */ + retval = ext2fs_extent_block_csum(fs, inum, eh, &crc); + if (retval) + return retval; + t->et_checksum = ext2fs_cpu_to_le32(crc); + return retval; +} + +int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, + char *bitmap, int size) +{ + struct ext4_group_desc *gdp = (struct ext4_group_desc *) + ext2fs_group_desc(fs, fs->group_desc, group); + __u32 provided, calculated; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + provided = gdp->bg_inode_bitmap_csum_lo; + calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, + size); + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) + provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16; + else + calculated &= 0xFFFF; + + return provided == calculated; +} + +errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group, + char *bitmap, int size) +{ + __u32 crc; + struct ext4_group_desc *gdp = (struct ext4_group_desc *) + ext2fs_group_desc(fs, fs->group_desc, group); + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); + gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF; + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) + gdp->bg_inode_bitmap_csum_hi = crc >> 16; + + return 0; +} + +int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, + char *bitmap, int size) +{ + struct ext4_group_desc *gdp = (struct ext4_group_desc *) + ext2fs_group_desc(fs, fs->group_desc, group); + __u32 provided, calculated; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + provided = gdp->bg_block_bitmap_csum_lo; + calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, + size); + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) + provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16; + else + calculated &= 0xFFFF; + + return provided == calculated; +} + +errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group, + char *bitmap, int size) +{ + __u32 crc; + struct ext4_group_desc *gdp = (struct ext4_group_desc *) + ext2fs_group_desc(fs, fs->group_desc, group); + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); + gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF; + if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) + gdp->bg_block_bitmap_csum_hi = crc >> 16; + + return 0; +} + +static errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext2_inode_large *inode, + __u32 *crc, int has_hi) +{ + __u32 gen; + struct ext2_inode_large *desc = inode; + size_t size = EXT2_INODE_SIZE(fs->super); + __u16 old_lo; + __u16 old_hi = 0; + + old_lo = inode->i_checksum_lo; + inode->i_checksum_lo = 0; + if (has_hi) { + old_hi = inode->i_checksum_hi; + inode->i_checksum_hi = 0; + } + + inum = ext2fs_cpu_to_le32(inum); + gen = inode->i_generation; + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, + sizeof(inum)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)desc, size); + + inode->i_checksum_lo = old_lo; + if (has_hi) + inode->i_checksum_hi = old_hi; + return 0; +} + +int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_inode_large *inode) +{ + errcode_t retval; + __u32 provided, calculated; + unsigned int i, has_hi; + char *cp; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && + inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); + + provided = ext2fs_le16_to_cpu(inode->i_checksum_lo); + retval = ext2fs_inode_csum(fs, inum, inode, &calculated, has_hi); + if (retval) + return 0; + if (has_hi) { + __u32 hi = ext2fs_le16_to_cpu(inode->i_checksum_hi); + provided |= hi << 16; + } else + calculated &= 0xFFFF; + + if (provided == calculated) + return 1; + + /* + * If the checksum didn't match, it's possible it was due to + * the inode being all zero's. It's unlikely this is the + * case, but it can happen. So check for it here. (We only + * check the base inode since that's good enough, and it's not + * worth the bother to figure out how much of the extended + * inode, if any, is present.) + */ + for (cp = (char *) inode, i = 0; + i < sizeof(struct ext2_inode); + cp++, i++) + if (*cp) + return 0; + return 1; /* Inode must have been all zero's */ +} + +errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_inode_large *inode) +{ + errcode_t retval; + __u32 crc; + int has_hi; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && + inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); + + retval = ext2fs_inode_csum(fs, inum, inode, &crc, has_hi); + if (retval) + return retval; + inode->i_checksum_lo = ext2fs_cpu_to_le16(crc & 0xFFFF); + if (has_hi) + inode->i_checksum_hi = ext2fs_cpu_to_le16(crc >> 16); + return 0; +} + +__u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group) +{ + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, + group); + size_t offset, size = EXT2_DESC_SIZE(fs->super); + __u16 crc = 0; +#ifdef WORDS_BIGENDIAN + struct ext4_group_desc swabdesc; + size_t save_size = size; + const size_t ext4_bg_size = sizeof(struct ext4_group_desc); + struct ext2_group_desc *save_desc = desc; + + /* Have to swab back to little-endian to do the checksum */ + if (size > ext4_bg_size) + size = ext4_bg_size; + memcpy(&swabdesc, desc, size); + ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); + desc = (struct ext2_group_desc *) &swabdesc; + group = ext2fs_swab32(group); +#endif + + if (ext2fs_has_feature_metadata_csum(fs->super)) { + /* new metadata csum code */ + __u16 old_crc; + __u32 crc32; + + old_crc = desc->bg_checksum; + desc->bg_checksum = 0; + crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group, + sizeof(group)); + crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc, + size); + desc->bg_checksum = old_crc; +#ifdef WORDS_BIGENDIAN + if (save_size > ext4_bg_size) + crc32 = ext2fs_crc32c_le(crc32, + (unsigned char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); +#endif + crc = crc32 & 0xFFFF; + goto out; + } + + /* old crc16 code */ + offset = offsetof(struct ext2_group_desc, bg_checksum); + crc = ext2fs_crc16(~0, fs->super->s_uuid, + sizeof(fs->super->s_uuid)); + crc = ext2fs_crc16(crc, &group, sizeof(group)); + crc = ext2fs_crc16(crc, desc, offset); + offset += sizeof(desc->bg_checksum); /* skip checksum */ + /* for checksum of struct ext4_group_desc do the rest...*/ + if (offset < size) { + crc = ext2fs_crc16(crc, (char *)desc + offset, + size - offset); + } +#ifdef WORDS_BIGENDIAN + /* + * If the size of the bg descriptor is greater than 64 + * bytes, which is the size of the traditional ext4 bg + * descriptor, checksum the rest of the descriptor here + */ + if (save_size > ext4_bg_size) + crc = ext2fs_crc16(crc, (char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); +#endif + +out: + return crc; +} + +int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) +{ + if (ext2fs_has_group_desc_csum(fs) && + (ext2fs_bg_checksum(fs, group) != + ext2fs_group_desc_csum(fs, group))) + return 0; + + return 1; +} + +void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group) +{ + if (!ext2fs_has_group_desc_csum(fs)) + return; + + /* ext2fs_bg_checksum_set() sets the actual checksum field but + * does not calculate the checksum itself. */ + ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group)); +} + +static __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap, + __u32 inodes_per_grp, dgrp_t grp_no) +{ + ext2_ino_t i, start_ino, end_ino; + + start_ino = grp_no * inodes_per_grp + 1; + end_ino = start_ino + inodes_per_grp - 1; + + for (i = end_ino; i >= start_ino; i--) { + if (ext2fs_fast_test_inode_bitmap2(bitmap, i)) + return i - start_ino + 1; + } + return inodes_per_grp; +} + +/* update the bitmap flags, set the itable high watermark, and calculate + * checksums for the group descriptors */ +errcode_t ext2fs_set_gdt_csum(ext2_filsys fs) +{ + struct ext2_super_block *sb = fs->super; + int dirty = 0; + dgrp_t i; + + if (!fs->inode_map) + return EXT2_ET_NO_INODE_BITMAP; + + if (!ext2fs_has_group_desc_csum(fs)) + return 0; + + for (i = 0; i < fs->group_desc_count; i++) { + __u32 old_csum = ext2fs_bg_checksum(fs, i); + __u32 old_unused = ext2fs_bg_itable_unused(fs, i); + __u32 old_flags = ext2fs_bg_flags(fs, i); + __u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i); + __u32 old_free_blocks_count = ext2fs_bg_free_blocks_count(fs, i); + + if (old_free_blocks_count == sb->s_blocks_per_group && + i != fs->group_desc_count - 1) + ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); + + if (old_free_inodes_count == sb->s_inodes_per_group) { + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); + ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group); + } else { + int unused = + sb->s_inodes_per_group - + find_last_inode_ingrp(fs->inode_map, + sb->s_inodes_per_group, i); + + ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT); + ext2fs_bg_itable_unused_set(fs, i, unused); + } + + ext2fs_group_desc_csum_set(fs, i); + if (old_flags != ext2fs_bg_flags(fs, i)) + dirty = 1; + if (old_unused != ext2fs_bg_itable_unused(fs, i)) + dirty = 1; + if (old_csum != ext2fs_bg_checksum(fs, i)) + dirty = 1; + } + if (dirty) + ext2fs_mark_super_dirty(fs); + return 0; +} + +#ifdef DEBUG +#include "e2p/e2p.h" + +void print_csum(const char *msg, ext2_filsys fs, dgrp_t group) +{ + __u16 crc1, crc2, crc3; + dgrp_t swabgroup; + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, + group); + size_t size = EXT2_DESC_SIZE(fs->super); + struct ext2_super_block *sb = fs->super; + int offset = offsetof(struct ext2_group_desc, bg_checksum); +#ifdef WORDS_BIGENDIAN + struct ext4_group_desc swabdesc; + struct ext2_group_desc *save_desc = desc; + const size_t ext4_bg_size = sizeof(struct ext4_group_desc); + size_t save_size = size; +#endif + +#ifdef WORDS_BIGENDIAN + /* Have to swab back to little-endian to do the checksum */ + if (size > ext4_bg_size) + size = ext4_bg_size; + memcpy(&swabdesc, desc, size); + ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); + desc = (struct ext2_group_desc *) &swabdesc; + + swabgroup = ext2fs_swab32(group); +#else + swabgroup = group; +#endif + + crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid)); + crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup)); + crc3 = ext2fs_crc16(crc2, desc, offset); + offset += sizeof(desc->bg_checksum); /* skip checksum */ + /* for checksum of struct ext4_group_desc do the rest...*/ + if (offset < size) + crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset); +#ifdef WORDS_BIGENDIAN + if (save_size > ext4_bg_size) + crc3 = ext2fs_crc16(crc3, (char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); +#endif + + printf("%s UUID %s=%04x, grp %u=%04x: %04x=%04x\n", + msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3, + ext2fs_group_desc_csum(fs, group)); +} + +unsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23, + 0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb }; + +int main(int argc, char **argv) +{ + struct ext2_super_block param; + errcode_t retval; + ext2_filsys fs; + int i; + __u16 csum1, csum2, csum_known = 0xd3a4; + + memset(¶m, 0, sizeof(param)); + ext2fs_blocks_count_set(¶m, 32768); +#if 0 + param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT; + param.s_desc_size = 128; + csum_known = 0x5b6e; +#endif + + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, + test_io_manager, &fs); + if (retval) { + com_err("setup", retval, + "While initializing filesystem"); + exit(1); + } + memcpy(fs->super->s_uuid, sb_uuid, 16); + fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM; + + for (i=0; i < fs->group_desc_count; i++) { + ext2fs_block_bitmap_loc_set(fs, i, 124); + ext2fs_inode_bitmap_loc_set(fs, i, 125); + ext2fs_inode_table_loc_set(fs, i, 126); + ext2fs_bg_free_blocks_count_set(fs, i, 31119); + ext2fs_bg_free_inodes_count_set(fs, i, 15701); + ext2fs_bg_used_dirs_count_set(fs, i, 2); + ext2fs_bg_flags_zap(fs, i); + }; + + csum1 = ext2fs_group_desc_csum(fs, 0); + print_csum("csum0000", fs, 0); + + if (csum1 != csum_known) { + printf("checksum for group 0 should be %04x\n", csum_known); + exit(1); + } + csum2 = ext2fs_group_desc_csum(fs, 1); + print_csum("csum0001", fs, 1); + if (csum1 == csum2) { + printf("checksums for different groups shouldn't match\n"); + exit(1); + } + csum2 = ext2fs_group_desc_csum(fs, 2); + print_csum("csumffff", fs, 2); + if (csum1 == csum2) { + printf("checksums for different groups shouldn't match\n"); + exit(1); + } + ext2fs_bg_checksum_set(fs, 0, csum1); + csum2 = ext2fs_group_desc_csum(fs, 0); + print_csum("csum_set", fs, 0); + if (csum1 != csum2) { + printf("checksums should not depend on checksum field\n"); + exit(1); + } + if (!ext2fs_group_desc_csum_verify(fs, 0)) { + printf("checksums should verify against gd_checksum\n"); + exit(1); + } + memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid)); + print_csum("new_uuid", fs, 0); + if (ext2fs_group_desc_csum_verify(fs, 0) != 0) { + printf("checksums for different filesystems shouldn't match\n"); + exit(1); + } + csum1 = ext2fs_group_desc_csum(fs, 0); + ext2fs_bg_checksum_set(fs, 0, csum1); + print_csum("csum_new", fs, 0); + ext2fs_bg_free_blocks_count_set(fs, 0, 1); + csum2 = ext2fs_group_desc_csum(fs, 0); + print_csum("csum_blk", fs, 0); + if (csum1 == csum2) { + printf("checksums for different data shouldn't match\n"); + exit(1); + } + ext2fs_free(fs); + + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/csum.o b/jni/e2fsprogs/lib/ext2fs/csum.o new file mode 100755 index 0000000000000000000000000000000000000000..b54f2798af21e8297283ac7128cff8d2bc258d5d GIT binary patch literal 17400 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 +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b); +static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b); +static EXT2_QSORT_TYPE (*sortfunc32)(const void *a, const void *b); + +/* + * helper function for making a new directory block list (for + * initialize and copy). + */ +static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, + ext2_ino_t count, + struct ext2_db_entry2 *list, + ext2_dblist *ret_dblist) +{ + ext2_dblist dblist = NULL; + errcode_t retval; + ext2_ino_t num_dirs; + size_t len; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if ((ret_dblist == 0) && fs->dblist && + (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST)) + return 0; + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist); + if (retval) + goto cleanup; + memset(dblist, 0, sizeof(struct ext2_struct_dblist)); + + dblist->magic = EXT2_ET_MAGIC_DBLIST; + dblist->fs = fs; + if (size) + dblist->size = size; + else { + retval = ext2fs_get_num_dirs(fs, &num_dirs); + if (retval) + goto cleanup; + dblist->size = (num_dirs * 2) + 12; + } + len = (size_t) sizeof(struct ext2_db_entry2) * dblist->size; + dblist->count = count; + retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry2), + &dblist->list); + if (retval) + goto cleanup; + + if (list) + memcpy(dblist->list, list, len); + else + memset(dblist->list, 0, len); + if (ret_dblist) + *ret_dblist = dblist; + else + fs->dblist = dblist; + return 0; +cleanup: + if (dblist) + ext2fs_free_mem(&dblist); + return retval; +} + +/* + * Initialize a directory block list + */ +errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist) +{ + ext2_dblist dblist; + errcode_t retval; + + retval = make_dblist(fs, 0, 0, 0, &dblist); + if (retval) + return retval; + + dblist->sorted = 1; + if (ret_dblist) + *ret_dblist = dblist; + else + fs->dblist = dblist; + + return 0; +} + +/* + * Copy a directory block list + */ +errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest) +{ + ext2_dblist dblist; + errcode_t retval; + + retval = make_dblist(src->fs, src->size, src->count, src->list, + &dblist); + if (retval) + return retval; + dblist->sorted = src->sorted; + *dest = dblist; + return 0; +} + +/* + * Close a directory block list + * + * (moved to closefs.c) + */ + + +/* + * Add a directory block to the directory block list + */ +errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino, + blk64_t blk, e2_blkcnt_t blockcnt) +{ + struct ext2_db_entry2 *new_entry; + errcode_t retval; + unsigned long old_size; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (dblist->count >= dblist->size) { + old_size = dblist->size * sizeof(struct ext2_db_entry2); + dblist->size += dblist->size > 200 ? dblist->size / 2 : 100; + retval = ext2fs_resize_mem(old_size, (size_t) dblist->size * + sizeof(struct ext2_db_entry2), + &dblist->list); + if (retval) { + dblist->size = old_size / sizeof(struct ext2_db_entry2); + return retval; + } + } + new_entry = dblist->list + ( dblist->count++); + new_entry->blk = blk; + new_entry->ino = ino; + new_entry->blockcnt = blockcnt; + + dblist->sorted = 0; + + return 0; +} + +/* + * Change the directory block to the directory block list + */ +errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino, + blk64_t blk, e2_blkcnt_t blockcnt) +{ + dgrp_t i; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + for (i=0; i < dblist->count; i++) { + if ((dblist->list[i].ino != ino) || + (dblist->list[i].blockcnt != blockcnt)) + continue; + dblist->list[i].blk = blk; + dblist->sorted = 0; + return 0; + } + return EXT2_ET_DB_NOT_FOUND; +} + +void ext2fs_dblist_sort2(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)) +{ + if (!sortfunc) + sortfunc = dir_block_cmp2; + qsort(dblist->list, (size_t) dblist->count, + sizeof(struct ext2_db_entry2), sortfunc); + dblist->sorted = 1; +} + +/* + * This function iterates over the directory block list + */ +errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist, + int (*func)(ext2_filsys fs, + struct ext2_db_entry2 *db_info, + void *priv_data), + unsigned long long start, + unsigned long long count, + void *priv_data) +{ + unsigned long long i, end; + int ret; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + end = start + count; + if (!dblist->sorted) + ext2fs_dblist_sort2(dblist, 0); + if (end > dblist->count) + end = dblist->count; + for (i = start; i < end; i++) { + ret = (*func)(dblist->fs, &dblist->list[i], priv_data); + if (ret & DBLIST_ABORT) + return 0; + } + return 0; +} + +errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist, + int (*func)(ext2_filsys fs, + struct ext2_db_entry2 *db_info, + void *priv_data), + void *priv_data) +{ + return ext2fs_dblist_iterate3(dblist, func, 0, dblist->count, + priv_data); +} + +static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b) +{ + const struct ext2_db_entry2 *db_a = + (const struct ext2_db_entry2 *) a; + const struct ext2_db_entry2 *db_b = + (const struct ext2_db_entry2 *) b; + + if (db_a->blk != db_b->blk) + return (int) (db_a->blk - db_b->blk); + + if (db_a->ino != db_b->ino) + return (int) (db_a->ino - db_b->ino); + + return (db_a->blockcnt - db_b->blockcnt); +} + +blk64_t ext2fs_dblist_count2(ext2_dblist dblist) +{ + return dblist->count; +} + +errcode_t ext2fs_dblist_get_last2(ext2_dblist dblist, + struct ext2_db_entry2 **entry) +{ + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (dblist->count == 0) + return EXT2_ET_DBLIST_EMPTY; + + if (entry) + *entry = dblist->list + ( dblist->count-1); + return 0; +} + +errcode_t ext2fs_dblist_drop_last(ext2_dblist dblist) +{ + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (dblist->count == 0) + return EXT2_ET_DBLIST_EMPTY; + + dblist->count--; + return 0; +} + +/* + * Legacy 32-bit versions + */ + +/* + * Add a directory block to the directory block list + */ +errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, + int blockcnt) +{ + return ext2fs_add_dir_block2(dblist, ino, blk, blockcnt); +} + +/* + * Change the directory block to the directory block list + */ +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, + int blockcnt) +{ + return ext2fs_set_dir_block2(dblist, ino, blk, blockcnt); +} + +void ext2fs_dblist_sort(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)) +{ + if (sortfunc) { + sortfunc32 = sortfunc; + sortfunc = dir_block_cmp; + } else + sortfunc = dir_block_cmp2; + qsort(dblist->list, (size_t) dblist->count, + sizeof(struct ext2_db_entry2), sortfunc); + dblist->sorted = 1; +} + +/* + * This function iterates over the directory block list + */ +struct iterate_passthrough { + int (*func)(ext2_filsys fs, + struct ext2_db_entry *db_info, + void *priv_data); + void *priv_data; +}; + +static int passthrough_func(ext2_filsys fs, + struct ext2_db_entry2 *db_info, + void *priv_data) +{ + struct iterate_passthrough *p = priv_data; + struct ext2_db_entry db; + int ret; + + db.ino = db_info->ino; + db.blk = (blk_t) db_info->blk; + db.blockcnt = (int) db_info->blockcnt; + ret = (p->func)(fs, &db, p->priv_data); + db_info->ino = db.ino; + db_info->blk = db.blk; + db_info->blockcnt = db.blockcnt; + return ret; +} + +errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, + int (*func)(ext2_filsys fs, + struct ext2_db_entry *db_info, + void *priv_data), + void *priv_data) +{ + struct iterate_passthrough pass; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + pass.func = func; + pass.priv_data = priv_data; + + return ext2fs_dblist_iterate2(dblist, passthrough_func, &pass); +} + +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b) +{ + const struct ext2_db_entry2 *db_a = + (const struct ext2_db_entry2 *) a; + const struct ext2_db_entry2 *db_b = + (const struct ext2_db_entry2 *) b; + + struct ext2_db_entry a32, b32; + + a32.ino = db_a->ino; a32.blk = db_a->blk; + a32.blockcnt = db_a->blockcnt; + + b32.ino = db_b->ino; b32.blk = db_b->blk; + b32.blockcnt = db_b->blockcnt; + + return sortfunc32(&a32, &b32); +} + +int ext2fs_dblist_count(ext2_dblist dblist) +{ + return dblist->count; +} + +errcode_t ext2fs_dblist_get_last(ext2_dblist dblist, + struct ext2_db_entry **entry) +{ + static struct ext2_db_entry ret_entry; + struct ext2_db_entry2 *last; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (dblist->count == 0) + return EXT2_ET_DBLIST_EMPTY; + + if (!entry) + return 0; + + last = dblist->list + dblist->count -1; + + ret_entry.ino = last->ino; + ret_entry.blk = last->blk; + ret_entry.blockcnt = last->blockcnt; + *entry = &ret_entry; + + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/dblist.o b/jni/e2fsprogs/lib/ext2fs/dblist.o new file mode 100755 index 0000000000000000000000000000000000000000..a87a527943249ce6269fc7b8be26dd7651304a55 GIT binary patch literal 7632 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 H(f$7ie>L_Z literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/dblist_dir.c b/jni/e2fsprogs/lib/ext2fs/dblist_dir.c new file mode 100755 index 0000000..864a3ca --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/dblist_dir.c @@ -0,0 +1,88 @@ +/* + * dblist_dir.c --- iterate by directory entry + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info, + void *priv_data); + +errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + errcode_t retval; + struct dir_context ctx; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + ctx.dir = 0; + ctx.flags = flags; + if (block_buf) + ctx.buf = block_buf; + else { + retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf); + if (retval) + return retval; + } + ctx.func = func; + ctx.priv_data = priv_data; + ctx.errcode = 0; + + retval = ext2fs_dblist_iterate2(dblist, db_dir_proc, &ctx); + + if (!block_buf) + ext2fs_free_mem(&ctx.buf); + if (retval) + return retval; + return ctx.errcode; +} + +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry2 *db_info, + void *priv_data) +{ + struct ext2_inode inode; + struct dir_context *ctx; + int ret; + + ctx = (struct dir_context *) priv_data; + ctx->dir = db_info->ino; + ctx->errcode = 0; + + ctx->errcode = ext2fs_read_inode(fs, ctx->dir, &inode); + if (ctx->errcode) + return DBLIST_ABORT; + if (inode.i_flags & EXT4_INLINE_DATA_FL) + ret = ext2fs_inline_data_dir_iterate(fs, ctx->dir, ctx); + else + ret = ext2fs_process_dir_block(fs, &db_info->blk, + db_info->blockcnt, 0, 0, + priv_data); + if ((ret & BLOCK_ABORT) && !ctx->errcode) + return DBLIST_ABORT; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/dblist_dir.o b/jni/e2fsprogs/lib/ext2fs/dblist_dir.o new file mode 100755 index 0000000000000000000000000000000000000000..6f8a5cfd319c063faa0102bf21b0bc81ab316454 GIT binary patch literal 2184 zcmbVMPiP!f82{c*w%M4q3Dy`PCevsRX~Dr1ksbsGT5W_XrRXsoCcBenasSBdpwScz z?4{mZks^o^|G~zK7p2*gfxUR}(0V9dl(bdYst5Jr40Kt4-`n?gCzIsjTXw$h`+dLf z&->oIdFT1_FQkMZy#!sSfu&KR#UlgVma0u7V0Mkv&CdGpR;MNEn}!*F+M3z^%$Ny3 zuT6(v7}H_HaKen(Xuf;<+K+|bzWyg8M*i3#dIdEez6xv=Sfgf!Ps8qxQnS&zwA~(q zG%ke=qHmbTdV7?jaj7F;+Kw_O?B=eKIoW=K>SC7aXz7DplcKh1M>P}I#i5}s9Zof}R!dc5D-o8lU%8Z!GnlumOQH9SVA)P(CAr`aK ziXu%w!zq@#|F zIPU9#d9DKIHHDdHda8WlF3EKaI8RCU|AWFO68H^;bDj~Uv-mTHKM=#$z~jaI(Vi-w zJ25;P!~crmc=!A3F{P#9kDumZ0@wYM<$Fcf3cR&|tX!p3^2!0hIJHuBE_;Df@=DrV z@jWkYzwTFZUbX7v3%;{ltmIxJt6T{@>)gw)K3NT1*eXwcxmc(Ml2-^k-wizNDU^$a zvghR8z}@5SHRY{3E52LmvwhFaJB4y3?@@kP^0@`*I=z)6s~Y%$yA1hOiRIoFRQXdh zm$&3&f#%k%r~1?T{|cWsz7_kHo$f(L)Ol$_!X&;ij3sZ5tpc8nA11Km&Er_cZ2aTv zf+FrHkl$%erQdD+J>qwZb0lYRMb&)-zWCDpYxxqKT95PIPxP&QN$y7~K1u&j0joMt qN!`DOuR%Fz|Kn=@dS4vJGuH8X|33js)&|r+)C;O%7Q^@_ +#endif +#include "ext2fs.h" + +static const char *lookup_table = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + +/** + * ext2fs_digest_encode() - + * + * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. + * The encoded string is roughly 4/3 times the size of the input string. + */ +int ext2fs_digest_encode(const char *src, int len, char *dst) +{ + int i = 0, bits = 0, ac = 0; + char *cp = dst; + + while (i < len) { + ac += (((unsigned char) src[i]) << bits); + bits += 8; + do { + *cp++ = lookup_table[ac & 0x3f]; + ac >>= 6; + bits -= 6; + } while (bits >= 6); + i++; + } + if (bits) + *cp++ = lookup_table[ac & 0x3f]; + return cp - dst; +} + +int ext2fs_digest_decode(const char *src, int len, char *dst) +{ + int i = 0, bits = 0, ac = 0; + const char *p; + char *cp = dst; + + while (i < len) { + p = strchr(lookup_table, src[i]); + if (p == NULL || src[i] == 0) + return -1; + ac += (p - lookup_table) << bits; + bits += 6; + if (bits >= 8) { + *cp++ = ac & 0xff; + ac >>= 8; + bits -= 8; + } + i++; + } + if (ac) + return -1; + return cp - dst; +} + + +#ifdef UNITTEST +static const struct { + unsigned char d[32]; + unsigned int len; + const char *ed; +} tests[] = { + { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32, + "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF" + }, + { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32, + "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K" + }, + { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32, + "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM" + }, + { { 0x00, }, 1, + "AA" + }, + { { 0x01, }, 1, + "BA" + }, + { { 0x01, 0x02 }, 2, + "BIA" + }, + { { 0x01, 0x02, 0x03 }, 3, + "BIwA" + }, + { { 0x01, 0x02, 0x03, 0x04 }, 4, + "BIwAEA" + }, + { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5, + "BIwAE8P" + }, + { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6, + "BIwAE8v," + }, + { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7, + "BIwAE8v,9D" + }, +}; + +int main(int argc, char **argv) +{ + int i, ret, len; + int errors = 0; + char tmp[1024], tmp2[1024]; + + if (argc == 3 && !strcmp(argv[1], "encode")) { + memset(tmp, 0, sizeof(tmp)); + ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp); + puts(tmp); + exit(0); + } + if (argc == 3 && !strcmp(argv[1], "decode")) { + memset(tmp, 0, sizeof(tmp)); + ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp); + puts(tmp); + fprintf(stderr, "returned %d\n", ret); + exit(0); + } + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + memset(tmp, 0, sizeof(tmp)); + ret = ext2fs_digest_encode((const char *) tests[i].d, + tests[i].len, tmp); + len = strlen(tmp); + printf("Test Digest %d (returned %d): ", i, ret); + if (ret != len) { + printf("FAILED returned %d, string length was %d\n", + ret, len); + errors++; + continue; + } else if (strcmp(tmp, tests[i].ed) != 0) { + printf("FAILED: got %s, expected %s\n", tmp, + tests[i].ed); + errors++; + continue; + } + ret = ext2fs_digest_decode(tmp, len, tmp2); + if (ret != tests[i].len) { + printf("FAILED decode returned %d, expected %d\n", + ret, tests[i].len); + errors++; + continue; + } + if (memcmp(tmp2, tests[i].d, ret) != 0) { + puts("FAILED: decode mismatched"); + errors++; + continue; + } + printf("OK\n"); + } + for (i = 1; i < argc; i++) { + memset(tmp, 0, sizeof(tmp)); + ret = ext2fs_digest_encode(argv[i], strlen(argv[i]), tmp); + len = strlen(tmp); + printf("Digest of '%s' is '%s' (returned %d, length %d)\n", + argv[i], tmp, ret, len); + } + return errors; +} + +#endif /* UNITTEST */ diff --git a/jni/e2fsprogs/lib/ext2fs/digest_encode.o b/jni/e2fsprogs/lib/ext2fs/digest_encode.o new file mode 100755 index 0000000000000000000000000000000000000000..c6ce843c64a04ae6c87d75bc5f42eee630f73d2d GIT binary patch literal 2456 zcmbtVO>7%Q6n>k{&qg&#iCf$fh!ZJNNr6?IrjUrsmZq(NwuJsbK?392o7luZiM=gp zOGU&9wHJbrKuAS_3r@u$NJwOFMHUC(LNCApQ0U1nr{3yAWWG0^vCYOgAf7ZcZ@zhd z^SxR7-6O}3wrLtE(db)h>=a7$NoPa1gldrwmenHN-Uv|TuYKg+>7`0FKyKBK(MxWr z*Q%6ssvzF3QowS{`z+Vcy65h;(;10X%7G=tu+5GV`vWtE=)n@= zvAsd`fuUKIGHgb6Q=jqO$aU-|%eqzB-$BcFk?S#yCPj>^o&I`^y|kcWh?v;l+^nh^ zT%!XyQ1`FZYJkrR8jb&#eBv&s0d-YS``;V7u^+rF-_j$$R1a&nH?Op>ZtB|diXOcG zd2wLfY zwD6NA`*pen*XXNp)$rGSVb8vT6Wm2`i@W~F+`<-hNp5R(;aTk}F?ZmAYvNkjccmCv z-@G!l3jPF->h&FZ_VCn^qsPL}J^#Y-6DMDse(BWdGiP6Z<=m^UMbF3L_RMS|`PN)2 zoypEGhJ1~Cmsi!9<9|sMwR5UX?c+t+~liAE*Xu=GcU~{KTpj|#i z+B*YUzb{C8fbn1%L{T)=Gpg^=dU!vKG0qAkTsxZ%`ySo-S=)_veN^)Wr^7w;=N~nL z7IO|*JKd|cI3k_ew!pUpvK4;@xQ0kd@K)-gH{lBWN+=C`h4ZRY(?>23z7*?L{0o71 zNvphTTvUuavQ1lY#&8$8m4?2K1cb|U%SQM`KBQs~G zqNZanI%LMO>9n13DDUKAi5!`ktYe$UPM&=-??hvB($r2wW^&QAO{r{l?!tV;iJni{ z1pl#_d?cQnwewEI&cw2DFBrE4_%9PPMkcZ$2G&byv5JD?Q71~nadVuf13ZoK6haYM zK4Y&Cw!@3&XzgbIZ+;K%dW#T0%SZFQ=S;Sxj`E9V%=_{!X_07d1~Bgz#lDPL7|pUK z4S$p14y+tXeYfiO=3`(S!+VE<%&Y8SBE-A@5NNCX@5}qEJe;5Hl)u8i2FCfvFq&me z=0DU7LT6hRwfdy)ZRS1c|B$e5Ov+EK{O* +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +#define EXT4_MAX_REC_LEN ((1<<16)-1) + +errcode_t ext2fs_get_rec_len(ext2_filsys fs, + struct ext2_dir_entry *dirent, + unsigned int *rec_len) +{ + unsigned int len = dirent->rec_len; + + if (fs->blocksize < 65536) + *rec_len = len; + else if (len == EXT4_MAX_REC_LEN || len == 0) + *rec_len = fs->blocksize; + else + *rec_len = (len & 65532) | ((len & 3) << 16); + return 0; +} + +errcode_t ext2fs_set_rec_len(ext2_filsys fs, + unsigned int len, + struct ext2_dir_entry *dirent) +{ + if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3)) + return EINVAL; + if (len < 65536) { + dirent->rec_len = len; + return 0; + } + if (len == fs->blocksize) { + if (fs->blocksize == 65536) + dirent->rec_len = EXT4_MAX_REC_LEN; + else + dirent->rec_len = 0; + } else + dirent->rec_len = (len & 65532) | ((len >> 16) & 3); + return 0; +} + +/* + * This function checks to see whether or not a potential deleted + * directory entry looks valid. What we do is check the deleted entry + * and each successive entry to make sure that they all look valid and + * that the last deleted entry ends at the beginning of the next + * undeleted entry. Returns 1 if the deleted entry looks valid, zero + * if not valid. + */ +static int ext2fs_validate_entry(ext2_filsys fs, char *buf, + unsigned int offset, + unsigned int final_offset) +{ + struct ext2_dir_entry *dirent; + unsigned int rec_len; +#define DIRENT_MIN_LENGTH 12 + + while ((offset < final_offset) && + (offset <= fs->blocksize - DIRENT_MIN_LENGTH)) { + dirent = (struct ext2_dir_entry *)(buf + offset); + if (ext2fs_get_rec_len(fs, dirent, &rec_len)) + return 0; + offset += rec_len; + if ((rec_len < 8) || + ((rec_len % 4) != 0) || + ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len)) + return 0; + } + return (offset == final_offset); +} + +errcode_t ext2fs_dir_iterate2(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + struct dir_context ctx; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_check_directory(fs, dir); + if (retval) + return retval; + + ctx.dir = dir; + ctx.flags = flags; + if (block_buf) + ctx.buf = block_buf; + else { + retval = ext2fs_get_mem(fs->blocksize, &ctx.buf); + if (retval) + return retval; + } + ctx.func = func; + ctx.priv_data = priv_data; + ctx.errcode = 0; + retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0, + ext2fs_process_dir_block, &ctx); + if (!block_buf) + ext2fs_free_mem(&ctx.buf); + if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) { + (void) ext2fs_inline_data_dir_iterate(fs, dir, &ctx); + retval = 0; + } + if (retval) + return retval; + return ctx.errcode; +} + +struct xlate { + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data); + void *real_private; +}; + +static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entry EXT2FS_ATTR((unused)), + struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *priv_data) +{ + struct xlate *xl = (struct xlate *) priv_data; + + return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); +} + +errcode_t ext2fs_dir_iterate(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + struct xlate xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_dir_iterate2(fs, dir, flags, block_buf, + xlate_func, &xl); +} + + +/* + * Helper function which is private to this module. Used by + * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() + */ +int ext2fs_process_dir_block(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct dir_context *ctx = (struct dir_context *) priv_data; + unsigned int offset = 0; + unsigned int next_real_entry = 0; + int ret = 0; + int changed = 0; + int do_abort = 0; + unsigned int rec_len, size, buflen; + int entry; + struct ext2_dir_entry *dirent; + int csum_size = 0; + int inline_data; + errcode_t retval = 0; + + if (blockcnt < 0) + return 0; + + entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE; + + /* If a dir has inline data, we don't need to read block */ + inline_data = !!(ctx->flags & DIRENT_FLAG_INCLUDE_INLINE_DATA); + if (!inline_data) { + ctx->errcode = ext2fs_read_dir_block4(fs, *blocknr, ctx->buf, 0, + ctx->dir); + if (ctx->errcode) + return BLOCK_ABORT; + /* If we handle a normal dir, we traverse the entire block */ + buflen = fs->blocksize; + } else { + buflen = ctx->buflen; + } + + if (ext2fs_has_feature_metadata_csum(fs->super)) + csum_size = sizeof(struct ext2_dir_entry_tail); + + if (buflen < 8) { + ctx->errcode = EXT2_ET_DIR_CORRUPTED; + return BLOCK_ABORT; + } + while (offset < buflen - 8) { + dirent = (struct ext2_dir_entry *) (ctx->buf + offset); + if (ext2fs_get_rec_len(fs, dirent, &rec_len)) + return BLOCK_ABORT; + if (((offset + rec_len) > buflen) || + (rec_len < 8) || + ((rec_len % 4) != 0) || + ((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len)) { + ctx->errcode = EXT2_ET_DIR_CORRUPTED; + return BLOCK_ABORT; + } + if (!dirent->inode) { + /* + * We just need to check metadata_csum when this + * dir hasn't inline data. That means that 'buflen' + * should be blocksize. + */ + if (!inline_data && + (offset == buflen - csum_size) && + (dirent->rec_len == csum_size) && + (dirent->name_len == EXT2_DIR_NAME_LEN_CSUM)) { + if (!(ctx->flags & DIRENT_FLAG_INCLUDE_CSUM)) + goto next; + entry = DIRENT_CHECKSUM; + } else if (!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) + goto next; + } + + ret = (ctx->func)(ctx->dir, + (next_real_entry > offset) ? + DIRENT_DELETED_FILE : entry, + dirent, offset, + buflen, ctx->buf, + ctx->priv_data); + if (entry < DIRENT_OTHER_FILE) + entry++; + + if (ret & DIRENT_CHANGED) { + if (ext2fs_get_rec_len(fs, dirent, &rec_len)) + return BLOCK_ABORT; + changed++; + } + if (ret & DIRENT_ABORT) { + do_abort++; + break; + } +next: + if (next_real_entry == offset) + next_real_entry += rec_len; + + if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { + size = (ext2fs_dirent_name_len(dirent) + 11) & ~3; + + if (rec_len != size) { + unsigned int final_offset; + + final_offset = offset + rec_len; + offset += size; + while (offset < final_offset && + !ext2fs_validate_entry(fs, ctx->buf, + offset, + final_offset)) + offset += 4; + continue; + } + } + offset += rec_len; + } + + if (changed) { + if (!inline_data) { + ctx->errcode = ext2fs_write_dir_block4(fs, *blocknr, + ctx->buf, + 0, ctx->dir); + if (ctx->errcode) + return BLOCK_ABORT; + } else { + /* + * return BLOCK_INLINE_DATA_CHANGED to notify caller + * that inline data has been changed. + */ + retval = BLOCK_INLINE_DATA_CHANGED; + } + } + if (do_abort) + return retval | BLOCK_ABORT; + return retval; +} diff --git a/jni/e2fsprogs/lib/ext2fs/dir_iterate.o b/jni/e2fsprogs/lib/ext2fs/dir_iterate.o new file mode 100755 index 0000000000000000000000000000000000000000..1def5ec7200c7397fcabcfabd171c441f2d22d50 GIT binary patch literal 5280 zcmb_gT})iZ6+U+_lwE`QwL@eKOB&LG6L0Kn<%QO=}CMQYt%MZ`PMUfh8t@%w=X8y7i3kH5>-(i+6pjK7gwsB)(>~pqV0F) z&McQ}+&r`+-JO|l&i|Y_GjRFqPkqCuX{4G)@6q;5p+x5!x5tJU8WaF!DMcTy)KPJ@ znu=>xRJ5v%qCa3vSyhy`>M-sy^8ORX_yKhf3*EZC~zk+RZOM2vEVI%BYt)u*!4jb!W z1MKW#+n{$)leV$#0y{CjtZV_TA38Eb-7I(6H}jDNe>>R@UW0FIF4|2Uz6EHi1e&0v zaqC+3>H`1!lAn1k#De)Nm>2UP#;kXb(#L*7Z`X_Ur-knte3v?zj`ecCg1D9a*L@#u zO;=^N3ff#+58CsEw%oN;TW&#bvlmmX_8WSuozWw?h*$HtQ8*(1kJ1fW~T~d?tmy8NGhaR&+e(IMy*8 z>qgvHbpIhMOmo@;H22?RKLQ@sl}SBoZ-5@Miy8e{+iIa=DM&?SpHG|Vzll6REU)~8 zjG~gsx|fOG5%z+gq&{VT_Mh7^z|nY`aV2w&>EU+?ek*$Alk#2cT@W!r90YGFVsB0N zW=p!y$;Sfk$DZs~%IEAys?ENJy;#6rEQVWiZ=?>|nbcYA$wB*ip(S@cg)iKaE1jl% z=_I~K@ino}=j>Us-(?-w3&Gr1HQJX2Hb^u5T^fDr-~ajn>o~{#tnIJlTyITSRlpv` z*?bst-8p0I8}`W7u>VZ!t91Gb&B!BuhuB}nX+P_Pto>M*``rg!8R%|`_MUk+2Om-Fg)MYI}xR-}}lI=0nZh#2Vw88{cb81(tp(>gx$TyY+bgAQYs z!FL2=lwU<1TZ8Qji2FKx#*^z&T#C zx^w?=-N^X5jxz31O!kovvmM%ncThmWw zO9fe5!y0O9MRrTaU5ENR9}ecO>A~CrYV11XZ{W_sy#d3+aG{MNwT zj5A%nlaTNEo5+8@vpcX~oa0;5VcZQ;ei-j5$?rEgPwq>spk|kF?=10K#;sou+IZ6x z*KoJq#68RL*lb3PXmaI=jy#rmVqq}Jyw`-{rSf9kNAaJ0c(fVpy>tFM|TA@#BH9<^k=`VlA z64RpQh;|m2B52>*rtPV$31TW~JFuJ1W!pqrd#H9wDbJaQ){^C z3`xg+-R5<)cK+$9t$(K0vB}SNqjfm;m-+P?n6CslB)k6d!K|Q9OS>)VE9CaE97ju`?bJ7w++bA2>M2s zJ!0R1eOKaYE(`(o3&>&mMIjHxLH76?rkqn4mRlMlm1|`XgX{QMPPgu$A}28X5#;Sg z|0dRU!~b;;{CoG1gS%{3IsNybw?NN!Uh%~F-_q|E^fjPS?HRe{jPF$-`bCNJLjtK+ zZn#54JLbWE~UbKl=9`2x;?nc_ouu#__$3vU0IIGU&W{7t9<#rhhF)6$AhbLUnBJ>IqKY#IhlNH zU?OrUIx=)2nlvM3JeinMXl&4o4M#2vCCpfI3~(r6jzmLA@K7i=HaZGoMao3+WF#IP zH6tTtT)`7&G6HTl^!(k>V00ofU`CS{6J})8Oh#czG!mP*II6@j&!}0R4kSz_EYDv^ zjK$1}3AQxy+{jpLm_qTfq#5e{_ID0XB%_#1H<@54X(r&Qf`;NFLvb@ARJxZPU(LbD zKmtC|~%6B0jEsuH~^UzbC!|jP-lt@kgomKCHQ$vS0O|U{Q_TbhkWqt2Hle z5CCJcOe!+EE%}dl7?k~r@Br3#^B@276KzQnG9SlS@vHaLli>I2W|nq&dDP2AHiJu> Gm;XPWJhBP^ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/dirblock.c b/jni/e2fsprogs/lib/ext2fs/dirblock.c new file mode 100755 index 0000000..54b2777 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/dirblock.c @@ -0,0 +1,113 @@ +/* + * dirblock.c --- directory block routines. + * + * Copyright (C) 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block, + void *buf, int flags EXT2FS_ATTR((unused)), + ext2_ino_t ino) +{ + errcode_t retval; + int corrupt = 0; + + retval = io_channel_read_blk64(fs->io, block, 1, buf); + if (retval) + return retval; + + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_dir_block_csum_verify(fs, ino, + (struct ext2_dir_entry *)buf)) + corrupt = 1; + +#ifdef WORDS_BIGENDIAN + retval = ext2fs_dirent_swab_in(fs, buf, flags); +#endif + if (!retval && corrupt) + retval = EXT2_ET_DIR_CSUM_INVALID; + return retval; +} + +errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block, + void *buf, int flags EXT2FS_ATTR((unused))) +{ + return ext2fs_read_dir_block4(fs, block, buf, flags, 0); +} + +errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags EXT2FS_ATTR((unused))) +{ + return ext2fs_read_dir_block3(fs, block, buf, flags); +} + +errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, + void *buf) +{ + return ext2fs_read_dir_block3(fs, block, buf, 0); +} + + +errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block, + void *inbuf, int flags EXT2FS_ATTR((unused)), + ext2_ino_t ino) +{ + errcode_t retval; + char *buf = inbuf; + +#ifdef WORDS_BIGENDIAN + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + memcpy(buf, inbuf, fs->blocksize); + retval = ext2fs_dirent_swab_out(fs, buf, flags); + if (retval) + return retval; +#endif + retval = ext2fs_dir_block_csum_set(fs, ino, + (struct ext2_dir_entry *)buf); + if (retval) + goto out; + + retval = io_channel_write_blk64(fs->io, block, 1, buf); + +out: +#ifdef WORDS_BIGENDIAN + ext2fs_free_mem(&buf); +#endif + return retval; +} + +errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block, + void *inbuf, int flags EXT2FS_ATTR((unused))) +{ + return ext2fs_write_dir_block4(fs, block, inbuf, flags, 0); +} + +errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, + void *inbuf, int flags EXT2FS_ATTR((unused))) +{ + return ext2fs_write_dir_block3(fs, block, inbuf, flags); +} + +errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, + void *inbuf) +{ + return ext2fs_write_dir_block3(fs, block, inbuf, 0); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/dirblock.o b/jni/e2fsprogs/lib/ext2fs/dirblock.o new file mode 100755 index 0000000000000000000000000000000000000000..53358fcce3bd7c1c74062dad28f30eb3fc003ad8 GIT binary patch literal 2968 zcmdUwPiP}m9LIl?$=WO%n`#$bjCP6^tP2ipt=fag!&dEKk+Pud$stXrCNzH_8Qs{*PdrA%={(f(MuYH|PRPf}3%zN{B z-`}72`^{wDdj84_F~a~g4EP#O?i2;McK&27t_MY*n7oiwh= zCUKAOb4KH7+N~x$(N`N|DEmnRzLM*d@NWUk()!k&4}Z-4_W7MQ z##6cm#-Vk+=5%_S3r#%7_MYkd)c+RnJh5i42HSPi9H32W2+uPFK4}jy-`0@8d*L6M z)@912xA|NX?IP`W=B-`bzA^9Y9+-*C%E!O8r`V@#qhg!X3$xk7TqyS))9SQRnEUx(-3sg;_By^#H}gT{at?KV$k>qH{$STKWg8E*cp6X#yiU^ zlE=^Ji;~}UhJTObUd_MkD>C}CQO|&GL~f$^qqsqSl)Yf1SD25;_*_Ta%i@ppOUz~6 zkbTMgJ?65H$Y$^t6}L5jr#NncOC(T7<5}j5A$|q-D4%zjt9;b^kVd;9=^?myye6K| zxcZ0?*Q+h?o(6I4lLA`<_@2h^4ov0sca0Bge2()b|4EInYdod#n*;cRtT~5%SR%ILn1{cFoCF zUoSfNAD3U<0K4KAGPZ{ru(Rc2(Jgrc465$&&h<*(b59&9gNmD3(WqT2d#?TBOD{iO z^)lHt4&~;Y)k>!50_G#rv9n-Ty^5Dv#(ASiGiMwMGpqRNIJ1y1JK0>ORB{VWV6t3T zd+HRH76Fa+{Y13yV;o9lCR#oN6Dzj7OvA*wJry+MKVCmYdo#kv&;0VK_eDwgF;KVg z2(F0f?;dRmy5RUuf2i?3{7*T?OyI1KNp|=LLwe`Qm3sHpckwY~6hB;zI3Mah+|!53 zU(Fl1sn)vgfvBQHXy0cRIwp*>{k4#DmA{JhE-t7hLIIvHasBuBp6sY3%3huSGi2e| PWU|hM{(|Gv6lMPxJU1l( literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/dirhash.c b/jni/e2fsprogs/lib/ext2fs/dirhash.c new file mode 100755 index 0000000..42fe98b --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/dirhash.c @@ -0,0 +1,307 @@ +/* + * dirhash.c -- Calculate the hash of a directory entry + * + * Copyright (c) 2001 Daniel Phillips + * + * Copyright (c) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +/* + * Keyed 32-bit hash function using TEA in a Davis-Meyer function + * H0 = Key + * Hi = E Mi(Hi-1) + Hi-1 + * + * (see Applied Cryptography, 2nd edition, p448). + * + * Jeremy Fitzhardinge 1998 + * + * This code is made available under the terms of the GPL + */ +#define DELTA 0x9E3779B9 + +static void TEA_transform(__u32 buf[4], __u32 const in[]) +{ + __u32 sum = 0; + __u32 b0 = buf[0], b1 = buf[1]; + __u32 a = in[0], b = in[1], c = in[2], d = in[3]; + int n = 16; + + do { + sum += DELTA; + b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); + b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); + } while(--n); + + buf[0] += b0; + buf[1] += b1; +} + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The generic round function. The application is so specific that + * we don't bother protecting all the arguments with parens, as is generally + * good macro practice, in favor of extra legibility. + * Rotation is separate from addition to prevent recomputation + */ +#define ROUND(f, a, b, c, d, x, s) \ + (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) +#define K1 0 +#define K2 013240474631UL +#define K3 015666365641UL + +/* + * Basic cut-down MD4 transform. Returns only 32 bits of result. + */ +static void halfMD4Transform (__u32 buf[4], __u32 const in[]) +{ + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + ROUND(F, a, b, c, d, in[0] + K1, 3); + ROUND(F, d, a, b, c, in[1] + K1, 7); + ROUND(F, c, d, a, b, in[2] + K1, 11); + ROUND(F, b, c, d, a, in[3] + K1, 19); + ROUND(F, a, b, c, d, in[4] + K1, 3); + ROUND(F, d, a, b, c, in[5] + K1, 7); + ROUND(F, c, d, a, b, in[6] + K1, 11); + ROUND(F, b, c, d, a, in[7] + K1, 19); + + /* Round 2 */ + ROUND(G, a, b, c, d, in[1] + K2, 3); + ROUND(G, d, a, b, c, in[3] + K2, 5); + ROUND(G, c, d, a, b, in[5] + K2, 9); + ROUND(G, b, c, d, a, in[7] + K2, 13); + ROUND(G, a, b, c, d, in[0] + K2, 3); + ROUND(G, d, a, b, c, in[2] + K2, 5); + ROUND(G, c, d, a, b, in[4] + K2, 9); + ROUND(G, b, c, d, a, in[6] + K2, 13); + + /* Round 3 */ + ROUND(H, a, b, c, d, in[3] + K3, 3); + ROUND(H, d, a, b, c, in[7] + K3, 9); + ROUND(H, c, d, a, b, in[2] + K3, 11); + ROUND(H, b, c, d, a, in[6] + K3, 15); + ROUND(H, a, b, c, d, in[1] + K3, 3); + ROUND(H, d, a, b, c, in[5] + K3, 9); + ROUND(H, c, d, a, b, in[0] + K3, 11); + ROUND(H, b, c, d, a, in[4] + K3, 15); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#undef ROUND +#undef F +#undef G +#undef H +#undef K1 +#undef K2 +#undef K3 + +/* The old legacy hash */ +static ext2_dirhash_t dx_hack_hash (const char *name, int len, + int unsigned_flag) +{ + __u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; + const unsigned char *ucp = (const unsigned char *) name; + const signed char *scp = (const signed char *) name; + int c; + + while (len--) { + if (unsigned_flag) + c = (int) *ucp++; + else + c = (int) *scp++; + hash = hash1 + (hash0 ^ (c * 7152373)); + + if (hash & 0x80000000) hash -= 0x7fffffff; + hash1 = hash0; + hash0 = hash; + } + return (hash0 << 1); +} + +static void str2hashbuf(const char *msg, int len, __u32 *buf, int num, + int unsigned_flag) +{ + __u32 pad, val; + int i, c; + const unsigned char *ucp = (const unsigned char *) msg; + const signed char *scp = (const signed char *) msg; + + pad = (__u32)len | ((__u32)len << 8); + pad |= pad << 16; + + val = pad; + if (len > num*4) + len = num * 4; + for (i=0; i < len; i++) { + if (unsigned_flag) + c = (int) ucp[i]; + else + c = (int) scp[i]; + + val = c + (val << 8); + if ((i % 4) == 3) { + *buf++ = val; + val = pad; + num--; + } + } + if (--num >= 0) + *buf++ = val; + while (--num >= 0) + *buf++ = pad; +} + +/* + * Returns the hash of a filename. If len is 0 and name is NULL, then + * this function can be used to test whether or not a hash version is + * supported. + * + * The seed is an 4 longword (32 bits) "secret" which can be used to + * uniquify a hash. If the seed is all zero's, then some default seed + * may be used. + * + * A particular hash version specifies whether or not the seed is + * represented, and whether or not the returned hash is 32 bits or 64 + * bits. 32 bit hashes will return 0 for the minor hash. + * + * This function doesn't do any normalization or casefolding of the + * input string. To take charset encoding into account, use + * ext2fs_dirhash2. + * + */ +errcode_t ext2fs_dirhash(int version, const char *name, int len, + const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash) +{ + __u32 hash; + __u32 minor_hash = 0; + const char *p; + int i; + __u32 in[8], buf[4]; + int unsigned_flag = 0; + + /* Initialize the default seed for the hash checksum functions */ + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + + /* Check to see if the seed is all zero's */ + if (seed) { + for (i=0; i < 4; i++) { + if (seed[i]) + break; + } + if (i < 4) + memcpy(buf, seed, sizeof(buf)); + } + + switch (version) { + case EXT2_HASH_LEGACY_UNSIGNED: + unsigned_flag++; + /* fallthrough */ + case EXT2_HASH_LEGACY: + hash = dx_hack_hash(name, len, unsigned_flag); + break; + case EXT2_HASH_HALF_MD4_UNSIGNED: + unsigned_flag++; + /* fallthrough */ + case EXT2_HASH_HALF_MD4: + p = name; + while (len > 0) { + str2hashbuf(p, len, in, 8, unsigned_flag); + halfMD4Transform(buf, in); + len -= 32; + p += 32; + } + minor_hash = buf[2]; + hash = buf[1]; + break; + case EXT2_HASH_TEA_UNSIGNED: + unsigned_flag++; + /* fallthrough */ + case EXT2_HASH_TEA: + p = name; + while (len > 0) { + str2hashbuf(p, len, in, 4, unsigned_flag); + TEA_transform(buf, in); + len -= 16; + p += 16; + } + hash = buf[0]; + minor_hash = buf[1]; + break; + default: + *ret_hash = 0; + return EXT2_ET_DIRHASH_UNSUPP; + } + *ret_hash = hash & ~1; + if (ret_minor_hash) + *ret_minor_hash = minor_hash; + return 0; +} + +/* + * Returns the hash of a filename considering normalization and + * casefolding. This is a wrapper around ext2fs_dirhash with string + * encoding support based on the nls_table and the flags. Check + * ext2fs_dirhash for documentation on the input and output parameters. + */ +errcode_t ext2fs_dirhash2(int version, const char *name, int len, + const struct ext2fs_nls_table *charset, + int hash_flags, const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash) +{ + errcode_t r; + int dlen; + + if (len && charset && (hash_flags & EXT4_CASEFOLD_FL)) { + char buff[PATH_MAX]; + + dlen = charset->ops->casefold(charset, + (const unsigned char *) name, len, + (unsigned char *) buff, sizeof(buff)); + if (dlen < 0) { + if (dlen == -EINVAL) + goto opaque_seq; + + return dlen; + } + r = ext2fs_dirhash(version, buff, dlen, seed, ret_hash, + ret_minor_hash); + return r; + } + +opaque_seq: + return ext2fs_dirhash(version, name, len, seed, ret_hash, + ret_minor_hash); +} diff --git a/jni/e2fsprogs/lib/ext2fs/dirhash.o b/jni/e2fsprogs/lib/ext2fs/dirhash.o new file mode 100755 index 0000000000000000000000000000000000000000..3dfde588382b83d5627db345048f4dbe981ac0e6 GIT binary patch literal 5576 zcmb_ge{56N6+X`|CeL;Zgpj2r1P9To4pm)#b+A9s9x~lBt4x#4q-_O43dx*>fa0VR zETFNuld7_pz+ z=e#&<-JlQI_uO;O`OZ1tJ=eL9Z$A0dX9Ai=-lNgaX>R6eiJotnlT8s#3c<2E8JL>F!16a`xk774y3*&+GIS@>zZ<*Za@_y8C;-lf8g2syfTJpCQu zU5}W~wLBGU$VJ34zD2`D>`xIskPD1C18(d`O{<7~vLC^S9OCzzLnAqPI-cIoIW)RC zTnVTgw)t|{=F4G?8(VTfE{({csPC@CH1x~OA6(7;^^M!be5|sV^~qh>^VqTptjDol z%RODP>zm2Cu@M-*el?xl ziQYpW#$%_`*?;^*`V)KR*h|Qf5!^DCz1g%v=!-IZ?FQ8=8?m>Vl9!kc)(d6$8JhVi z_*-0$jr|Zka18CT=mihFm$3)aOHAv+p6AjRqT{*Lu}FKD7ET#jD8lE#e%!Qds(e!H zA&2PVGOP{qn&{xq=Sl2P!|&C;(vesOwJxl=jhy#k{{haU)P_BiQOAh-%J>+oLukycH|5;g z=#z5WamyGO*kZSk#pl@8JzZIJ;?n{gK9{S(3+Djb7tm{==sPRAj)mKq69Z@RtnW;g z+e~L|GZm&$GxtR;f6f*A$h^p-7jAqKCF-83+ucm$UW@whW<+NUZ_5cNS~?Ruytc?L<^r#y@nC{03H|g8gz^& zxRAN$1Q)U9;i|o@;krDYn9pN-#%NW2$NTHLKrg`nEOol<&muEdHjam^A6p##15yXr8bQCT}(+|g>fDkC#3q7 z`xZFhcCKH610By9-@xDK8Xn`we*19T7}B2{&;4EGJ^~K^E<(rng5%*aj_iXE$IV&# zk>kz%CIW|l6QQfsGl%D-gdZP{8>5b&=8UoRBlwZ??89+m{QvyOIrHJ%D?ifzKAd~y zNBYvm3Gu!QKRl9EhU}hC<_C8l?kUt=#^2<)iXYdYgPrIUNAVzZ$VYT)ALAkDP^;)v zuf?NeRdGL;`{*Q1UBmt4dJ8%HzJz;?V<3jQ<2VMe`A%ZDC_U~-BD0?Rk@bkhIf{%J z+!sdRc$)i6?k%{7bZveyUH;9RIk{IN4(=svZyC*@2+PxKqlF__PfcTve66n5R0Q0l zkx)bB|c{yVhCx2LqKTOUFb+;W)_LR=SR*#xaL&$W3 zh;tpdc*Q=&_MIAWpE>Lk_3o$8v!5n;?3w4we)v6c2=-4zm$9Y{;Yj_W5%ub}$`J;w2i%uJ`YKnCtuRlp*%C3GG zgQ9`{R;}0bT*u3N{qu$>7V0z52k=k$fh@IS+^h5#bqIK*c8qKAVf*eNYgOGCTk&E2 zQ`mHVq-Kn-%dA1Z{a>%i1aC}r5AVS;;CPRh*Go!&RM;gF-k|%^64$aFJcd0dj3@tt zexeFu6IqkV@*DY5U+&`{sO zQQGk@4=D&L%AW!_8#cpv3=9dnj&%V&}d)cv!DOsVznbE#%zxOIb>@6E zEmiToD*0G*pYX_!_j}R=nK3*&UgPJEiu(z7TKo3$_r^_F@#LBjgk?+pvpKomb{I>n z^Y<`YKcM{oz!Tr&GGssI*z@=5{~mPpvDxKA6~9v@%mbgxdjEd| DNF~vs literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/dosio.c b/jni/e2fsprogs/lib/ext2fs/dosio.c new file mode 100755 index 0000000..d0cf269 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/dosio.c @@ -0,0 +1,459 @@ +/* + * dosio.c -- Disk I/O module for the ext2fs/DOS library. + * + * Copyright (c) 1997 by Theodore Ts'o. + * + * Copyright (c) 1997 Mark Habersack + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include "utils.h" +#include "dosio.h" +#include "et/com_err.h" +#include "ext2_err.h" +#include "ext2fs/io.h" + +/* + * Some helper macros + */ +#define LINUX_EXT2FS 0x83 +#define LINUX_SWAP 0x82 +#define WRITE_ERR(_msg_) write(2, _msg_, strlen(_msg_)) +#define WRITE_ERR_S(_msg_) write(2, _msg_, sizeof(_msg_)) + +/* + * Exported variables + */ +unsigned long _dio_error; +unsigned long _dio_hw_error; + +/* + * Array of all opened partitions + */ +static PARTITION **partitions = NULL; +static unsigned short npart = 0; /* Number of mapped partitions */ +static PARTITION *active = NULL; + +/* + * I/O Manager routine prototypes + */ +static errcode_t dos_open(const char *dev, int flags, io_channel *channel); +static errcode_t dos_close(io_channel channel); +static errcode_t dos_set_blksize(io_channel channel, int blksize); +static errcode_t dos_read_blk(io_channel channel, unsigned long block, + int count, void *buf); +static errcode_t dos_write_blk(io_channel channel, unsigned long block, + int count, const void *buf); +static errcode_t dos_flush(io_channel channel); + +static struct struct_io_manager struct_dos_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "DOS I/O Manager", + .open = dos_open, + .close = dos_close, + .set_blksize = dos_set_blksize, + .read_blk = dos_read_blk, + .write_blk = dos_write_blk, + .flush = dos_flush +}; + +io_manager dos_io_manager = &struct_dos_manager; + +/* + * Macro taken from unix_io.c + */ +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +/* + * Calculates a CHS address of a sector from its LBA + * offset for the given partition. + */ +static void lba2chs(unsigned long lba_addr, CHS *chs, PARTITION *part) +{ + unsigned long abss; + + chs->offset = lba_addr & 0x000001FF; + abss = (lba_addr >> 9) + part->start; + chs->cyl = abss / (part->sects * part->heads); + chs->head = (abss / part->sects) % part->heads; + chs->sector = (abss % part->sects) + 1; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +/* + * Scans the passed partition table looking for *pno partition + * that has LINUX_EXT2FS type. + * + * TODO: + * For partition numbers >5 Linux uses DOS extended partitions - + * dive into them an return an appropriate entry. Also dive into + * extended partitions when scanning for a first Linux/ext2fs. + */ +static PTABLE_ENTRY *scan_partition_table(PTABLE_ENTRY *pentry, + unsigned short phys, + unsigned char *pno) +{ + unsigned i; + + if(*pno != 0xFF && *pno >= 5) + return NULL; /* We don't support extended partitions for now */ + + if(*pno != 0xFF) + { + if(pentry[*pno].type == LINUX_EXT2FS) + return &pentry[*pno]; + else + { + if(!pentry[*pno].type) + *pno = 0xFE; + else if(pentry[*pno].type == LINUX_SWAP) + *pno = 0xFD; + return NULL; + } + } + + for(i = 0; i < 4; i++) + if(pentry[i].type == LINUX_EXT2FS) + { + *pno = i; + return &pentry[i]; + } + + return NULL; +} + +/* + * Allocate libext2fs structures associated with I/O manager + */ +static io_channel alloc_io_channel(PARTITION *part) +{ + io_channel ioch; + + ioch = (io_channel)malloc(sizeof(struct struct_io_channel)); + if (!ioch) + return NULL; + memset(ioch, 0, sizeof(struct struct_io_channel)); + ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL; + ioch->manager = dos_io_manager; + ioch->name = (char *)malloc(strlen(part->dev)+1); + if (!ioch->name) { + free(ioch); + return NULL; + } + strcpy(ioch->name, part->dev); + ioch->private_data = part; + ioch->block_size = 1024; /* The smallest ext2fs block size */ + ioch->read_error = 0; + ioch->write_error = 0; + + return ioch; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +/* + * Open the 'name' partition, initialize all information structures + * we need to keep and create libext2fs I/O manager. + */ +static errcode_t dos_open(const char *dev, int flags, io_channel *channel) +{ + unsigned char *tmp, sec[512]; + PARTITION *part; + PTABLE_ENTRY *pent; + PARTITION **newparts; + + if(!dev) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + + /* + * First check whether the dev name is OK + */ + tmp = (unsigned char*)strrchr(dev, '/'); + if(!tmp) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + *tmp = 0; + if(strcmp(dev, "/dev")) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + *tmp++ = '/'; + + /* + * Check whether the partition data is already in cache + */ + + part = (PARTITION*)malloc(sizeof(PARTITION)); + if (!part) + return ENOMEM; + { + int i = 0; + + for(;i < npart; i++) + if(!strcmp(partitions[i]->dev, dev)) + { + /* Found it! Make it the active one */ + active = partitions[i]; + *channel = alloc_io_channel(active); + if (!*channel) + return ENOMEM; + return 0; + } + } + + /* + * Drive number & optionally partn number + */ + switch(tmp[0]) + { + case 'h': + case 's': + part->phys = 0x80; + part->phys += toupper(tmp[2]) - 'A'; + /* + * Do we have the partition number? + */ + if(tmp[3]) + part->pno = isdigit((int)tmp[3]) ? tmp[3] - '0' - 1: 0; + else + part->pno = 0xFF; + break; + + case 'f': + if(tmp[2]) + part->phys = isdigit((int)tmp[2]) ? tmp[2] - '0' : 0; + else + part->phys = 0x00; /* We'll assume /dev/fd0 */ + break; + + default: + _dio_error = ERR_BADDEV; + return ENODEV; + } + + if(part->phys < 0x80) + { + /* We don't support floppies for now */ + _dio_error = ERR_NOTSUPP; + return EINVAL; + } + + part->dev = strdup(dev); + + /* + * Get drive's geometry + */ + _dio_hw_error = biosdisk(DISK_GET_GEOMETRY, + part->phys, + 0, /* head */ + 0, /* cylinder */ + 1, /* sector */ + 1, /* just one sector */ + sec); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + free(part->dev); + free(part); + return EFAULT; + } + + /* + * Calculate the geometry + */ + part->cyls = (unsigned short)(((sec[0] >> 6) << 8) + sec[1] + 1); + part->heads = sec[3] + 1; + part->sects = sec[0] & 0x3F; + + /* + * Now that we know all we need, let's look for the partition + */ + _dio_hw_error = biosdisk(DISK_READ, part->phys, 0, 0, 1, 1, sec); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + free(part->dev); + free(part); + return EFAULT; + } + + pent = (PTABLE_ENTRY*)&sec[0x1BE]; + pent = scan_partition_table(pent, part->phys, &part->pno); + + if(!pent) + { + _dio_error = part->pno == 0xFE ? ERR_EMPTYPART : + part->pno == 0xFD ? ERR_LINUXSWAP : ERR_NOTEXT2FS; + free(part->dev); + free(part); + return ENODEV; + } + + /* + * Calculate the remaining figures + */ + { + unsigned long fsec, fhead, fcyl; + + fsec = (unsigned long)(pent->start_sec & 0x3F); + fhead = (unsigned long)pent->start_head; + fcyl = ((pent->start_sec >> 6) << 8) + pent->start_cyl; + part->start = fsec + fhead * part->sects + fcyl * + (part->heads * part->sects) - 1; + part->len = pent->size; + } + + /* + * Add the partition to the table + */ + newparts = (PARTITION**)realloc(partitions, sizeof(PARTITION) * npart); + if (!newparts) { + free(part); + return ENOMEM; + } + partitions = newparts; + partitions[npart++] = active = part; + + /* + * Now alloc all libe2fs structures + */ + *channel = alloc_io_channel(active); + if (!*channel) + return ENOMEM; + + return 0; +} + +static errcode_t dos_close(io_channel channel) +{ + free(channel->name); + free(channel); + + return 0; +} + +static errcode_t dos_set_blksize(io_channel channel, int blksize) +{ + channel->block_size = blksize; + + return 0; +} + +static errcode_t dos_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + PARTITION *part; + size_t size; + ext2_loff_t loc; + CHS chs; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + part = (PARTITION*)channel->private_data; + + size = (size_t)((count < 0) ? -count : count * channel->block_size); + loc = (ext2_loff_t) block * channel->block_size; + + lba2chs(loc, &chs, part); + /* + * Potential bug here: + * If DJGPP is used then reads of >18 sectors will fail! + * Have to rewrite biosdisk. + */ + _dio_hw_error = biosdisk(DISK_READ, + part->phys, + chs.head, + chs.cyl, + chs.sector, + size < 512 ? 1 : size/512, + buf); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + return EFAULT; + } + + return 0; +} + +static errcode_t dos_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + PARTITION *part; + size_t size; + ext2_loff_t loc; + CHS chs; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + part = (PARTITION*)channel->private_data; + + if(count == 1) + size = (size_t)channel->block_size; + else + { + if (count < 0) + size = (size_t)-count; + else + size = (size_t)(count * channel->block_size); + } + + loc = (ext2_loff_t)block * channel->block_size; + lba2chs(loc, &chs, part); + _dio_hw_error = biosdisk(DISK_WRITE, + part->phys, + chs.head, + chs.cyl, + chs.sector, + size < 512 ? 1 : size/512, + (void*)buf); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + return EFAULT; + } + + return 0; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +static errcode_t dos_flush(io_channel channel) +{ + /* + * No buffers, no flush... + */ + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/dupfs.c b/jni/e2fsprogs/lib/ext2fs/dupfs.c new file mode 100755 index 0000000..02721e1 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/dupfs.c @@ -0,0 +1,122 @@ +/* + * dupfs.c --- duplicate a ext2 filesystem handle + * + * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest) +{ + ext2_filsys fs; + errcode_t retval; + + EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + *fs = *src; + fs->device_name = 0; + fs->super = 0; + fs->orig_super = 0; + fs->group_desc = 0; + fs->inode_map = 0; + fs->block_map = 0; + fs->badblocks = 0; + fs->dblist = 0; + fs->mmp_buf = 0; + fs->mmp_cmp = 0; + fs->mmp_fd = -1; + + io_channel_bumpcount(fs->io); + if (fs->icache) + fs->icache->refcount++; + + retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name); + if (retval) + goto errout; + strcpy(fs->device_name, src->device_name); + + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); + if (retval) + goto errout; + memcpy(fs->super, src->super, SUPERBLOCK_SIZE); + + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); + if (retval) + goto errout; + memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE); + + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, + &fs->group_desc); + if (retval) + goto errout; + memcpy(fs->group_desc, src->group_desc, + (size_t) fs->desc_blocks * fs->blocksize); + + if (src->inode_map) { + retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map); + if (retval) + goto errout; + } + if (src->block_map) { + retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map); + if (retval) + goto errout; + } + if (src->badblocks) { + retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks); + if (retval) + goto errout; + } + if (src->dblist) { + retval = ext2fs_copy_dblist(src->dblist, &fs->dblist); + if (retval) + goto errout; + } + if (src->mmp_buf) { + retval = ext2fs_get_mem(src->blocksize, &fs->mmp_buf); + if (retval) + goto errout; + memcpy(fs->mmp_buf, src->mmp_buf, src->blocksize); + } + if (src->mmp_fd >= 0) { + fs->mmp_fd = dup(src->mmp_fd); + if (fs->mmp_fd < 0) { + retval = EXT2_ET_MMP_OPEN_DIRECT; + goto errout; + } + } + if (src->mmp_cmp) { + int align = ext2fs_get_dio_alignment(src->mmp_fd); + + retval = ext2fs_get_memalign(src->blocksize, align, + &fs->mmp_cmp); + if (retval) + goto errout; + memcpy(fs->mmp_cmp, src->mmp_cmp, src->blocksize); + } + *dest = fs; + return 0; +errout: + ext2fs_free(fs); + return retval; + +} + diff --git a/jni/e2fsprogs/lib/ext2fs/dupfs.o b/jni/e2fsprogs/lib/ext2fs/dupfs.o new file mode 100755 index 0000000000000000000000000000000000000000..23349d4188953fb4f4945204a7ebb675ee09ecfe GIT binary patch literal 3160 zcmbtWO>7%g5T0E-WDU-bL)D}zjcX}LHd0n~52X?k+K2{Hsj5;`Brae!_9nLKpUB=; zO#>p8FZ2+Jh>8mWB^Q*O;DD%nqK67{=mC1@36N6>DF`l99K2GaGV?sodEV}xc#=JD zzBk{zZ)V><`{UUQZ|a%`a%gY|4n2tiOgw)$x5U(f7)CyQL;K}mHM(;U(Ka?C$<9`D zva=n@bqvk&GVRYFl>YeUv7yEOx(jd_^BzefRzz&One4g&JBk%^jC+dn_KTLcg?V+1r`Ub;lS3F!Ho^81+Z5Xj+iAA5Y|pd3#daOMKQWI1 zYh&q@)}oxT0n1Bgt(GwWiF6hOW?aP>jkQq>`srgFa|~LfnQDh2%Oi~tg$>H3+5Pnu zxxRZ;Bd$|C@igWM&Q0X3b!(MtU41hH>>&=P&oZt8t~mHe+I{}S`j z5?}TePIUQ3#%k?Fj8{kxo{_*@pUGS)&V`oZ4a`A3&0r4wqu3XeTbzpw#&Hituh19u z&IIRQ#r(3b#NV`+*ELn-cz~feO&arnuEC)Rqidz+ts^ghU;&& zxu@DpG_a?yBcJjEa>cn|OV8sGa;cZSo}^}4hTeHq`hb4#Ir3RH5Zi^$8HzC;ci+GL z5%8u|o$HoYj2!BedD`R9Qg!c*ueC^L$HWcI9?HP0ex6hAby8*hX5 z;iPsvo`f{|69NTTj^gCp@cdl-#OPQ0m(j?((RgxxZWw<5jU$51zX(U+AH0H|9TCu< z0gs|+2*48pClUQ4E^w^gHy)xtrsNU&5!=R(tW~8BGf`)(?@8h>BG)%d>^`~_7fA3=Xz7Zg0M#D5Zk-&61*B_1MOhw=|AxTWB#epkU& z{kIhy?}*;`Rl(JB^hCiEy=Z__{0jN&omcQNCH^Iz51@W7v5Pp@-P4PW+=5+LDA)2= z8o7LJc?BA7J&&g1RLF45lH=y=dfi?Dv+k5_(?wja5i5r&N{t>w;e}EyXO~M$)rwPf z!OYhxVp6!e+(%p}xfQzy5fOJ5JW^72sxq3Fz^v9>$9(JJJJSu<&R=0cPBFJww=0f} z#%*#%yILsskj1*=0K$t6GY=-_cI^eUD;2U+1@kn0Wnt>Nc}i*C|Cl~OE&lc4(B94PA~ms%qE5|5%F S|K5}v{|}3?%Yw-S@&5x@{UvMw literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/expanddir.c b/jni/e2fsprogs/lib/ext2fs/expanddir.c new file mode 100755 index 0000000..b5d5abd --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/expanddir.c @@ -0,0 +1,143 @@ +/* + * expand.c --- expand an ext2fs directory + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +struct expand_dir_struct { + int done; + int newblocks; + blk64_t goal; + errcode_t err; + ext2_ino_t dir; +}; + +static int expand_dir_proc(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; + blk64_t new_blk; + char *block; + errcode_t retval; + + if (*blocknr) { + if (blockcnt >= 0) + es->goal = *blocknr; + return 0; + } + if (blockcnt && + (EXT2FS_B2C(fs, es->goal) == EXT2FS_B2C(fs, es->goal+1))) + new_blk = es->goal+1; + else { + es->goal &= ~EXT2FS_CLUSTER_MASK(fs); + retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk); + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + es->newblocks++; + ext2fs_block_alloc_stats2(fs, new_blk, +1); + } + if (blockcnt > 0) { + retval = ext2fs_new_dir_block(fs, 0, 0, &block); + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + es->done = 1; + retval = ext2fs_write_dir_block4(fs, new_blk, block, 0, + es->dir); + ext2fs_free_mem(&block); + } else + retval = ext2fs_zero_blocks2(fs, new_blk, 1, NULL, NULL); + if (blockcnt >= 0) + es->goal = new_blk; + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + *blocknr = new_blk; + + if (es->done) + return (BLOCK_CHANGED | BLOCK_ABORT); + else + return BLOCK_CHANGED; +} + +errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) +{ + errcode_t retval; + struct expand_dir_struct es; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!fs->block_map) + return EXT2_ET_NO_BLOCK_BITMAP; + + retval = ext2fs_check_directory(fs, dir); + if (retval) + return retval; + + retval = ext2fs_read_inode(fs, dir, &inode); + if (retval) + return retval; + + es.done = 0; + es.err = 0; + es.goal = ext2fs_find_inode_goal(fs, dir, &inode, 0); + es.newblocks = 0; + es.dir = dir; + + retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND, + 0, expand_dir_proc, &es); + if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) + return ext2fs_inline_data_expand(fs, dir); + + if (es.err) + return es.err; + if (!es.done) + return EXT2_ET_EXPAND_DIR_ERR; + + /* + * Update the size and block count fields in the inode. + */ + retval = ext2fs_read_inode(fs, dir, &inode); + if (retval) + return retval; + + retval = ext2fs_inode_size_set(fs, &inode, + EXT2_I_SIZE(&inode) + fs->blocksize); + if (retval) + return retval; + ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); + + retval = ext2fs_write_inode(fs, dir, &inode); + if (retval) + return retval; + + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/expanddir.o b/jni/e2fsprogs/lib/ext2fs/expanddir.o new file mode 100755 index 0000000000000000000000000000000000000000..d237cbbd556de4e922b00deba9981d072dff1ffd GIT binary patch literal 3424 zcmbVOUu+ab7@xgu;SLG~TBJ(GiJMU4*t8 zB!>ynm{>KYA^s^y;$0u~1=G94q%})=bk%qD4-}z4u#FK+D@X3b#AP!HNMnX2+VtV_2%ltrs8V9IytR&R4*^I zmkO$04Jw)yS^VUu#L72+1(nd9dB$FW-R3Z`Az+1kNA*1RoV!&kUuWzf$qUOh`IwaN z)hx)rC3$eACO?h+G<;oNI8j1KA5W|8)q;AWT43xNw?%9C8FcZM``P4!xW~CqKOar0$b~^_;;-) zOQI%HkH>|0pXM>V?#cse;0HKakmJmr#q!4y}CqoK_B= z56u)&%Sc2k2b9oz52{g<(7)3EX^Ctssmvn&vWl8K#CfRDpF=*B!*pJ+u1*{+qK_u$ zRsENH3kv#aU2!$9*!`4muU^5qewlBpUhQuyt?XbHVzw$x%qrwh@IJe!)XuxYs3&}3&`VT_!IWZ)Nk;$6*kLcbE#3|=fUfMI{-U( zkJj1ukL2*xy`%=ZZ;89`F#ZlofAAGnYJMuzLpcBCjdUiORrjb?M(=l1KLDRuL{HFN zqJ0Q9WPB9!pOmv&H$yUtLB@MsoM8od*g4v=|EkGm*e9JL&K@!Hc<>ID@gD3a+e4yu zxR=dzMpQ?_rx*0n>cpWUdXM)YizSWJVCNfVCYwm7I(zz}J<&b{Nn?vWF=hN1Q{HS> zb~bddFt8SZzZAgY+0Bc}KttP>&jX*;seOTl4s18GKYoX(i^PI^!RC%S)Fh~*k|{`@ zX*&Y0V|VX)V7^ru8C*Mx;IsSS^}qx8JSbzY0omrVFYOUs z*2=B)n-4zWgTDYn_p@`yhySDx{)`X)gAe|`k6+yf|Io)yj}L#?hd<`SzX(2!osb9Z zCI4O%Yr=8Aobitf-{7E(wSq^Z2{UzzJg-iHQ-8VfE`gJM*S`SlhzoDv7VXcJ3wOu! zs|(-c;s-^`l6~A?XSBHRMh8W_`0=1Ye0N_=x$vzvg@5N=_%;{bB3hj6;P=cKVHe)) zpt!Rxe7g&86>IxG)dT|`T-KSHXLG%$vU+UDj1BAYM8=He(wQ+9&6r6enuC-@W9g9* zGnJFnL@FIO^=x7sAG3y@Ob+WtJg%QirenidNjA@p8mTxLmdL4$Y3d{9h_g>XZrdD8 z8%YVL%rm5An`6;bI%h_ofAQ75*_;s@7U7vg`l*aDVoIGenMBUCZAmC&8p66n5~*Y& zW$JMwXXtixkjNnQ(M&of_V6B!v1m4z$r&dxkB!hQ>Seof0^Bcgp1qDRGDgmPYAtFc zQ5qcy + +#define N_(a) a + +static const char * const text[] = { + N_( "EXT2FS Library version android-t-qpr1-beta-2-gpl-369-g8ed4b2673"), + N_( "Wrong magic number for ext2_filsys structure"), + N_( "Wrong magic number for badblocks_list structure"), + N_( "Wrong magic number for badblocks_iterate structure"), + N_( "Wrong magic number for inode_scan structure"), + N_( "Wrong magic number for io_channel structure"), + N_( "Wrong magic number for unix io_channel structure"), + N_( "Wrong magic number for io_manager structure"), + N_( "Wrong magic number for block_bitmap structure"), + N_( "Wrong magic number for inode_bitmap structure"), + N_( "Wrong magic number for generic_bitmap structure"), + N_( "Wrong magic number for test io_channel structure"), + N_( "Wrong magic number for directory block list structure"), + N_( "Wrong magic number for icount structure"), + N_( "Wrong magic number for Powerquest io_channel structure"), + N_( "Wrong magic number for ext2 file structure"), + N_( "Wrong magic number for Ext2 Image Header"), + N_( "Wrong magic number for inode io_channel structure"), + N_( "Wrong magic number for ext4 extent handle"), + N_( "Bad magic number in super-block"), + N_( "Filesystem revision too high"), + N_( "Attempt to write to filesystem opened read-only"), + N_( "Can't read group descriptors"), + N_( "Can't write group descriptors"), + N_( "Corrupt group descriptor: bad block for block bitmap"), + N_( "Corrupt group descriptor: bad block for inode bitmap"), + N_( "Corrupt group descriptor: bad block for inode table"), + N_( "Can't write an inode bitmap"), + N_( "Can't read an inode bitmap"), + N_( "Can't write a block bitmap"), + N_( "Can't read a block bitmap"), + N_( "Can't write an inode table"), + N_( "Can't read an inode table"), + N_( "Can't read next inode"), + N_( "Filesystem has unexpected block size"), + N_( "EXT2 directory corrupted"), + N_( "Attempt to read block from filesystem resulted in short read"), + N_( "Attempt to write block to filesystem resulted in short write"), + N_( "No free space in the directory"), + N_( "Inode bitmap not loaded"), + N_( "Block bitmap not loaded"), + N_( "Illegal inode number"), + N_( "Illegal block number"), + N_( "Internal error in ext2fs_expand_dir"), + N_( "Not enough space to build proposed filesystem"), + N_( "Illegal block number passed to ext2fs_mark_block_bitmap"), + N_( "Illegal block number passed to ext2fs_unmark_block_bitmap"), + N_( "Illegal block number passed to ext2fs_test_block_bitmap"), + N_( "Illegal inode number passed to ext2fs_mark_inode_bitmap"), + N_( "Illegal inode number passed to ext2fs_unmark_inode_bitmap"), + N_( "Illegal inode number passed to ext2fs_test_inode_bitmap"), + N_( "Attempt to fudge end of block bitmap past the real end"), + N_( "Attempt to fudge end of inode bitmap past the real end"), + N_( "Illegal indirect block found" ), + N_( "Illegal doubly indirect block found" ), + N_( "Illegal triply indirect block found" ), + N_( "Block bitmaps are not the same"), + N_( "Inode bitmaps are not the same"), + N_( "Illegal or malformed device name"), + N_( "A block group is missing an inode table"), + N_( "The ext2 superblock is corrupt"), + N_( "Illegal generic bit number passed to ext2fs_mark_generic_bitmap"), + N_( "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap"), + N_( "Illegal generic bit number passed to ext2fs_test_generic_bitmap"), + N_( "Too many symbolic links encountered."), + N_( "The callback function will not handle this case"), + N_( "The inode is from a bad block in the inode table"), + N_( "Filesystem has unsupported feature(s)"), + N_( "Filesystem has unsupported read-only feature(s)"), + N_( "IO Channel failed to seek on read or write"), + N_( "Memory allocation failed"), + N_( "Invalid argument passed to ext2 library"), + N_( "Could not allocate block in ext2 filesystem"), + N_( "Could not allocate inode in ext2 filesystem"), + N_( "Ext2 inode is not a directory"), + N_( "Too many references in table"), + N_( "File not found by ext2_lookup"), + N_( "File open read-only"), + N_( "Ext2 directory block not found"), + N_( "Ext2 directory already exists"), + N_( "Unimplemented ext2 library function"), + N_( "User cancel requested"), + N_( "Ext2 file too big"), + N_( "Supplied journal device not a block device"), + N_( "Journal superblock not found"), + N_( "Journal must be at least 1024 blocks"), + N_( "Unsupported journal version"), + N_( "Error loading external journal"), + N_( "Journal not found"), + N_( "Directory hash unsupported"), + N_( "Illegal extended attribute block number"), + N_( "Cannot create filesystem with requested number of inodes"), + N_( "E2image snapshot not in use"), + N_( "Too many reserved group descriptor blocks"), + N_( "Resize inode is corrupt"), + N_( "Tried to set block bmap with missing indirect block"), + N_( "TDB: Success"), + N_( "TDB: Corrupt database"), + N_( "TDB: IO Error"), + N_( "TDB: Locking error"), + N_( "TDB: Out of memory"), + N_( "TDB: Record exists"), + N_( "TDB: Lock exists on other keys"), + N_( "TDB: Invalid parameter"), + N_( "TDB: Record does not exist"), + N_( "TDB: Write not permitted"), + N_( "Ext2fs directory block list is empty"), + N_( "Attempt to modify a block mapping via a read-only block iterator"), + N_( "Wrong magic number for ext4 extent saved path"), + N_( "Wrong magic number for 64-bit generic bitmap"), + N_( "Wrong magic number for 64-bit block bitmap"), + N_( "Wrong magic number for 64-bit inode bitmap"), + N_( "Wrong magic number --- RESERVED_13"), + N_( "Wrong magic number --- RESERVED_14"), + N_( "Wrong magic number --- RESERVED_15"), + N_( "Wrong magic number --- RESERVED_16"), + N_( "Wrong magic number --- RESERVED_17"), + N_( "Wrong magic number --- RESERVED_18"), + N_( "Wrong magic number --- RESERVED_19"), + N_( "Corrupt extent header"), + N_( "Corrupt extent index"), + N_( "Corrupt extent"), + N_( "No free space in extent map"), + N_( "Inode does not use extents"), + N_( "No 'next' extent"), + N_( "No 'previous' extent"), + N_( "No 'up' extent"), + N_( "No 'down' extent"), + N_( "No current node"), + N_( "Ext2fs operation not supported"), + N_( "No room to insert extent in node"), + N_( "Splitting would result in empty node"), + N_( "Extent not found"), + N_( "Operation not supported for inodes containing extents"), + N_( "Extent length is invalid"), + N_( "I/O Channel does not support 64-bit block numbers"), + N_( "Can't check if filesystem is mounted due to missing mtab file"), + N_( "Filesystem too large to use legacy bitmaps"), + N_( "MMP: invalid magic number"), + N_( "MMP: device currently active"), + N_( "MMP: e2fsck being run"), + N_( "MMP: block number beyond filesystem range"), + N_( "MMP: undergoing an unknown operation"), + N_( "MMP: filesystem still in use"), + N_( "MMP: open with O_DIRECT failed"), + N_( "Block group descriptor size incorrect"), + N_( "Inode checksum does not match inode"), + N_( "Inode bitmap checksum does not match bitmap"), + N_( "Extent block checksum does not match extent block"), + N_( "Directory block does not have space for checksum"), + N_( "Directory block checksum does not match directory block"), + N_( "Extended attribute block checksum does not match block"), + N_( "Superblock checksum does not match superblock"), + N_( "Unknown checksum algorithm"), + N_( "MMP block checksum does not match"), + N_( "Ext2 file already exists"), + N_( "Block bitmap checksum does not match bitmap"), + N_( "Cannot iterate data blocks of an inode containing inline data"), + N_( "Extended attribute has an invalid name length"), + N_( "Extended attribute has an invalid value length"), + N_( "Extended attribute has an incorrect hash"), + N_( "Extended attribute block has a bad header"), + N_( "Extended attribute key not found"), + N_( "Insufficient space to store extended attribute data"), + N_( "Filesystem is missing ext_attr or inline_data feature"), + N_( "Inode doesn't have inline data"), + N_( "No block for an inode with inline data"), + N_( "No free space in inline data"), + N_( "Wrong magic number for extended attribute structure"), + N_( "Inode seems to contain garbage"), + N_( "Extended attribute has an invalid value offset"), + N_( "Journal flags inconsistent"), + N_( "Undo file corrupt"), + N_( "Wrong undo file for this filesystem"), + N_( "File system is corrupted"), + N_( "Bad CRC detected in file system"), + N_( "The journal superblock is corrupt"), + N_( "Inode is corrupted"), + N_( "Inode containing extended attribute value is corrupted"), + N_( "Group descriptors not loaded"), + N_( "The internal ext2_filsys data structure appears to be corrupted"), + N_( "Found cyclic loop in extent tree"), + N_( "Operation not supported on an external journal"), + 0 +}; + +struct error_table { + char const * const * msgs; + long base; + int n_msgs; +}; +struct et_list { + struct et_list *next; + const struct error_table * table; +}; +extern struct et_list *_et_list; + +const struct error_table et_ext2_error_table = { text, 2133571328L, 183 }; + +static struct et_list link = { 0, 0 }; + +void initialize_ext2_error_table_r(struct et_list **list); +void initialize_ext2_error_table(void); + +void initialize_ext2_error_table(void) { + initialize_ext2_error_table_r(&_et_list); +} + +/* For Heimdal compatibility */ +void initialize_ext2_error_table_r(struct et_list **list) +{ + struct et_list *et, **end; + + for (end = list, et = *list; et; end = &et->next, et = et->next) + if (et->table->msgs == text) + return; + et = malloc(sizeof(struct et_list)); + if (et == 0) { + if (!link.table) + et = &link; + else + return; + } + et->table = &et_ext2_error_table; + et->next = 0; + *end = et; +} diff --git a/jni/e2fsprogs/lib/ext2fs/ext2_err.o b/jni/e2fsprogs/lib/ext2fs/ext2_err.o new file mode 100755 index 0000000000000000000000000000000000000000..cfeca8dc61b850572925710bc768c6a2648a732a GIT binary patch literal 15104 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/ext_attr.c b/jni/e2fsprogs/lib/ext2fs/ext_attr.c new file mode 100755 index 0000000..5525045 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/ext_attr.c @@ -0,0 +1,1777 @@ +/* + * ext_attr.c --- extended attribute blocks + * + * Copyright (C) 2001 Andreas Gruenbacher, + * + * Copyright (C) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2_ext_attr.h" +#include "ext4_acl.h" + +#include "ext2fs.h" + +static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash) +{ + struct ext2_inode inode; + errcode_t retval; + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + *hash = ext2fs_get_ea_inode_hash(&inode); + return 0; +} + +#define NAME_HASH_SHIFT 5 +#define VALUE_HASH_SHIFT 16 + +/* + * ext2_xattr_hash_entry() + * + * Compute the hash of an extended attribute. + */ +__u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data) +{ + __u32 hash = 0; + unsigned char *name = (((unsigned char *) entry) + + sizeof(struct ext2_ext_attr_entry)); + int n; + + for (n = 0; n < entry->e_name_len; n++) { + hash = (hash << NAME_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ + *name++; + } + + /* The hash needs to be calculated on the data in little-endian. */ + 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--) { + hash = (hash << VALUE_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ + ext2fs_le32_to_cpu(*value++); + } + } + + return hash; +} + +__u32 ext2fs_ext_attr_hash_entry_signed(struct ext2_ext_attr_entry *entry, + void *data) +{ + __u32 hash = 0; + signed char *name = (((signed char *) entry) + + sizeof(struct ext2_ext_attr_entry)); + int n; + + for (n = 0; n < entry->e_name_len; n++) { + hash = (hash << NAME_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ + *name++; + } + + /* The hash needs to be calculated on the data in little-endian. */ + 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--) { + hash = (hash << VALUE_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ + ext2fs_le32_to_cpu(*value++); + } + } + + return hash; +} + + +/* + * ext2fs_ext_attr_hash_entry3() + * + * Compute the hash of an extended attribute. This version of the + * function supports hashing entries that reference external inodes + * (ea_inode feature) as well as calculating the old legacy signed + * hash variant. + */ +errcode_t ext2fs_ext_attr_hash_entry3(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash, + __u32 *signed_hash) +{ + *hash = ext2fs_ext_attr_hash_entry(entry, data); + if (signed_hash) + *signed_hash = ext2fs_ext_attr_hash_entry_signed(entry, data); + + if (entry->e_value_inum) { + __u32 ea_inode_hash; + errcode_t retval; + + retval = read_ea_inode_hash(fs, entry->e_value_inum, + &ea_inode_hash); + if (retval) + return retval; + + *hash = (*hash << VALUE_HASH_SHIFT) ^ + (*hash >> (8*sizeof(*hash) - VALUE_HASH_SHIFT)) ^ + ea_inode_hash; + if (signed_hash) + *signed_hash = (*signed_hash << VALUE_HASH_SHIFT) ^ + (*signed_hash >> (8*sizeof(*hash) - + VALUE_HASH_SHIFT)) ^ + ea_inode_hash; + } + return 0; +} + +/* + * ext2fs_ext_attr_hash_entry2() + * + * Compute the hash of an extended attribute. + * This version of the function supports hashing entries that reference + * external inodes (ea_inode feature). + */ +errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash) +{ + return ext2fs_ext_attr_hash_entry3(fs, entry, data, hash, NULL); +} + +#undef NAME_HASH_SHIFT +#undef VALUE_HASH_SHIFT + +#define BLOCK_HASH_SHIFT 16 + +/* Mirrors ext4_xattr_rehash() implementation in kernel. */ +void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header, + struct ext2_ext_attr_entry *end) +{ + struct ext2_ext_attr_entry *here; + __u32 hash = 0; + + here = (struct ext2_ext_attr_entry *)(header+1); + while (here < end && !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; +} + +#undef BLOCK_HASH_SHIFT + +__u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode) +{ + return inode->i_atime; +} + +void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash) +{ + inode->i_atime = hash; +} + +__u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode) +{ + return ((__u64)inode->i_ctime << 32) | inode->osd1.linux1.l_i_version; +} + +void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count) +{ + inode->i_ctime = (__u32)(ref_count >> 32); + inode->osd1.linux1.l_i_version = (__u32)ref_count; +} + +static errcode_t check_ext_attr_header(struct ext2_ext_attr_header *header) +{ + if ((header->h_magic != EXT2_EXT_ATTR_MAGIC_v1 && + header->h_magic != EXT2_EXT_ATTR_MAGIC) || + header->h_blocks != 1) + return EXT2_ET_BAD_EA_HEADER; + + return 0; +} + +errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, void *buf, + ext2_ino_t inum) +{ + int csum_failed = 0; + errcode_t retval; + + retval = io_channel_read_blk64(fs->io, block, 1, buf); + if (retval) + return retval; + + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_ext_attr_block_csum_verify(fs, inum, block, buf)) + csum_failed = 1; + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); +#endif + + retval = check_ext_attr_header(buf); + if (retval == 0 && csum_failed) + retval = EXT2_ET_EXT_ATTR_CSUM_INVALID; + + return retval; +} + +errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf) +{ + return ext2fs_read_ext_attr3(fs, block, buf, 0); +} + +errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) +{ + return ext2fs_read_ext_attr2(fs, block, buf); +} + +errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, void *inbuf, + ext2_ino_t inum) +{ + errcode_t retval; + char *write_buf; + +#ifdef WORDS_BIGENDIAN + retval = ext2fs_get_mem(fs->blocksize, &write_buf); + if (retval) + return retval; + ext2fs_swap_ext_attr(write_buf, inbuf, fs->blocksize, 1); +#else + write_buf = (char *) inbuf; +#endif + + retval = ext2fs_ext_attr_block_csum_set(fs, inum, block, + (struct ext2_ext_attr_header *)write_buf); + if (retval) + return retval; + + retval = io_channel_write_blk64(fs->io, block, 1, write_buf); +#ifdef WORDS_BIGENDIAN + ext2fs_free_mem(&write_buf); +#endif + if (!retval) + ext2fs_mark_changed(fs); + return retval; +} + +errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf) +{ + return ext2fs_write_ext_attr3(fs, block, inbuf, 0); +} + +errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) +{ + return ext2fs_write_ext_attr2(fs, block, inbuf); +} + +/* + * This function adjusts the reference count of the EA block. + */ +errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk, + char *block_buf, int adjust, + __u32 *newcount, ext2_ino_t inum) +{ + errcode_t retval; + struct ext2_ext_attr_header *header; + char *buf = 0; + + if ((blk >= ext2fs_blocks_count(fs->super)) || + (blk < fs->super->s_first_data_block)) + return EXT2_ET_BAD_EA_BLOCK_NUM; + + if (!block_buf) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + block_buf = buf; + } + + retval = ext2fs_read_ext_attr3(fs, blk, block_buf, inum); + if (retval) + goto errout; + + header = (struct ext2_ext_attr_header *) block_buf; + header->h_refcount += adjust; + if (newcount) + *newcount = header->h_refcount; + + retval = ext2fs_write_ext_attr3(fs, blk, block_buf, inum); + if (retval) + goto errout; + +errout: + if (buf) + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk, + char *block_buf, int adjust, + __u32 *newcount) +{ + return ext2fs_adjust_ea_refcount3(fs, blk, block_buf, adjust, + newcount, 0); +} + +errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, int adjust, + __u32 *newcount) +{ + return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust, + newcount); +} + +/* Manipulate the contents of extended attribute regions */ +struct ext2_xattr { + int name_index; + char *name; + char *short_name; + void *value; + unsigned int value_len; + ext2_ino_t ea_ino; +}; + +struct ext2_xattr_handle { + errcode_t magic; + ext2_filsys fs; + struct ext2_xattr *attrs; + int capacity; + int count; + int ibody_count; + ext2_ino_t ino; + unsigned int flags; +}; + +static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h, + unsigned int expandby) +{ + struct ext2_xattr *new_attrs; + errcode_t err; + + err = ext2fs_get_arrayzero(h->capacity + expandby, + sizeof(struct ext2_xattr), &new_attrs); + if (err) + return err; + + memcpy(new_attrs, h->attrs, h->capacity * sizeof(struct ext2_xattr)); + ext2fs_free_mem(&h->attrs); + h->capacity += expandby; + h->attrs = new_attrs; + + return 0; +} + +struct ea_name_index { + int index; + const char *name; +}; + +/* Keep these names sorted in order of decreasing specificity. */ +static struct ea_name_index ea_names[] = { + {10, "gnu."}, + {3, "system.posix_acl_default"}, + {2, "system.posix_acl_access"}, + {8, "system.richacl"}, + {6, "security."}, + {4, "trusted."}, + {7, "system."}, + {1, "user."}, + {0, NULL}, +}; + +static const char *find_ea_prefix(int index) +{ + struct ea_name_index *e; + + for (e = ea_names; e->name; e++) + if (e->index == index) + return e->name; + + return NULL; +} + +static int find_ea_index(const char *fullname, const char **name, int *index) +{ + struct ea_name_index *e; + + for (e = ea_names; e->name; e++) { + if (strncmp(fullname, e->name, strlen(e->name)) == 0) { + *name = fullname + strlen(e->name); + *index = e->index; + return 1; + } + } + return 0; +} + +errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode_large *inode) +{ + struct ext2_ext_attr_header *header; + void *block_buf = NULL; + blk64_t blk; + errcode_t err; + struct ext2_inode_large i; + + /* Read inode? */ + if (inode == NULL) { + err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i, + sizeof(struct ext2_inode_large)); + if (err) + return err; + inode = &i; + } + + /* Do we already have an EA block? */ + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); + if (blk == 0) + return 0; + + /* Find block, zero it, write back */ + if ((blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { + err = EXT2_ET_BAD_EA_BLOCK_NUM; + goto out; + } + + err = ext2fs_get_mem(fs->blocksize, &block_buf); + if (err) + goto out; + + err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); + if (err) + goto out2; + + /* We only know how to deal with v2 EA blocks */ + header = (struct ext2_ext_attr_header *) block_buf; + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { + err = EXT2_ET_BAD_EA_HEADER; + goto out2; + } + + header->h_refcount--; + err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); + if (err) + goto out2; + + /* Erase link to block */ + ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0); + if (header->h_refcount == 0) + ext2fs_block_alloc_stats2(fs, blk, -1); + err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1); + if (err) + goto out2; + + /* Write inode? */ + if (inode == &i) { + err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i, + sizeof(struct ext2_inode_large)); + if (err) + goto out2; + } + +out2: + ext2fs_free_mem(&block_buf); +out: + return err; +} + +static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode_large *inode) +{ + struct ext2_ext_attr_header *header; + void *block_buf = NULL; + blk64_t blk, goal; + errcode_t err; + + /* Do we already have an EA block? */ + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); + if (blk != 0) { + if ((blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { + err = EXT2_ET_BAD_EA_BLOCK_NUM; + goto out; + } + + err = ext2fs_get_mem(fs->blocksize, &block_buf); + if (err) + goto out; + + err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); + if (err) + goto out2; + + /* We only know how to deal with v2 EA blocks */ + header = (struct ext2_ext_attr_header *) block_buf; + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { + err = EXT2_ET_BAD_EA_HEADER; + goto out2; + } + + /* Single-user block. We're done here. */ + if (header->h_refcount == 1) + goto out2; + + /* We need to CoW the block. */ + header->h_refcount--; + err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); + if (err) + goto out2; + } else { + /* No block, we must increment i_blocks */ + err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode, + 1); + if (err) + goto out; + } + + /* Allocate a block */ + goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0); + err = ext2fs_alloc_block2(fs, goal, NULL, &blk); + if (err) + goto out2; + ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk); +out2: + if (block_buf) + ext2fs_free_mem(&block_buf); +out: + return err; +} + + +static inline int +posix_acl_xattr_count(size_t size) +{ + if (size < sizeof(posix_acl_xattr_header)) + return -1; + size -= sizeof(posix_acl_xattr_header); + if (size % sizeof(posix_acl_xattr_entry)) + return -1; + return size / sizeof(posix_acl_xattr_entry); +} + +/* + * The lgetxattr function returns data formatted in the POSIX extended + * attribute format. The on-disk format uses a more compact encoding. + * See the ext4_acl_to_disk in fs/ext4/acl.c. + */ +static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size, + void *out_buf, size_t *size_out) +{ + const posix_acl_xattr_header *header = + (const posix_acl_xattr_header*) value; + const posix_acl_xattr_entry *end, *entry = + (const posix_acl_xattr_entry *)(header+1); + ext4_acl_header *ext_acl; + size_t s; + char *e; + + int count; + + if (!value) + return EINVAL; + if (size < sizeof(posix_acl_xattr_header)) + return ENOMEM; + if (header->a_version != ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION)) + return EINVAL; + + count = posix_acl_xattr_count(size); + ext_acl = out_buf; + ext_acl->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION); + + if (count <= 0) + return EINVAL; + + e = (char *) out_buf + sizeof(ext4_acl_header); + s = sizeof(ext4_acl_header); + for (end = entry + count; entry != end;entry++) { + ext4_acl_entry *disk_entry = (ext4_acl_entry*) e; + disk_entry->e_tag = entry->e_tag; + disk_entry->e_perm = entry->e_perm; + + switch(ext2fs_le16_to_cpu(entry->e_tag)) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + e += sizeof(ext4_acl_entry_short); + s += sizeof(ext4_acl_entry_short); + break; + case ACL_USER: + case ACL_GROUP: + disk_entry->e_id = entry->e_id; + e += sizeof(ext4_acl_entry); + s += sizeof(ext4_acl_entry); + break; + default: + return EINVAL; + } + } + *size_out = s; + return 0; +} + +static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size, + void **out_buf, size_t *size_out) +{ + posix_acl_xattr_header *header; + posix_acl_xattr_entry *entry; + const ext4_acl_header *ext_acl = (const ext4_acl_header *) value; + errcode_t err; + const char *cp; + char *out; + + if ((!value) || + (size < sizeof(ext4_acl_header)) || + (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))) + return EINVAL; + + err = ext2fs_get_mem(size * 2, &out); + if (err) + return err; + + header = (posix_acl_xattr_header *) out; + header->a_version = ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION); + entry = (posix_acl_xattr_entry *) (out + sizeof(posix_acl_xattr_header)); + + cp = (const char *) value + sizeof(ext4_acl_header); + size -= sizeof(ext4_acl_header); + + while (size > 0) { + const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp; + + entry->e_tag = disk_entry->e_tag; + entry->e_perm = disk_entry->e_perm; + + switch(ext2fs_le16_to_cpu(entry->e_tag)) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + entry->e_id = 0; + cp += sizeof(ext4_acl_entry_short); + size -= sizeof(ext4_acl_entry_short); + break; + case ACL_USER: + case ACL_GROUP: + entry->e_id = disk_entry->e_id; + cp += sizeof(ext4_acl_entry); + size -= sizeof(ext4_acl_entry); + break; + default: + ext2fs_free_mem(&out); + return EINVAL; + } + entry++; + } + *out_buf = out; + *size_out = ((char *) entry - out); + return 0; +} + +static errcode_t +write_xattrs_to_buffer(ext2_filsys fs, struct ext2_xattr *attrs, int count, + void *entries_start, unsigned int storage_size, + unsigned int value_offset_correction, int write_hash) +{ + struct ext2_xattr *x; + struct ext2_ext_attr_entry *e = entries_start; + char *end = (char *) entries_start + storage_size; + unsigned int value_size; + errcode_t err; + + memset(entries_start, 0, storage_size); + for (x = attrs; x < attrs + count; x++) { + value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) / + EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD; + + /* Fill out e appropriately */ + e->e_name_len = strlen(x->short_name); + e->e_name_index = x->name_index; + + e->e_value_size = x->value_len; + e->e_value_inum = x->ea_ino; + + /* Store name */ + memcpy((char *)e + sizeof(*e), x->short_name, e->e_name_len); + if (x->ea_ino) { + e->e_value_offs = 0; + } else { + end -= value_size; + e->e_value_offs = end - (char *) entries_start + + value_offset_correction; + memcpy(end, x->value, e->e_value_size); + } + + if (write_hash || x->ea_ino) { + err = ext2fs_ext_attr_hash_entry2(fs, e, + x->ea_ino ? 0 : end, + &e->e_hash); + if (err) + return err; + } else + e->e_hash = 0; + + e = EXT2_EXT_ATTR_NEXT(e); + *(__u32 *)e = 0; + } + return 0; +} + +errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle) +{ + ext2_filsys fs = handle->fs; + const unsigned int inode_size = EXT2_INODE_SIZE(fs->super); + struct ext2_inode_large *inode; + char *start, *block_buf = NULL; + struct ext2_ext_attr_header *header; + __u32 ea_inode_magic; + blk64_t blk; + unsigned int storage_size; + unsigned int i; + errcode_t err; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); + i = inode_size; + if (i < sizeof(*inode)) + i = sizeof(*inode); + err = ext2fs_get_memzero(i, &inode); + if (err) + return err; + + err = ext2fs_read_inode_full(fs, handle->ino, EXT2_INODE(inode), + inode_size); + if (err) + goto out; + + /* If extra_isize isn't set, we need to set it now */ + if (inode->i_extra_isize == 0 && + inode_size > EXT2_GOOD_OLD_INODE_SIZE) { + char *p = (char *)inode; + size_t extra = fs->super->s_want_extra_isize; + + if (extra == 0) + extra = sizeof(__u32); + memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra); + inode->i_extra_isize = extra; + } + if (inode->i_extra_isize & 3) { + err = EXT2_ET_INODE_CORRUPTED; + goto out; + } + + /* Does the inode have space for EA? */ + if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || + inode_size <= EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize + + sizeof(__u32)) + goto write_ea_block; + + /* Write the inode EA */ + ea_inode_magic = EXT2_EXT_ATTR_MAGIC; + memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize, &ea_inode_magic, sizeof(__u32)); + storage_size = inode_size - EXT2_GOOD_OLD_INODE_SIZE - + inode->i_extra_isize - sizeof(__u32); + start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + sizeof(__u32); + + err = write_xattrs_to_buffer(fs, handle->attrs, handle->ibody_count, + start, storage_size, 0, 0); + if (err) + goto out; +write_ea_block: + /* Are we done? */ + if (handle->ibody_count == handle->count && + !ext2fs_file_acl_block(fs, EXT2_INODE(inode))) + goto skip_ea_block; + + /* Write the EA block */ + err = ext2fs_get_memzero(fs->blocksize, &block_buf); + if (err) + goto out; + + storage_size = fs->blocksize - sizeof(struct ext2_ext_attr_header); + start = block_buf + sizeof(struct ext2_ext_attr_header); + + err = write_xattrs_to_buffer(fs, handle->attrs + handle->ibody_count, + handle->count - handle->ibody_count, start, + storage_size, start - block_buf, 1); + if (err) + goto out2; + + /* Write a header on the EA block */ + header = (struct ext2_ext_attr_header *) block_buf; + header->h_magic = EXT2_EXT_ATTR_MAGIC; + header->h_refcount = 1; + header->h_blocks = 1; + + /* Get a new block for writing */ + err = prep_ea_block_for_write(fs, handle->ino, inode); + if (err) + goto out2; + + /* Finally, write the new EA block */ + blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode)); + err = ext2fs_write_ext_attr3(fs, blk, block_buf, handle->ino); + if (err) + goto out2; + +skip_ea_block: + blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); + if (!block_buf && blk) { + /* xattrs shrunk, free the block */ + err = ext2fs_free_ext_attr(fs, handle->ino, inode); + if (err) + goto out; + } + + /* Write the inode */ + err = ext2fs_write_inode_full(fs, handle->ino, EXT2_INODE(inode), + inode_size); + if (err) + goto out2; + +out2: + ext2fs_free_mem(&block_buf); +out: + ext2fs_free_mem(&inode); + return err; +} + +static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle, + struct ext2_inode_large *inode, + struct ext2_ext_attr_entry *entries, + unsigned int storage_size, + char *value_start) +{ + struct ext2_xattr *x; + struct ext2_ext_attr_entry *entry, *end; + const char *prefix; + unsigned int remain, prefix_len; + errcode_t err; + unsigned int values_size = storage_size + + ((char *)entries - value_start); + + /* find the end */ + end = entries; + remain = storage_size; + while (remain >= sizeof(struct ext2_ext_attr_entry) && + !EXT2_EXT_IS_LAST_ENTRY(end)) { + + /* header eats this space */ + remain -= sizeof(struct ext2_ext_attr_entry); + + /* is attribute name valid? */ + if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain) + return EXT2_ET_EA_BAD_NAME_LEN; + + /* attribute len eats this space */ + remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len); + end = EXT2_EXT_ATTR_NEXT(end); + } + + entry = entries; + remain = storage_size; + while (remain >= sizeof(struct ext2_ext_attr_entry) && + !EXT2_EXT_IS_LAST_ENTRY(entry)) { + + /* Allocate space for more attrs? */ + if (handle->count == handle->capacity) { + err = ext2fs_xattrs_expand(handle, 4); + if (err) + return err; + } + + x = handle->attrs + handle->count; + + /* header eats this space */ + remain -= sizeof(struct ext2_ext_attr_entry); + + /* attribute len eats this space */ + remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); + + /* Extract name */ + prefix = find_ea_prefix(entry->e_name_index); + prefix_len = (prefix ? strlen(prefix) : 0); + err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1, + &x->name); + if (err) + return err; + if (prefix) + memcpy(x->name, prefix, prefix_len); + if (entry->e_name_len) + memcpy(x->name + prefix_len, + (char *)entry + sizeof(*entry), + entry->e_name_len); + x->short_name = x->name + prefix_len; + x->name_index = entry->e_name_index; + + /* Check & copy value */ + if (!ext2fs_has_feature_ea_inode(handle->fs->super) && + entry->e_value_inum != 0) + return EXT2_ET_BAD_EA_BLOCK_NUM; + + if (entry->e_value_inum == 0) { + if (entry->e_value_size > remain) + return EXT2_ET_EA_BAD_VALUE_SIZE; + + if (entry->e_value_offs + entry->e_value_size > values_size) + return EXT2_ET_EA_BAD_VALUE_OFFSET; + + if (entry->e_value_size > 0 && + value_start + entry->e_value_offs < + (char *)end + sizeof(__u32)) + return EXT2_ET_EA_BAD_VALUE_OFFSET; + + remain -= entry->e_value_size; + + err = ext2fs_get_mem(entry->e_value_size, &x->value); + if (err) + return err; + memcpy(x->value, value_start + entry->e_value_offs, + entry->e_value_size); + } else { + struct ext2_inode *ea_inode; + ext2_file_t ea_file; + + if (entry->e_value_offs != 0) + return EXT2_ET_EA_BAD_VALUE_OFFSET; + + if (entry->e_value_size > (64 * 1024)) + return EXT2_ET_EA_BAD_VALUE_SIZE; + + err = ext2fs_get_mem(entry->e_value_size, &x->value); + if (err) + return err; + + err = ext2fs_file_open(handle->fs, entry->e_value_inum, + 0, &ea_file); + if (err) + return err; + + ea_inode = ext2fs_file_get_inode(ea_file); + if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) || + !(ea_inode->i_flags & EXT4_EA_INODE_FL) || + ea_inode->i_links_count == 0) + err = EXT2_ET_EA_INODE_CORRUPTED; + else if ((__u64) ext2fs_file_get_size(ea_file) != + entry->e_value_size) + err = EXT2_ET_EA_BAD_VALUE_SIZE; + else + err = ext2fs_file_read(ea_file, x->value, + entry->e_value_size, 0); + ext2fs_file_close(ea_file); + if (err) + return err; + } + + x->ea_ino = entry->e_value_inum; + x->value_len = entry->e_value_size; + + /* e_hash may be 0 in older inode's ea */ + if (entry->e_hash != 0) { + __u32 hash, signed_hash; + + void *data = (entry->e_value_inum != 0) ? + 0 : value_start + entry->e_value_offs; + + err = ext2fs_ext_attr_hash_entry3(handle->fs, entry, + data, &hash, + &signed_hash); + if (err) + return err; + if ((entry->e_hash != hash) && + (entry->e_hash != signed_hash)) { + struct ext2_inode child; + + /* Check whether this is an old Lustre-style + * ea_inode reference. + */ + err = ext2fs_read_inode(handle->fs, + entry->e_value_inum, + &child); + if (err) + return err; + if (child.i_mtime != handle->ino || + child.i_generation != inode->i_generation) + return EXT2_ET_BAD_EA_HASH; + } + } + + handle->count++; + entry = EXT2_EXT_ATTR_NEXT(entry); + } + + return 0; +} + +static void xattrs_free_keys(struct ext2_xattr_handle *h) +{ + struct ext2_xattr *a = h->attrs; + int i; + + for (i = 0; i < h->capacity; i++) { + if (a[i].name) + ext2fs_free_mem(&a[i].name); + if (a[i].value) + ext2fs_free_mem(&a[i].value); + } + h->count = 0; + h->ibody_count = 0; +} + +errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle) +{ + struct ext2_inode_large *inode; + struct ext2_ext_attr_header *header; + __u32 ea_inode_magic; + unsigned int storage_size; + char *start, *block_buf = NULL; + blk64_t blk; + size_t i; + errcode_t err; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); + i = EXT2_INODE_SIZE(handle->fs->super); + if (i < sizeof(*inode)) + i = sizeof(*inode); + err = ext2fs_get_memzero(i, &inode); + if (err) + return err; + + err = ext2fs_read_inode_full(handle->fs, handle->ino, + (struct ext2_inode *)inode, + EXT2_INODE_SIZE(handle->fs->super)); + if (err) + goto out; + + xattrs_free_keys(handle); + + /* Does the inode have space for EA? */ + if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || + EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + + sizeof(__u32)) + goto read_ea_block; + if (inode->i_extra_isize & 3) { + err = EXT2_ET_INODE_CORRUPTED; + goto out; + } + + /* Look for EA in the inode */ + memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize, sizeof(__u32)); + if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { + storage_size = EXT2_INODE_SIZE(handle->fs->super) - + EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize - + sizeof(__u32); + start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + sizeof(__u32); + + err = read_xattrs_from_buffer(handle, inode, + (struct ext2_ext_attr_entry *) start, + storage_size, start); + if (err) + goto out; + + handle->ibody_count = handle->count; + } + +read_ea_block: + /* Look for EA in a separate EA block */ + blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode); + if (blk != 0) { + if ((blk < handle->fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(handle->fs->super))) { + err = EXT2_ET_BAD_EA_BLOCK_NUM; + goto out; + } + + err = ext2fs_get_mem(handle->fs->blocksize, &block_buf); + if (err) + goto out; + + err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf, + handle->ino); + if (err) + goto out3; + + /* We only know how to deal with v2 EA blocks */ + header = (struct ext2_ext_attr_header *) block_buf; + if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { + err = EXT2_ET_BAD_EA_HEADER; + goto out3; + } + + /* Read EAs */ + storage_size = handle->fs->blocksize - + sizeof(struct ext2_ext_attr_header); + start = block_buf + sizeof(struct ext2_ext_attr_header); + err = read_xattrs_from_buffer(handle, inode, + (struct ext2_ext_attr_entry *) start, + storage_size, block_buf); + if (err) + goto out3; + + ext2fs_free_mem(&block_buf); + } + + ext2fs_free_mem(&block_buf); + ext2fs_free_mem(&inode); + return 0; + +out3: + ext2fs_free_mem(&block_buf); +out: + ext2fs_free_mem(&inode); + return err; +} + +errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h, + int (*func)(char *name, char *value, + size_t value_len, void *data), + void *data) +{ + struct ext2_xattr *x; + int dirty = 0; + int ret; + + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); + for (x = h->attrs; x < h->attrs + h->count; x++) { + ret = func(x->name, x->value, x->value_len, data); + if (ret & XATTR_CHANGED) + dirty = 1; + if (ret & XATTR_ABORT) + break; + } + + if (dirty) + return ext2fs_xattrs_write(h); + return 0; +} + +errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key, + void **value, size_t *value_len) +{ + struct ext2_xattr *x; + char *val; + errcode_t err; + + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); + for (x = h->attrs; x < h->attrs + h->count; x++) { + if (strcmp(x->name, key)) + continue; + + if (!(h->flags & XATTR_HANDLE_FLAG_RAW) && + ((strcmp(key, "system.posix_acl_default") == 0) || + (strcmp(key, "system.posix_acl_access") == 0))) { + err = convert_disk_buffer_to_posix_acl(x->value, x->value_len, + value, value_len); + return err; + } else { + err = ext2fs_get_mem(x->value_len, &val); + if (err) + return err; + memcpy(val, x->value, x->value_len); + *value = val; + *value_len = x->value_len; + return 0; + } + } + + return EXT2_ET_EA_KEY_NOT_FOUND; +} + +errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino, + size_t *size) +{ + struct ext2_ext_attr_entry *entry; + struct ext2_inode_large *inode; + __u32 ea_inode_magic; + unsigned int minoff; + char *start; + size_t i; + errcode_t err; + + i = EXT2_INODE_SIZE(fs->super); + if (i < sizeof(*inode)) + i = sizeof(*inode); + err = ext2fs_get_memzero(i, &inode); + if (err) + return err; + + err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode, + EXT2_INODE_SIZE(fs->super)); + if (err) + goto out; + + /* Does the inode have size for EA? */ + if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + + sizeof(__u32)) { + err = EXT2_ET_INLINE_DATA_NO_SPACE; + goto out; + } + + minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32); + memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize, sizeof(__u32)); + if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { + /* has xattrs. calculate the size */ + start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + sizeof(__u32); + entry = (struct ext2_ext_attr_entry *) start; + while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { + if (!entry->e_value_inum && entry->e_value_size) { + unsigned int offs = entry->e_value_offs; + if (offs < minoff) + minoff = offs; + } + entry = EXT2_EXT_ATTR_NEXT(entry); + } + *size = minoff - ((char *)entry - (char *)start) - sizeof(__u32); + } else { + /* no xattr. return a maximum size */ + *size = EXT2_EXT_ATTR_SIZE(minoff - + EXT2_EXT_ATTR_LEN(strlen("data")) - + EXT2_EXT_ATTR_ROUND - sizeof(__u32)); + } + +out: + ext2fs_free_mem(&inode); + return err; +} + +static errcode_t xattr_create_ea_inode(ext2_filsys fs, const void *value, + size_t value_len, ext2_ino_t *ea_ino) +{ + struct ext2_inode inode; + ext2_ino_t ino; + ext2_file_t file; + __u32 hash; + errcode_t ret; + + ret = ext2fs_new_inode(fs, 0, 0, 0, &ino); + if (ret) + return ret; + + memset(&inode, 0, sizeof(inode)); + inode.i_flags |= EXT4_EA_INODE_FL; + if (ext2fs_has_feature_extents(fs->super)) + inode.i_flags |= EXT4_EXTENTS_FL; + inode.i_size = 0; + inode.i_mode = LINUX_S_IFREG | 0600; + inode.i_links_count = 1; + ret = ext2fs_write_new_inode(fs, ino, &inode); + if (ret) + return ret; + /* + * ref_count and hash utilize inode's i_*time fields. + * ext2fs_write_new_inode() call above initializes these fields with + * current time. That's why ref count and hash updates are done + * separately below. + */ + ext2fs_set_ea_inode_ref(&inode, 1); + hash = ext2fs_crc32c_le(fs->csum_seed, value, value_len); + ext2fs_set_ea_inode_hash(&inode, hash); + + ret = ext2fs_write_inode(fs, ino, &inode); + if (ret) + return ret; + + ret = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file); + if (ret) + return ret; + ret = ext2fs_file_write(file, value, value_len, NULL); + ext2fs_file_close(file); + if (ret) + return ret; + + ext2fs_inode_alloc_stats2(fs, ino, 1 /* inuse */, 0 /* isdir */); + + *ea_ino = ino; + return 0; +} + +static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode_large inode; + __u64 ref_count; + errcode_t ret; + + ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, + sizeof(inode)); + if (ret) + goto out; + + ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(&inode)); + ref_count--; + ext2fs_set_ea_inode_ref(EXT2_INODE(&inode), ref_count); + + if (ref_count) + goto write_out; + + inode.i_links_count = 0; + inode.i_dtime = fs->now ? fs->now : time(0); + + ret = ext2fs_free_ext_attr(fs, ino, &inode); + if (ret) + goto write_out; + + if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) { + ret = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL, + 0, ~0ULL); + if (ret) + goto out; + } + + ext2fs_inode_alloc_stats2(fs, ino, -1 /* inuse */, 0 /* is_dir */); + +write_out: + ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, + sizeof(inode)); +out: + return ret; +} + +static errcode_t xattr_update_entry(ext2_filsys fs, struct ext2_xattr *x, + const char *name, const char *short_name, + int index, const void *value, + size_t value_len, int in_inode) +{ + ext2_ino_t ea_ino = 0; + void *new_value = NULL; + char *new_name = NULL; + int name_len; + errcode_t ret; + + if (!x->name) { + name_len = strlen(name); + ret = ext2fs_get_mem(name_len + 1, &new_name); + if (ret) + goto fail; + memcpy(new_name, name, name_len + 1); + } + + ret = ext2fs_get_mem(value_len, &new_value); + if (ret) + goto fail; + memcpy(new_value, value, value_len); + + if (in_inode) { + ret = xattr_create_ea_inode(fs, value, value_len, &ea_ino); + if (ret) + goto fail; + } + + if (x->ea_ino) { + ret = xattr_inode_dec_ref(fs, x->ea_ino); + if (ret) + goto fail; + } + + if (!x->name) { + x->name = new_name; + x->short_name = new_name + (short_name - name); + } + x->name_index = index; + + if (x->value) + ext2fs_free_mem(&x->value); + x->value = new_value; + x->value_len = value_len; + x->ea_ino = ea_ino; + return 0; +fail: + if (new_name) + ext2fs_free_mem(&new_name); + if (new_value) + ext2fs_free_mem(&new_value); + if (ea_ino) + xattr_inode_dec_ref(fs, ea_ino); + return ret; +} + +static int xattr_find_position(struct ext2_xattr *attrs, int count, + const char *shortname, int name_idx) +{ + struct ext2_xattr *x; + int i; + int shortname_len, x_shortname_len; + + shortname_len = strlen(shortname); + + for (i = 0, x = attrs; i < count; i++, x++) { + if (name_idx < x->name_index) + break; + if (name_idx > x->name_index) + continue; + + x_shortname_len = strlen(x->short_name); + if (shortname_len < x_shortname_len) + break; + if (shortname_len > x_shortname_len) + continue; + + if (memcmp(shortname, x->short_name, shortname_len) <= 0) + break; + } + return i; +} + +static errcode_t xattr_array_update(struct ext2_xattr_handle *h, + const char *name, + const void *value, size_t value_len, + int ibody_free, int block_free, + int old_idx, int in_inode) +{ + struct ext2_xattr tmp; + int add_to_ibody; + int needed; + int name_len, name_idx = 0; + const char *shortname = name; + int new_idx; + int ret; + + find_ea_index(name, &shortname, &name_idx); + name_len = strlen(shortname); + + needed = EXT2_EXT_ATTR_LEN(name_len); + if (!in_inode) + needed += EXT2_EXT_ATTR_SIZE(value_len); + + if (old_idx >= 0 && old_idx < h->ibody_count) { + ibody_free += EXT2_EXT_ATTR_LEN(name_len); + if (!h->attrs[old_idx].ea_ino) + ibody_free += EXT2_EXT_ATTR_SIZE( + h->attrs[old_idx].value_len); + } + + if (needed <= ibody_free) { + if (old_idx < 0) { + new_idx = h->ibody_count; + add_to_ibody = 1; + goto add_new; + } + + /* Update the existing entry. */ + ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, + shortname, name_idx, value, + value_len, in_inode); + if (ret) + return ret; + if (h->ibody_count <= old_idx) { + /* Move entry from block to the end of ibody. */ + tmp = h->attrs[old_idx]; + memmove(h->attrs + h->ibody_count + 1, + h->attrs + h->ibody_count, + (old_idx - h->ibody_count) * sizeof(*h->attrs)); + h->attrs[h->ibody_count] = tmp; + h->ibody_count++; + } + return 0; + } + + if (h->ibody_count <= old_idx) { + block_free += EXT2_EXT_ATTR_LEN(name_len); + if (!h->attrs[old_idx].ea_ino) + block_free += + EXT2_EXT_ATTR_SIZE(h->attrs[old_idx].value_len); + } + + if (needed > block_free) + return EXT2_ET_EA_NO_SPACE; + + if (old_idx >= 0) { + /* Update the existing entry. */ + ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, + shortname, name_idx, value, + value_len, in_inode); + if (ret) + return ret; + if (old_idx < h->ibody_count) { + /* + * Move entry from ibody to the block. Note that + * entries in the block are sorted. + */ + new_idx = xattr_find_position(h->attrs + h->ibody_count, + h->count - h->ibody_count, + shortname, name_idx); + new_idx += h->ibody_count - 1; + tmp = h->attrs[old_idx]; + memmove(h->attrs + old_idx, h->attrs + old_idx + 1, + (new_idx - old_idx) * sizeof(*h->attrs)); + h->attrs[new_idx] = tmp; + h->ibody_count--; + } + return 0; + } + + new_idx = xattr_find_position(h->attrs + h->ibody_count, + h->count - h->ibody_count, + shortname, name_idx); + new_idx += h->ibody_count; + add_to_ibody = 0; + +add_new: + if (h->count == h->capacity) { + ret = ext2fs_xattrs_expand(h, 4); + if (ret) + return ret; + } + + ret = xattr_update_entry(h->fs, &h->attrs[h->count], name, shortname, + name_idx, value, value_len, in_inode); + if (ret) + return ret; + + tmp = h->attrs[h->count]; + memmove(h->attrs + new_idx + 1, h->attrs + new_idx, + (h->count - new_idx)*sizeof(*h->attrs)); + h->attrs[new_idx] = tmp; + if (add_to_ibody) + h->ibody_count++; + h->count++; + return 0; +} + +static int space_used(struct ext2_xattr *attrs, int count) +{ + int total = 0; + struct ext2_xattr *x; + int i, len; + + for (i = 0, x = attrs; i < count; i++, x++) { + len = strlen(x->short_name); + total += EXT2_EXT_ATTR_LEN(len); + if (!x->ea_ino) + total += EXT2_EXT_ATTR_SIZE(x->value_len); + } + return total; +} + +/* + * The minimum size of EA value when you start storing it in an external inode + * size of block - size of header - size of 1 entry - 4 null bytes + */ +#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) \ + ((b) - EXT2_EXT_ATTR_LEN(3) - sizeof(struct ext2_ext_attr_header) - 4) + +errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *h, + const char *name, + const void *value, + size_t value_len) +{ + ext2_filsys fs = h->fs; + const int inode_size = EXT2_INODE_SIZE(fs->super); + struct ext2_inode_large *inode = NULL; + struct ext2_xattr *x; + char *new_value; + int ibody_free, block_free; + int in_inode = 0; + int old_idx = -1; + int extra_isize; + errcode_t ret; + + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); + + ret = ext2fs_get_mem(value_len, &new_value); + if (ret) + return ret; + if (!(h->flags & XATTR_HANDLE_FLAG_RAW) && + ((strcmp(name, "system.posix_acl_default") == 0) || + (strcmp(name, "system.posix_acl_access") == 0))) { + ret = convert_posix_acl_to_disk_buffer(value, value_len, + new_value, &value_len); + if (ret) + goto out; + } else if (value_len) + memcpy(new_value, value, value_len); + + /* Imitate kernel behavior by skipping update if value is the same. */ + for (x = h->attrs; x < h->attrs + h->count; x++) { + if (!strcmp(x->name, name)) { + if (!x->ea_ino && x->value_len == value_len && + (!value_len || + !memcmp(x->value, new_value, value_len))) { + ret = 0; + goto out; + } + old_idx = x - h->attrs; + break; + } + } + + ret = ext2fs_get_memzero(inode_size, &inode); + if (ret) + goto out; + ret = ext2fs_read_inode_full(fs, h->ino, + (struct ext2_inode *)inode, + inode_size); + if (ret) + goto out; + if (inode_size > EXT2_GOOD_OLD_INODE_SIZE) { + extra_isize = inode->i_extra_isize; + if (extra_isize == 0) { + extra_isize = fs->super->s_want_extra_isize; + if (extra_isize == 0) + extra_isize = sizeof(__u32); + } + ibody_free = inode_size - EXT2_GOOD_OLD_INODE_SIZE; + ibody_free -= extra_isize; + /* Extended attribute magic and final null entry. */ + ibody_free -= sizeof(__u32) * 2; + ibody_free -= space_used(h->attrs, h->ibody_count); + } else + ibody_free = 0; + + /* Inline data can only go to ibody. */ + if (strcmp(name, "system.data") == 0) { + if (h->ibody_count <= old_idx) { + ret = EXT2_ET_FILESYSTEM_CORRUPTED; + goto out; + } + ret = xattr_array_update(h, name, new_value, value_len, + ibody_free, + 0 /* block_free */, old_idx, + 0 /* in_inode */); + if (ret) + goto out; + goto write_out; + } + + block_free = fs->blocksize; + block_free -= sizeof(struct ext2_ext_attr_header); + /* Final null entry. */ + block_free -= sizeof(__u32); + block_free -= space_used(h->attrs + h->ibody_count, + h->count - h->ibody_count); + + if (ext2fs_has_feature_ea_inode(fs->super) && + value_len > EXT4_XATTR_MIN_LARGE_EA_SIZE(fs->blocksize)) + in_inode = 1; + + ret = xattr_array_update(h, name, new_value, value_len, ibody_free, + block_free, old_idx, in_inode); + if (ret == EXT2_ET_EA_NO_SPACE && !in_inode && + ext2fs_has_feature_ea_inode(fs->super)) + ret = xattr_array_update(h, name, new_value, value_len, + ibody_free, block_free, old_idx, 1 /* in_inode */); + if (ret) + goto out; + +write_out: + ret = ext2fs_xattrs_write(h); +out: + if (inode) + ext2fs_free_mem(&inode); + ext2fs_free_mem(&new_value); + return ret; +} + +errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle, + const char *key) +{ + struct ext2_xattr *x; + struct ext2_xattr *end = handle->attrs + handle->count; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); + for (x = handle->attrs; x < end; x++) { + if (strcmp(x->name, key) == 0) { + ext2fs_free_mem(&x->name); + ext2fs_free_mem(&x->value); + if (x->ea_ino) + xattr_inode_dec_ref(handle->fs, x->ea_ino); + memmove(x, x + 1, (end - x - 1)*sizeof(*x)); + memset(end - 1, 0, sizeof(*end)); + if (x < handle->attrs + handle->ibody_count) + handle->ibody_count--; + handle->count--; + return ext2fs_xattrs_write(handle); + } + } + + /* no key found, success! */ + return 0; +} + +errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino, + struct ext2_xattr_handle **handle) +{ + struct ext2_xattr_handle *h; + errcode_t err; + + if (!ext2fs_has_feature_xattr(fs->super) && + !ext2fs_has_feature_inline_data(fs->super)) + return EXT2_ET_MISSING_EA_FEATURE; + + err = ext2fs_get_memzero(sizeof(*h), &h); + if (err) + return err; + + h->magic = EXT2_ET_MAGIC_EA_HANDLE; + h->capacity = 4; + err = ext2fs_get_arrayzero(h->capacity, sizeof(struct ext2_xattr), + &h->attrs); + if (err) { + ext2fs_free_mem(&h); + return err; + } + h->count = 0; + h->ino = ino; + h->fs = fs; + *handle = h; + return 0; +} + +errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle) +{ + struct ext2_xattr_handle *h = *handle; + + EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); + xattrs_free_keys(h); + ext2fs_free_mem(&h->attrs); + ext2fs_free_mem(handle); + return 0; +} + +errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count) +{ + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); + *count = handle->count; + return 0; +} + +errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle, + unsigned int *new_flags, unsigned int *old_flags) +{ + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); + if (old_flags) + *old_flags = handle->flags; + if (new_flags) + handle->flags = *new_flags; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/ext_attr.o b/jni/e2fsprogs/lib/ext2fs/ext_attr.o new file mode 100755 index 0000000000000000000000000000000000000000..ec7a43eb2f45d1ab02817d280d819f67aeee4540 GIT binary patch literal 31888 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/extent.c b/jni/e2fsprogs/lib/ext2fs/extent.c new file mode 100755 index 0000000..82e75cc --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/extent.c @@ -0,0 +1,1877 @@ +/* + * extent.c --- routines to implement extents support + * + * Copyright (C) 2007 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "e2image.h" + +#undef DEBUG + +/* + * Definitions to be dropped in lib/ext2fs/ext2fs.h + */ + +/* + * Private definitions + */ + +struct extent_path { + char *buf; + int entries; + int max_entries; + int left; + int visit_num; + int flags; + blk64_t end_blk; + blk64_t blk; + void *curr; +}; + + +struct ext2_extent_handle { + errcode_t magic; + ext2_filsys fs; + ext2_ino_t ino; + struct ext2_inode *inode; + struct ext2_inode inodebuf; + int type; + int level; + int max_depth; + int max_paths; + struct extent_path *path; +}; + +struct ext2_extent_path { + errcode_t magic; + int leaf_height; + blk64_t lblk; +}; + +/* + * Useful Debugging stuff + */ + +#ifdef DEBUG +static void dbg_show_header(struct ext3_extent_header *eh) +{ + printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n", + ext2fs_le16_to_cpu(eh->eh_magic), + ext2fs_le16_to_cpu(eh->eh_entries), + ext2fs_le16_to_cpu(eh->eh_max), + ext2fs_le16_to_cpu(eh->eh_depth), + ext2fs_le32_to_cpu(eh->eh_generation)); +} + +static void dbg_show_index(struct ext3_extent_idx *ix) +{ + printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n", + ext2fs_le32_to_cpu(ix->ei_block), + ext2fs_le32_to_cpu(ix->ei_leaf), + ext2fs_le16_to_cpu(ix->ei_leaf_hi), + ext2fs_le16_to_cpu(ix->ei_unused)); +} + +static void dbg_show_extent(struct ext3_extent *ex) +{ + printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n", + ext2fs_le32_to_cpu(ex->ee_block), + ext2fs_le32_to_cpu(ex->ee_block) + + ext2fs_le16_to_cpu(ex->ee_len) - 1, + ext2fs_le16_to_cpu(ex->ee_len), + ext2fs_le32_to_cpu(ex->ee_start), + ext2fs_le16_to_cpu(ex->ee_start_hi)); +} + +static void dbg_print_extent(char *desc, struct ext2fs_extent *extent) +{ + if (desc) + printf("%s: ", desc); + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ", + extent->e_lblk, extent->e_lblk + extent->e_len - 1, + extent->e_len, extent->e_pblk); + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF) + fputs("LEAF ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fputs("UNINIT ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + fputs("2ND_VISIT ", stdout); + if (!extent->e_flags) + fputs("(none)", stdout); + fputc('\n', stdout); + +} + +static void dump_path(const char *tag, struct ext2_extent_handle *handle, + struct extent_path *path) +{ + struct extent_path *ppp = path; + printf("%s: level=%d\n", tag, handle->level); + + do { + printf("%s: path=%ld buf=%p entries=%d max_entries=%d left=%d " + "visit_num=%d flags=0x%x end_blk=%llu curr=%p(%ld)\n", + tag, (ppp - handle->path), ppp->buf, ppp->entries, + ppp->max_entries, ppp->left, ppp->visit_num, ppp->flags, + ppp->end_blk, ppp->curr, ppp->curr - (void *)ppp->buf); + printf(" "); + dbg_show_header((struct ext3_extent_header *)ppp->buf); + if (ppp->curr) { + printf(" "); + dbg_show_index(ppp->curr); + printf(" "); + dbg_show_extent(ppp->curr); + } + ppp--; + } while (ppp >= handle->path); + fflush(stdout); + + return; +} + +#else +#define dbg_show_header(eh) do { } while (0) +#define dbg_show_index(ix) do { } while (0) +#define dbg_show_extent(ex) do { } while (0) +#define dbg_print_extent(desc, ex) do { } while (0) +#define dump_path(tag, handle, path) do { } while (0) +#endif + +/* + * Verify the extent header as being sane + */ +errcode_t ext2fs_extent_header_verify(void *ptr, int size) +{ + int eh_max, entry_size; + struct ext3_extent_header *eh = ptr; + + dbg_show_header(eh); + if (ext2fs_le16_to_cpu(eh->eh_magic) != EXT3_EXT_MAGIC) + return EXT2_ET_EXTENT_HEADER_BAD; + if (ext2fs_le16_to_cpu(eh->eh_entries) > ext2fs_le16_to_cpu(eh->eh_max)) + return EXT2_ET_EXTENT_HEADER_BAD; + if (eh->eh_depth == 0) + entry_size = sizeof(struct ext3_extent); + else + entry_size = sizeof(struct ext3_extent_idx); + + eh_max = (size - sizeof(*eh)) / entry_size; + /* Allow two extent-sized items at the end of the block, for + * ext4_extent_tail with checksum in the future. */ + if ((ext2fs_le16_to_cpu(eh->eh_max) > eh_max) || + (ext2fs_le16_to_cpu(eh->eh_max) < (eh_max - 2))) + return EXT2_ET_EXTENT_HEADER_BAD; + + return 0; +} + + +/* + * Begin functions to handle an inode's extent information + */ +void ext2fs_extent_free(ext2_extent_handle_t handle) +{ + int i; + + if (!handle) + return; + + if (handle->path) { + for (i = 1; i < handle->max_paths; i++) { + if (handle->path[i].buf) + ext2fs_free_mem(&handle->path[i].buf); + } + ext2fs_free_mem(&handle->path); + } + ext2fs_free_mem(&handle); +} + +errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino, + ext2_extent_handle_t *ret_handle) +{ + return ext2fs_extent_open2(fs, ino, NULL, ret_handle); +} + +errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t *ret_handle) +{ + struct ext2_extent_handle *handle; + errcode_t retval; + int i; + struct ext3_extent_header *eh; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!inode) + if ((ino == 0) || (ino > fs->super->s_inodes_count)) + return EXT2_ET_BAD_INODE_NUM; + + retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle); + if (retval) + return retval; + memset(handle, 0, sizeof(struct ext2_extent_handle)); + + handle->ino = ino; + handle->fs = fs; + + if (inode) { + handle->inode = inode; + } else { + handle->inode = &handle->inodebuf; + retval = ext2fs_read_inode(fs, ino, handle->inode); + if (retval) + goto errout; + } + + eh = (struct ext3_extent_header *) &handle->inode->i_block[0]; + + for (i=0; i < EXT2_N_BLOCKS; i++) + if (handle->inode->i_block[i]) + break; + if (i >= EXT2_N_BLOCKS) { + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); + eh->eh_depth = 0; + eh->eh_entries = 0; + i = (sizeof(handle->inode->i_block) - sizeof(*eh)) / + sizeof(struct ext3_extent); + eh->eh_max = ext2fs_cpu_to_le16(i); + handle->inode->i_flags |= EXT4_EXTENTS_FL; + } + + if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) { + retval = EXT2_ET_INODE_NOT_EXTENT; + goto errout; + } + + retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block)); + if (retval) + goto errout; + + handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth); + handle->type = ext2fs_le16_to_cpu(eh->eh_magic); + + handle->max_paths = handle->max_depth + 1; + retval = ext2fs_get_memzero(handle->max_paths * + sizeof(struct extent_path), + &handle->path); + handle->path[0].buf = (char *) handle->inode->i_block; + + handle->path[0].left = handle->path[0].entries = + ext2fs_le16_to_cpu(eh->eh_entries); + handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max); + handle->path[0].curr = 0; + handle->path[0].end_blk = + (EXT2_I_SIZE(handle->inode) + fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(fs->super); + handle->path[0].blk = 0; + handle->path[0].visit_num = 1; + handle->level = 0; + handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE; + + *ret_handle = handle; + return 0; + +errout: + ext2fs_extent_free(handle); + return retval; +} + +/* + * This function is responsible for (optionally) moving through the + * extent tree and then returning the current extent + */ +errcode_t ext2fs_extent_get(ext2_extent_handle_t handle, + int flags, struct ext2fs_extent *extent) +{ + struct extent_path *path, *newpath, *tp; + struct ext3_extent_header *eh; + struct ext3_extent_idx *ix = 0; + struct ext3_extent *ex; + errcode_t retval; + blk64_t blk; + blk64_t end_blk; + int orig_op, op, l; + int failed_csum = 0; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + + orig_op = op = flags & EXT2_EXTENT_MOVE_MASK; + +retry: + path = handle->path + handle->level; + if ((orig_op == EXT2_EXTENT_NEXT) || + (orig_op == EXT2_EXTENT_NEXT_LEAF)) { + if (handle->level < handle->max_depth) { + /* interior node */ + if (path->visit_num == 0) { + path->visit_num++; + op = EXT2_EXTENT_DOWN; + } else if (path->left > 0) + op = EXT2_EXTENT_NEXT_SIB; + else if (handle->level > 0) + op = EXT2_EXTENT_UP; + else + return EXT2_ET_EXTENT_NO_NEXT; + } else { + /* leaf node */ + if (path->left > 0) + op = EXT2_EXTENT_NEXT_SIB; + else if (handle->level > 0) + op = EXT2_EXTENT_UP; + else + return EXT2_ET_EXTENT_NO_NEXT; + } + if (op != EXT2_EXTENT_NEXT_SIB) { +#ifdef DEBUG_GET_EXTENT + printf("<<<< OP = %s\n", + (op == EXT2_EXTENT_DOWN) ? "down" : + ((op == EXT2_EXTENT_UP) ? "up" : "unknown")); +#endif + } + } + + if ((orig_op == EXT2_EXTENT_PREV) || + (orig_op == EXT2_EXTENT_PREV_LEAF)) { + if (handle->level < handle->max_depth) { + /* interior node */ + if (path->visit_num > 0 ) { + /* path->visit_num = 0; */ + op = EXT2_EXTENT_DOWN_AND_LAST; + } else if (path->left < path->entries-1) + op = EXT2_EXTENT_PREV_SIB; + else if (handle->level > 0) + op = EXT2_EXTENT_UP; + else + return EXT2_ET_EXTENT_NO_PREV; + } else { + /* leaf node */ + if (path->left < path->entries-1) + op = EXT2_EXTENT_PREV_SIB; + else if (handle->level > 0) + op = EXT2_EXTENT_UP; + else + return EXT2_ET_EXTENT_NO_PREV; + } + if (op != EXT2_EXTENT_PREV_SIB) { +#ifdef DEBUG_GET_EXTENT + printf("<<<< OP = %s\n", + (op == EXT2_EXTENT_DOWN_AND_LAST) ? "down/last" : + ((op == EXT2_EXTENT_UP) ? "up" : "unknown")); +#endif + } + } + + if (orig_op == EXT2_EXTENT_LAST_LEAF) { + if ((handle->level < handle->max_depth) && + (path->left == 0)) + op = EXT2_EXTENT_DOWN; + else + op = EXT2_EXTENT_LAST_SIB; +#ifdef DEBUG_GET_EXTENT + printf("<<<< OP = %s\n", + (op == EXT2_EXTENT_DOWN) ? "down" : "last_sib"); +#endif + } + + switch (op) { + case EXT2_EXTENT_CURRENT: + ix = path->curr; + break; + case EXT2_EXTENT_ROOT: + handle->level = 0; + path = handle->path + handle->level; + /* fallthrough */ + case EXT2_EXTENT_FIRST_SIB: + path->left = path->entries; + path->curr = 0; + /* fallthrough */ + case EXT2_EXTENT_NEXT_SIB: + if (path->left <= 0) + return EXT2_ET_EXTENT_NO_NEXT; + if (path->curr) { + ix = path->curr; + ix++; + } else { + eh = (struct ext3_extent_header *) path->buf; + ix = EXT_FIRST_INDEX(eh); + } + path->left--; + path->curr = ix; + path->visit_num = 0; + break; + case EXT2_EXTENT_PREV_SIB: + if (!path->curr || + path->left+1 >= path->entries) + return EXT2_ET_EXTENT_NO_PREV; + ix = path->curr; + ix--; + path->curr = ix; + path->left++; + if (handle->level < handle->max_depth) + path->visit_num = 1; + break; + case EXT2_EXTENT_LAST_SIB: + eh = (struct ext3_extent_header *) path->buf; + path->curr = EXT_LAST_EXTENT(eh); + ix = path->curr; + path->left = 0; + path->visit_num = 0; + break; + case EXT2_EXTENT_UP: + if (handle->level <= 0) + return EXT2_ET_EXTENT_NO_UP; + handle->level--; + path--; + ix = path->curr; + if ((orig_op == EXT2_EXTENT_PREV) || + (orig_op == EXT2_EXTENT_PREV_LEAF)) + path->visit_num = 0; + break; + case EXT2_EXTENT_DOWN: + case EXT2_EXTENT_DOWN_AND_LAST: + if (!path->curr ||(handle->level >= handle->max_depth)) + return EXT2_ET_EXTENT_NO_DOWN; + + ix = path->curr; + newpath = path + 1; + if (!newpath->buf) { + retval = ext2fs_get_mem(handle->fs->blocksize, + &newpath->buf); + if (retval) + return retval; + } + blk = ext2fs_le32_to_cpu(ix->ei_leaf) + + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); + for (l = handle->level, tp = path; l > 0; l--, tp--) { + if (blk == tp->blk) + return EXT2_ET_EXTENT_CYCLE; + } + newpath->blk = blk; + if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) && + (handle->fs->io != handle->fs->image_io)) + memset(newpath->buf, 0, handle->fs->blocksize); + else { + retval = io_channel_read_blk64(handle->fs->io, + blk, 1, newpath->buf); + if (retval) + return retval; + } + handle->level++; + + eh = (struct ext3_extent_header *) newpath->buf; + + retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize); + if (retval) { + handle->level--; + return retval; + } + + if (!(handle->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_extent_block_csum_verify(handle->fs, handle->ino, + eh)) + failed_csum = 1; + + newpath->left = newpath->entries = + ext2fs_le16_to_cpu(eh->eh_entries); + newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max); + + /* Make sure there is at least one extent present */ + if (newpath->left <= 0) + return EXT2_ET_EXTENT_NO_DOWN; + + if (path->left > 0) { + ix++; + newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block); + } else + newpath->end_blk = path->end_blk; + + path = newpath; + if (op == EXT2_EXTENT_DOWN) { + ix = EXT_FIRST_INDEX((struct ext3_extent_header *) eh); + path->curr = ix; + path->left = path->entries - 1; + path->visit_num = 0; + } else { + ix = EXT_LAST_INDEX((struct ext3_extent_header *) eh); + path->curr = ix; + path->left = 0; + if (handle->level < handle->max_depth) + path->visit_num = 1; + } +#ifdef DEBUG_GET_EXTENT + printf("Down to level %d/%d, end_blk=%llu\n", + handle->level, handle->max_depth, + path->end_blk); +#endif + break; + default: + return EXT2_ET_OP_NOT_SUPPORTED; + } + + if (!ix) + return EXT2_ET_NO_CURRENT_NODE; + + extent->e_flags = 0; +#ifdef DEBUG_GET_EXTENT + printf("(Left %d)\n", path->left); +#endif + + if (handle->level == handle->max_depth) { + ex = (struct ext3_extent *) ix; + + extent->e_pblk = ext2fs_le32_to_cpu(ex->ee_start) + + ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32); + extent->e_lblk = ext2fs_le32_to_cpu(ex->ee_block); + extent->e_len = ext2fs_le16_to_cpu(ex->ee_len); + extent->e_flags |= EXT2_EXTENT_FLAGS_LEAF; + if (extent->e_len > EXT_INIT_MAX_LEN) { + extent->e_len -= EXT_INIT_MAX_LEN; + extent->e_flags |= EXT2_EXTENT_FLAGS_UNINIT; + } + } else { + extent->e_pblk = ext2fs_le32_to_cpu(ix->ei_leaf) + + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); + extent->e_lblk = ext2fs_le32_to_cpu(ix->ei_block); + if (path->left > 0) { + ix++; + end_blk = ext2fs_le32_to_cpu(ix->ei_block); + } else + end_blk = path->end_blk; + + extent->e_len = end_blk - extent->e_lblk; + } + if (path->visit_num) + extent->e_flags |= EXT2_EXTENT_FLAGS_SECOND_VISIT; + + if (((orig_op == EXT2_EXTENT_NEXT_LEAF) || + (orig_op == EXT2_EXTENT_PREV_LEAF)) && + (handle->level != handle->max_depth)) + goto retry; + + if ((orig_op == EXT2_EXTENT_LAST_LEAF) && + ((handle->level != handle->max_depth) || + (path->left != 0))) + goto retry; + + if (failed_csum) + return EXT2_ET_EXTENT_CSUM_INVALID; + + return 0; +} + +static errcode_t update_path(ext2_extent_handle_t handle) +{ + blk64_t blk; + errcode_t retval; + struct ext3_extent_idx *ix; + struct ext3_extent_header *eh; + + if (handle->level == 0) { + retval = ext2fs_write_inode(handle->fs, handle->ino, + handle->inode); + } else { + ix = handle->path[handle->level - 1].curr; + blk = ext2fs_le32_to_cpu(ix->ei_leaf) + + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); + + /* then update the checksum */ + eh = (struct ext3_extent_header *) + handle->path[handle->level].buf; + retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino, + eh); + if (retval) + return retval; + + retval = io_channel_write_blk64(handle->fs->io, + blk, 1, handle->path[handle->level].buf); + } + return retval; +} + +#if 0 +errcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle, + ext2_extent_path_t *ret_path) +{ + ext2_extent_path_t save_path; + struct ext2fs_extent extent; + struct ext2_extent_info info; + errcode_t retval; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval) + return retval; + + retval = ext2fs_extent_get_info(handle, &info); + if (retval) + return retval; + + retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path); + if (retval) + return retval; + memset(save_path, 0, sizeof(struct ext2_extent_path)); + + save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH; + save_path->leaf_height = info.max_depth - info.curr_level - 1; + save_path->lblk = extent.e_lblk; + + *ret_path = save_path; + return 0; +} + +errcode_t ext2fs_extent_free_path(ext2_extent_path_t path) +{ + EXT2_CHECK_MAGIC(path, EXT2_ET_MAGIC_EXTENT_PATH); + + ext2fs_free_mem(&path); + return 0; +} +#endif + +/* + * Go to the node at leaf_level which contains logical block blk. + * + * leaf_level is height from the leaf node level, i.e. + * leaf_level 0 is at leaf node, leaf_level 1 is 1 above etc. + * + * If "blk" has no mapping (hole) then handle is left at last + * extent before blk. + */ +errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle, + int leaf_level, blk64_t blk) +{ + struct ext2fs_extent extent; + errcode_t retval; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); + if (retval) { + if (retval == EXT2_ET_EXTENT_NO_NEXT) + retval = EXT2_ET_EXTENT_NOT_FOUND; + return retval; + } + + if (leaf_level > handle->max_depth) { +#ifdef DEBUG + printf("leaf level %d greater than tree depth %d\n", + leaf_level, handle->max_depth); +#endif + return EXT2_ET_OP_NOT_SUPPORTED; + } + +#ifdef DEBUG + printf("goto extent ino %u, level %d, %llu\n", handle->ino, + leaf_level, blk); +#endif + +#ifdef DEBUG_GOTO_EXTENTS + dbg_print_extent("root", &extent); +#endif + while (1) { + if (handle->max_depth - handle->level == leaf_level) { + /* block is in this &extent */ + if ((blk >= extent.e_lblk) && + (blk < extent.e_lblk + extent.e_len)) + return 0; + if (blk < extent.e_lblk) { + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_PREV_SIB, + &extent); + return EXT2_ET_EXTENT_NOT_FOUND; + } + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_NEXT_SIB, + &extent); + if (retval == EXT2_ET_EXTENT_NO_NEXT) + return EXT2_ET_EXTENT_NOT_FOUND; + if (retval) + return retval; + continue; + } + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB, + &extent); + if (retval == EXT2_ET_EXTENT_NO_NEXT) + goto go_down; + if (retval) + return retval; + +#ifdef DEBUG_GOTO_EXTENTS + dbg_print_extent("next", &extent); +#endif + if (blk == extent.e_lblk) + goto go_down; + if (blk > extent.e_lblk) + continue; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB, + &extent); + if (retval) + return retval; + +#ifdef DEBUG_GOTO_EXTENTS + dbg_print_extent("prev", &extent); +#endif + + go_down: + retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN, + &extent); + if (retval) + return retval; + +#ifdef DEBUG_GOTO_EXTENTS + dbg_print_extent("down", &extent); +#endif + } +} + +errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle, + blk64_t blk) +{ + return ext2fs_extent_goto2(handle, 0, blk); +} + +/* + * Traverse back up to root fixing parents of current node as needed. + * + * If we changed start of first entry in a node, fix parent index start + * and so on. + * + * Safe to call for any position in node; if not at the first entry, + * it will simply return. + * + * Note a subtlety of this function -- if there happen to be two extents + * mapping the same lblk and someone calls fix_parents on the second of the two + * extents, the position of the extent handle after the call will be the second + * extent if nothing happened, or the first extent if something did. A caller + * in this situation must use ext2fs_extent_goto() after calling this function. + * Or simply don't map the same lblk with two extents, ever. + */ +errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle) +{ + int retval = 0; + int orig_height; + blk64_t start; + struct extent_path *path; + struct ext2fs_extent extent; + struct ext2_extent_info info; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + + path = handle->path + handle->level; + if (!path->curr) + return EXT2_ET_NO_CURRENT_NODE; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval) + goto done; + + /* modified node's start block */ + start = extent.e_lblk; + + if ((retval = ext2fs_extent_get_info(handle, &info))) + return retval; + orig_height = info.max_depth - info.curr_level; + + /* traverse up until index not first, or startblk matches, or top */ + while (handle->level > 0 && + (path->left == path->entries - 1)) { + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); + if (retval) + goto done; + if (extent.e_lblk == start) + break; + path = handle->path + handle->level; + extent.e_len += (extent.e_lblk - start); + extent.e_lblk = start; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + update_path(handle); + } + + /* put handle back to where we started */ + retval = ext2fs_extent_goto2(handle, orig_height, start); +done: + return retval; +} + +errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, + int flags EXT2FS_ATTR((unused)), + struct ext2fs_extent *extent) +{ + struct extent_path *path; + struct ext3_extent_idx *ix; + struct ext3_extent *ex; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + + path = handle->path + handle->level; + if (!path->curr) + return EXT2_ET_NO_CURRENT_NODE; + +#ifdef DEBUG + printf("extent replace: %u ", handle->ino); + dbg_print_extent(0, extent); +#endif + + if (handle->level == handle->max_depth) { + ex = path->curr; + + ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk); + ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF); + ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32); + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) { + if (extent->e_len > EXT_UNINIT_MAX_LEN) + return EXT2_ET_EXTENT_INVALID_LENGTH; + ex->ee_len = ext2fs_cpu_to_le16(extent->e_len + + EXT_INIT_MAX_LEN); + } else { + if (extent->e_len > EXT_INIT_MAX_LEN) + return EXT2_ET_EXTENT_INVALID_LENGTH; + ex->ee_len = ext2fs_cpu_to_le16(extent->e_len); + } + } else { + ix = path->curr; + + ix->ei_leaf = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF); + ix->ei_leaf_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32); + ix->ei_block = ext2fs_cpu_to_le32(extent->e_lblk); + ix->ei_unused = 0; + } + update_path(handle); + return 0; +} + +static int splitting_at_eof(struct ext2_extent_handle *handle, + struct extent_path *path) +{ + struct extent_path *ppp = path; + dump_path(__func__, handle, path); + + if (handle->level == 0) + return 0; + + do { + if (ppp->left) + return 0; + ppp--; + } while (ppp >= handle->path); + + return 1; +} + +/* + * allocate a new block, move half the current node to it, and update parent + * + * handle will be left pointing at original record. + */ +static errcode_t extent_node_split(ext2_extent_handle_t handle, + int expand_allowed) +{ + errcode_t retval = 0; + blk64_t new_node_pblk; + blk64_t new_node_start; + blk64_t orig_lblk; + blk64_t goal_blk = 0; + int orig_height; + char *block_buf = NULL; + struct ext2fs_extent extent; + struct extent_path *path, *newpath = 0; + struct ext3_extent_header *eh, *neweh; + int tocopy; + int new_root = 0; + struct ext2_extent_info info; + int no_balance; + + /* basic sanity */ + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + +#ifdef DEBUG + printf("splitting node at level %d\n", handle->level); +#endif + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval) + goto done; + + retval = ext2fs_extent_get_info(handle, &info); + if (retval) + goto done; + + /* save the position we were originally splitting... */ + orig_height = info.max_depth - info.curr_level; + orig_lblk = extent.e_lblk; + + /* Try to put the index block before the first extent */ + path = handle->path + handle->level; + eh = (struct ext3_extent_header *) path->buf; + if (handle->level == handle->max_depth) { + struct ext3_extent *ex; + + ex = EXT_FIRST_EXTENT(eh); + goal_blk = ext2fs_le32_to_cpu(ex->ee_start) + + ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32); + } else { + struct ext3_extent_idx *ix; + + ix = EXT_FIRST_INDEX(eh); + goal_blk = ext2fs_le32_to_cpu(ix->ei_leaf) + + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); + } + goal_blk -= EXT2FS_CLUSTER_RATIO(handle->fs); + goal_blk &= ~EXT2FS_CLUSTER_MASK(handle->fs); + + /* Is there room in the parent for a new entry? */ + if (handle->level && + (handle->path[handle->level - 1].entries >= + handle->path[handle->level - 1].max_entries)) { + +#ifdef DEBUG + printf("parent level %d full; splitting it too\n", + handle->level - 1); +#endif + /* split the parent */ + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); + if (retval) + goto done; + + retval = extent_node_split(handle, expand_allowed); + if (retval) + goto done; + + /* get handle back to our original split position */ + retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk); + if (retval) + goto done; + } + + /* At this point, parent should have room for this split */ + path = handle->path + handle->level; + if (!path->curr) + return EXT2_ET_NO_CURRENT_NODE; + + /* + * Normally, we try to split a full node in half. This doesn't turn + * out so well if we're tacking extents on the end of the file because + * then we're stuck with a tree of half-full extent blocks. This of + * course doesn't apply to the root level. + */ + no_balance = expand_allowed ? splitting_at_eof(handle, path) : 0; + + /* extent header of the current node we'll split */ + eh = (struct ext3_extent_header *)path->buf; + + /* splitting root level means moving them all out */ + if (handle->level == 0) { + new_root = 1; + tocopy = ext2fs_le16_to_cpu(eh->eh_entries); + retval = ext2fs_get_memzero((handle->max_paths + 1) * + sizeof(struct extent_path), + &newpath); + if (retval) + goto done; + } else { + if (no_balance) + tocopy = 1; + else + tocopy = ext2fs_le16_to_cpu(eh->eh_entries) / 2; + } + +#ifdef DEBUG + printf("will copy out %d of %d entries at level %d\n", + tocopy, ext2fs_le16_to_cpu(eh->eh_entries), + handle->level); +#endif + + if (!tocopy && !no_balance) { +#ifdef DEBUG + printf("Nothing to copy to new block!\n"); +#endif + retval = EXT2_ET_CANT_SPLIT_EXTENT; + goto done; + } + + /* first we need a new block, or can do nothing. */ + block_buf = malloc(handle->fs->blocksize); + if (!block_buf) { + retval = ENOMEM; + goto done; + } + + if (!goal_blk) + goal_blk = ext2fs_find_inode_goal(handle->fs, handle->ino, + handle->inode, 0); + retval = ext2fs_alloc_block2(handle->fs, goal_blk, block_buf, + &new_node_pblk); + if (retval) + goto done; + +#ifdef DEBUG + printf("will copy to new node at block %lu\n", + (unsigned long) new_node_pblk); +#endif + + /* Copy data into new block buffer */ + /* First the header for the new block... */ + neweh = (struct ext3_extent_header *) block_buf; + memcpy(neweh, eh, sizeof(struct ext3_extent_header)); + neweh->eh_entries = ext2fs_cpu_to_le16(tocopy); + neweh->eh_max = ext2fs_cpu_to_le16((handle->fs->blocksize - + sizeof(struct ext3_extent_header)) / + sizeof(struct ext3_extent)); + + /* then the entries for the new block... */ + memcpy(EXT_FIRST_INDEX(neweh), + EXT_FIRST_INDEX(eh) + + (ext2fs_le16_to_cpu(eh->eh_entries) - tocopy), + sizeof(struct ext3_extent_idx) * tocopy); + + new_node_start = ext2fs_le32_to_cpu(EXT_FIRST_INDEX(neweh)->ei_block); + + /* then update the checksum */ + retval = ext2fs_extent_block_csum_set(handle->fs, handle->ino, neweh); + if (retval) + goto done; + + /* ...and write the new node block out to disk. */ + retval = io_channel_write_blk64(handle->fs->io, new_node_pblk, 1, + block_buf); + + if (retval) + goto done; + + /* OK! we've created the new node; now adjust the tree */ + + /* current path now has fewer active entries, we copied some out */ + if (handle->level == 0) { + memcpy(newpath, path, + sizeof(struct extent_path) * handle->max_paths); + handle->path = newpath; + newpath = path; + path = handle->path; + path->entries = 1; + path->left = path->max_entries - 1; + handle->max_depth++; + handle->max_paths++; + eh->eh_depth = ext2fs_cpu_to_le16(handle->max_depth); + } else { + path->entries -= tocopy; + path->left -= tocopy; + } + + eh->eh_entries = ext2fs_cpu_to_le16(path->entries); + /* this writes out the node, incl. the modified header */ + retval = update_path(handle); + if (retval) + goto done; + + /* now go up and insert/replace index for new node we created */ + if (new_root) { + retval = ext2fs_extent_get(handle, EXT2_EXTENT_FIRST_SIB, &extent); + if (retval) + goto done; + + extent.e_lblk = new_node_start; + extent.e_pblk = new_node_pblk; + extent.e_len = handle->path[0].end_blk - extent.e_lblk; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + } else { + __u32 new_node_length; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); + /* will insert after this one; it's length is shorter now */ + new_node_length = new_node_start - extent.e_lblk; + extent.e_len -= new_node_length; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + + /* now set up the new extent and insert it */ + extent.e_lblk = new_node_start; + extent.e_pblk = new_node_pblk; + extent.e_len = new_node_length; + retval = ext2fs_extent_insert(handle, EXT2_EXTENT_INSERT_AFTER, &extent); + if (retval) + goto done; + } + + /* get handle back to our original position */ + retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk); + if (retval) + goto done; + + /* new node hooked in, so update inode block count (do this here?) */ + ext2fs_iblk_add_blocks(handle->fs, handle->inode, 1); + retval = ext2fs_write_inode(handle->fs, handle->ino, + handle->inode); + if (retval) + goto done; + +done: + if (newpath) + ext2fs_free_mem(&newpath); + free(block_buf); + + return retval; +} + +errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle) +{ + return extent_node_split(handle, 0); +} + +errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags, + struct ext2fs_extent *extent) +{ + struct extent_path *path; + struct ext3_extent_idx *ix; + struct ext3_extent_header *eh; + errcode_t retval; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + +#ifdef DEBUG + printf("extent insert: %u ", handle->ino); + dbg_print_extent(0, extent); +#endif + + path = handle->path + handle->level; + + if (path->entries >= path->max_entries) { + if (flags & EXT2_EXTENT_INSERT_NOSPLIT) { + return EXT2_ET_CANT_INSERT_EXTENT; + } else { +#ifdef DEBUG + printf("node full (level %d) - splitting\n", + handle->level); +#endif + retval = extent_node_split(handle, 1); + if (retval) + return retval; + path = handle->path + handle->level; + } + } + + eh = (struct ext3_extent_header *) path->buf; + if (path->curr) { + ix = path->curr; + if (flags & EXT2_EXTENT_INSERT_AFTER) { + ix++; + path->left--; + } + } else { + ix = EXT_FIRST_INDEX(eh); + path->left = -1; + } + + path->curr = ix; + + if (path->left >= 0) + memmove(ix + 1, ix, + (path->left+1) * sizeof(struct ext3_extent_idx)); + path->left++; + path->entries++; + + eh = (struct ext3_extent_header *) path->buf; + eh->eh_entries = ext2fs_cpu_to_le16(path->entries); + + retval = ext2fs_extent_replace(handle, 0, extent); + if (retval) + goto errout; + + retval = update_path(handle); + if (retval) + goto errout; + + return 0; + +errout: + ext2fs_extent_delete(handle, 0); + return retval; +} + +/* + * Sets the physical block for a logical file block in the extent tree. + * + * May: map unmapped, unmap mapped, or remap mapped blocks. + * + * Mapping an unmapped block adds a single-block extent. + * + * Unmapping first or last block modifies extent in-place + * - But may need to fix parent's starts too in first-block case + * + * Mapping any unmapped block requires adding a (single-block) extent + * and inserting into proper point in tree. + * + * Modifying (unmapping or remapping) a block in the middle + * of an extent requires splitting the extent. + * - Remapping case requires new single-block extent. + * + * Remapping first or last block adds an extent. + * + * We really need extent adding to be smart about merging. + */ + +errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, + blk64_t logical, blk64_t physical, int flags) +{ + errcode_t ec, retval = 0; + int mapped = 1; /* logical is mapped? */ + int orig_height; + int extent_uninit = 0; + int prev_uninit = 0; + int next_uninit = 0; + int new_uninit = 0; + int max_len = EXT_INIT_MAX_LEN; + int has_prev, has_next; + blk64_t orig_lblk; + struct extent_path *path; + struct ext2fs_extent extent, next_extent, prev_extent; + struct ext2fs_extent newextent; + struct ext2_extent_info info; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + +#ifdef DEBUG + printf("set_bmap ino %u log %lld phys %lld flags %d\n", + handle->ino, logical, physical, flags); +#endif + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + + path = handle->path + handle->level; + + if (flags & EXT2_EXTENT_SET_BMAP_UNINIT) { + new_uninit = 1; + max_len = EXT_UNINIT_MAX_LEN; + } + + /* if (re)mapping, set up new extent to insert */ + if (physical) { + newextent.e_len = 1; + newextent.e_pblk = physical; + newextent.e_lblk = logical; + newextent.e_flags = EXT2_EXTENT_FLAGS_LEAF; + if (new_uninit) + newextent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT; + } + + /* special case if the extent tree is completely empty */ + if ((handle->max_depth == 0) && (path->entries == 0)) { + retval = ext2fs_extent_insert(handle, 0, &newextent); + return retval; + } + + /* save our original location in the extent tree */ + if ((retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &extent))) { + if (retval != EXT2_ET_NO_CURRENT_NODE) + return retval; + memset(&extent, 0, sizeof(extent)); + } + if ((retval = ext2fs_extent_get_info(handle, &info))) + return retval; + orig_height = info.max_depth - info.curr_level; + orig_lblk = extent.e_lblk; + + /* go to the logical spot we want to (re/un)map */ + retval = ext2fs_extent_goto(handle, logical); + if (retval) { + if (retval == EXT2_ET_EXTENT_NOT_FOUND) { + retval = 0; + mapped = 0; + if (!physical) { +#ifdef DEBUG + printf("block %llu already unmapped\n", + logical); +#endif + goto done; + } + } else + goto done; + } + + /* + * This may be the extent *before* the requested logical, + * if it's currently unmapped. + * + * Get the previous and next leaf extents, if they are present. + */ + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval) + goto done; + if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) + extent_uninit = 1; + retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &next_extent); + if (retval) { + has_next = 0; + if (retval != EXT2_ET_EXTENT_NO_NEXT) + goto done; + } else { + dbg_print_extent("set_bmap: next_extent", + &next_extent); + has_next = 1; + if (next_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) + next_uninit = 1; + } + retval = ext2fs_extent_goto(handle, logical); + if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND) + goto done; + retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_LEAF, &prev_extent); + if (retval) { + has_prev = 0; + if (retval != EXT2_ET_EXTENT_NO_PREV) + goto done; + } else { + has_prev = 1; + dbg_print_extent("set_bmap: prev_extent", + &prev_extent); + if (prev_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) + prev_uninit = 1; + } + retval = ext2fs_extent_goto(handle, logical); + if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND) + goto done; + + /* check if already pointing to the requested physical */ + if (mapped && (new_uninit == extent_uninit) && + (extent.e_pblk + (logical - extent.e_lblk) == physical)) { +#ifdef DEBUG + printf("physical block (at %llu) unchanged\n", logical); +#endif + goto done; + } + + if (!mapped) { +#ifdef DEBUG + printf("mapping unmapped logical block %llu\n", logical); +#endif + if ((logical == extent.e_lblk + extent.e_len) && + (physical == extent.e_pblk + extent.e_len) && + (new_uninit == extent_uninit) && + ((int) extent.e_len < max_len-1)) { + extent.e_len++; + retval = ext2fs_extent_replace(handle, 0, &extent); + } else if ((logical == extent.e_lblk - 1) && + (physical == extent.e_pblk - 1) && + (new_uninit == extent_uninit) && + ((int) extent.e_len < max_len - 1)) { + extent.e_len++; + extent.e_lblk--; + extent.e_pblk--; + retval = ext2fs_extent_replace(handle, 0, &extent); + } else if (has_next && + (logical == next_extent.e_lblk - 1) && + (physical == next_extent.e_pblk - 1) && + (new_uninit == next_uninit) && + ((int) next_extent.e_len < max_len - 1)) { + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_NEXT_LEAF, + &next_extent); + if (retval) + goto done; + next_extent.e_len++; + next_extent.e_lblk--; + next_extent.e_pblk--; + retval = ext2fs_extent_replace(handle, 0, &next_extent); + } else if (logical < extent.e_lblk) + retval = ext2fs_extent_insert(handle, 0, &newextent); + else + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &newextent); + if (retval) + goto done; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto done; + } else if ((logical == extent.e_lblk) && (extent.e_len == 1)) { +#ifdef DEBUG + printf("(re/un)mapping only block in extent\n"); +#endif + if (physical) { + retval = ext2fs_extent_replace(handle, 0, &newextent); + } else { + retval = ext2fs_extent_delete(handle, 0); + if (retval) + goto done; + ec = ext2fs_extent_fix_parents(handle); + if (ec != EXT2_ET_NO_CURRENT_NODE) + retval = ec; + } + + if (retval) + goto done; + } else if (logical == extent.e_lblk + extent.e_len - 1) { +#ifdef DEBUG + printf("(re/un)mapping last block in extent\n"); +#endif + if (physical) { + if (has_next && + (logical == (next_extent.e_lblk - 1)) && + (physical == (next_extent.e_pblk - 1)) && + (new_uninit == next_uninit) && + ((int) next_extent.e_len < max_len - 1)) { + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_NEXT_LEAF, &next_extent); + if (retval) + goto done; + next_extent.e_len++; + next_extent.e_lblk--; + next_extent.e_pblk--; + retval = ext2fs_extent_replace(handle, 0, + &next_extent); + if (retval) + goto done; + } else + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &newextent); + if (retval) + goto done; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto done; + /* + * Now pointing at inserted extent; move back to prev. + * + * We cannot use EXT2_EXTENT_PREV to go back; note the + * subtlety in the comment for fix_parents(). + */ + retval = ext2fs_extent_goto(handle, logical); + if (retval) + goto done; + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_CURRENT, + &extent); + if (retval) + goto done; + } + extent.e_len--; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + } else if (logical == extent.e_lblk) { +#ifdef DEBUG + printf("(re/un)mapping first block in extent\n"); +#endif + if (physical) { + if (has_prev && + (logical == (prev_extent.e_lblk + + prev_extent.e_len)) && + (physical == (prev_extent.e_pblk + + prev_extent.e_len)) && + (new_uninit == prev_uninit) && + ((int) prev_extent.e_len < max_len-1)) { + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_PREV_LEAF, &prev_extent); + if (retval) + goto done; + prev_extent.e_len++; + retval = ext2fs_extent_replace(handle, 0, + &prev_extent); + } else + retval = ext2fs_extent_insert(handle, + 0, &newextent); + if (retval) + goto done; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto done; + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_NEXT_LEAF, + &extent); + if (retval) + goto done; + } + extent.e_pblk++; + extent.e_lblk++; + extent.e_len--; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto done; + } else { + __u32 save_length; + blk64_t save_lblk; + struct ext2fs_extent save_extent; + errcode_t r2; + +#ifdef DEBUG + printf("(re/un)mapping in middle of extent\n"); +#endif + /* need to split this extent; later */ + save_lblk = extent.e_lblk; + save_length = extent.e_len; + save_extent = extent; + + /* shorten pre-split extent */ + extent.e_len = (logical - extent.e_lblk); + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + /* insert our new extent, if any */ + if (physical) { + /* insert new extent after current */ + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &newextent); + if (retval) { + r2 = ext2fs_extent_goto(handle, save_lblk); + if (r2 == 0) + (void)ext2fs_extent_replace(handle, 0, + &save_extent); + goto done; + } + } + /* add post-split extent */ + extent.e_pblk += extent.e_len + 1; + extent.e_lblk += extent.e_len + 1; + extent.e_len = save_length - extent.e_len - 1; + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &extent); + if (retval) { + if (physical) { + r2 = ext2fs_extent_goto(handle, + newextent.e_lblk); + if (r2 == 0) + (void)ext2fs_extent_delete(handle, 0); + } + r2 = ext2fs_extent_goto(handle, save_lblk); + if (r2 == 0) + (void)ext2fs_extent_replace(handle, 0, + &save_extent); + goto done; + } + } + +done: + /* get handle back to its position */ + if (orig_height > handle->max_depth) + orig_height = handle->max_depth; /* In case we shortened the tree */ + ext2fs_extent_goto2(handle, orig_height, orig_lblk); + return retval; +} + +errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags) +{ + struct extent_path *path; + char *cp; + struct ext3_extent_header *eh; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + if (!(handle->fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!handle->path) + return EXT2_ET_NO_CURRENT_NODE; + +#ifdef DEBUG + { + struct ext2fs_extent extent; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &extent); + if (retval == 0) { + printf("extent delete %u ", handle->ino); + dbg_print_extent(0, &extent); + } + } +#endif + + path = handle->path + handle->level; + if (!path->curr) + return EXT2_ET_NO_CURRENT_NODE; + + cp = path->curr; + + /* Sanity check before memmove() */ + if (path->left < 0) + return EXT2_ET_EXTENT_LEAF_BAD; + + if (path->left) { + memmove(cp, cp + sizeof(struct ext3_extent_idx), + path->left * sizeof(struct ext3_extent_idx)); + path->left--; + } else { + struct ext3_extent_idx *ix = path->curr; + ix--; + path->curr = ix; + } + if (--path->entries == 0) + path->curr = 0; + + /* if non-root node has no entries left, remove it & parent ptr to it */ + if (path->entries == 0 && handle->level) { + if (!(flags & EXT2_EXTENT_DELETE_KEEP_EMPTY)) { + struct ext2fs_extent extent; + + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, + &extent); + if (retval) + return retval; + + retval = ext2fs_extent_delete(handle, flags); + handle->inode->i_blocks -= + (handle->fs->blocksize * + EXT2FS_CLUSTER_RATIO(handle->fs)) / 512; + retval = ext2fs_write_inode(handle->fs, handle->ino, + handle->inode); + ext2fs_block_alloc_stats2(handle->fs, + extent.e_pblk, -1); + } + } else { + eh = (struct ext3_extent_header *) path->buf; + eh->eh_entries = ext2fs_cpu_to_le16(path->entries); + if ((path->entries == 0) && (handle->level == 0)) { + eh->eh_depth = 0; + handle->max_depth = 0; + } + retval = update_path(handle); + } + return retval; +} + +errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle, + struct ext2_extent_info *info) +{ + struct extent_path *path; + + EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); + + memset(info, 0, sizeof(struct ext2_extent_info)); + + path = handle->path + handle->level; + if (path) { + if (path->curr) + info->curr_entry = ((char *) path->curr - path->buf) / + sizeof(struct ext3_extent_idx); + else + info->curr_entry = 0; + info->num_entries = path->entries; + info->max_entries = path->max_entries; + info->bytes_avail = (path->max_entries - path->entries) * + sizeof(struct ext3_extent); + } + + info->curr_level = handle->level; + info->max_depth = handle->max_depth; + info->max_lblk = EXT_MAX_EXTENT_LBLK; + info->max_pblk = EXT_MAX_EXTENT_PBLK; + info->max_len = EXT_INIT_MAX_LEN; + info->max_uninit_len = EXT_UNINIT_MAX_LEN; + + return 0; +} + +static int ul_log2(unsigned long arg) +{ + int l = 0; + + arg >>= 1; + while (arg) { + l++; + arg >>= 1; + } + return l; +} + +size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle) +{ + size_t iblock_sz = sizeof(((struct ext2_inode *)NULL)->i_block); + size_t iblock_extents = (iblock_sz - sizeof(struct ext3_extent_header)) / + sizeof(struct ext3_extent); + size_t extents_per_block = (handle->fs->blocksize - + sizeof(struct ext3_extent_header)) / + sizeof(struct ext3_extent); + static unsigned int last_blocksize = 0; + static size_t last_result = 0; + + if (last_blocksize && last_blocksize == handle->fs->blocksize) + return last_result; + + last_result = 1 + ((ul_log2(EXT_MAX_EXTENT_LBLK) - ul_log2(iblock_extents)) / + ul_log2(extents_per_block)); + last_blocksize = handle->fs->blocksize; + return last_result; +} + +errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + ext2_extent_handle_t handle; + struct ext2fs_extent extent; + errcode_t errcode; + int save_flags = fs->flags; + + if (!ext2fs_has_feature_metadata_csum(fs->super) || + (inode && !(inode->i_flags & EXT4_EXTENTS_FL))) + return 0; + + errcode = ext2fs_extent_open2(fs, ino, inode, &handle); + if (errcode) { + if (errcode == EXT2_ET_INODE_NOT_EXTENT) + errcode = 0; + return errcode; + } + + fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS; + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); + if (errcode) + goto out; + + do { + /* Skip to the end of a block of leaf nodes */ + if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) { + errcode = ext2fs_extent_get(handle, + EXT2_EXTENT_LAST_SIB, + &extent); + if (errcode) + break; + } + + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent); + if (errcode == EXT2_ET_EXTENT_CSUM_INVALID) + errcode = update_path(handle); + } while (errcode == 0); + +out: + /* Ok if we run off the end */ + if (errcode == EXT2_ET_EXTENT_NO_NEXT) + errcode = 0; + ext2fs_extent_free(handle); + fs->flags = save_flags; + return errcode; +} + +errcode_t ext2fs_decode_extent(struct ext2fs_extent *to, void *addr, int len) +{ + struct ext3_extent *from = (struct ext3_extent *)addr; + + if (len != sizeof(struct ext3_extent)) + return EXT2_ET_INVALID_ARGUMENT; + + to->e_pblk = ext2fs_le32_to_cpu(from->ee_start) + + ((__u64) ext2fs_le16_to_cpu(from->ee_start_hi) + << 32); + to->e_lblk = ext2fs_le32_to_cpu(from->ee_block); + to->e_len = ext2fs_le16_to_cpu(from->ee_len); + to->e_flags = EXT2_EXTENT_FLAGS_LEAF; + if (to->e_len > EXT_INIT_MAX_LEN) { + to->e_len -= EXT_INIT_MAX_LEN; + to->e_flags |= EXT2_EXTENT_FLAGS_UNINIT; + } + + return 0; +} + +errcode_t ext2fs_count_blocks(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t *ret_count) +{ + ext2_extent_handle_t handle = NULL; + struct ext2fs_extent extent; + errcode_t errcode; + int i; + blk64_t blkcount = 0; + blk64_t *intermediate_nodes; + + errcode = ext2fs_extent_open2(fs, ino, inode, &handle); + if (errcode) + goto out; + + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); + if (errcode) + goto out; + + errcode = ext2fs_get_array(handle->max_depth, sizeof(blk64_t), + &intermediate_nodes); + if (errcode) + goto out; + + blkcount = handle->level; + while (!errcode) { + if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) { + blkcount += extent.e_len; + for (i = 0; i < handle->level; i++) { + if (intermediate_nodes[i] != + handle->path[i].end_blk) { + blkcount++; + intermediate_nodes[i] = + handle->path[i].end_blk; + } + } + } + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent); + } + ext2fs_free_mem(&intermediate_nodes); +out: + *ret_count = blkcount; + ext2fs_extent_free(handle); + + return 0; +} + +#ifdef DEBUG +/* + * Override debugfs's prompt + */ +const char *debug_prog_name = "tst_extents"; + +#endif + diff --git a/jni/e2fsprogs/lib/ext2fs/extent.o b/jni/e2fsprogs/lib/ext2fs/extent.o new file mode 100755 index 0000000000000000000000000000000000000000..950cd727bcb1f0d0e01db744525bb27665bd1a70 GIT binary patch literal 23128 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/fallocate.c b/jni/e2fsprogs/lib/ext2fs/fallocate.c new file mode 100755 index 0000000..5cde7d5 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/fallocate.c @@ -0,0 +1,873 @@ +/* + * fallocate.c -- Allocate large chunks of file. + * + * Copyright (C) 2014 Oracle. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" + +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#define min(a, b) ((a) < (b) ? (a) : (b)) + +#undef DEBUG + +#ifdef DEBUG +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) +#else +# define dbg_printf(f, a...) +#endif + +/* + * Extent-based fallocate code. + * + * Find runs of unmapped logical blocks by starting at start and walking the + * extents until we reach the end of the range we want. + * + * For each run of unmapped blocks, try to find the extents on either side of + * the range. If there's a left extent that can grow by at least a cluster and + * there are lblocks between start and the next lcluster after start, see if + * there's an implied cluster allocation; if so, zero the blocks (if the left + * extent is initialized) and adjust the extent. Ditto for the blocks between + * the end of the last full lcluster and end, if there's a right extent. + * + * Try to attach as much as we can to the left extent, then try to attach as + * much as we can to the right extent. For the remainder, try to allocate the + * whole range; map in whatever we get; and repeat until we're done. + * + * To attach to a left extent, figure out the maximum amount we can add to the + * extent and try to allocate that much, and append if successful. To attach + * to a right extent, figure out the max we can add to the extent, try to + * allocate that much, and prepend if successful. + * + * We need an alloc_range function that tells us how much we can allocate given + * a maximum length and one of a suggested start, a fixed start, or a fixed end + * point. + * + * Every time we modify the extent tree we also need to update the block stats. + * + * At the end, update i_blocks and i_size appropriately. + */ + +static void dbg_print_extent(const char *desc EXT2FS_ATTR((unused)), + const struct ext2fs_extent *extent EXT2FS_ATTR((unused))) +{ +#ifdef DEBUG + if (desc) + printf("%s: ", desc); + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ", + extent->e_lblk, extent->e_lblk + extent->e_len - 1, + extent->e_len, extent->e_pblk); + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF) + fputs("LEAF ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fputs("UNINIT ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + fputs("2ND_VISIT ", stdout); + if (!extent->e_flags) + fputs("(none)", stdout); + fputc('\n', stdout); + fflush(stdout); +#endif +} + +static errcode_t claim_range(ext2_filsys fs, struct ext2_inode *inode, + blk64_t blk, blk64_t len) +{ + blk64_t clusters; + + clusters = (len + EXT2FS_CLUSTER_RATIO(fs) - 1) / + EXT2FS_CLUSTER_RATIO(fs); + ext2fs_block_alloc_stats_range(fs, blk, + clusters * EXT2FS_CLUSTER_RATIO(fs), +1); + return ext2fs_iblk_add_blocks(fs, inode, clusters); +} + +static errcode_t ext_falloc_helper(ext2_filsys fs, + int flags, + ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + struct ext2fs_extent *left_ext, + struct ext2fs_extent *right_ext, + blk64_t range_start, blk64_t range_len, + blk64_t alloc_goal) +{ + struct ext2fs_extent newex, ex; + int op; + blk64_t fillable, pblk, plen, x, y; + blk64_t eof_blk = 0, cluster_fill = 0; + errcode_t err; + blk_t max_extent_len, max_uninit_len, max_init_len; + +#ifdef DEBUG + printf("%s: ", __func__); + if (left_ext) + printf("left_ext=%llu--%llu, ", left_ext->e_lblk, + left_ext->e_lblk + left_ext->e_len - 1); + if (right_ext) + printf("right_ext=%llu--%llu, ", right_ext->e_lblk, + right_ext->e_lblk + right_ext->e_len - 1); + printf("start=%llu len=%llu, goal=%llu\n", range_start, range_len, + alloc_goal); + fflush(stdout); +#endif + /* Can't create initialized extents past EOF? */ + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) + eof_blk = EXT2_I_SIZE(inode) / fs->blocksize; + + /* The allocation goal must be as far into a cluster as range_start. */ + alloc_goal = (alloc_goal & ~EXT2FS_CLUSTER_MASK(fs)) | + (range_start & EXT2FS_CLUSTER_MASK(fs)); + + max_uninit_len = EXT_UNINIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs); + max_init_len = EXT_INIT_MAX_LEN & ~EXT2FS_CLUSTER_MASK(fs); + + /* We must lengthen the left extent to the end of the cluster */ + if (left_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) { + /* How many more blocks can be attached to left_ext? */ + if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fillable = max_uninit_len - left_ext->e_len; + else + fillable = max_init_len - left_ext->e_len; + + if (fillable > range_len) + fillable = range_len; + if (fillable == 0) + goto expand_right; + + /* + * If range_start isn't on a cluster boundary, try an + * implied cluster allocation for left_ext. + */ + cluster_fill = EXT2FS_CLUSTER_RATIO(fs) - + (range_start & EXT2FS_CLUSTER_MASK(fs)); + cluster_fill &= EXT2FS_CLUSTER_MASK(fs); + if (cluster_fill == 0) + goto expand_right; + + if (cluster_fill > fillable) + cluster_fill = fillable; + + /* Don't expand an initialized left_ext beyond EOF */ + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) { + x = left_ext->e_lblk + left_ext->e_len - 1; + dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n", + __func__, x, x + cluster_fill, eof_blk); + if (eof_blk >= x && eof_blk <= x + cluster_fill) + cluster_fill = eof_blk - x; + if (cluster_fill == 0) + goto expand_right; + } + + err = ext2fs_extent_goto(handle, left_ext->e_lblk); + if (err) + goto expand_right; + left_ext->e_len += cluster_fill; + range_start += cluster_fill; + range_len -= cluster_fill; + alloc_goal += cluster_fill; + + dbg_print_extent("ext_falloc clus left+", left_ext); + err = ext2fs_extent_replace(handle, 0, left_ext); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + /* Zero blocks */ + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) { + err = ext2fs_zero_blocks2(fs, left_ext->e_pblk + + left_ext->e_len - + cluster_fill, cluster_fill, + NULL, NULL); + if (err) + goto out; + } + } + +expand_right: + /* We must lengthen the right extent to the beginning of the cluster */ + if (right_ext && EXT2FS_CLUSTER_RATIO(fs) > 1) { + /* How much can we attach to right_ext? */ + if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fillable = max_uninit_len - right_ext->e_len; + else + fillable = max_init_len - right_ext->e_len; + + if (fillable > range_len) + fillable = range_len; + if (fillable == 0) + goto try_merge; + + /* + * If range_end isn't on a cluster boundary, try an implied + * cluster allocation for right_ext. + */ + cluster_fill = right_ext->e_lblk & EXT2FS_CLUSTER_MASK(fs); + if (cluster_fill == 0) + goto try_merge; + + err = ext2fs_extent_goto(handle, right_ext->e_lblk); + if (err) + goto out; + + if (cluster_fill > fillable) + cluster_fill = fillable; + right_ext->e_lblk -= cluster_fill; + right_ext->e_pblk -= cluster_fill; + right_ext->e_len += cluster_fill; + range_len -= cluster_fill; + + dbg_print_extent("ext_falloc clus right+", right_ext); + err = ext2fs_extent_replace(handle, 0, right_ext); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + /* Zero blocks if necessary */ + if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) { + err = ext2fs_zero_blocks2(fs, right_ext->e_pblk, + cluster_fill, NULL, NULL); + if (err) + goto out; + } + } + +try_merge: + /* Merge both extents together, perhaps? */ + if (left_ext && right_ext) { + /* Are the two extents mergeable? */ + if ((left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) != + (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) + goto try_left; + + /* User requires init/uninit but extent is uninit/init. */ + if (((flags & EXT2_FALLOCATE_FORCE_INIT) && + (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) || + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) && + !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT))) + goto try_left; + + /* + * Skip initialized extent unless user wants to zero blocks + * or requires init extent. + */ + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (!(flags & EXT2_FALLOCATE_ZERO_BLOCKS) || + !(flags & EXT2_FALLOCATE_FORCE_INIT))) + goto try_left; + + /* Will it even fit? */ + x = left_ext->e_len + range_len + right_ext->e_len; + if (x > (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT ? + max_uninit_len : max_init_len)) + goto try_left; + + err = ext2fs_extent_goto(handle, left_ext->e_lblk); + if (err) + goto try_left; + + /* Allocate blocks */ + y = left_ext->e_pblk + left_ext->e_len; + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL | + EXT2_NEWRANGE_MIN_LENGTH, y, + right_ext->e_pblk - y + 1, NULL, + &pblk, &plen); + if (err) + goto try_left; + if (pblk + plen != right_ext->e_pblk) + goto try_left; + err = claim_range(fs, inode, pblk, plen); + if (err) + goto out; + + /* Modify extents */ + left_ext->e_len = x; + dbg_print_extent("ext_falloc merge", left_ext); + err = ext2fs_extent_replace(handle, 0, left_ext); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &newex); + if (err) + goto out; + err = ext2fs_extent_delete(handle, 0); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + *right_ext = *left_ext; + + /* Zero blocks */ + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, range_start, range_len, + NULL, NULL); + if (err) + goto out; + } + + return 0; + } + +try_left: + /* Extend the left extent */ + if (left_ext) { + /* How many more blocks can be attached to left_ext? */ + if (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fillable = max_uninit_len - left_ext->e_len; + else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS) + fillable = max_init_len - left_ext->e_len; + else + fillable = 0; + + /* User requires init/uninit but extent is uninit/init. */ + if (((flags & EXT2_FALLOCATE_FORCE_INIT) && + (left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) || + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) && + !(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT))) + goto try_right; + + if (fillable > range_len) + fillable = range_len; + + /* Don't expand an initialized left_ext beyond EOF */ + x = left_ext->e_lblk + left_ext->e_len - 1; + if (!(flags & EXT2_FALLOCATE_INIT_BEYOND_EOF)) { + dbg_printf("%s: lend=%llu newlend=%llu eofblk=%llu\n", + __func__, x, x + fillable, eof_blk); + if (eof_blk >= x && eof_blk <= x + fillable) + fillable = eof_blk - x; + } + + if (fillable == 0) + goto try_right; + + /* Test if the right edge of the range is already mapped? */ + if (EXT2FS_CLUSTER_RATIO(fs) > 1) { + err = ext2fs_map_cluster_block(fs, ino, inode, + x + fillable, &pblk); + if (err) + goto out; + if (pblk) + fillable -= 1 + ((x + fillable) + & EXT2FS_CLUSTER_MASK(fs)); + if (fillable == 0) + goto try_right; + } + + /* Allocate range of blocks */ + x = left_ext->e_pblk + left_ext->e_len; + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL | + EXT2_NEWRANGE_MIN_LENGTH, + x, fillable, NULL, &pblk, &plen); + if (err) + goto try_right; + err = claim_range(fs, inode, pblk, plen); + if (err) + goto out; + + /* Modify left_ext */ + err = ext2fs_extent_goto(handle, left_ext->e_lblk); + if (err) + goto out; + range_start += plen; + range_len -= plen; + left_ext->e_len += plen; + dbg_print_extent("ext_falloc left+", left_ext); + err = ext2fs_extent_replace(handle, 0, left_ext); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + /* Zero blocks if necessary */ + if (!(left_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL); + if (err) + goto out; + } + } + +try_right: + /* Extend the right extent */ + if (right_ext) { + /* How much can we attach to right_ext? */ + if (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fillable = max_uninit_len - right_ext->e_len; + else if (flags & EXT2_FALLOCATE_ZERO_BLOCKS) + fillable = max_init_len - right_ext->e_len; + else + fillable = 0; + + /* User requires init/uninit but extent is uninit/init. */ + if (((flags & EXT2_FALLOCATE_FORCE_INIT) && + (right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT)) || + ((flags & EXT2_FALLOCATE_FORCE_UNINIT) && + !(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT))) + goto try_anywhere; + + if (fillable > range_len) + fillable = range_len; + if (fillable == 0) + goto try_anywhere; + + /* Test if the left edge of the range is already mapped? */ + if (EXT2FS_CLUSTER_RATIO(fs) > 1) { + err = ext2fs_map_cluster_block(fs, ino, inode, + right_ext->e_lblk - fillable, &pblk); + if (err) + goto out; + if (pblk) + fillable -= EXT2FS_CLUSTER_RATIO(fs) - + ((right_ext->e_lblk - fillable) + & EXT2FS_CLUSTER_MASK(fs)); + if (fillable == 0) + goto try_anywhere; + } + + /* + * FIXME: It would be nice if we could handle allocating a + * variable range from a fixed end point instead of just + * skipping to the general allocator if the whole range is + * unavailable. + */ + err = ext2fs_new_range(fs, EXT2_NEWRANGE_FIXED_GOAL | + EXT2_NEWRANGE_MIN_LENGTH, + right_ext->e_pblk - fillable, + fillable, NULL, &pblk, &plen); + if (err) + goto try_anywhere; + err = claim_range(fs, inode, + pblk & ~EXT2FS_CLUSTER_MASK(fs), + plen + (pblk & EXT2FS_CLUSTER_MASK(fs))); + if (err) + goto out; + + /* Modify right_ext */ + err = ext2fs_extent_goto(handle, right_ext->e_lblk); + if (err) + goto out; + range_len -= plen; + right_ext->e_lblk -= plen; + right_ext->e_pblk -= plen; + right_ext->e_len += plen; + dbg_print_extent("ext_falloc right+", right_ext); + err = ext2fs_extent_replace(handle, 0, right_ext); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + /* Zero blocks if necessary */ + if (!(right_ext->e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, pblk, + plen + cluster_fill, NULL, NULL); + if (err) + goto out; + } + } + +try_anywhere: + /* Try implied cluster alloc on the left and right ends */ + if (range_len > 0 && (range_start & EXT2FS_CLUSTER_MASK(fs))) { + cluster_fill = EXT2FS_CLUSTER_RATIO(fs) - + (range_start & EXT2FS_CLUSTER_MASK(fs)); + cluster_fill &= EXT2FS_CLUSTER_MASK(fs); + if (cluster_fill > range_len) + cluster_fill = range_len; + newex.e_lblk = range_start; + err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk, + &pblk); + if (err) + goto out; + if (pblk == 0) + goto try_right_implied; + newex.e_pblk = pblk; + newex.e_len = cluster_fill; + newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 : + EXT2_EXTENT_FLAGS_UNINIT); + dbg_print_extent("ext_falloc iclus left+", &newex); + ext2fs_extent_goto(handle, newex.e_lblk); + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &ex); + if (err == EXT2_ET_NO_CURRENT_NODE) + ex.e_lblk = 0; + else if (err) + goto out; + + if (ex.e_lblk > newex.e_lblk) + op = 0; /* insert before */ + else + op = EXT2_EXTENT_INSERT_AFTER; + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n", + __func__, op ? "after" : "before", ex.e_lblk, + newex.e_lblk); + err = ext2fs_extent_insert(handle, op, &newex); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, newex.e_pblk, + newex.e_len, NULL, NULL); + if (err) + goto out; + } + + range_start += cluster_fill; + range_len -= cluster_fill; + } + +try_right_implied: + y = range_start + range_len; + if (range_len > 0 && (y & EXT2FS_CLUSTER_MASK(fs))) { + cluster_fill = y & EXT2FS_CLUSTER_MASK(fs); + if (cluster_fill > range_len) + cluster_fill = range_len; + newex.e_lblk = y & ~EXT2FS_CLUSTER_MASK(fs); + err = ext2fs_map_cluster_block(fs, ino, inode, newex.e_lblk, + &pblk); + if (err) + goto out; + if (pblk == 0) + goto no_implied; + newex.e_pblk = pblk; + newex.e_len = cluster_fill; + newex.e_flags = (flags & EXT2_FALLOCATE_FORCE_INIT ? 0 : + EXT2_EXTENT_FLAGS_UNINIT); + dbg_print_extent("ext_falloc iclus right+", &newex); + ext2fs_extent_goto(handle, newex.e_lblk); + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &ex); + if (err == EXT2_ET_NO_CURRENT_NODE) + ex.e_lblk = 0; + else if (err) + goto out; + + if (ex.e_lblk > newex.e_lblk) + op = 0; /* insert before */ + else + op = EXT2_EXTENT_INSERT_AFTER; + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n", + __func__, op ? "after" : "before", ex.e_lblk, + newex.e_lblk); + err = ext2fs_extent_insert(handle, op, &newex); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, newex.e_pblk, + newex.e_len, NULL, NULL); + if (err) + goto out; + } + + range_len -= cluster_fill; + } + +no_implied: + if (range_len == 0) + return 0; + + newex.e_lblk = range_start; + if (flags & EXT2_FALLOCATE_FORCE_INIT) { + max_extent_len = max_init_len; + newex.e_flags = 0; + } else { + max_extent_len = max_uninit_len; + newex.e_flags = EXT2_EXTENT_FLAGS_UNINIT; + } + pblk = alloc_goal; + y = range_len; + for (x = 0; x < y;) { + cluster_fill = newex.e_lblk & EXT2FS_CLUSTER_MASK(fs); + fillable = min(range_len + cluster_fill, max_extent_len); + err = ext2fs_new_range(fs, 0, pblk & ~EXT2FS_CLUSTER_MASK(fs), + fillable, + NULL, &pblk, &plen); + if (err) + goto out; + err = claim_range(fs, inode, pblk, plen); + if (err) + goto out; + + /* Create extent */ + newex.e_pblk = pblk + cluster_fill; + newex.e_len = plen - cluster_fill; + dbg_print_extent("ext_falloc create", &newex); + ext2fs_extent_goto(handle, newex.e_lblk); + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &ex); + if (err == EXT2_ET_NO_CURRENT_NODE) + ex.e_lblk = 0; + else if (err) + goto out; + + if (ex.e_lblk > newex.e_lblk) + op = 0; /* insert before */ + else + op = EXT2_EXTENT_INSERT_AFTER; + dbg_printf("%s: inserting %s lblk %llu newex=%llu\n", + __func__, op ? "after" : "before", ex.e_lblk, + newex.e_lblk); + err = ext2fs_extent_insert(handle, op, &newex); + if (err) + goto out; + err = ext2fs_extent_fix_parents(handle); + if (err) + goto out; + + if (!(newex.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + (flags & EXT2_FALLOCATE_ZERO_BLOCKS)) { + err = ext2fs_zero_blocks2(fs, pblk, plen, NULL, NULL); + if (err) + goto out; + } + + /* Update variables at end of loop */ + x += plen - cluster_fill; + range_len -= plen - cluster_fill; + newex.e_lblk += plen - cluster_fill; + pblk += plen - cluster_fill; + if (pblk >= ext2fs_blocks_count(fs->super)) + pblk = fs->super->s_first_data_block; + } + +out: + return err; +} + +static errcode_t extent_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t goal, + blk64_t start, blk64_t len) +{ + ext2_extent_handle_t handle; + struct ext2fs_extent left_extent, right_extent; + struct ext2fs_extent *left_adjacent, *right_adjacent; + errcode_t err; + blk64_t range_start, range_end = 0, end, next; + blk64_t count, goal_distance; + + end = start + len - 1; + err = ext2fs_extent_open2(fs, ino, inode, &handle); + if (err) + return err; + + /* + * Find the extent closest to the start of the alloc range. We don't + * check the return value because _goto() sets the current node to the + * next-lowest extent if 'start' is in a hole; or the next-highest + * extent if there aren't any lower ones; or doesn't set a current node + * if there was a real error reading the extent tree. In that case, + * _get() will error out. + */ +start_again: + ext2fs_extent_goto(handle, start); + err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &left_extent); + if (err == EXT2_ET_NO_CURRENT_NODE) { + blk64_t max_blocks = ext2fs_blocks_count(fs->super); + + if (goal == ~0ULL) + goal = ext2fs_find_inode_goal(fs, ino, inode, start); + err = ext2fs_find_first_zero_block_bitmap2(fs->block_map, + goal, max_blocks - 1, &goal); + goal += start; + err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL, + NULL, start, len, goal); + goto errout; + } else if (err) + goto errout; + + dbg_print_extent("ext_falloc initial", &left_extent); + next = left_extent.e_lblk + left_extent.e_len; + if (left_extent.e_lblk > start) { + /* The nearest extent we found was beyond start??? */ + goal = left_extent.e_pblk - (left_extent.e_lblk - start); + err = ext_falloc_helper(fs, flags, ino, inode, handle, NULL, + &left_extent, start, + left_extent.e_lblk - start, goal); + if (err) + goto errout; + + goto start_again; + } else if (next >= start) { + range_start = next; + left_adjacent = &left_extent; + } else { + range_start = start; + left_adjacent = NULL; + } + goal = left_extent.e_pblk + (range_start - left_extent.e_lblk); + + do { + err = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, + &right_extent); + dbg_printf("%s: ino=%d get next =%d\n", __func__, ino, + (int)err); + dbg_print_extent("ext_falloc next", &right_extent); + /* Stop if we've seen this extent before */ + if (!err && right_extent.e_lblk <= left_extent.e_lblk) + err = EXT2_ET_EXTENT_NO_NEXT; + + if (err && err != EXT2_ET_EXTENT_NO_NEXT) + goto errout; + if (err == EXT2_ET_EXTENT_NO_NEXT || + right_extent.e_lblk > end + 1) { + range_end = end; + right_adjacent = NULL; + } else { + /* Handle right_extent.e_lblk <= end */ + range_end = right_extent.e_lblk - 1; + right_adjacent = &right_extent; + } + goal_distance = range_start - next; + if (err != EXT2_ET_EXTENT_NO_NEXT && + goal_distance > (range_end - right_extent.e_lblk)) + goal = right_extent.e_pblk - + (right_extent.e_lblk - range_start); + + dbg_printf("%s: ino=%d rstart=%llu rend=%llu\n", __func__, ino, + range_start, range_end); + err = 0; + if (range_start <= range_end) { + count = range_end - range_start + 1; + err = ext_falloc_helper(fs, flags, ino, inode, handle, + left_adjacent, right_adjacent, + range_start, count, goal); + if (err) + goto errout; + } + + if (range_end == end) + break; + + err = ext2fs_extent_goto(handle, right_extent.e_lblk); + if (err) + goto errout; + next = right_extent.e_lblk + right_extent.e_len; + left_extent = right_extent; + left_adjacent = &left_extent; + range_start = next; + goal = left_extent.e_pblk + (range_start - left_extent.e_lblk); + } while (range_end < end); + +errout: + ext2fs_extent_free(handle); + return err; +} + +/* + * Map physical blocks to a range of logical blocks within a file. The range + * of logical blocks are (start, start + len). If there are already extents, + * the mappings will try to extend the mappings; otherwise, it will try to map + * start as if logical block 0 points to goal. If goal is ~0ULL, then the goal + * is calculated based on the inode group. + * + * Flags: + * - EXT2_FALLOCATE_ZERO_BLOCKS: Zero the blocks that are allocated. + * - EXT2_FALLOCATE_FORCE_INIT: Create only initialized extents. + * - EXT2_FALLOCATE_FORCE_UNINIT: Create only uninitialized extents. + * - EXT2_FALLOCATE_INIT_BEYOND_EOF: Create extents beyond EOF. + * + * If neither FORCE_INIT nor FORCE_UNINIT are specified, this function will + * try to expand any extents it finds, zeroing blocks as necessary. + */ +errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, + struct ext2_inode *inode, blk64_t goal, + blk64_t start, blk64_t len) +{ + struct ext2_inode inode_buf; + blk64_t blk, x, zero_blk, last = 0; + int zero_len = 0; + errcode_t err; + + if (((flags & EXT2_FALLOCATE_FORCE_INIT) && + (flags & EXT2_FALLOCATE_FORCE_UNINIT)) || + (flags & ~EXT2_FALLOCATE_ALL_FLAGS)) + return EXT2_ET_INVALID_ARGUMENT; + + if (len > ext2fs_blocks_count(fs->super)) + return EXT2_ET_BLOCK_ALLOC_FAIL; + else if (len == 0) + return 0; + + /* Read inode structure if necessary */ + if (!inode) { + err = ext2fs_read_inode(fs, ino, &inode_buf); + if (err) + return err; + inode = &inode_buf; + } + dbg_printf("%s: ino=%d start=%llu len=%llu goal=%llu\n", __func__, ino, + start, len, goal); + + if (inode->i_flags & EXT4_EXTENTS_FL) { + err = extent_fallocate(fs, flags, ino, inode, goal, start, len); + goto out; + } + + /* XXX: Allocate a bunch of blocks the slow way */ + for (blk = start; blk < start + len; blk++) { + err = ext2fs_bmap2(fs, ino, inode, NULL, 0, blk, 0, &x); + if (err) + return err; + if (x) + continue; + + err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC, + blk, 0, &x); + if (err) + goto errout; + if ((zero_len && (x != last+1)) || + (zero_len >= 65536)) { + err = ext2fs_zero_blocks2(fs, zero_blk, zero_len, + NULL, NULL); + zero_len = 0; + if (err) + goto errout; + } + if (zero_len == 0) { + zero_blk = x; + zero_len = 1; + } else { + zero_len++; + } + last = x; + } + +out: + if (inode == &inode_buf) + ext2fs_write_inode(fs, ino, inode); +errout: + if (zero_len) + ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL); + return err; +} diff --git a/jni/e2fsprogs/lib/ext2fs/fallocate.o b/jni/e2fsprogs/lib/ext2fs/fallocate.o new file mode 100755 index 0000000000000000000000000000000000000000..e45810ac3d1fb7863b547d4430bdf3fdff0c3476 GIT binary patch literal 13536 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 +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +struct ext2_file { + errcode_t magic; + ext2_filsys fs; + ext2_ino_t ino; + struct ext2_inode inode; + int flags; + __u64 pos; + blk64_t blockno; + blk64_t physblock; + char *buf; +}; + +struct block_entry { + blk64_t physblock; + unsigned char sha[EXT2FS_SHA512_LENGTH]; +}; +typedef struct block_entry *block_entry_t; + +#define BMAP_BUFFER (file->buf + fs->blocksize) + +errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + int flags, ext2_file_t *ret) +{ + ext2_file_t file; + errcode_t retval; + + /* + * Don't let caller create or open a file for writing if the + * filesystem is read-only. + */ + if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) && + !(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + retval = ext2fs_get_mem(sizeof(struct ext2_file), &file); + if (retval) + return retval; + + memset(file, 0, sizeof(struct ext2_file)); + file->magic = EXT2_ET_MAGIC_EXT2_FILE; + file->fs = fs; + file->ino = ino; + file->flags = flags & EXT2_FILE_MASK; + + if (inode) { + memcpy(&file->inode, inode, sizeof(struct ext2_inode)); + } else { + retval = ext2fs_read_inode(fs, ino, &file->inode); + if (retval) + goto fail; + } + + retval = ext2fs_get_array(3, fs->blocksize, &file->buf); + if (retval) + goto fail; + + *ret = file; + return 0; + +fail: + if (file->buf) + ext2fs_free_mem(&file->buf); + ext2fs_free_mem(&file); + return retval; +} + +errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, + int flags, ext2_file_t *ret) +{ + return ext2fs_file_open2(fs, ino, NULL, flags, ret); +} + +/* + * This function returns the filesystem handle of a file from the structure + */ +ext2_filsys ext2fs_file_get_fs(ext2_file_t file) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return 0; + return file->fs; +} + +/* + * This function returns the pointer to the inode of a file from the structure + */ +struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return NULL; + return &file->inode; +} + +/* This function returns the inode number from the structure */ +ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return 0; + return file->ino; +} + +/* + * This function flushes the dirty block buffer out to disk if + * necessary. + */ +errcode_t ext2fs_file_flush(ext2_file_t file) +{ + errcode_t retval; + ext2_filsys fs; + int ret_flags; + blk64_t dontcare; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + if (!(file->flags & EXT2_FILE_BUF_VALID) || + !(file->flags & EXT2_FILE_BUF_DIRTY)) + return 0; + + /* Is this an uninit block? */ + if (file->physblock && file->inode.i_flags & EXT4_EXTENTS_FL) { + retval = ext2fs_bmap2(fs, file->ino, &file->inode, BMAP_BUFFER, + 0, file->blockno, &ret_flags, &dontcare); + if (retval) + return retval; + if (ret_flags & BMAP_RET_UNINIT) { + retval = ext2fs_bmap2(fs, file->ino, &file->inode, + BMAP_BUFFER, BMAP_SET, + file->blockno, 0, + &file->physblock); + if (retval) + return retval; + } + } + + /* + * OK, the physical block hasn't been allocated yet. + * Allocate it. + */ + if (!file->physblock) { + retval = ext2fs_bmap2(fs, file->ino, &file->inode, + BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0, + file->blockno, 0, &file->physblock); + if (retval) + return retval; + } + + retval = io_channel_write_blk64(fs->io, file->physblock, 1, file->buf); + if (retval) + return retval; + + file->flags &= ~EXT2_FILE_BUF_DIRTY; + + return retval; +} + +/* + * This function synchronizes the file's block buffer and the current + * file position, possibly invalidating block buffer if necessary + */ +static errcode_t sync_buffer_position(ext2_file_t file) +{ + blk64_t b; + errcode_t retval; + + b = file->pos / file->fs->blocksize; + if (b != file->blockno) { + retval = ext2fs_file_flush(file); + if (retval) + return retval; + file->flags &= ~EXT2_FILE_BUF_VALID; + } + file->blockno = b; + return 0; +} + +/* + * This function loads the file's block buffer with valid data from + * the disk as necessary. + * + * If dontfill is true, then skip initializing the buffer since we're + * going to be replacing its entire contents anyway. If set, then the + * function basically only sets file->physblock and EXT2_FILE_BUF_VALID + */ +#define DONTFILL 1 +static errcode_t load_buffer(ext2_file_t file, int dontfill) +{ + ext2_filsys fs = file->fs; + errcode_t retval; + int ret_flags; + + if (!(file->flags & EXT2_FILE_BUF_VALID)) { + retval = ext2fs_bmap2(fs, file->ino, &file->inode, + BMAP_BUFFER, 0, file->blockno, &ret_flags, + &file->physblock); + if (retval) + return retval; + if (!dontfill) { + if (file->physblock && + !(ret_flags & BMAP_RET_UNINIT)) { + retval = io_channel_read_blk64(fs->io, + file->physblock, + 1, file->buf); + if (retval) + return retval; + } else + memset(file->buf, 0, fs->blocksize); + } + file->flags |= EXT2_FILE_BUF_VALID; + } + return 0; +} + + +errcode_t ext2fs_file_close(ext2_file_t file) +{ + errcode_t retval; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + retval = ext2fs_file_flush(file); + + if (file->buf) + ext2fs_free_mem(&file->buf); + ext2fs_free_mem(&file); + + return retval; +} + + +static errcode_t +ext2fs_file_read_inline_data(ext2_file_t file, void *buf, + unsigned int wanted, unsigned int *got) +{ + ext2_filsys fs; + errcode_t retval; + unsigned int count = 0; + size_t size; + + fs = file->fs; + retval = ext2fs_inline_data_get(fs, file->ino, &file->inode, + file->buf, &size); + if (retval) + return retval; + + if (file->pos >= size) + goto out; + + count = size - file->pos; + if (count > wanted) + count = wanted; + memcpy(buf, file->buf + file->pos, count); + file->pos += count; + buf = (char *) buf + count; + +out: + if (got) + *got = count; + return retval; +} + + +errcode_t ext2fs_file_read(ext2_file_t file, void *buf, + unsigned int wanted, unsigned int *got) +{ + ext2_filsys fs; + errcode_t retval = 0; + unsigned int start, c, count = 0; + __u64 left; + char *ptr = (char *) buf; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + /* If an inode has inline data, things get complicated. */ + if (file->inode.i_flags & EXT4_INLINE_DATA_FL) + return ext2fs_file_read_inline_data(file, buf, wanted, got); + + while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) { + retval = sync_buffer_position(file); + if (retval) + goto fail; + retval = load_buffer(file, 0); + if (retval) + goto fail; + + start = file->pos % fs->blocksize; + c = fs->blocksize - start; + if (c > wanted) + c = wanted; + left = EXT2_I_SIZE(&file->inode) - file->pos ; + if (c > left) + c = left; + + memcpy(ptr, file->buf+start, c); + file->pos += c; + ptr += c; + count += c; + wanted -= c; + } + +fail: + if (got) + *got = count; + return retval; +} + + +static errcode_t +ext2fs_file_write_inline_data(ext2_file_t file, const void *buf, + unsigned int nbytes, unsigned int *written) +{ + ext2_filsys fs; + errcode_t retval; + unsigned int count = 0; + size_t size; + + fs = file->fs; + retval = ext2fs_inline_data_get(fs, file->ino, &file->inode, + file->buf, &size); + if (retval) + return retval; + + if (file->pos < size) { + count = nbytes - file->pos; + memcpy(file->buf + file->pos, buf, count); + + retval = ext2fs_inline_data_set(fs, file->ino, &file->inode, + file->buf, count); + if (retval == EXT2_ET_INLINE_DATA_NO_SPACE) + goto expand; + if (retval) + return retval; + + file->pos += count; + + /* Update inode size */ + if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) { + errcode_t rc; + + rc = ext2fs_file_set_size2(file, file->pos); + if (retval == 0) + retval = rc; + } + + if (written) + *written = count; + return 0; + } + +expand: + retval = ext2fs_inline_data_expand(fs, file->ino); + if (retval) + return retval; + /* + * reload inode and return no space error + * + * XXX: file->inode could be copied from the outside + * in ext2fs_file_open2(). We have no way to modify + * the outside inode. + */ + retval = ext2fs_read_inode(fs, file->ino, &file->inode); + if (retval) + return retval; + return EXT2_ET_INLINE_DATA_NO_SPACE; +} + + +errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, + unsigned int nbytes, unsigned int *written) +{ + ext2_filsys fs; + errcode_t retval = 0; + unsigned int start, c, count = 0; + const char *ptr = (const char *) buf; + block_entry_t new_block = NULL, old_block = NULL; + int bmap_flags = 0; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + if (!(file->flags & EXT2_FILE_WRITE)) + return EXT2_ET_FILE_RO; + + /* If an inode has inline data, things get complicated. */ + if (file->inode.i_flags & EXT4_INLINE_DATA_FL) { + retval = ext2fs_file_write_inline_data(file, buf, nbytes, + written); + if (retval != EXT2_ET_INLINE_DATA_NO_SPACE) + return retval; + /* fall through to read data from the block */ + retval = 0; + } + + while (nbytes > 0) { + retval = sync_buffer_position(file); + if (retval) + goto fail; + + start = file->pos % fs->blocksize; + c = fs->blocksize - start; + if (c > nbytes) + c = nbytes; + + /* + * We only need to do a read-modify-update cycle if + * we're doing a partial write. + */ + retval = load_buffer(file, (c == fs->blocksize)); + if (retval) + goto fail; + + file->flags |= EXT2_FILE_BUF_DIRTY; + memcpy(file->buf+start, ptr, c); + + /* + * OK, the physical block hasn't been allocated yet. + * Allocate it. + */ + if (!file->physblock) { + bmap_flags = (file->ino ? BMAP_ALLOC : 0); + if (fs->flags & EXT2_FLAG_SHARE_DUP) { + new_block = calloc(1, sizeof(*new_block)); + if (!new_block) { + retval = EXT2_ET_NO_MEMORY; + goto fail; + } + ext2fs_sha512((const unsigned char*)file->buf, + fs->blocksize, new_block->sha); + old_block = ext2fs_hashmap_lookup( + fs->block_sha_map, + new_block->sha, + sizeof(new_block->sha)); + } + + if (old_block) { + file->physblock = old_block->physblock; + bmap_flags |= BMAP_SET; + free(new_block); + new_block = NULL; + } + + retval = ext2fs_bmap2(fs, file->ino, &file->inode, + BMAP_BUFFER, + bmap_flags, + file->blockno, 0, + &file->physblock); + if (retval) { + free(new_block); + new_block = NULL; + goto fail; + } + + if (new_block) { + new_block->physblock = file->physblock; + int ret = ext2fs_hashmap_add(fs->block_sha_map, + new_block, new_block->sha, + sizeof(new_block->sha)); + if (ret) { + retval = EXT2_ET_NO_MEMORY; + free(new_block); + goto fail; + } + } + + if (bmap_flags & BMAP_SET) { + ext2fs_iblk_add_blocks(fs, &file->inode, 1); + ext2fs_write_inode(fs, file->ino, &file->inode); + } + } + + file->pos += c; + ptr += c; + count += c; + nbytes -= c; + } + +fail: + /* Update inode size */ + if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) { + errcode_t rc; + + rc = ext2fs_file_set_size2(file, file->pos); + if (retval == 0) + retval = rc; + } + + if (written) + *written = count; + return retval; +} + +errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, + int whence, __u64 *ret_pos) +{ + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + if (whence == EXT2_SEEK_SET) + file->pos = offset; + else if (whence == EXT2_SEEK_CUR) + file->pos += offset; + else if (whence == EXT2_SEEK_END) + file->pos = EXT2_I_SIZE(&file->inode) + offset; + else + return EXT2_ET_INVALID_ARGUMENT; + + if (ret_pos) + *ret_pos = file->pos; + + return 0; +} + +errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, + int whence, ext2_off_t *ret_pos) +{ + __u64 loffset, ret_loffset = 0; + errcode_t retval; + + loffset = offset; + retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset); + if (ret_pos) + *ret_pos = (ext2_off_t) ret_loffset; + return retval; +} + + +/* + * This function returns the size of the file, according to the inode + */ +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return EXT2_ET_MAGIC_EXT2_FILE; + *ret_size = EXT2_I_SIZE(&file->inode); + return 0; +} + +/* + * This function returns the size of the file, according to the inode + */ +ext2_off_t ext2fs_file_get_size(ext2_file_t file) +{ + __u64 size; + + if (ext2fs_file_get_lsize(file, &size)) + return 0; + if ((size >> 32) != 0) + return 0; + return size; +} + +/* Zero the parts of the last block that are past EOF. */ +static errcode_t ext2fs_file_zero_past_offset(ext2_file_t file, + ext2_off64_t offset) +{ + ext2_filsys fs = file->fs; + char *b = NULL; + ext2_off64_t off = offset % fs->blocksize; + blk64_t blk; + int ret_flags; + errcode_t retval; + + if (off == 0) + return 0; + + retval = sync_buffer_position(file); + if (retval) + return retval; + + /* Is there an initialized block at the end? */ + retval = ext2fs_bmap2(fs, file->ino, NULL, NULL, 0, + offset / fs->blocksize, &ret_flags, &blk); + if (retval) + return retval; + if ((blk == 0) || (ret_flags & BMAP_RET_UNINIT)) + return 0; + + /* Zero to the end of the block */ + retval = ext2fs_get_mem(fs->blocksize, &b); + if (retval) + return retval; + + /* Read/zero/write block */ + retval = io_channel_read_blk64(fs->io, blk, 1, b); + if (retval) + goto out; + + memset(b + off, 0, fs->blocksize - off); + + retval = io_channel_write_blk64(fs->io, blk, 1, b); + if (retval) + goto out; + +out: + ext2fs_free_mem(&b); + return retval; +} + +/* + * This function sets the size of the file, truncating it if necessary + * + */ +errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size) +{ + ext2_off64_t old_size; + errcode_t retval; + blk64_t old_truncate, truncate_block; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + if (size && ext2fs_file_block_offset_too_big(file->fs, &file->inode, + (size - 1) / file->fs->blocksize)) + return EXT2_ET_FILE_TOO_BIG; + truncate_block = ((size + file->fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(file->fs->super)); + old_size = EXT2_I_SIZE(&file->inode); + old_truncate = ((old_size + file->fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(file->fs->super)); + + retval = ext2fs_inode_size_set(file->fs, &file->inode, size); + if (retval) + return retval; + + if (file->ino) { + retval = ext2fs_write_inode(file->fs, file->ino, &file->inode); + if (retval) + return retval; + } + + retval = ext2fs_file_zero_past_offset(file, size); + if (retval) + return retval; + + if (truncate_block >= old_truncate) + return 0; + + return ext2fs_punch(file->fs, file->ino, &file->inode, 0, + truncate_block, ~0ULL); +} + +errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size) +{ + return ext2fs_file_set_size2(file, size); +} diff --git a/jni/e2fsprogs/lib/ext2fs/fileio.o b/jni/e2fsprogs/lib/ext2fs/fileio.o new file mode 100755 index 0000000000000000000000000000000000000000..ae3fc74838275ac042b9bb8f6b6ff58367d56645 GIT binary patch literal 11416 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/finddev.c b/jni/e2fsprogs/lib/ext2fs/finddev.c new file mode 100755 index 0000000..cd85ef5 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/finddev.c @@ -0,0 +1,218 @@ +/* + * finddev.c -- this routine attempts to find a particular device in + * /dev + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +struct dir_list { + char *name; + struct dir_list *next; +}; + +/* + * This function adds an entry to the directory list + */ +static void add_to_dirlist(const char *name, struct dir_list **list) +{ + struct dir_list *dp; + + dp = malloc(sizeof(struct dir_list)); + if (!dp) + return; + dp->name = malloc(strlen(name)+1); + if (!dp->name) { + free(dp); + return; + } + strcpy(dp->name, name); + dp->next = *list; + *list = dp; +} + +/* + * This function frees a directory list + */ +static void free_dirlist(struct dir_list **list) +{ + struct dir_list *dp, *next; + + for (dp = *list; dp; dp = next) { + next = dp->next; + free(dp->name); + free(dp); + } + *list = 0; +} + +static int scan_dir(char *dirname, dev_t device, struct dir_list **list, + char **ret_path) +{ + DIR *dir; + struct dirent *dp; + char path[1024], *cp; + int dirlen; + struct stat st; + + dirlen = strlen(dirname); + if ((dir = opendir(dirname)) == NULL) + return errno; + dp = readdir(dir); + while (dp) { + if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) + goto skip_to_next; + if (dp->d_name[0] == '.' && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) + goto skip_to_next; + sprintf(path, "%s/%s", dirname, dp->d_name); + if (stat(path, &st) < 0) + goto skip_to_next; + if (S_ISDIR(st.st_mode)) + add_to_dirlist(path, list); + if (ext2fsP_is_disk_device(st.st_mode) && + st.st_rdev == device) { + cp = malloc(strlen(path)+1); + if (!cp) { + closedir(dir); + return ENOMEM; + } + strcpy(cp, path); + *ret_path = cp; + goto success; + } + skip_to_next: + dp = readdir(dir); + } +success: + closedir(dir); + return 0; +} + +/* + * This function finds the pathname to a block device with a given + * device number. It returns a pointer to allocated memory to the + * pathname on success, and NULL on failure. + */ +char *ext2fs_find_block_device(dev_t device) +{ + struct dir_list *list = 0, *new_list = 0; + struct dir_list *current; + char *ret_path = 0; + int level = 0; + + /* + * Add the starting directories to search... + */ + add_to_dirlist("/devices", &list); + add_to_dirlist("/devfs", &list); + add_to_dirlist("/dev", &list); + + while (list) { + current = list; + list = list->next; +#ifdef DEBUG + printf("Scanning directory %s\n", current->name); +#endif + scan_dir(current->name, device, &new_list, &ret_path); + free(current->name); + free(current); + if (ret_path) + break; + /* + * If we're done checking at this level, descend to + * the next level of subdirectories. (breadth-first) + */ + if (list == 0) { + list = new_list; + new_list = 0; + /* Avoid infinite loop */ + if (++level >= EXT2FS_MAX_NESTED_LINKS) + break; + } + } + free_dirlist(&list); + free_dirlist(&new_list); + return ret_path; +} + + +#ifdef DEBUG +int main(int argc, char** argv) +{ + char *devname, *tmp; + int major, minor; + dev_t device; + const char *errmsg = "Couldn't parse %s: %s\n"; + + if ((argc != 2) && (argc != 3)) { + fprintf(stderr, "Usage: %s device_number\n", argv[0]); + fprintf(stderr, "\t: %s major minor\n", argv[0]); + exit(1); + } + if (argc == 2) { + device = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "device number", argv[1]); + exit(1); + } + } else { + major = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "major number", argv[1]); + exit(1); + } + minor = strtoul(argv[2], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "minor number", argv[2]); + exit(1); + } + device = makedev(major, minor); + printf("Looking for device 0x%04x (%d:%d)\n", device, + major, minor); + } + devname = ext2fs_find_block_device(device); + if (devname) { + printf("Found device! %s\n", devname); + free(devname); + } else { + printf("Couldn't find device.\n"); + } + return 0; +} + +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/finddev.o b/jni/e2fsprogs/lib/ext2fs/finddev.o new file mode 100755 index 0000000000000000000000000000000000000000..bc817cae28a061f5a5ba5a106e357c6a5fb08a5a GIT binary patch literal 3712 zcmbtXUuaWT82@f=tG8O)YU}F!mpBy4{>0WfQP|)z>(+sa(>Z)lvzXp$F-_VeNL|NP z2#kU+hIMR=sj0$97y}2685mRN9>$*R7<+LWDefWSi;fL$h9UcX=blr~uFca!Z0XrZz1Bv%b@qtxYr)Yo?LQXM^s{PMV!t zOx0^<(7l#j@7CL?TJNS3RLUg@MNV^*^b z8FVY1uwmHMnQX+p7^B%cG0MFLU4_H`beTDfwcFJb9$K& zGcB(mUTXu5og{jLIVK*Kx9j!pJo5VjHuLcLIs1U^+C+a5b;w;eBfr#d66z5s*0Ln( zF}IYe6qx);#Dlt2kUL@#zE{I$9`W-YHBnB)%C#{(o`w7hl3Vs_HoXiwY(wQPbe7sx z=H3O~)9mTq1=a&Q9CvNvtdd@$KGL;Xv_$B^%vOd_Kp(bp_`jI7BZn zXB(c2$c1qee#@5vxiadHy|Ww8hnxe~bPj#P^S8*|#(F(?D$k$~mUXSLmfK@Dr2QH5 zsLM8{>h+J9R|e-*)-%1BDnYwiL@!xJ%e@;iZsxOXb++XLIGY1@wIb`N>NaIe?&n&r zV7u6#lX}c8W{%L4k2dxp=3 zbt>TgV8}D$^TB&o;eN%Odrj1f=g3F!Q9IWC6EU!@AY#<}tiF?G%k5OcyXV#NNqel^ zePK0l(TAG{om0axCrvyV@&s*4Z{Cz9ip8Ue)$eIy1qG)lhkS2tf6M+GF`+1N?Xc zoYP;(&PxsONCSLt1N_|vI5+e{es?v%xhHvaB4Ep#ir;7De5DUpFO1^1NZyM+zQPA2 zuJ|gp-9Em;KbH6!_{BGAe&prMkK+y#gK@p>`!&2>>ay6a;W|IA;kw^R4OcO;ou4&a zxBrKRFK410e`z@GJ$!*%O|U)AjJU7^PJ8m_p! z7n1KM$D{l0(Qv(PwuV2Uj6)vMaJ_CB4cGIX(s12QMZ@)Tx!(X^D`RLz{4zy>^!sr2 zzQ=vIy0=sxDm&`ly6)qvdyCSURBZG#g;P#E8qPT58Hx@LMl#9B;BYEFoX*ft%5mlw z;aGBH#7ShJ7R^v{)JcGb4^%Sk@Fe9x88RJ z`mvLg9!(7=GDFh4b0RX7ijFwKB_Wh8L+O2y;WR9zPe!~Cq=X|w!->Jjv3N2zzcCVx zV@bRLYB)w=IL$1d4tq*U=MxfwXm{k8l+>g(?an^1a6CNzxq)hPNCl^aS=@y=kvnEnp&-eswO yix=8Z`77vsOqgmbK+17>e&ce@_2ZH%eO13Z!2G^hWm10Pd*mj^$p1q6_5TGeP(G;u literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/flushb.c b/jni/e2fsprogs/lib/ext2fs/flushb.c new file mode 100755 index 0000000..bb7daf4 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/flushb.c @@ -0,0 +1,88 @@ +/* + * flushb.c --- Hides system-dependent information for both syncing a + * device to disk and to flush any buffers from disk cache. + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#include /* This may define BLKFLSBUF */ +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since + * not all portable header file does so for us. This really should be + * fixed in the glibc header files. (Recent glibcs appear to define + * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be + * defined anywhere portable.) Until then.... + */ +#ifdef __linux__ +#ifndef BLKFLSBUF +#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ +#endif +#ifndef FDFLUSH +#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */ +#endif +#endif + +/* + * This function will sync a device/file, and optionally attempt to + * flush the buffer cache. The latter is basically only useful for + * system benchmarks and for torturing systems in burn-in tests. :) + */ +errcode_t ext2fs_sync_device(int fd, int flushb) +{ + /* + * We always sync the device in case we're running on old + * kernels for which we can lose data if we don't. (There + * still is a race condition for those kernels, but this + * reduces it greatly.) + */ +#if defined(HAVE_FSYNC) + if (fsync (fd) == -1) + return errno; +#endif + + if (flushb) { + errcode_t retval = 0; + +#ifdef BLKFLSBUF + if (ioctl (fd, BLKFLSBUF, 0) == 0) + return 0; + retval = errno; +#elif defined(__linux__) +#warning BLKFLSBUF not defined +#endif +#ifdef FDFLUSH + /* In case this is a floppy */ + if (ioctl(fd, FDFLUSH, 0) == 0) + return 0; + if (retval == 0) + retval = errno; +#elif defined(__linux__) +#warning FDFLUSH not defined +#endif + return retval; + } + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/flushb.o b/jni/e2fsprogs/lib/ext2fs/flushb.o new file mode 100755 index 0000000000000000000000000000000000000000..75d0f2032b1bac0d95dbdf5999f070cda43249f5 GIT binary patch literal 1488 zcmbu9&1(};5Wr_Q(WDSdv8@QTZp9p=;3H`jdR$sRDijZ;J$YESn@tl;c4c=hjTH^% zA85g=lB4|t#0CTvFJ1-lrl6-D>#aS6IJ5g+`jTu;4&=R=-+b)6*|&Ldd*zO*C?G_E z_i$rtzB;-E>tYN*0(1v>J zZ9_ZGqJ227x6prse4P}WP|lT=m#cpg+APJ^0dA7-BgS8p@(+2ed9NNDdyZmemyR1xQG`NNgdkp0}t+z&V%bDr1H|p!8`XQs`mPg^&&&WS)eSnT6{O!c~6QB;@ z=OG#7wU8$V;)9T!9pH;d&P(;f{*kTYPn=awnjFHXhj1~MDI9c4Dnv6QA)b!Za9!g% z@ezraBreC-B`(J|B`(Kb;`|KO@0lL+?25?(dpiJTxz(!e1Yj7p=Q%EvT`Q;nbKJmY zcki!X_XE><1W|@vGK!vAwE;8dioW639Lp%!TV>0JA{kJuJn>5#%mU^IUSMwEUaQic zEwDLS@{rwTIo{ZRZUxMjKGkluG>45Yi4+_|kI)Sv)_+rU9wqJvH}TH)3gr^hdoeuZ z!`|hb-U%V`Zp1ywAfp=nCQhPN6+_1MM8o*HM>6 n^e@;vDsksO;swPyDUW6>@&&IT>wh*Pc+8)FL +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "hashmap.h" + +void ext2fs_free(ext2_filsys fs) +{ + if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)) + return; + if (fs->image_io != fs->io) { + if (fs->image_io) + io_channel_close(fs->image_io); + } + if (fs->io) { + io_channel_close(fs->io); + } + if (fs->device_name) + ext2fs_free_mem(&fs->device_name); + if (fs->super) + ext2fs_free_mem(&fs->super); + if (fs->orig_super) + ext2fs_free_mem(&fs->orig_super); + if (fs->group_desc) + ext2fs_free_mem(&fs->group_desc); + if (fs->block_map) + ext2fs_free_block_bitmap(fs->block_map); + if (fs->inode_map) + ext2fs_free_inode_bitmap(fs->inode_map); + if (fs->image_header) + ext2fs_free_mem(&fs->image_header); + + if (fs->badblocks) + ext2fs_badblocks_list_free(fs->badblocks); + fs->badblocks = 0; + + if (fs->dblist) + ext2fs_free_dblist(fs->dblist); + + if (fs->icache) + ext2fs_free_inode_cache(fs->icache); + + if (fs->mmp_buf) + ext2fs_free_mem(&fs->mmp_buf); + if (fs->mmp_cmp) + ext2fs_free_mem(&fs->mmp_cmp); + + if (fs->block_sha_map) + ext2fs_hashmap_free(fs->block_sha_map); + + fs->magic = 0; + + ext2fs_zero_blocks2(NULL, 0, 0, NULL, NULL); + ext2fs_free_mem(&fs); +} + +/* + * This procedure frees a badblocks list. + */ +void ext2fs_u32_list_free(ext2_u32_list bb) +{ + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return; + + if (bb->list) + ext2fs_free_mem(&bb->list); + bb->list = 0; + ext2fs_free_mem(&bb); +} + +void ext2fs_badblocks_list_free(ext2_badblocks_list bb) +{ + ext2fs_u32_list_free((ext2_u32_list) bb); +} + + +/* + * Free a directory block list + */ +void ext2fs_free_dblist(ext2_dblist dblist) +{ + if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST)) + return; + + if (dblist->list) + ext2fs_free_mem(&dblist->list); + dblist->list = 0; + if (dblist->fs && dblist->fs->dblist == dblist) + dblist->fs->dblist = 0; + dblist->magic = 0; + ext2fs_free_mem(&dblist); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/freefs.o b/jni/e2fsprogs/lib/ext2fs/freefs.o new file mode 100755 index 0000000000000000000000000000000000000000..2cedfab5e734bb255d5e2806ff72b98462beeaae GIT binary patch literal 3128 zcmbtWPiPcZ82@Hx)9h+YwWt(KofUI1g$zyVAqT+?8cje%i$W=db#^o9Zrwj&cNC3+ zkzNu|Fd*Wkg+LGLr4$4Wct~$KsuWL6Sz84qr<5Mt(xBh>=DnFW-_F`YAI!e@{eHji z&wKOD%w8Egb|hgKpoRetAhZ+;@FpFuvtpTrG%DYI2TwLG8Fx1h!9ueeTCcjZt$haE z#~9mboiehmf#$8JrI$bbl`_(6X8=wScU$onv#r;t8|Wf!daY^ryzoVCT#toziga6i zpA6by9DGLcf_%tFd`PeR;9B{J92jc_!g|4h1>D}vAl^2{UuFDB&L^V&dl+vRQGSr| zXh-r7Fdpp)f12@&EdLne(boN~G5?;WCYTOwU6(q?c(fz@JmW``(S2TLyui=Kl^C5Z@Icox1)Qe3z1JvN& zm(;oZSN$ntc4;E!+3Qs`r&-OTVa-9lGz9lS&j*FFQ~f4$-mN!EwQ6Q)#2&Iou&}Lo z(J*Gd0ORs*V^@y_{b+wIP=Fs3xH#OK8SnXI>ko;G1w? zar#H7r@V6}E^tiy6Z|UYUFg>>*EIdz0jC!}4X)qc0Y9bTDc@E6dK#{M;=~6aF8+N@ zze$Vpn}%=J@P9R&&Q^^+dA_{<10C?MHGGQ-g7ch)<8vL18yc>k=R*zuFi->Z$@{_U z@jBp-JK!%m;C(Vz7oLYKK_G`2uKKaeaMh1D8Ls*W?7CZaY|p*m0bavXjoeh-b#s&X za;f2gU8q$mZZ*o~%eBJUT)yO0oau;Dsal(KI$p(}NAqDV&vw-6H05 zDsD`if>S64c;3N^Fl{48b%`34%el{o+d-z$=tKyN(4_?s^)9p13u z{LM+egekprgE<)x|3`{J#Of|A%B~L)EXK8C=BezbJ)gq>xNH66LS +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +struct ext2fs_struct_generic_bitmap_32 { + errcode_t magic; + ext2_filsys fs; + __u32 start, end; + __u32 real_end; + char * description; + char * bitmap; + errcode_t base_error_code; + __u32 reserved[7]; +}; + +typedef struct ext2fs_struct_generic_bitmap_32 *ext2fs_generic_bitmap_32; + +#define EXT2FS_IS_32_BITMAP(bmap) \ + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \ + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \ + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP)) + +#define EXT2FS_IS_64_BITMAP(bmap) \ + (((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \ + ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \ + ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64)) + +/* + * Used by previously inlined function, so we have to export this and + * not change the function signature + */ +void ext2fs_warn_bitmap2(ext2fs_generic_bitmap gen_bitmap, + int code, unsigned long arg) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + +#ifndef OMIT_COM_ERR + if (bitmap->description) + com_err(0, bitmap->base_error_code+code, + "#%lu for %s", arg, bitmap->description); + else + com_err(0, bitmap->base_error_code + code, "#%lu", arg); +#endif +} + +static errcode_t check_magic(ext2fs_generic_bitmap bitmap) +{ + if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || + (bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) || + (bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP))) + return EXT2_ET_MAGIC_GENERIC_BITMAP; + return 0; +} + +errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs, + __u32 start, __u32 end, __u32 real_end, + const char *descr, char *init_map, + ext2fs_generic_bitmap *ret) +{ + ext2fs_generic_bitmap_32 bitmap; + errcode_t retval; + size_t size; + + retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap_32), + &bitmap); + if (retval) + return retval; + + bitmap->magic = magic; + bitmap->fs = fs; + bitmap->start = start; + bitmap->end = end; + bitmap->real_end = real_end; + switch (magic) { + case EXT2_ET_MAGIC_INODE_BITMAP: + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; + break; + case EXT2_ET_MAGIC_BLOCK_BITMAP: + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; + break; + default: + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; + } + if (descr) { + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); + if (retval) { + ext2fs_free_mem(&bitmap); + return retval; + } + strcpy(bitmap->description, descr); + } else + bitmap->description = 0; + + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); + /* Round up to allow for the BT x86 instruction */ + size = (size + 7) & ~3; + retval = ext2fs_get_mem(size, &bitmap->bitmap); + if (retval) { + ext2fs_free_mem(&bitmap->description); + ext2fs_free_mem(&bitmap); + return retval; + } + + if (init_map) + memcpy(bitmap->bitmap, init_map, size); + else + memset(bitmap->bitmap, 0, size); + *ret = (ext2fs_generic_bitmap) bitmap; + return 0; +} + +errcode_t ext2fs_allocate_generic_bitmap(__u32 start, + __u32 end, + __u32 real_end, + const char *descr, + ext2fs_generic_bitmap *ret) +{ + return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0, + start, end, real_end, descr, 0, ret); +} + +errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap gen_src, + ext2fs_generic_bitmap *dest) +{ + ext2fs_generic_bitmap_32 src = (ext2fs_generic_bitmap_32) gen_src; + + return (ext2fs_make_generic_bitmap(src->magic, src->fs, + src->start, src->end, + src->real_end, + src->description, src->bitmap, + dest)); +} + +void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap gen_bitmap) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + + if (check_magic(gen_bitmap)) + return; + + bitmap->magic = 0; + if (bitmap->description) { + ext2fs_free_mem(&bitmap->description); + bitmap->description = 0; + } + if (bitmap->bitmap) { + ext2fs_free_mem(&bitmap->bitmap); + bitmap->bitmap = 0; + } + ext2fs_free_mem(&bitmap); +} + +int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + return ext2fs_test_generic_bmap(bitmap, bitno); + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "test_bitmap(%lu)", (unsigned long) bitno); +#endif + return 0; + } + + if ((bitno < bitmap32->start) || (bitno > bitmap32->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); + return 0; + } + return ext2fs_test_bit(bitno - bitmap32->start, bitmap32->bitmap); +} + +int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 bitno) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + return ext2fs_mark_generic_bmap(bitmap, bitno); + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "mark_bitmap(%lu)", (unsigned long) bitno); +#endif + return 0; + } + + if ((bitno < bitmap32->start) || (bitno > bitmap32->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); + return 0; + } + return ext2fs_set_bit(bitno - bitmap32->start, bitmap32->bitmap); +} + +int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + return ext2fs_unmark_generic_bmap(bitmap, bitno); + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "mark_bitmap(%lu)", (unsigned long) bitno); +#endif + return 0; + } + + if ((bitno < bitmap32->start) || (bitno > bitmap32->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); + return 0; + } + return ext2fs_clear_bit(bitno - bitmap32->start, bitmap32->bitmap); +} + +__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + return ext2fs_get_generic_bmap_start(bitmap); + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "get_bitmap_start"); +#endif + return 0; + } + + return bitmap32->start; +} + +__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + return ext2fs_get_generic_bmap_end(bitmap); + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "get_bitmap_end"); +#endif + return 0; + } + return bitmap32->end; +} + +void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap) +{ + ext2fs_generic_bitmap_32 bitmap32 = (ext2fs_generic_bitmap_32) bitmap; + + if (!EXT2FS_IS_32_BITMAP(bitmap)) { + if (EXT2FS_IS_64_BITMAP(bitmap)) { + ext2fs_warn_bitmap32(bitmap, __func__); + ext2fs_clear_generic_bmap(bitmap); + return; + } +#ifndef OMIT_COM_ERR + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "clear_generic_bitmap"); +#endif + return; + } + + memset(bitmap32->bitmap, 0, + (size_t) (((bitmap32->real_end - bitmap32->start) / 8) + 1)); +} + +errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap gen_bitmap, + errcode_t magic, errcode_t neq, + ext2_ino_t end, ext2_ino_t *oend) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + + EXT2_CHECK_MAGIC(bitmap, magic); + + if (end > bitmap->real_end) + return neq; + if (oend) + *oend = bitmap->end; + bitmap->end = end; + return 0; +} + +errcode_t ext2fs_resize_generic_bitmap(errcode_t magic, + __u32 new_end, __u32 new_real_end, + ext2fs_generic_bitmap gen_bmap) +{ + ext2fs_generic_bitmap_32 bmap = (ext2fs_generic_bitmap_32) gen_bmap; + errcode_t retval; + size_t size, new_size; + __u32 bitno; + + if (!bmap || (bmap->magic != magic)) + return magic; + + /* + * If we're expanding the bitmap, make sure all of the new + * parts of the bitmap are zero. + */ + if (new_end > bmap->end) { + bitno = bmap->real_end; + if (bitno > new_end) + bitno = new_end; + for (; bitno > bmap->end; bitno--) + ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap); + } + if (new_real_end == bmap->real_end) { + bmap->end = new_end; + return 0; + } + + size = ((bmap->real_end - bmap->start) / 8) + 1; + new_size = ((new_real_end - bmap->start) / 8) + 1; + + if (size != new_size) { + retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap); + if (retval) + return retval; + } + if (new_size > size) + memset(bmap->bitmap + size, 0, new_size - size); + + bmap->end = new_end; + bmap->real_end = new_real_end; + return 0; +} + +errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq, + ext2fs_generic_bitmap gen_bm1, + ext2fs_generic_bitmap gen_bm2) +{ + ext2fs_generic_bitmap_32 bm1 = (ext2fs_generic_bitmap_32) gen_bm1; + ext2fs_generic_bitmap_32 bm2 = (ext2fs_generic_bitmap_32) gen_bm2; + blk_t i; + + if (!bm1 || bm1->magic != magic) + return magic; + if (!bm2 || bm2->magic != magic) + return magic; + + if ((bm1->start != bm2->start) || + (bm1->end != bm2->end) || + (memcmp(bm1->bitmap, bm2->bitmap, + (size_t) (bm1->end - bm1->start)/8))) + return neq; + + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) + if (ext2fs_fast_test_block_bitmap(gen_bm1, i) != + ext2fs_fast_test_block_bitmap(gen_bm2, i)) + return neq; + + return 0; +} + +void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap gen_map) +{ + ext2fs_generic_bitmap_32 map = (ext2fs_generic_bitmap_32) gen_map; + __u32 i, j; + + /* Protect loop from wrap-around if map->real_end is maxed */ + for (i=map->end+1, j = i - map->start; + i <= map->real_end && i > map->end; + i++, j++) + ext2fs_set_bit(j, map->bitmap); +} + +errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap gen_bmap, + errcode_t magic, + __u32 start, __u32 num, + void *out) +{ + ext2fs_generic_bitmap_32 bmap = (ext2fs_generic_bitmap_32) gen_bmap; + + if (!bmap || (bmap->magic != magic)) + return magic; + + if ((start < bmap->start) || (start+num-1 > bmap->real_end)) + return EXT2_ET_INVALID_ARGUMENT; + + memcpy(out, bmap->bitmap + ((start - bmap->start) >> 3), (num+7) >> 3); + return 0; +} + +errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap gen_bmap, + errcode_t magic, + __u32 start, __u32 num, + void *in) +{ + ext2fs_generic_bitmap_32 bmap = (ext2fs_generic_bitmap_32) gen_bmap; + + if (!bmap || (bmap->magic != magic)) + return magic; + + if ((start < bmap->start) || (start+num-1 > bmap->real_end)) + return EXT2_ET_INVALID_ARGUMENT; + + memcpy(bmap->bitmap + ((start - bmap->start) >> 3), in, (num+7) >> 3); + return 0; +} + +/* + * Compare @mem to zero buffer by 256 bytes. + * Return 1 if @mem is zeroed memory, otherwise return 0. + */ +int ext2fs_mem_is_zero(const char *mem, size_t len) +{ + static const char zero_buf[256]; + + while (len >= sizeof(zero_buf)) { + if (memcmp(mem, zero_buf, sizeof(zero_buf))) + return 0; + len -= sizeof(zero_buf); + mem += sizeof(zero_buf); + } + /* Deal with leftover bytes. */ + if (len) + return !memcmp(mem, zero_buf, len); + return 1; +} + +/* + * Return true if all of the bits in a specified range are clear + */ +static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap gen_bitmap, + unsigned int start, + unsigned int len) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + size_t start_byte, len_byte = len >> 3; + unsigned int start_bit, len_bit = len % 8; + int first_bit = 0; + int last_bit = 0; + int mark_count = 0; + int mark_bit = 0; + int i; + const char *ADDR = bitmap->bitmap; + + start -= bitmap->start; + start_byte = start >> 3; + start_bit = start % 8; + + if (start_bit != 0) { + /* + * The compared start block number or start inode number + * is not the first bit in a byte. + */ + mark_count = 8 - start_bit; + if (len < 8 - start_bit) { + mark_count = (int)len; + mark_bit = len + start_bit - 1; + } else + mark_bit = 7; + + for (i = mark_count; i > 0; i--, mark_bit--) + first_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the first byte. + * If there is any marked bit, this function returns 0. + */ + if (first_bit & ADDR[start_byte]) + return 0; + else if (len <= 8 - start_bit) + return 1; + + start_byte++; + len_bit = (len - mark_count) % 8; + len_byte = (len - mark_count) >> 3; + } + + /* + * The compared start block number or start inode number is + * the first bit in a byte. + */ + if (len_bit != 0) { + /* + * The compared end block number or end inode number is + * not the last bit in a byte. + */ + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--) + last_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the last byte. + * If there is any marked bit, this function returns 0. + */ + if (last_bit & ADDR[start_byte + len_byte]) + return 0; + else if (len_byte == 0) + return 1; + } + + /* Check whether all bytes are 0 */ + return ext2fs_mem_is_zero(ADDR + start_byte, len_byte); +} + +errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap gen_bitmap, + __u32 start, __u32 end, + __u32 *out) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + blk_t b; + + if (start < bitmap->start || end > bitmap->end || start > end) { + ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + while (start <= end) { + b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap); + if (!b) { + *out = start; + return 0; + } + start++; + } + + return ENOENT; +} + +errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap gen_bitmap, + __u32 start, __u32 end, + __u32 *out) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + blk_t b; + + if (start < bitmap->start || end > bitmap->end || start > end) { + ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + while (start <= end) { + b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap); + if (b) { + *out = start; + return 0; + } + start++; + } + + return ENOENT; +} + +int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap gen_bitmap, + blk_t block, int num) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); + if ((block < bitmap->start) || (block > bitmap->real_end) || + (block+num-1 > bitmap->real_end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, + block, bitmap->description); + return 0; + } + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap) + bitmap, block, num); +} + +int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap gen_bitmap, + ext2_ino_t inode, int num) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP); + if ((inode < bitmap->start) || (inode > bitmap->real_end) || + (inode+num-1 > bitmap->real_end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST, + inode, bitmap->description); + return 0; + } + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap) + bitmap, inode, num); +} + +void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap gen_bitmap, + blk_t block, int num) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + int i; + + if ((block < bitmap->start) || (block > bitmap->end) || + (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap); +} + +void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap gen_bitmap, + blk_t block, int num) +{ + ext2fs_generic_bitmap_32 bitmap = (ext2fs_generic_bitmap_32) gen_bitmap; + int i; + + if ((block < bitmap->start) || (block > bitmap->end) || + (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_fast_clear_bit(block + i - bitmap->start, + bitmap->bitmap); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/gen_bitmap.o b/jni/e2fsprogs/lib/ext2fs/gen_bitmap.o new file mode 100755 index 0000000000000000000000000000000000000000..8c531f05929fa18ddf55bae4feeb6be2d8397120 GIT binary patch literal 15608 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/gen_bitmap64.c b/jni/e2fsprogs/lib/ext2fs/gen_bitmap64.c new file mode 100755 index 0000000..4289e81 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/gen_bitmap64.c @@ -0,0 +1,981 @@ +/* + * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and + * block bitmaps. + * + * Copyright (C) 2007, 2008 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "bmap64.h" + +/* + * Design of 64-bit bitmaps + * + * In order maintain ABI compatibility with programs that don't + * understand about 64-bit blocks/inodes, + * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap() + * will create old-style bitmaps unless the application passes the + * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is + * passed, then we know the application has been recompiled, so we can + * use the new-style bitmaps. If it is not passed, we have to return + * an error if trying to open a filesystem which needs 64-bit bitmaps. + * + * The new bitmaps use a new set of structure magic numbers, so that + * both the old-style and new-style interfaces can identify which + * version of the data structure was used. Both the old-style and + * new-style interfaces will support either type of bitmap, although + * of course 64-bit operation will only be possible when both the + * new-style interface and the new-style bitmap are used. + * + * For example, the new bitmap interfaces will check the structure + * magic numbers and so will be able to detect old-stype bitmap. If + * they see an old-style bitmap, they will pass it to the gen_bitmap.c + * functions for handling. The same will be true for the old + * interfaces as well. + * + * The new-style interfaces will have several different back-end + * implementations, so we can support different encodings that are + * appropriate for different applications. In general the default + * should be whatever makes sense, and what the application/library + * will use. However, e2fsck may need specialized implementations for + * its own uses. For example, when doing parent directory pointer + * loop detections in pass 3, the bitmap will *always* be sparse, so + * e2fsck can request an encoding which is optimized for that. + */ + +static void warn_bitmap(ext2fs_generic_bitmap_64 bitmap, + int code, __u64 arg) +{ +#ifndef OMIT_COM_ERR + if (bitmap->description) + com_err(0, bitmap->base_error_code+code, + "#%llu for %s", (unsigned long long) arg, + bitmap->description); + else + com_err(0, bitmap->base_error_code + code, "#%llu", + (unsigned long long) arg); +#endif +} + +#ifdef ENABLE_BMAP_STATS_OPS +#define INC_STAT(map, name) map->stats.name +#else +#define INC_STAT(map, name) ;; +#endif + + +errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic, + int type, __u64 start, __u64 end, + __u64 real_end, + const char *descr, + ext2fs_generic_bitmap *ret) +{ + ext2fs_generic_bitmap_64 bitmap; + struct ext2_bitmap_ops *ops; + ext2_ino_t num_dirs; + errcode_t retval; + + if (!type) + type = EXT2FS_BMAP64_BITARRAY; + + switch (type) { + case EXT2FS_BMAP64_BITARRAY: + ops = &ext2fs_blkmap64_bitarray; + break; + case EXT2FS_BMAP64_RBTREE: + ops = &ext2fs_blkmap64_rbtree; + break; + case EXT2FS_BMAP64_AUTODIR: + retval = ext2fs_get_num_dirs(fs, &num_dirs); + if (retval || num_dirs > (fs->super->s_inodes_count / 320)) + ops = &ext2fs_blkmap64_bitarray; + else + ops = &ext2fs_blkmap64_rbtree; + break; + default: + return EINVAL; + } + + retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64), + &bitmap); + if (retval) + return retval; + +#ifdef ENABLE_BMAP_STATS + if (gettimeofday(&bitmap->stats.created, + (struct timezone *) NULL) == -1) { + perror("gettimeofday"); + ext2fs_free_mem(&bitmap); + return 1; + } + bitmap->stats.type = type; +#endif + + /* XXX factor out, repeated in copy_bmap */ + bitmap->magic = magic; + bitmap->fs = fs; + bitmap->start = start; + bitmap->end = end; + bitmap->real_end = real_end; + bitmap->bitmap_ops = ops; + bitmap->cluster_bits = 0; + switch (magic) { + case EXT2_ET_MAGIC_INODE_BITMAP64: + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; + break; + case EXT2_ET_MAGIC_BLOCK_BITMAP64: + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; + bitmap->cluster_bits = fs->cluster_ratio_bits; + break; + default: + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; + } + if (descr) { + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); + if (retval) { + ext2fs_free_mem(&bitmap); + return retval; + } + strcpy(bitmap->description, descr); + } else + bitmap->description = 0; + + retval = bitmap->bitmap_ops->new_bmap(fs, bitmap); + if (retval) { + ext2fs_free_mem(&bitmap->description); + ext2fs_free_mem(&bitmap); + return retval; + } + + *ret = (ext2fs_generic_bitmap) bitmap; + return 0; +} + +#ifdef ENABLE_BMAP_STATS +static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap) +{ + struct ext2_bmap_statistics *stats = &bitmap->stats; +#ifdef ENABLE_BMAP_STATS_OPS + float mark_seq_perc = 0.0, test_seq_perc = 0.0; + float mark_back_perc = 0.0, test_back_perc = 0.0; + struct timeval now; + double inuse; + + if (stats->test_count) { + test_seq_perc = ((float)stats->test_seq / + stats->test_count) * 100; + test_back_perc = ((float)stats->test_back / + stats->test_count) * 100; + } + + if (stats->mark_count) { + mark_seq_perc = ((float)stats->mark_seq / + stats->mark_count) * 100; + mark_back_perc = ((float)stats->mark_back / + stats->mark_count) * 100; + } + + if (gettimeofday(&now, (struct timezone *) NULL) == -1) { + perror("gettimeofday"); + return; + } + + inuse = (double) now.tv_sec + \ + (((double) now.tv_usec) * 0.000001); + inuse -= (double) stats->created.tv_sec + \ + (((double) stats->created.tv_usec) * 0.000001); +#endif /* ENABLE_BMAP_STATS_OPS */ + + fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description, + stats->type); + fprintf(stderr, "=================================================\n"); +#ifdef ENABLE_BMAP_STATS_OPS + fprintf(stderr, "%16llu bits long\n", + bitmap->real_end - bitmap->start); + fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n", + stats->copy_count, stats->resize_count); + fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n", + stats->mark_count, stats->unmark_count); + fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n", + stats->test_count, stats->mark_ext_count); + fprintf(stderr, "%16lu unmark_bmap_extent\n" + "%16lu test_clear_bmap_extent\n", + stats->unmark_ext_count, stats->test_ext_count); + fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n", + stats->set_range_count, stats->get_range_count); + fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n", + stats->clear_count, stats->test_seq, test_seq_perc); + fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n" + "%16llu bits tested backwards (%.2f%%)\n", + stats->mark_seq, mark_seq_perc, + stats->test_back, test_back_perc); + fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n" + "%16.2f seconds in use\n", + stats->mark_back, mark_back_perc, inuse); +#endif /* ENABLE_BMAP_STATS_OPS */ +} +#endif + +void ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + + if (!bmap) + return; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + ext2fs_free_generic_bitmap(gen_bmap); + return; + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return; + +#ifdef ENABLE_BMAP_STATS + if (getenv("E2FSPROGS_BITMAP_STATS")) { + ext2fs_print_bmap_statistics(bmap); + bmap->bitmap_ops->print_stats(bmap); + } +#endif + + bmap->bitmap_ops->free_bmap(bmap); + + if (bmap->description) { + ext2fs_free_mem(&bmap->description); + bmap->description = 0; + } + bmap->magic = 0; + ext2fs_free_mem(&bmap); +} + +errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src, + ext2fs_generic_bitmap *dest) +{ + ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64) gen_src; + char *descr, *new_descr; + ext2fs_generic_bitmap_64 new_bmap; + errcode_t retval; + + if (!src) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(src)) + return ext2fs_copy_generic_bitmap(gen_src, dest); + + if (!EXT2FS_IS_64_BITMAP(src)) + return EINVAL; + + /* Allocate a new bitmap struct */ + retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64), + &new_bmap); + if (retval) + return retval; + + +#ifdef ENABLE_BMAP_STATS_OPS + src->stats.copy_count++; +#endif +#ifdef ENABLE_BMAP_STATS + if (gettimeofday(&new_bmap->stats.created, + (struct timezone *) NULL) == -1) { + perror("gettimeofday"); + ext2fs_free_mem(&new_bmap); + return 1; + } + new_bmap->stats.type = src->stats.type; +#endif + + /* Copy all the high-level parts over */ + new_bmap->magic = src->magic; + new_bmap->fs = src->fs; + new_bmap->start = src->start; + new_bmap->end = src->end; + new_bmap->real_end = src->real_end; + new_bmap->bitmap_ops = src->bitmap_ops; + new_bmap->base_error_code = src->base_error_code; + new_bmap->cluster_bits = src->cluster_bits; + + descr = src->description; + if (descr) { + retval = ext2fs_get_mem(strlen(descr)+10, &new_descr); + if (retval) { + ext2fs_free_mem(&new_bmap); + return retval; + } + strcpy(new_descr, "copy of "); + strcat(new_descr, descr); + new_bmap->description = new_descr; + } + + retval = src->bitmap_ops->copy_bmap(src, new_bmap); + if (retval) { + ext2fs_free_mem(&new_bmap->description); + ext2fs_free_mem(&new_bmap); + return retval; + } + + *dest = (ext2fs_generic_bitmap) new_bmap; + + return 0; +} + +errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap, + __u64 new_end, + __u64 new_real_end) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + + if (!bmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bmap)) + return ext2fs_resize_generic_bitmap(gen_bmap->magic, new_end, + new_real_end, gen_bmap); + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return EINVAL; + + INC_STAT(bmap, resize_count); + + return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end); +} + +errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap, + errcode_t neq, + __u64 end, __u64 *oend) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (!bitmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + ext2_ino_t tmp_oend; + int retval; + + retval = ext2fs_fudge_generic_bitmap_end(gen_bitmap, + bitmap->magic, + neq, end, &tmp_oend); + if (oend) + *oend = tmp_oend; + return retval; + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + if (end > bitmap->real_end) + return neq; + if (oend) + *oend = bitmap->end; + bitmap->end = end; + return 0; +} + +__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap gen_bitmap) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (!bitmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bitmap)) + return ext2fs_get_generic_bitmap_start(gen_bitmap); + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + return bitmap->start; +} + +__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (!bitmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bitmap)) + return ext2fs_get_generic_bitmap_end(gen_bitmap); + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + return bitmap->end; +} + +void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap gen_bitmap) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (EXT2FS_IS_32_BITMAP(bitmap)) + ext2fs_clear_generic_bitmap(gen_bitmap); + else + bitmap->bitmap_ops->clear_bmap(bitmap); +} + +int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap gen_bitmap, + __u64 arg) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (!bitmap) + return 0; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + if (arg & ~0xffffffffULL) { + ext2fs_warn_bitmap2(gen_bitmap, + EXT2FS_MARK_ERROR, 0xffffffff); + return 0; + } + return ext2fs_mark_generic_bitmap(gen_bitmap, arg); + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return 0; + + arg >>= bitmap->cluster_bits; + +#ifdef ENABLE_BMAP_STATS_OPS + if (arg == bitmap->stats.last_marked + 1) + bitmap->stats.mark_seq++; + if (arg < bitmap->stats.last_marked) + bitmap->stats.mark_back++; + bitmap->stats.last_marked = arg; + bitmap->stats.mark_count++; +#endif + + if ((arg < bitmap->start) || (arg > bitmap->end)) { + warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg); + return 0; + } + + return bitmap->bitmap_ops->mark_bmap(bitmap, arg); +} + +int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap gen_bitmap, + __u64 arg) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + + if (!bitmap) + return 0; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + if (arg & ~0xffffffffULL) { + ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_UNMARK_ERROR, + 0xffffffff); + return 0; + } + return ext2fs_unmark_generic_bitmap(gen_bitmap, arg); + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return 0; + + arg >>= bitmap->cluster_bits; + + INC_STAT(bitmap, unmark_count); + + if ((arg < bitmap->start) || (arg > bitmap->end)) { + warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg); + return 0; + } + + return bitmap->bitmap_ops->unmark_bmap(bitmap, arg); +} + +int ext2fs_test_generic_bmap(ext2fs_generic_bitmap gen_bitmap, + __u64 arg) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + if (!bitmap) + return 0; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + if (arg & ~0xffffffffULL) { + ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR, + 0xffffffff); + return 0; + } + return ext2fs_test_generic_bitmap(gen_bitmap, arg); + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return 0; + + arg >>= bitmap->cluster_bits; + +#ifdef ENABLE_BMAP_STATS_OPS + bitmap->stats.test_count++; + if (arg == bitmap->stats.last_tested + 1) + bitmap->stats.test_seq++; + if (arg < bitmap->stats.last_tested) + bitmap->stats.test_back++; + bitmap->stats.last_tested = arg; +#endif + + if ((arg < bitmap->start) || (arg > bitmap->end)) { + warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg); + return 0; + } + + return bitmap->bitmap_ops->test_bmap(bitmap, arg); +} + +errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap gen_bmap, + __u64 start, unsigned int num, + void *in) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + + if (!bmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + if ((start+num-1) & ~0xffffffffULL) { + ext2fs_warn_bitmap2(gen_bmap, EXT2FS_UNMARK_ERROR, + 0xffffffff); + return EINVAL; + } + return ext2fs_set_generic_bitmap_range(gen_bmap, bmap->magic, + start, num, in); + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return EINVAL; + + INC_STAT(bmap, set_range_count); + + return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in); +} + +errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap gen_bmap, + __u64 start, unsigned int num, + void *out) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + + if (!bmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + if ((start+num-1) & ~0xffffffffULL) { + ext2fs_warn_bitmap2(gen_bmap, + EXT2FS_UNMARK_ERROR, 0xffffffff); + return EINVAL; + } + return ext2fs_get_generic_bitmap_range(gen_bmap, bmap->magic, + start, num, out); + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return EINVAL; + + INC_STAT(bmap, get_range_count); + + return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out); +} + +errcode_t ext2fs_compare_generic_bmap(errcode_t neq, + ext2fs_generic_bitmap gen_bm1, + ext2fs_generic_bitmap gen_bm2) +{ + ext2fs_generic_bitmap_64 bm1 = (ext2fs_generic_bitmap_64) gen_bm1; + ext2fs_generic_bitmap_64 bm2 = (ext2fs_generic_bitmap_64) gen_bm2; + blk64_t i; + + if (!bm1 || !bm2) + return EINVAL; + if (bm1->magic != bm2->magic) + return EINVAL; + + /* Now we know both bitmaps have the same magic */ + if (EXT2FS_IS_32_BITMAP(bm1)) + return ext2fs_compare_generic_bitmap(bm1->magic, neq, + gen_bm1, gen_bm2); + + if (!EXT2FS_IS_64_BITMAP(bm1)) + return EINVAL; + + if ((bm1->start != bm2->start) || + (bm1->end != bm2->end)) + return neq; + + for (i = bm1->start; i < bm1->end; i++) { + int ret1, ret2; + ret1 = !!ext2fs_test_generic_bmap(gen_bm1, i); + ret2 = !!ext2fs_test_generic_bmap(gen_bm2, i); + if (ret1 != ret2) { + return neq; + } + } + + return 0; +} + +void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap gen_bmap) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + __u64 start, num; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + ext2fs_set_generic_bitmap_padding(gen_bmap); + return; + } + + start = bmap->end + 1; + num = bmap->real_end - bmap->end; + bmap->bitmap_ops->mark_bmap_extent(bmap, start, num); + /* XXX ought to warn on error */ +} + +int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, + blk64_t block, unsigned int num) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + __u64 end = block + num; + + if (!bmap) + return EINVAL; + + if (num == 1) + return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap) + bmap, block); + + if (EXT2FS_IS_32_BITMAP(bmap)) { + if ((block & ~0xffffffffULL) || + ((block+num-1) & ~0xffffffffULL)) { + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, + EXT2FS_UNMARK_ERROR, 0xffffffff); + return EINVAL; + } + return ext2fs_test_block_bitmap_range( + (ext2fs_generic_bitmap) bmap, block, num); + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return EINVAL; + + INC_STAT(bmap, test_ext_count); + + /* convert to clusters if necessary */ + block >>= bmap->cluster_bits; + end += (1ULL << bmap->cluster_bits) - 1; + end >>= bmap->cluster_bits; + num = end - block; + + if ((block < bmap->start) || (block > bmap->end) || + (block+num-1 > bmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block, + bmap->description); + return EINVAL; + } + + return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num); +} + +void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, + blk64_t block, unsigned int num) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + __u64 end = block + num; + + if (!bmap) + return; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + if ((block & ~0xffffffffULL) || + ((block+num-1) & ~0xffffffffULL)) { + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, + EXT2FS_UNMARK_ERROR, 0xffffffff); + return; + } + ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap, + block, num); + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return; + + INC_STAT(bmap, mark_ext_count); + + /* convert to clusters if necessary */ + block >>= bmap->cluster_bits; + end += (1ULL << bmap->cluster_bits) - 1; + end >>= bmap->cluster_bits; + num = end - block; + + if ((block < bmap->start) || (block > bmap->end) || + (block+num-1 > bmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bmap->description); + return; + } + + bmap->bitmap_ops->mark_bmap_extent(bmap, block, num); +} + +void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, + blk64_t block, unsigned int num) +{ + ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap; + __u64 end = block + num; + + if (!bmap) + return; + + if (EXT2FS_IS_32_BITMAP(bmap)) { + if ((block & ~0xffffffffULL) || + ((block+num-1) & ~0xffffffffULL)) { + ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, + EXT2FS_UNMARK_ERROR, 0xffffffff); + return; + } + ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap, + block, num); + } + + if (!EXT2FS_IS_64_BITMAP(bmap)) + return; + + INC_STAT(bmap, unmark_ext_count); + + /* convert to clusters if necessary */ + block >>= bmap->cluster_bits; + end += (1ULL << bmap->cluster_bits) - 1; + end >>= bmap->cluster_bits; + num = end - block; + + if ((block < bmap->start) || (block > bmap->end) || + (block+num-1 > bmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, + bmap->description); + return; + } + + bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num); +} + +void ext2fs_warn_bitmap32(ext2fs_generic_bitmap gen_bitmap, const char *func) +{ + ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap; + +#ifndef OMIT_COM_ERR + if (bitmap && bitmap->description) + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "called %s with 64-bit bitmap for %s", func, + bitmap->description); + else + com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, + "called %s with 64-bit bitmap", func); +#endif +} + +errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, + ext2fs_block_bitmap *bitmap) +{ + ext2fs_generic_bitmap_64 bmap, cmap; + ext2fs_block_bitmap gen_bmap = *bitmap, gen_cmap; + errcode_t retval; + blk64_t i, next, b_end, c_end; + + bmap = (ext2fs_generic_bitmap_64) gen_bmap; + if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap)) + return 0; /* Nothing to do */ + + retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap", + &gen_cmap); + if (retval) + return retval; + + cmap = (ext2fs_generic_bitmap_64) gen_cmap; + i = bmap->start; + b_end = bmap->end; + bmap->end = bmap->real_end; + c_end = cmap->end; + cmap->end = cmap->real_end; + while (i < bmap->real_end) { + retval = ext2fs_find_first_set_block_bitmap2(gen_bmap, + i, bmap->real_end, &next); + if (retval) + break; + ext2fs_mark_block_bitmap2(gen_cmap, next); + i = EXT2FS_C2B(fs, EXT2FS_B2C(fs, next) + 1); + } + bmap->end = b_end; + cmap->end = c_end; + ext2fs_free_block_bitmap(gen_bmap); + *bitmap = (ext2fs_block_bitmap) cmap; + return 0; +} + +errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 start, __u64 end, __u64 *out) +{ + ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap; + __u64 cstart, cend, cout; + errcode_t retval; + + if (!bitmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + blk_t blk = 0; + + if (((start) & ~0xffffffffULL) || + ((end) & ~0xffffffffULL)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start, + end, &blk); + if (retval == 0) + *out = blk; + return retval; + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + cstart = start >> bmap64->cluster_bits; + cend = end >> bmap64->cluster_bits; + + if (cstart < bmap64->start || cend > bmap64->end || start > end) { + warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + if (bmap64->bitmap_ops->find_first_zero) { + retval = bmap64->bitmap_ops->find_first_zero(bmap64, cstart, + cend, &cout); + if (retval) + return retval; + found: + cout <<= bmap64->cluster_bits; + *out = (cout >= start) ? cout : start; + return 0; + } + + for (cout = cstart; cout <= cend; cout++) + if (!bmap64->bitmap_ops->test_bmap(bmap64, cout)) + goto found; + + return ENOENT; +} + +errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap, + __u64 start, __u64 end, __u64 *out) +{ + ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap; + __u64 cstart, cend, cout; + errcode_t retval; + + if (!bitmap) + return EINVAL; + + if (EXT2FS_IS_32_BITMAP(bitmap)) { + blk_t blk = 0; + + if (((start) & ~0xffffffffULL) || + ((end) & ~0xffffffffULL)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + retval = ext2fs_find_first_set_generic_bitmap(bitmap, start, + end, &blk); + if (retval == 0) + *out = blk; + return retval; + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + cstart = start >> bmap64->cluster_bits; + cend = end >> bmap64->cluster_bits; + + if (cstart < bmap64->start || cend > bmap64->end || start > end) { + warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + if (bmap64->bitmap_ops->find_first_set) { + retval = bmap64->bitmap_ops->find_first_set(bmap64, cstart, + cend, &cout); + if (retval) + return retval; + found: + cout <<= bmap64->cluster_bits; + *out = (cout >= start) ? cout : start; + return 0; + } + + for (cout = cstart; cout <= cend; cout++) + if (bmap64->bitmap_ops->test_bmap(bmap64, cout)) + goto found; + + return ENOENT; +} + +errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, + blk64_t end, blk64_t *out) +{ + blk64_t next; + blk64_t tot_set = 0; + errcode_t retval = 0; + + while (start < end) { + retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, + start, end, &next); + if (retval) { + if (retval == ENOENT) + retval = 0; + break; + } + start = next; + + retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, + start, end, &next); + if (retval == 0) { + tot_set += next - start; + start = next + 1; + } else if (retval == ENOENT) { + retval = 0; + tot_set += end - start + 1; + break; + } else + break; + } + + if (!retval) + *out = EXT2FS_NUM_B2C(fs, tot_set); + return retval; +} diff --git a/jni/e2fsprogs/lib/ext2fs/gen_bitmap64.o b/jni/e2fsprogs/lib/ext2fs/gen_bitmap64.o new file mode 100755 index 0000000000000000000000000000000000000000..e4882f2d6f5f149efe26ac469365584e40fca96b GIT binary patch literal 19520 zcmeHOeQaIjd4I33L#~4fU&#_a65Eh;HU*P}GzAUDbrK*0sFNznLGeB3_dM_OKJWAOew@P-_q5+zlSnwd67C;dBfdGPS^cA)RpBh!vNmCsTEy=gWfU8$eGvcQ}|ak$PJrHWWxCXoNKYH9-JmnhFW6&`P+8`GszHG#dRa8KK~ zT6cu{B@&4$KNiKVQ(`0fmiA>_c>6Y`OVc8Qe)3~%awXpnb*{s|1?iHH5j?xZ-QUv~ zIhYWiL3S}2*vD!A$v`jdk7J?iGY#-b!j--S9oWa%XlCx*{w)*8jUy+LneWYyI^;-V z;@l>8WC}Je!k%6>-Ug$1U3Un4dzMmFU;&O?%&wE)k=xy&ou(IQ}W_dEvX1 z`oQxCz9+4rDe&P`lD@%n!uhdL-nsp46R>k&?~}B5&BQr8kHIJ7@JA|}I8waSmCAVy zKRDQ$v>NnTyfj@(q832b;U>vJ`iVRiJGX!1#QaI=XEcF+7QnBGa_wWhk0)2+-;O!t zzppo1C-A(4c$|-w7Ug55Sszb}4;aVCP!H&5j`vSYKi1bB;%k*mKA$BFLj8<2yNV?j-Uk*?>M>X$Ji< z#(f`<8;)b4 z3&&WzbYzk_eyhi>C!=2n|$kJ!*R~FUMA|n{bmjMVb`8*x~63O{XxfQp{`1b*^NgU8Pi=-=nq$;|Pp zwWP^0&LhV*H5{LT&-~i833XU(=$~6KcW-+3cp_2v)GXu@s|C*#_LMbPziyQE>!r{m zia*R3#7=y^|FXnR6V41iim}6Sjm*z~jj>r3JDBf2Xzctl<$Bvk)L$Iek|=+zxJZ9R zt*deVHOqYG+DvM6cs=-l)|FpWoleSG8`e%|c;1G3l3L*2XU%Swdc(D%%{$!#wn7)b zjzn$aI+E)zuE%E~=QL{_Y9Z^`Dx>p+Id{;#sLngKj*n=~g>25FwvLa5_M-JFpSAWD zvA>LGCRukA>*EF2<{$gw-TxO~to;zah}kD`onORWiTePa;V{;a8LUlx2u8Ful;2MeN5iQbYr__!y zjL)xaknbtyzEE8F?6qh!>CZBx4wUgE_LK{`=JK^>cer2hEz!PEhx|Fl%>4Yai`lQS z)^M%k;{!gA^{LPzeJV8T(_>O^c&1Aq;;=K=lhY2Oqu+1xT#2zJ_9-S2rx=91^^5F?vI)1Hrt)=v03H1PfHjEi1?O31s_C__*I`V-JXZIV`bBv>&bTaii{SXfNUtOFbrc)&I1k<>?h3o<~tfo@r0vJxmAQ&CqU` zxBb|v&akkL(AeQV4yzYpLaoEw~RWZd_GxjXU6mhd(<-1JA z)HwZtdt3K4rpkCIriiQGd`w{s8h0%+F3w}rkuf!9V#@DTIA&Ah{G3Nymh0QcF{JNP zKaQawhEBxA(CT2GykHE4&Pk@R9`rQ`>lD_#l)OXs_lVbnvX7ZXoD$P>k~Y+#ENY`Y zFJU~BkLM#%bmno@nN5=4J}kuhk;=I~*Q%^@4jgOP$uVH8Gnm&V zQwg{GNj;ZBO>KvK?y1m^e+M};EANu7!`Sei8FPKG=H)&3)2u0Y_dGtzzR)k%Ys(z^ z#y#?!Yi56swaEl9o_+KC08jIF!#!!hNaOghcJRD<*1l2KdC;5hrYNrlZDvQSbwjQ9 zy74T23OY^8nwM*K|E&eS0btESjX6?&#@tDLXR*fPJg+*k)~HTuFX|orzUn@_XOZ{p zC;6V`61?}V_~SX)pWmX;2SwPCzp$gOnf$jE--OQIM=|r0(xT=krP=xE$=aai&%@t7 z9`9*2c@r_> zam1`&8%ZCO%a|ahbI}y~QG5N}|IU9+?R5|IV2=2?=q~&&sN{-bY|9v)L4UKIh+oW6 zYDdIGkXwj7+HEc5`Fx;EyAEW`avjKcg?`lSdC`{`*LnQrgu3(I%fPx%eZ#%XwbT`Q zP>!dg-5KaaS*Tyz%KdU)<(U%o1`qY^kngAd9XX?InNyVYV_;k4dm++-?@;c=_X_%c z>*M@r{uRoPcS|w((H4;(z&;}Rv7WL2q4L9?KOs;39tYnu&Z2hBW4@f1vk=xr&Hb8% zLB4Vg;%+f#KCCaO=lZ=D;x4E!T%**v_n(xSp)z^q!kWYy!aYG)o|T0)O?h91qis?9^Ye0M z?k3FTEts!bn!a;w3(gr*ueLljf$_J<9M4*&dB*+ax&4)Q?7MP>LT`U=u)8a}&)u`` z-iNk6_}Tj&%51!U+h^LgW**wsw(TL;IXJYhaj?75b!Pkea$Sw9ha11xTj*)ru>O{v zy@f{n>(34~b`R!3xgZZD4Lq957a*gvZ_jWcmzTzF(eHoq5y}-=&4qnKxyIF9EsNY; zAM{$}Zd~2hw@3By56*S=We0XOqVwV2!GXrLx3{is#VbwcuHYYBiN_vviN{wauB&gr zXG6{{_o#ELV0^cE@!`al`W09FMa`erChL>+4R~Da{__VQ;XK`K7TzHQI(Qq)tlJay z4UGXO`Eb7JuO9y0ym*cB)oiVASR(?-chqw^HwCAIuS5Bgr)ugOIx6yB5xy-!zv(jH z8uXj4@SPUE@qlk@neQ<8wpRG+NyoK3;4ABwbl?*OsUH)X*U#hoobWwEW@DF{17)*# z`yCLzm%{x%UES}C!gnZ;SJtnlP*%^&d+Q?QoxMoDRrCX{LxFx3I~S_$+sv0 z__yMZdt$TkyiXrL5poVxUJ_vCU_}G1z`R$kiMGK5kfXKI;xESV zzXkbG{CCIjFN7VU_|L`2c_#+{aSYxN)9*3x(+)a*U&FzB5U!2Vr#(gv4-umHGjLTD z{ygNf-?QS%DG8;$F?RSyjQr1w{@)iD`?&zTpNY}`pW#P8UL3CQ@^b=y|2W3Ke+U}+ zU&lc;FJJTVy958C#`TvX|1>^!;iddNG4kis4)p=QpDS?tZ!vawK*sy@WdXmRGjLmr z_>a+_Wu{g;Y;)?Xd)`#A---;Ifr+l2oF zzv{=O{Qncf|3{*K`>zH3evZNI=VSE08*=F1$7R9uM$pWyh>^b^b|!!OH36f}QIE#( z-x_0we-b%31M-)jYjF3?7&(6?{5P+x=Ks?e{vQbcP-DQab#*cHq5fwD_j3|h07u5d z#u)vVLw;2JWMlA5jGU{)Ux#i8^z`!{ZhsQP|6Pf<7gtyF|8)%i39$M6>uUw0Z@Qr^?r1-}}8DE?lIoI|MFyeMBvTmVQg5w~%8v%zf~GEaHwxPm9=(t_)_6yI#**f?xAxV3*u z)(zCh#^Dl!+c>=0;8spraMg2_D70B{)l=~;Mvjf!Z3e$y2Zi4;gWG<`WAFp1pfSfK zQ-%lLkaZ97#(>5D-6qA3_zec{lOjS~btkz`0-pFM4FB!oRN_){J$0+WTMYkUakkp+ zEukG1TRSpP!?zgauQ?3Ut{?9E)5>S{4W@Mo#AhmqC@`m22V+`AbyL%8)NYI48FnezbM5bET@)c70gM0pf)oYv-(m2VCFsL)UN`t}7=Hc_DZIjR<|OFDa<1S;NcisxZvEdo z8-s_ioD+g;e5&ofEx5*~;-`!p8=q4lIS;ttIxV=$QM@QP^|5l+HwEp8r-NJncbnj< z=YY_*3$F4N?=W)OjGVIu-)Qjbr6{o9O$P5W_-2E*-xxfQ-`0VG!S6NveNsfi{6`JG z#qeJ*MTGoT&mM#SmgSfG1>mnSxXM(#ybliX>$%0#Azb&bCqlUHM~fkRRb2q+dQAJ( z{UzshUW)5JvLl3_mAZT|gopQqDo4*(-VX8WK2MFJ{JNiO7Go){`?jqiT=!>tL%8n4 z#zMI6w@!s{-B;;4P5ae-(sEg+DX#mWbO;}6^k#HDAzb%8M?<*oKVAvpy3aTr!e7^* z&h0I%>mJVFJwhfpywB{)X9xE5W%Ip-eQvmr?;P6aglT8rZoDbju%4XRd>(Hcs$M_f zAvf@-Yt85SvaJQQ(RLKRD>snK_jYP0!w?WnM-Q2R+S)nT-=7;OcrCJ3+yi_1GhMy; zVeO%FaL+&?vu8Nhm610SWztZ-7o?pcw$M9V=jxp$x%{vdT<`C1fN+F^#KDWO%{`GNfwr7(&=MhIF2346WKQhT!9_VrxTT z*7fK5sXa5OFE^kT6N)~1+2C}o1A~QJ>wUldJGUSKJ9jI+%6R@|VP+`X)zv$&E0O~$ zl?)JRyzva)$noR|y{qI$l%*4t)qB+rbIHG=c;n^m>?+AW22zVah~kJQDwRr*lp`L zWdCO^f^x7cTgcKTYg^a4ReM|Q&LxM13j4VUa?>oY; zKdQg}J_7>p!$j +#include "crc32c_defs.h" +#include + +#define ENTRIES_PER_LINE 4 + +#if CRC_LE_BITS > 8 +# define LE_TABLE_ROWS (CRC_LE_BITS/8) +# define LE_TABLE_SIZE 256 +#else +# define LE_TABLE_ROWS 1 +# define LE_TABLE_SIZE (1 << CRC_LE_BITS) +#endif + +#if CRC_BE_BITS > 8 +# define BE_TABLE_ROWS (CRC_BE_BITS/8) +# define BE_TABLE_SIZE 256 +#else +# define BE_TABLE_ROWS 1 +# define BE_TABLE_SIZE (1 << CRC_BE_BITS) +#endif + +static uint32_t crc32table_be[BE_TABLE_ROWS][256]; +static uint32_t crc32ctable_le[LE_TABLE_ROWS][256]; + +/** + * crc32init_le() - allocate and initialize LE table data + * + * crc is the crc of the byte i; other entries are filled in based on the + * fact that crctable[i^j] = crctable[i] ^ crctable[j]. + * + */ +static void crc32cinit_le(void) +{ + unsigned i, j; + uint32_t crc = 1; + + crc32ctable_le[0][0] = 0; + + for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) { + crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0); + for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) + crc32ctable_le[0][i + j] = crc ^ crc32ctable_le[0][j]; + } + for (i = 0; i < LE_TABLE_SIZE; i++) { + crc = crc32ctable_le[0][i]; + for (j = 1; j < LE_TABLE_ROWS; j++) { + crc = crc32ctable_le[0][crc & 0xff] ^ (crc >> 8); + crc32ctable_le[j][i] = crc; + } + } +} + +/** + * crc32init_be() - allocate and initialize BE table data + */ +static void crc32init_be(void) +{ + unsigned i, j; + uint32_t crc = 0x80000000; + + crc32table_be[0][0] = 0; + + for (i = 1; i < BE_TABLE_SIZE; i <<= 1) { + crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); + for (j = 0; j < i; j++) + crc32table_be[0][i + j] = crc ^ crc32table_be[0][j]; + } + for (i = 0; i < BE_TABLE_SIZE; i++) { + crc = crc32table_be[0][i]; + for (j = 1; j < BE_TABLE_ROWS; j++) { + crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8); + crc32table_be[j][i] = crc; + } + } +} + +static void output_table(uint32_t (*table)[256], int rows, int len, char *trans) +{ + int i, j; + + for (j = 0 ; j < rows; j++) { + printf("{"); + for (i = 0; i < len - 1; i++) { + if (i % ENTRIES_PER_LINE == 0) + printf("\n"); + printf("%s(0x%8.8xL), ", trans, table[j][i]); + } + printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]); + } +} + +int main(int argc, char **argv) +{ + printf("/* this file is generated - do not edit */\n\n"); + + if (CRC_BE_BITS > 1) { + crc32init_be(); + printf("static const uint32_t " + "crc32table_be[%d][%d] = {", + BE_TABLE_ROWS, BE_TABLE_SIZE); + output_table(crc32table_be, LE_TABLE_ROWS, + BE_TABLE_SIZE, "tobe"); + printf("};\n"); + } + if (CRC_LE_BITS > 1) { + crc32cinit_le(); + printf("static const uint32_t " + "crc32ctable_le[%d][%d] = {", + LE_TABLE_ROWS, LE_TABLE_SIZE); + output_table(crc32ctable_le, LE_TABLE_ROWS, + LE_TABLE_SIZE, "tole"); + printf("};\n"); + } + + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/get_num_dirs.c b/jni/e2fsprogs/lib/ext2fs/get_num_dirs.c new file mode 100755 index 0000000..f5644f8 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/get_num_dirs.c @@ -0,0 +1,50 @@ +/* + * get_num_dirs.c -- calculate number of directories + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +/* + * Returns the number of directories in the filesystem as reported by + * the group descriptors. Of course, the group descriptors could be + * wrong! + */ +errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs) +{ + dgrp_t i; + ext2_ino_t num_dirs, max_dirs; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + num_dirs = 0; + max_dirs = fs->super->s_inodes_per_group; + for (i = 0; i < fs->group_desc_count; i++) { + if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs) + num_dirs += max_dirs / 8; + else + num_dirs += ext2fs_bg_used_dirs_count(fs, i); + } + if (num_dirs > fs->super->s_inodes_count) + num_dirs = fs->super->s_inodes_count; + + *ret_num_dirs = num_dirs; + + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/get_num_dirs.o b/jni/e2fsprogs/lib/ext2fs/get_num_dirs.o new file mode 100755 index 0000000000000000000000000000000000000000..fd00874e62c390e34deaf54af0f955dac8ac21b3 GIT binary patch literal 1440 zcmbW1J#5oJ6oB8=DL5i(T8c{L?jm2fPoD}2BcI>FeO9ezB}K!PGc5Ma_+tF{rk>&c=_6uAwobd z0&n3!lN8{Nav)PKQV64`qmVDXb*0h!06TRh-f2alyQ}COmC$bT=Zmj}U$6hFB>cMx za1-;MNFZBAw!0bcTtwX&2b=qk(XN`Lb~_5T69b$1wqw+8V6J3}+L)vGL~(P}k+sl< zZ9H#B(FSTUNn9J#!{pIoIQ;2Udz{A|Yhw)+^Yz7X8*m$|CF`lfFxJNUEyszmcwQfS zOA@z-Ju!#ZGjf)n$D{vVly(yY?DseyWA#nF(_5c!;CtF>D*89buB6NPsryFNEL6%< zsW~mB&EX)U{G9@j2a7;9&XUPU91_ST1fRiVaA|}tM9z%98hRO0CP*Ys7e?U6ci|Dd zWe|tpj}v57U}yk86|vpeo`>Ks?GQ&`9JX< zhWS1{FUe;y^fQmR0=p*u#ZHE?!zV name translation + * + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * + * ext2fs_get_pathname(fs, dir, ino, name) + * + * This function translates takes two inode numbers into a + * string, placing the result in .

is the containing + * directory inode, and is the inode number itself. If + * is zero, then ext2fs_get_pathname will return pathname + * of the the directory . + * + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct get_pathname_struct { + ext2_ino_t search_ino; + ext2_ino_t parent; + char *name; + errcode_t errcode; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int get_pathname_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct get_pathname_struct *gp; + errcode_t retval; + int name_len = ext2fs_dirent_name_len(dirent); + + gp = (struct get_pathname_struct *) priv_data; + + if ((name_len == 2) && !strncmp(dirent->name, "..", 2)) + gp->parent = dirent->inode; + if (dirent->inode == gp->search_ino) { + retval = ext2fs_get_mem(name_len + 1, &gp->name); + if (retval) { + gp->errcode = retval; + return DIRENT_ABORT; + } + strncpy(gp->name, dirent->name, name_len); + gp->name[name_len] = '\0'; + return DIRENT_ABORT; + } + return 0; +} + +static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir, + ext2_ino_t ino, int maxdepth, + char *buf, char **name) +{ + struct get_pathname_struct gp; + char *parent_name = 0, *ret; + errcode_t retval; + + if (dir == ino) { + retval = ext2fs_get_mem(2, name); + if (retval) + return retval; + strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : "."); + return 0; + } + + if (!dir || (maxdepth < 0)) { + retval = ext2fs_get_mem(4, name); + if (retval) + return retval; + strcpy(*name, "..."); + return 0; + } + + gp.search_ino = ino; + gp.parent = 0; + gp.name = 0; + gp.errcode = 0; + + retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp); + if (retval == EXT2_ET_NO_DIRECTORY) { + char tmp[32]; + + if (ino) + snprintf(tmp, sizeof(tmp), "<%u>/<%u>", dir, ino); + else + snprintf(tmp, sizeof(tmp), "<%u>", dir); + retval = ext2fs_get_mem(strlen(tmp)+1, name); + if (retval) + goto cleanup; + strcpy(*name, tmp); + return 0; + } else if (retval) + goto cleanup; + if (gp.errcode) { + retval = gp.errcode; + goto cleanup; + } + + retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1, + buf, &parent_name); + if (retval) + goto cleanup; + if (!ino) { + *name = parent_name; + return 0; + } + + if (gp.name) + retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2, + &ret); + else + retval = ext2fs_get_mem(strlen(parent_name)+5, &ret); + if (retval) + goto cleanup; + + ret[0] = 0; + if (parent_name[1]) + strcat(ret, parent_name); + strcat(ret, "/"); + if (gp.name) + strcat(ret, gp.name); + else + strcat(ret, "???"); + *name = ret; + retval = 0; + +cleanup: + ext2fs_free_mem(&parent_name); + ext2fs_free_mem(&gp.name); + return retval; +} + +errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, + char **name) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + if (dir == ino) + ino = 0; + retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name); + ext2fs_free_mem(&buf); + return retval; + +} diff --git a/jni/e2fsprogs/lib/ext2fs/get_pathname.o b/jni/e2fsprogs/lib/ext2fs/get_pathname.o new file mode 100755 index 0000000000000000000000000000000000000000..6c4d11365dbfa764163eed7c24f76c89bf3d570c GIT binary patch literal 4248 zcmbtXUu;uV82@f>>smJcZpf0!3SpWJ;vEAukPx|HQ;QfO3q~G*QoD{VY+dcD0hw`R zK4^GZBT+PJHo#;fCi*~Po0vc{9*E&Z9`s4m!IpIK1&t5AiA()`=bqD@T~>MUB)jLF z-}%1Z_vd`)+xEdruf6Ou3{u0OA82W(P@={)OKV#!ZCVA%a;Ne0;(7n{qG@C&%y4OP zra553xQaF8 z%&oPZ`Fh(i{iEG=;4YeUy-;I=pB%QOxP|^$w6u7>YZ|d-Z<*0w%40sn7@A(}^ev0= zYG-rq+SumOH|FM2c^l%@d@@Wo&Pnq`$)?eJBAzD1)1<}2YsB-Ti2p>1kgMz92oa69 z8I%oT4q|>aL~k3$$6qkVO~`*Q<40beV}GYQPv-i3r5AY3_C_CLZ$h&No$;;Y=9{@c z=QHGOew&dk9-{nxGrYZgnDXTv}{T|^v5fODL)hwc0o_`~@%1N8Pa#5|8WA1RkVQ}HUkPUvu)MWW{g?>5_+ zhL5cVIc%TLi#xz?xV2osx$qygSpd#!Rg*yqUZfCZXCKIS0H1=;S31V%x&D z!nPAOXm1gAf&qK)9a$>{;Iq;;>+v3Qr3TnX$cpzSWTkIUtRO4wLSMyMhM$5HITG=p zhG?rBgQ$DtfzKzz`#Ly{cjdmX|L7reYu%cYxyl#uj`__NYwUaw?_$=FHHQ0QTPl_V z>J7;Iki96sP-{D_0m`!-&ps4&1hca1vu`+S->7PFY-MpJrjC2p)c|@6V2&; zsGTgbEQ|I%{mzT+{1GeKzkfeqqWC~8d3wvciS%&)P;yJh9;?IJL+fCWhw)xF86(X` zQ(c(QZwWnAj5+>xtvM2@+q~{;-&cO$-Ma9R$Qt_nH=xv4_0U-%JIInY>>x?B*DdU|M0Ql+8vKQyQN$3)u@eJEo0dEqhk3?Kp3%@b{D)BBq z78t@ucL{z8$~{jT1plM>YJmqdNq31_z^Hiyp8>K#^HcfN4_w`iu5`8v&h#tEPgcP% zSHTZe!S_|cyQ|>nXDj-HKD8o#3^-9UL z;d(wNG+fWmKJGsl9Iwt3se-F_@2#Iy75Nbj*Zs+9IC^?z+?Ke?vpTpVag}F<->t$k zR|S9Q;ol^Q{`T-Iyi|p!Q5GKOL4RK@Rq#FyS9i;%$0e@fflEhWK3jb2$sdq)i z_o0UCdEO~oD*M@>$v-960pPMU1k&Zf=j1-+!7J}*IFpX2&Jm_0&sI7y5VJCgvl+tA zuHND3=|m=)ie>tevB5;NKbavbJ~TL(z=Bm{VoJsbQ@kBWB$ZlEe;P7Tp{2phHkcSx zQoZR!LhP;NP$pr$^7puaTk5E@$Hcc_+LxZmFkC$QhpPR zv;AFiucmLM-DU;IS^2N#-N1S6P3KQi|H;Sbe-PtdzeAd4CZp$ob>HdX&D(9~<}DW|fq@Q2s}N2T!Z; +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_SYS_DISK_H +#include +#endif +#ifdef HAVE_LINUX_FD_H +#include +#include +#endif + +#if defined(__linux__) && defined(_IO) +#if !defined(BLKSSZGET) +#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ +#endif +#if !defined(BLKPBSZGET) +#define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */ +#endif +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Returns the logical sector size of a device + */ +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) +{ +#ifdef _WIN32 + *sectsize = 512; // just guessing + return 0; +#else // not _WIN32 + + int fd; + + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + +#ifdef BLKSSZGET + if (ioctl(fd, BLKSSZGET, sectsize) >= 0) { + close(fd); + return 0; + } +#endif +#ifdef DIOCGSECTORSIZE + if (ioctl(fd, DIOCGSECTORSIZE, sectsize) >= 0) { + close(fd); + return 0; + } +#endif + *sectsize = 0; + close(fd); + return 0; + +#endif // ifdef _WIN32 +} + +/* + * Return desired alignment for direct I/O + */ +int ext2fs_get_dio_alignment(int fd) +{ + int align = 0; + +#ifdef BLKSSZGET + if (ioctl(fd, BLKSSZGET, &align) < 0) + align = 0; +#endif +#ifdef DIOCGSECTORSIZE + if (align <= 0 && + ioctl(fd, DIOCGSECTORSIZE, &align) < 0) + align = 0; +#endif + +#ifdef _SC_PAGESIZE + if (align <= 0) + align = sysconf(_SC_PAGESIZE); +#endif +#ifdef HAVE_GETPAGESIZE + if (align <= 0) + align = getpagesize(); +#endif + if (align <= 0) + align = 4096; + + return align; +} + +/* + * Returns the physical sector size of a device + */ +errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize) +{ +#ifdef _WIN32 + + return ext2fs_get_device_sectsize(file, sectsize); + +#else // not _WIN32 + + int fd; + + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + +#ifdef BLKPBSZGET + if (ioctl(fd, BLKPBSZGET, sectsize) >= 0) { + close(fd); + return 0; + } +#endif +#ifdef DIOCGSECTORSIZE + /* This isn't really the physical sector size, but FreeBSD + * doesn't seem to have this concept. */ + if (ioctl(fd, DIOCGSECTORSIZE, sectsize) >= 0) { + close(fd); + return 0; + } +#endif + *sectsize = 0; + close(fd); + return 0; + +#endif // ifdef _WIN32 +} diff --git a/jni/e2fsprogs/lib/ext2fs/getsectsize.o b/jni/e2fsprogs/lib/ext2fs/getsectsize.o new file mode 100755 index 0000000000000000000000000000000000000000..d19562a2643953f08910ed6846c0d2b03c39dc49 GIT binary patch literal 2168 zcmb`HO=uHA6vy8tsYy*JRYVF^6R?65T-qWv2M?=O?V)NZ^}MdzNfX@c*6dQ!53n@e zZJ>e(N)H|k^r+aJEaW115jkVOzw1}OHFLBksnECq`K?lPr*a0)i25sAi_?jrh27)F6OQP29e{p z)E<`w9%@s7X@U0&{DHua3q0F}zZ1Ba=ZC=QGx8BGD6!+Adq59j>`IYSIhc1YF%yv7o?I!_#RE@i2jk(xKt#B@N`t+YE)Rg%e= z7NjiQF+esghsd|@-oIo!n*IpvC0n=5#9w*HVoE3KLUPGgZK6ANYMFHKw_Unn*@V?Z zl4>HOrQ3RIftYF{We~s$d4#NkY&#i8dx&-^P3_Q}JVtM$FqD-?_>1~aTf%sMhaA&A zEm-mR*lTN3`h`;F{ZbXC*!Bc?zjW%RjO$q#;Q!toF&0nH8a)sE%<=!>1!Pp>?Z-Zg zJB>bZFzm)qeibjyM4eAOe1gNPeaYgz@(=?XLM)x~`Z<1%lTObcV*Q_FLK;VV%;Wj< Te@5orn})n#aGDiNO{e%j)`TR% literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/getsize.c b/jni/e2fsprogs/lib/ext2fs/getsize.c new file mode 100755 index 0000000..a028634 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/getsize.c @@ -0,0 +1,315 @@ +/* + * getsize.c --- get the size of a partition. + * + * Copyright (C) 1995, 1995 Theodore Ts'o. + * Copyright (C) 2003 VMware, Inc. + * + * Windows version of ext2fs_get_device_size by Chris Li, VMware. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_LINUX_FD_H +#include +#endif +#ifdef HAVE_SYS_DISKLABEL_H +#include +#endif +#ifdef HAVE_SYS_DISK_H +#include +#endif +#ifdef __linux__ +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#include + +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) +#define BLKGETSIZE _IO(0x12,96) /* return device size */ +#endif + +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#endif + +#ifdef APPLE_DARWIN +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 +#endif /* APPLE_DARWIN */ + +#include "ext2_fs.h" +#include "ext2fs.h" + +#if defined(__CYGWIN__) || defined (WIN32) +#include "windows.h" +#include "winioctl.h" + +#if (_WIN32_WINNT >= 0x0500) +#define HAVE_GET_FILE_SIZE_EX 1 +#endif + +errcode_t ext2fs_get_device_size2(const char *file, int blocksize, + blk64_t *retblocks) +{ + int fd; + HANDLE h; + PARTITION_INFORMATION pi; + DISK_GEOMETRY gi; + DWORD retbytes; +#ifdef HAVE_GET_FILE_SIZE_EX + LARGE_INTEGER filesize; +#else + DWORD filesize; +#endif /* HAVE_GET_FILE_SIZE_EX */ + + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + h = (HANDLE)_get_osfhandle(fd); + if (DeviceIoControl(h, IOCTL_DISK_GET_PARTITION_INFO, + &pi, sizeof(PARTITION_INFORMATION), + &pi, sizeof(PARTITION_INFORMATION), + &retbytes, NULL)) { + + *retblocks = pi.PartitionLength.QuadPart / blocksize; + + } else if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY, + &gi, sizeof(DISK_GEOMETRY), + &gi, sizeof(DISK_GEOMETRY), + &retbytes, NULL)) { + + *retblocks = gi.BytesPerSector * + gi.SectorsPerTrack * + gi.TracksPerCylinder * + gi.Cylinders.QuadPart / blocksize; + +#ifdef HAVE_GET_FILE_SIZE_EX + } else if (GetFileSizeEx(h, &filesize)) { + *retblocks = filesize.QuadPart / blocksize; + } +#else + } else { + filesize = GetFileSize(h, NULL); + if (INVALID_FILE_SIZE != filesize) { + *retblocks = filesize / blocksize; + } + } +#endif /* HAVE_GET_FILE_SIZE_EX */ + + close(fd); + return 0; +} + +#else + +static int valid_offset (int fd, ext2_loff_t offset) +{ + char ch; + + if (ext2fs_llseek (fd, offset, 0) < 0) + return 0; + if (read (fd, &ch, 1) < 1) + return 0; + return 1; +} + +/* + * Returns the number of blocks in a partition + */ +errcode_t ext2fs_get_device_size2(const char *file, int blocksize, + blk64_t *retblocks) +{ + int fd, rc = 0; + unsigned long long size64; + ext2_loff_t high, low; + + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + +#if defined DKIOCGETBLOCKCOUNT && defined DKIOCGETBLOCKSIZE /* For Apple Darwin */ + unsigned int size; + + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0 && + ioctl(fd, DKIOCGETBLOCKSIZE, &size) >= 0) { + *retblocks = size64 * size / blocksize; + goto out; + } +#endif + +#ifdef BLKGETSIZE64 + { + int valid_blkgetsize64 = 1; +#ifdef __linux__ + struct utsname ut; + + if ((uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] < '6') && (ut.release[3] == '.'))) + valid_blkgetsize64 = 0; +#endif + if (valid_blkgetsize64 && + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { + *retblocks = size64 / blocksize; + goto out; + } + } +#endif /* BLKGETSIZE64 */ + +#ifdef BLKGETSIZE + { + unsigned long size; + + if (ioctl(fd, BLKGETSIZE, &size) >= 0) { + *retblocks = size / (blocksize / 512); + goto out; + } + } +#endif + +#ifdef FDGETPRM + { + struct floppy_struct this_floppy; + + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { + *retblocks = this_floppy.size / (blocksize / 512); + goto out; + } + } +#endif + +#ifdef HAVE_SYS_DISKLABEL_H + { + int part; + struct disklabel lab; + struct partition *pp; + char ch; + +#if defined(DIOCGMEDIASIZE) + { + off_t ms; + u_int bs; + if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) { + *retblocks = ms / blocksize; + goto out; + } + } +#elif defined(DIOCGDINFO) + /* old disklabel interface */ + part = strlen(file) - 1; + if (part >= 0) { + ch = file[part]; + if (isdigit(ch)) + part = 0; + else if (ch >= 'a' && ch <= 'h') + part = ch - 'a'; + else + part = -1; + } + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { + pp = &lab.d_partitions[part]; + if (pp->p_size) { + *retblocks = pp->p_size / (blocksize / 512); + goto out; + } + } +#endif /* defined(DIOCG*) */ + } +#endif /* HAVE_SYS_DISKLABEL_H */ + + { + ext2fs_struct_stat st; + + if (ext2fs_fstat(fd, &st) == 0) + if (S_ISREG(st.st_mode)) { + *retblocks = st.st_size / blocksize; + goto out; + } + } + + /* + * OK, we couldn't figure it out by using a specialized ioctl, + * which is generally the best way. So do binary search to + * find the size of the partition. + */ + low = 0; + for (high = 1024; valid_offset(fd, high); high *= 2) + low = high; + while (low < high - 1) { + const ext2_loff_t mid = (low + high) / 2; + + if (valid_offset (fd, mid)) + low = mid; + else + high = mid; + } + valid_offset(fd, 0); + size64 = low + 1; + *retblocks = size64 / blocksize; +out: + close(fd); + return rc; +} + +#endif /* WIN32 */ + +errcode_t ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks) +{ + errcode_t retval; + blk64_t blocks; + + retval = ext2fs_get_device_size2(file, blocksize, &blocks); + if (retval) + return retval; + if (blocks >= (1ULL << 32)) + return EFBIG; + *retblocks = (blk_t) blocks; + return 0; +} + +#ifdef DEBUG +int main(int argc, char **argv) +{ + blk64_t blocks; + int retval; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + retval = ext2fs_get_device_size2(argv[1], 1024, &blocks); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_get_device_size"); + exit(1); + } + printf("Device %s has %llu 1k blocks.\n", argv[1], + (unsigned long long) locks); + exit(0); +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/getsize.o b/jni/e2fsprogs/lib/ext2fs/getsize.o new file mode 100755 index 0000000000000000000000000000000000000000..18bdf421e17c43cd45ba158f5026be6ebd30fd9c GIT binary patch literal 2728 zcmbtWOKcle6usk@G?On?RX%DyW7;f|2uxA|O&5p(0u7?-A_8^MG=p)*iB-o=Y!iis zs&2giwIE@UMTAJ?wi~+wDGNT61th{7idfJfkoY$N2}ebOE|A7jEOYP7d(LE1uXvT_ z-FNP}-*=zW^UofC&Lc@6mIR-|_DP@sY{cx6pg6{Dq~jNdHm>pf zIKOaGE#~qgMuVCh>S_M!z$R$E?~?Jpols#%I{9I}19EPPy6mxYgR^ntbq z3QX=1@sDx)^+RCwW>w<7X;qiy=KcHR2h}OOO1nP_<%9V*Z|8pm?WwjE)@I7d zW{N&sNe!Dvv3@V_O%~5tch|xlS*pK%iQh|>**IdC zpNHfc#V;@@Qm@yUTJ&O!4A}iI;F)67U{03I^V!50Heb1p12RWGRam7ui*&eP70VF3oy!r4*zyDaBaF+0CRh+|?q@EBQ!* z`3c#tp&ZWv+DF)?l&#hw3SSGI-rP-%*7%OeXWD>??xe}hm z``DnkOvAS_Vr($`K5x}Qu~3IS0r-gGTQb(tLNfNM8&=n-*VlOLaYlEjn0vT>6KlXZ zU0!k2Uz&X;S7wrx2L!_Y$e4FpkHtgLh_|ob*XQfUf@tlvH;~Q_f%JNZ)Y_y#7h(@^ ze942tK#O;kt+BbRd9T>clC3y3LdM1KT!o=tb(6Hoa*XiDB!a0 z3ipSs6F@5tsLW;BR4x-<&t=+%9e9HS|Js2!I`FM3xQc#hk$)$D#(_846zlsIzjET^ z8?LNx95}wK%KFEF-%~*W26_GDr_O=5ak&<8ZfYTeE?msRqze~)1z$`L`+W(0CIP-c zbYen}Bw*Sf4vlKjU@)#H05yk$aV;26_!FRMdMp-+LMR$YgoP>`j_djv@I|5t-FNK7 zOAjM8a7Jjy^n^C5Plp1!77v}(@kbyU*LhfdTnonh6FR&ap)U^=ozx>*Fcj7yru#<$ z9gv|f0KRx4mhiuV`)d=lbG|FWVdxz7S)V@WobmPY%KzW?A)526*x@M2FXfLNDB%B0 zb}o9kgt=d^%4r|CoV$Mk$d)j{=Vs8$9m+f)y$PBJ@ixToC(R~N+}-$#$Gs1A&c)qT z>UaT_0(0^_?nJrL%{|BMowG_*{99(NckHe575NKb28FxT-_QFm=AP`RCBk0R|1o0j S*a*Qqk3Y{7rj1;>?f(PeCgv9a literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/hashmap.c b/jni/e2fsprogs/lib/ext2fs/hashmap.c new file mode 100755 index 0000000..697b2bc --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/hashmap.c @@ -0,0 +1,109 @@ +#include "hashmap.h" +#include + +struct ext2fs_hashmap { + uint32_t size; + uint32_t(*hash)(const void *key, size_t len); + void(*free)(void*); + struct ext2fs_hashmap_entry *first; + struct ext2fs_hashmap_entry *last; +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + struct ext2fs_hashmap_entry *entries[0]; +#if __GNUC_PREREQ (4, 8) +#pragma GCC diagnostic pop +#endif +}; + +uint32_t ext2fs_djb2_hash(const void *str, size_t size) +{ + int c; + const char *s = str; + uint32_t hash = 5381; + + while (size-- > 0) { + c = *s++; + hash = ((hash << 5) + hash) + c; + } + return hash; +} + +struct ext2fs_hashmap *ext2fs_hashmap_create( + uint32_t(*hash_fct)(const void*, size_t), + void(*free_fct)(void*), size_t size) +{ + struct ext2fs_hashmap *h = calloc(sizeof(struct ext2fs_hashmap) + + sizeof(struct ext2fs_hashmap_entry) * size, 1); + if (!h) + return NULL; + + h->size = size; + h->free = free_fct; + h->hash = hash_fct; + h->first = h->last = NULL; + return h; +} + +int ext2fs_hashmap_add(struct ext2fs_hashmap *h, + void *data, const void *key, size_t key_len) +{ + uint32_t hash = h->hash(key, key_len) % h->size; + struct ext2fs_hashmap_entry *e = malloc(sizeof(*e)); + + if (!e) + return -1; + + e->data = data; + e->key = key; + e->key_len = key_len; + e->next = h->entries[hash]; + h->entries[hash] = e; + + e->list_prev = NULL; + e->list_next = h->first; + if (h->first) + h->first->list_prev = e; + h->first = e; + if (!h->last) + h->last = e; + + return 0; +} + +void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key, + size_t key_len) +{ + struct ext2fs_hashmap_entry *iter; + uint32_t hash = h->hash(key, key_len) % h->size; + + for (iter = h->entries[hash]; iter; iter = iter->next) + if (iter->key_len == key_len && !memcmp(iter->key, key, key_len)) + return iter->data; + return NULL; +} + +void *ext2fs_hashmap_iter_in_order(struct ext2fs_hashmap *h, + struct ext2fs_hashmap_entry **it) +{ + *it = *it ? (*it)->list_next : h->first; + return *it ? (*it)->data : NULL; +} + +void ext2fs_hashmap_free(struct ext2fs_hashmap *h) +{ + size_t i; + + for (i = 0; i < h->size; ++i) { + struct ext2fs_hashmap_entry *it = h->entries[i]; + while (it) { + struct ext2fs_hashmap_entry *tmp = it->next; + if (h->free) + h->free(it->data); + free(it); + it = tmp; + } + } + free(h); +} diff --git a/jni/e2fsprogs/lib/ext2fs/hashmap.o b/jni/e2fsprogs/lib/ext2fs/hashmap.o new file mode 100755 index 0000000000000000000000000000000000000000..3f86fb3bb2f7e474c93d5ea8e8a3bf74bb248af2 GIT binary patch literal 2928 zcmbtWO=x3P6h1F6nZDReI-Qx?!RovUU1S79T1KcK_?TAhLUb4uW-%Bt>8q_xnvzCo ztzs}D1veHH1W{UWk;p7uC{94I*jdcXZUz|!{GqKb5*4Mm$yUSFD(7v4Mf ze(#)fzw_O5)4ub}^Unq}jnvTSTWYTqN|Xq<=a!gS6ozMOo9^rklCyh?oZ6t})OyJ& zZ@hb{)<;$3IbAztIpGlP*YVxZX#bW*FA2O?;Olkx8=CcG&7^9*&#Kn&7z5$nx(Ta= zdpXZPt=8ZUaO}0dr6=#TbnQ-aRj)L$-q6j)ZXY>&$Wup7<5=;o@pkxA+NAYIsdyJu zKicU5w;sz`Bl?E-{=Q^3`k5R2>%e0g@xJan4E}nuA@GnJXZA~b+_h!IbDoV-ve8_f zsDO{lYl3+ND^0AK*JkN#V-I!z27a8=2wBb!^w`B-q&Ntd~J}b zgc`iO%aXT2#gpZ2^ZF?EE|*?$Icng9oCkb;br{g0K8QV5=3IYSLj`-E!?!>1Ew=Jl zgY_{7B+uhAALFgLuty_}mR>e}J(r+*{~R?kQ1M$=4Gl+>buo5A-MZ8+yI1rCb}(i}QrI zC$YaF^QwKAD|)nhJm=KO339w{e#vu=-O(+lRg!lG_q4ehs5G(O0M{1yi2TT10q1kv zhtT6f(7m5!V4`=Jqfg7VfJaN_iv5H?bj2MPeWKRfm&4%4=O#F@&d|07Zd~(U&`$9% zLbT4mA3p)(yTyLZ)e9AM?kvi<8b0}!ZoD5d5N^Q&T2yu zlTHIWBk=;;$!H>wiP8wB35kE=;?`8;krST>J_`nl5!0HA(yzae@VhMio&rh4UsQhj zh!!y~x{jQ$DE;oUos72gZME|;AKYaz*7!Xc9S#(u6vK3j*BCeW1)gf3z_o~(kbL-4 zw{aUEg0$Z{>bp*X4)||@bmDb^2Rri%}U|--lYTpgu zJchv2aHryZS@LH50S|s(@?$*W!Ou&H8SnGpSGwR2OP>(@y{C5Ghbz6W_;97`dp=z0 zcg=?@oo@JWr4z;Tb|w`s*vkcqr*qk?y-*-5#%7k1v#F)oY-%w%SFrQRxrJmdKW*pz zA2Ye!{OgO9wX^B$BE=VS1v~!S3ok#uR7j=gmGks#SI0y;1*p{Nyqzl8l7u~*oXMxM zw%=(cZ+Bp+>1oQQGMQYO(yoyy<7tX774n7DRoIm*+mY$`7{5koWI3LYLi|tjBjRPN z9m+H=o9W*}D0TcV#y1cxK>nL($+(Q{AGySD!r{TOj9G_aO7ytEvc#DV_nGSPGZN<> z<{W-GuE~ualzz&vFArs3^vuNv`TD_6RN^X5`F?;2W8OQ!-)_qI8ZSIU@mJ9Mm>gAq iS=RrdbmTbJSjDUQe+K5?n?t_BA8#H-Ntn%1@&5sF-(H^p literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/i_block.c b/jni/e2fsprogs/lib/ext2fs/i_block.c new file mode 100755 index 0000000..2eecf02 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/i_block.c @@ -0,0 +1,90 @@ +/* + * i_block.c --- Manage the i_block field for i_blocks + * + * Copyright (C) 2008 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode, + blk64_t num_blocks) +{ + unsigned long long b = inode->i_blocks; + + if (ext2fs_has_feature_huge_file(fs->super)) + b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32; + + if (!ext2fs_has_feature_huge_file(fs->super) || + !(inode->i_flags & EXT4_HUGE_FILE_FL)) + num_blocks *= fs->blocksize / 512; + num_blocks *= EXT2FS_CLUSTER_RATIO(fs); + + b += num_blocks; + + if (ext2fs_has_feature_huge_file(fs->super)) + inode->osd2.linux2.l_i_blocks_hi = b >> 32; + else if (b > 0xFFFFFFFF) + return EOVERFLOW; + inode->i_blocks = b & 0xFFFFFFFF; + return 0; +} + +errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode, + blk64_t num_blocks) +{ + unsigned long long b = inode->i_blocks; + + if (ext2fs_has_feature_huge_file(fs->super)) + b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32; + + if (!ext2fs_has_feature_huge_file(fs->super) || + !(inode->i_flags & EXT4_HUGE_FILE_FL)) + num_blocks *= fs->blocksize / 512; + num_blocks *= EXT2FS_CLUSTER_RATIO(fs); + + if (num_blocks > b) + return EOVERFLOW; + + b -= num_blocks; + + if (ext2fs_has_feature_huge_file(fs->super)) + inode->osd2.linux2.l_i_blocks_hi = b >> 32; + inode->i_blocks = b & 0xFFFFFFFF; + return 0; +} + +errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b) +{ + if (!ext2fs_has_feature_huge_file(fs->super) || + !(inode->i_flags & EXT4_HUGE_FILE_FL)) + b *= fs->blocksize / 512; + b *= EXT2FS_CLUSTER_RATIO(fs); + + inode->i_blocks = b & 0xFFFFFFFF; + if (ext2fs_has_feature_huge_file(fs->super)) + inode->osd2.linux2.l_i_blocks_hi = b >> 32; + else if (b >> 32) + return EOVERFLOW; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/i_block.o b/jni/e2fsprogs/lib/ext2fs/i_block.o new file mode 100755 index 0000000000000000000000000000000000000000..9a651d041e9cb520eb20b545a7e405addb50ed66 GIT binary patch literal 2208 zcmcgtUr19?82|3B=5ETgkO<2*!G|SvQ3;fu4!O*S@IeZEh^}*9|KO&u&CpDo*n`wd zl913pAAE2xJyZ~T%J8X23!;Y#^=U&2gC4ervA*x@9CvqJkOZA^_nq%|e&65o-EH>r z)lP?^fLsc^fr2JcfR!VKJ>y#jPGsg(Wivai#rBr8AvI4nt+I`~EndDzY{yJFr4J@&sJZO^~=UJA} zSggmXy{}86AMUFXea&c(lbD0#Y42FV3$Y%pfp}VzHp3n!ExZ)&c@9cG2N}N(<8R6M zlw-EB9ZxJVKW!^|< zr#s@}8_%`L2*=U}pgQ>hPcRXndlJb!+O9)Hi}9v!B~+sOYPJ*IxAsD~wb zRf|2b+`+DOW)hg+pYGtV`?~=+qmFoX9u~K7F1E4PJ1X`YbE3IivG#y+w9FZwlTvf0 ziaA3+B9BbTIkWJRD$WA>_u?$b*mKtUh)Xj@9Go$Y=0{*_0Iw;IoUbz6lU_Vim*P2m z4{4?#5cH1?d2X5E$jJDZr=?wQ(c1x_1|M3=?H*9>oKa3yxuFsDlN<%`p;Pd=SXWhj z%`?Z-GWDENo`4CShosL{)9V6m-z#utxAzw8y~v3P-Y=3qSF?=c_)_I= z&W90<(&8S%W$-gs>Qn{C0r&++4&oui9r)q(;@-n~0Qer`QiWC!t9)Bt0L0FN^0+0g z^w%cv0qO@X-WQbAf8wu-lz1NyJB<&ma^zdH_2uDxT>8IZ!)2ViHeAL5J!(!yK@W_F zLgrW$P-z{E7$g0`Q6pj&>;8cOqdzzv7>yLuCi*3;kBvu7{Yv-s^O2}OFbaCu4El9* z*cc4^L#DJE_D76C(;uA(o5t|OkZBB#1Wg#pJJAE6N21}VzaQmPh-Bk{-b!CB&^W0# zi$eZUETR3u+XP68t9)hiFRp7JC7mA2-yc6?{2O4|=DbYcQsDmpx3`z`S=gPBL?LB- zDZ7QejRrq#apk$RlX^hdTW5;S_JlqDt`se2kp^%Rb*hQk@CDJoK7mu61W9}Od-4P^ Udu%dU7LD2?1sCN_KJ50t0aDJ*XaE2J literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/icount.c b/jni/e2fsprogs/lib/ext2fs/icount.c new file mode 100755 index 0000000..888a90b --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/icount.c @@ -0,0 +1,921 @@ +/* + * icount.c --- an efficient inode count abstraction + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "tdb.h" + +/* + * The data storage strategy used by icount relies on the observation + * that most inode counts are either zero (for non-allocated inodes), + * one (for most files), and only a few that are two or more + * (directories and files that are linked to more than one directory). + * + * Also, e2fsck tends to load the icount data sequentially. + * + * So, we use an inode bitmap to indicate which inodes have a count of + * one, and then use a sorted list to store the counts for inodes + * which are greater than one. + * + * We also use an optional bitmap to indicate which inodes are already + * in the sorted list, to speed up the use of this abstraction by + * e2fsck's pass 2. Pass 2 increments inode counts as it finds them, + * so this extra bitmap avoids searching the sorted list to see if a + * particular inode is on the sorted list already. + */ + +struct ext2_icount_el { + ext2_ino_t ino; + __u32 count; +}; + +struct ext2_icount { + errcode_t magic; + ext2fs_inode_bitmap single; + ext2fs_inode_bitmap multiple; + ext2_ino_t count; + ext2_ino_t size; + ext2_ino_t num_inodes; + ext2_ino_t cursor; + struct ext2_icount_el *list; + struct ext2_icount_el *last_lookup; +#ifdef CONFIG_TDB + char *tdb_fn; + TDB_CONTEXT *tdb; +#endif + __u16 *fullmap; +}; + +/* + * We now use a 32-bit counter field because it doesn't cost us + * anything extra for the in-memory data structure, due to alignment + * padding. But there's no point changing the interface if most of + * the time we only care if the number is bigger than 65,000 or not. + * So use the following translation function to return a 16-bit count. + */ +#define icount_16_xlate(x) (((x) > 65500) ? 65500 : (x)) + +void ext2fs_free_icount(ext2_icount_t icount) +{ + if (!icount) + return; + + icount->magic = 0; + if (icount->list) + ext2fs_free_mem(&icount->list); + if (icount->single) + ext2fs_free_inode_bitmap(icount->single); + if (icount->multiple) + ext2fs_free_inode_bitmap(icount->multiple); +#ifdef CONFIG_TDB + if (icount->tdb) + tdb_close(icount->tdb); + if (icount->tdb_fn) { + (void) unlink(icount->tdb_fn); + free(icount->tdb_fn); + } +#endif + + if (icount->fullmap) + ext2fs_free_mem(&icount->fullmap); + + ext2fs_free_mem(&icount); +} + +static errcode_t alloc_icount(ext2_filsys fs, int flags, ext2_icount_t *ret) +{ + ext2_icount_t icount; + errcode_t retval; + + *ret = 0; + + retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount); + if (retval) + return retval; + memset(icount, 0, sizeof(struct ext2_icount)); + icount->magic = EXT2_ET_MAGIC_ICOUNT; + icount->num_inodes = fs->super->s_inodes_count; + + if ((flags & EXT2_ICOUNT_OPT_FULLMAP) && + (flags & EXT2_ICOUNT_OPT_INCREMENT)) { + unsigned sz = sizeof(*icount->fullmap) * icount->num_inodes; + + retval = ext2fs_get_mem(sz, &icount->fullmap); + /* If we can't allocate, fall back */ + if (!retval) { + memset(icount->fullmap, 0, sz); + *ret = icount; + return 0; + } + } + + retval = ext2fs_allocate_inode_bitmap(fs, "icount", &icount->single); + if (retval) + goto errout; + + if (flags & EXT2_ICOUNT_OPT_INCREMENT) { + retval = ext2fs_allocate_inode_bitmap(fs, "icount_inc", + &icount->multiple); + if (retval) + goto errout; + } else + icount->multiple = 0; + + *ret = icount; + return 0; + +errout: + ext2fs_free_icount(icount); + return(retval); +} + +#ifdef CONFIG_TDB +struct uuid { + __u32 time_low; + __u16 time_mid; + __u16 time_hi_and_version; + __u16 clock_seq; + __u8 node[6]; +}; + +static void unpack_uuid(void *in, struct uuid *uu) +{ + __u8 *ptr = in; + __u32 tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; + + memcpy(uu->node, ptr, 6); +} + +static void uuid_unparse(void *uu, char *out) +{ + struct uuid uuid; + + unpack_uuid(uu, &uuid); + sprintf(out, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); +} +#endif + +errcode_t ext2fs_create_icount_tdb(ext2_filsys fs EXT2FS_NO_TDB_UNUSED, + char *tdb_dir EXT2FS_NO_TDB_UNUSED, + int flags EXT2FS_NO_TDB_UNUSED, + ext2_icount_t *ret EXT2FS_NO_TDB_UNUSED) +{ +#ifdef CONFIG_TDB + ext2_icount_t icount; + errcode_t retval; + char *fn, uuid[40]; + ext2_ino_t num_inodes; + mode_t save_umask; + int fd; + + retval = alloc_icount(fs, flags, &icount); + if (retval) + return retval; + + retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &fn); + if (retval) + goto errout; + uuid_unparse(fs->super->s_uuid, uuid); + sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid); + save_umask = umask(077); + fd = mkstemp(fn); + if (fd < 0) { + retval = errno; + ext2fs_free_mem(&fn); + goto errout; + } + icount->tdb_fn = fn; + umask(save_umask); + /* + * This is an overestimate of the size that we will need; the + * ideal value is the number of used inodes with a count + * greater than 1. OTOH the times when we really need this is + * with the backup programs that use lots of hard links, in + * which case the number of inodes in use approaches the ideal + * value. + */ + num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count; + + icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC, + O_RDWR | O_CREAT | O_TRUNC, 0600); + close(fd); + if (icount->tdb == NULL) { + retval = errno; + goto errout; + } + *ret = icount; + return 0; +errout: + ext2fs_free_icount(icount); + return(retval); +#else + return EXT2_ET_UNIMPLEMENTED; +#endif +} + +errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size, + ext2_icount_t hint, ext2_icount_t *ret) +{ + ext2_icount_t icount; + errcode_t retval; + size_t bytes; + ext2_ino_t i; + + if (hint) { + EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); + if (hint->size > size) + size = (size_t) hint->size; + } + + retval = alloc_icount(fs, flags, &icount); + if (retval) + return retval; + + if (icount->fullmap) + goto successout; + + if (size) { + icount->size = size; + } else { + /* + * Figure out how many special case inode counts we will + * have. We know we will need one for each directory; + * we also need to reserve some extra room for file links + */ + retval = ext2fs_get_num_dirs(fs, &icount->size); + if (retval) + goto errout; + icount->size += fs->super->s_inodes_count / 50; + } + + bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el)); +#if 0 + printf("Icount allocated %u entries, %d bytes.\n", + icount->size, bytes); +#endif + retval = ext2fs_get_array(icount->size, sizeof(struct ext2_icount_el), + &icount->list); + if (retval) + goto errout; + memset(icount->list, 0, bytes); + + icount->count = 0; + icount->cursor = 0; + + /* + * Populate the sorted list with those entries which were + * found in the hint icount (since those are ones which will + * likely need to be in the sorted list this time around). + */ + if (hint) { + for (i=0; i < hint->count; i++) + icount->list[i].ino = hint->list[i].ino; + icount->count = hint->count; + } + +successout: + *ret = icount; + return 0; + +errout: + ext2fs_free_icount(icount); + return(retval); +} + +errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, + unsigned int size, + ext2_icount_t *ret) +{ + return ext2fs_create_icount2(fs, flags, size, 0, ret); +} + +/* + * insert_icount_el() --- Insert a new entry into the sorted list at a + * specified position. + */ +static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, + ext2_ino_t ino, int pos) +{ + struct ext2_icount_el *el; + errcode_t retval; + ext2_ino_t new_size = 0; + int num; + + if (icount->last_lookup && icount->last_lookup->ino == ino) + return icount->last_lookup; + + if (icount->count >= icount->size) { + if (icount->count) { + new_size = icount->list[(unsigned)icount->count-1].ino; + new_size = (ext2_ino_t) (icount->count * + ((float) icount->num_inodes / new_size)); + } + if (new_size < (icount->size + 100)) + new_size = icount->size + 100; +#if 0 + printf("Reallocating icount %u entries...\n", new_size); +#endif + retval = ext2fs_resize_mem((size_t) icount->size * + sizeof(struct ext2_icount_el), + (size_t) new_size * + sizeof(struct ext2_icount_el), + &icount->list); + if (retval) + return 0; + icount->size = new_size; + } + num = (int) icount->count - pos; + if (num < 0) + return 0; /* should never happen */ + if (num) { + memmove(&icount->list[pos+1], &icount->list[pos], + sizeof(struct ext2_icount_el) * num); + } + icount->count++; + el = &icount->list[pos]; + el->count = 0; + el->ino = ino; + icount->last_lookup = el; + return el; +} + +/* + * get_icount_el() --- given an inode number, try to find icount + * information in the sorted list. If the create flag is set, + * and we can't find an entry, create one in the sorted list. + */ +static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, + ext2_ino_t ino, int create) +{ + int low, high, mid; + + if (!icount || !icount->list) + return 0; + + if (create && ((icount->count == 0) || + (ino > icount->list[(unsigned)icount->count-1].ino))) { + return insert_icount_el(icount, ino, (unsigned) icount->count); + } + if (icount->count == 0) + return 0; + + if (icount->cursor >= icount->count) + icount->cursor = 0; + if (ino == icount->list[icount->cursor].ino) + return &icount->list[icount->cursor++]; +#if 0 + printf("Non-cursor get_icount_el: %u\n", ino); +#endif + low = 0; + high = (int) icount->count-1; + while (low <= high) { + mid = ((unsigned)low + (unsigned)high) >> 1; + if (ino == icount->list[mid].ino) { + icount->cursor = mid+1; + return &icount->list[mid]; + } + if (ino < icount->list[mid].ino) + high = mid-1; + else + low = mid+1; + } + /* + * If we need to create a new entry, it should be right at + * low (where high will be left at low-1). + */ + if (create) + return insert_icount_el(icount, ino, low); + return 0; +} + +static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino, + __u32 count) +{ + struct ext2_icount_el *el; +#ifdef CONFIG_TDB + TDB_DATA key, data; + + if (icount->tdb) { + key.dptr = (unsigned char *) &ino; + key.dsize = sizeof(ext2_ino_t); + data.dptr = (unsigned char *) &count; + data.dsize = sizeof(__u32); + if (count) { + if (tdb_store(icount->tdb, key, data, TDB_REPLACE)) + return tdb_error(icount->tdb) + + EXT2_ET_TDB_SUCCESS; + } else { + if (tdb_delete(icount->tdb, key)) + return tdb_error(icount->tdb) + + EXT2_ET_TDB_SUCCESS; + } + return 0; + } +#endif + if (icount->fullmap) { + icount->fullmap[ino] = icount_16_xlate(count); + return 0; + } + + el = get_icount_el(icount, ino, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + + el->count = count; + return 0; +} + +static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino, + __u32 *count) +{ + struct ext2_icount_el *el; +#ifdef CONFIG_TDB + TDB_DATA key, data; + + if (icount->tdb) { + key.dptr = (unsigned char *) &ino; + key.dsize = sizeof(ext2_ino_t); + + data = tdb_fetch(icount->tdb, key); + if (data.dptr == NULL) { + *count = 0; + return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS; + } + + *count = *((__u32 *) data.dptr); + free(data.dptr); + return 0; + } +#endif + if (icount->fullmap) { + *count = icount->fullmap[ino]; + return 0; + } + + el = get_icount_el(icount, ino, 0); + if (!el) { + *count = 0; + return ENOENT; + } + + *count = el->count; + return 0; +} + +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) +{ + errcode_t ret = 0; + unsigned int i; + const char *bad = "bad icount"; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (icount->count > icount->size) { + fprintf(out, "%s: count > size\n", bad); + return EXT2_ET_INVALID_ARGUMENT; + } + for (i=1; i < icount->count; i++) { + if (icount->list[i-1].ino >= icount->list[i].ino) { + fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", + bad, i-1, icount->list[i-1].ino, + i, icount->list[i].ino); + ret = EXT2_ET_INVALID_ARGUMENT; + } + } + return ret; +} + +errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) +{ + __u32 val; + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + if (!icount->fullmap) { + if (ext2fs_test_inode_bitmap2(icount->single, ino)) { + *ret = 1; + return 0; + } + if (icount->multiple && + !ext2fs_test_inode_bitmap2(icount->multiple, ino)) { + *ret = 0; + return 0; + } + } + get_inode_count(icount, ino, &val); + *ret = icount_16_xlate(val); + return 0; +} + +errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret) +{ + __u32 curr_value; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + if (icount->fullmap) { + curr_value = icount_16_xlate(icount->fullmap[ino] + 1); + icount->fullmap[ino] = curr_value; + } else if (ext2fs_test_inode_bitmap2(icount->single, ino)) { + /* + * If the existing count is 1, then we know there is + * no entry in the list. + */ + if (set_inode_count(icount, ino, 2)) + return EXT2_ET_NO_MEMORY; + curr_value = 2; + ext2fs_unmark_inode_bitmap2(icount->single, ino); + } else if (icount->multiple) { + /* + * The count is either zero or greater than 1; if the + * inode is set in icount->multiple, then there should + * be an entry in the list, so we need to fix it. + */ + if (ext2fs_test_inode_bitmap2(icount->multiple, ino)) { + get_inode_count(icount, ino, &curr_value); + curr_value++; + if (set_inode_count(icount, ino, curr_value)) + return EXT2_ET_NO_MEMORY; + } else { + /* + * The count was zero; mark the single bitmap + * and return. + */ + ext2fs_mark_inode_bitmap2(icount->single, ino); + if (ret) + *ret = 1; + return 0; + } + } else { + /* + * The count is either zero or greater than 1; try to + * find an entry in the list to determine which. + */ + get_inode_count(icount, ino, &curr_value); + curr_value++; + if (set_inode_count(icount, ino, curr_value)) + return EXT2_ET_NO_MEMORY; + } + if (icount->multiple) + ext2fs_mark_inode_bitmap2(icount->multiple, ino); + if (ret) + *ret = icount_16_xlate(curr_value); + return 0; +} + +errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret) +{ + __u32 curr_value; + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (icount->fullmap) { + if (!icount->fullmap[ino]) + return EXT2_ET_INVALID_ARGUMENT; + + curr_value = --icount->fullmap[ino]; + if (ret) + *ret = icount_16_xlate(curr_value); + return 0; + } + + if (ext2fs_test_inode_bitmap2(icount->single, ino)) { + ext2fs_unmark_inode_bitmap2(icount->single, ino); + if (icount->multiple) + ext2fs_unmark_inode_bitmap2(icount->multiple, ino); + else { + set_inode_count(icount, ino, 0); + } + if (ret) + *ret = 0; + return 0; + } + + if (icount->multiple && + !ext2fs_test_inode_bitmap2(icount->multiple, ino)) + return EXT2_ET_INVALID_ARGUMENT; + + get_inode_count(icount, ino, &curr_value); + if (!curr_value) + return EXT2_ET_INVALID_ARGUMENT; + curr_value--; + if (set_inode_count(icount, ino, curr_value)) + return EXT2_ET_NO_MEMORY; + + if (curr_value == 1) + ext2fs_mark_inode_bitmap2(icount->single, ino); + if ((curr_value == 0) && icount->multiple) + ext2fs_unmark_inode_bitmap2(icount->multiple, ino); + + if (ret) + *ret = icount_16_xlate(curr_value); + return 0; +} + +errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, + __u16 count) +{ + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (icount->fullmap) + return set_inode_count(icount, ino, count); + + if (count == 1) { + ext2fs_mark_inode_bitmap2(icount->single, ino); + if (icount->multiple) + ext2fs_unmark_inode_bitmap2(icount->multiple, ino); + return 0; + } + if (count == 0) { + ext2fs_unmark_inode_bitmap2(icount->single, ino); + if (icount->multiple) { + /* + * If the icount->multiple bitmap is enabled, + * we can just clear both bitmaps and we're done + */ + ext2fs_unmark_inode_bitmap2(icount->multiple, ino); + } else + set_inode_count(icount, ino, 0); + return 0; + } + + if (set_inode_count(icount, ino, count)) + return EXT2_ET_NO_MEMORY; + ext2fs_unmark_inode_bitmap2(icount->single, ino); + if (icount->multiple) + ext2fs_mark_inode_bitmap2(icount->multiple, ino); + return 0; +} + +ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount) +{ + if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT) + return 0; + + return icount->size; +} + +#ifdef DEBUG + +ext2_filsys test_fs; +ext2_icount_t icount; + +#define EXIT 0x00 +#define FETCH 0x01 +#define STORE 0x02 +#define INCREMENT 0x03 +#define DECREMENT 0x04 + +struct test_program { + int cmd; + ext2_ino_t ino; + __u16 arg; + __u16 expected; +}; + +struct test_program prog[] = { + { STORE, 42, 42, 42 }, + { STORE, 1, 1, 1 }, + { STORE, 2, 2, 2 }, + { STORE, 3, 3, 3 }, + { STORE, 10, 1, 1 }, + { STORE, 42, 0, 0 }, + { INCREMENT, 5, 0, 1 }, + { INCREMENT, 5, 0, 2 }, + { INCREMENT, 5, 0, 3 }, + { INCREMENT, 5, 0, 4 }, + { DECREMENT, 5, 0, 3 }, + { DECREMENT, 5, 0, 2 }, + { DECREMENT, 5, 0, 1 }, + { DECREMENT, 5, 0, 0 }, + { FETCH, 10, 0, 1 }, + { FETCH, 1, 0, 1 }, + { FETCH, 2, 0, 2 }, + { FETCH, 3, 0, 3 }, + { INCREMENT, 1, 0, 2 }, + { DECREMENT, 2, 0, 1 }, + { DECREMENT, 2, 0, 0 }, + { FETCH, 12, 0, 0 }, + { EXIT, 0, 0, 0 } +}; + +struct test_program extended[] = { + { STORE, 1, 1, 1 }, + { STORE, 2, 2, 2 }, + { STORE, 3, 3, 3 }, + { STORE, 4, 4, 4 }, + { STORE, 5, 5, 5 }, + { STORE, 6, 1, 1 }, + { STORE, 7, 2, 2 }, + { STORE, 8, 3, 3 }, + { STORE, 9, 4, 4 }, + { STORE, 10, 5, 5 }, + { STORE, 11, 1, 1 }, + { STORE, 12, 2, 2 }, + { STORE, 13, 3, 3 }, + { STORE, 14, 4, 4 }, + { STORE, 15, 5, 5 }, + { STORE, 16, 1, 1 }, + { STORE, 17, 2, 2 }, + { STORE, 18, 3, 3 }, + { STORE, 19, 4, 4 }, + { STORE, 20, 5, 5 }, + { STORE, 21, 1, 1 }, + { STORE, 22, 2, 2 }, + { STORE, 23, 3, 3 }, + { STORE, 24, 4, 4 }, + { STORE, 25, 5, 5 }, + { STORE, 26, 1, 1 }, + { STORE, 27, 2, 2 }, + { STORE, 28, 3, 3 }, + { STORE, 29, 4, 4 }, + { STORE, 30, 5, 5 }, + { EXIT, 0, 0, 0 } +}; + +/* + * Setup the variables for doing the inode scan test. + */ +static void setup(void) +{ + errcode_t retval; + struct ext2_super_block param; + + initialize_ext2_error_table(); + + memset(¶m, 0, sizeof(param)); + ext2fs_blocks_count_set(¶m, 12000); + + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, + test_io_manager, &test_fs); + if (retval) { + com_err("setup", retval, + "while initializing filesystem"); + exit(1); + } + retval = ext2fs_allocate_tables(test_fs); + if (retval) { + com_err("setup", retval, + "while allocating tables for test filesystem"); + exit(1); + } +} + +int run_test(int flags, int size, char *dir, struct test_program *prog) +{ + errcode_t retval; + ext2_icount_t icount; + struct test_program *pc; + __u16 result; + int problem = 0; + + if (dir) { +#ifdef CONFIG_TDB + retval = ext2fs_create_icount_tdb(test_fs, dir, + flags, &icount); + if (retval) { + com_err("run_test", retval, + "while creating icount using tdb"); + exit(1); + } +#else + printf("Skipped\n"); + return 0; +#endif + } else { + retval = ext2fs_create_icount2(test_fs, flags, size, 0, + &icount); + if (retval) { + com_err("run_test", retval, "while creating icount"); + exit(1); + } + } + for (pc = prog; pc->cmd != EXIT; pc++) { + switch (pc->cmd) { + case FETCH: + printf("icount_fetch(%u) = ", pc->ino); + break; + case STORE: + retval = ext2fs_icount_store(icount, pc->ino, pc->arg); + if (retval) { + com_err("run_test", retval, + "while calling icount_store"); + exit(1); + } + printf("icount_store(%u, %u) = ", pc->ino, pc->arg); + break; + case INCREMENT: + retval = ext2fs_icount_increment(icount, pc->ino, 0); + if (retval) { + com_err("run_test", retval, + "while calling icount_increment"); + exit(1); + } + printf("icount_increment(%u) = ", pc->ino); + break; + case DECREMENT: + retval = ext2fs_icount_decrement(icount, pc->ino, 0); + if (retval) { + com_err("run_test", retval, + "while calling icount_decrement"); + exit(1); + } + printf("icount_decrement(%u) = ", pc->ino); + break; + } + retval = ext2fs_icount_fetch(icount, pc->ino, &result); + if (retval) { + com_err("run_test", retval, + "while calling icount_fetch"); + exit(1); + } + printf("%u (%s)\n", result, (result == pc->expected) ? + "OK" : "NOT OK"); + if (result != pc->expected) + problem++; + } + printf("icount size is %u\n", ext2fs_get_icount_size(icount)); + retval = ext2fs_icount_validate(icount, stdout); + if (retval) { + com_err("run_test", retval, "while calling icount_validate"); + exit(1); + } + ext2fs_free_icount(icount); + return problem; +} + + +int main(int argc, char **argv) +{ + int failed = 0; + + setup(); + printf("Standard icount run:\n"); + failed += run_test(0, 0, 0, prog); + printf("\nMultiple bitmap test:\n"); + failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, 0, prog); + printf("\nResizing icount:\n"); + failed += run_test(0, 3, 0, extended); + printf("\nStandard icount run with tdb:\n"); + failed += run_test(0, 0, ".", prog); + printf("\nMultiple bitmap test with tdb:\n"); + failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, ".", prog); + if (failed) + printf("FAILED!\n"); + return failed; +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/icount.o b/jni/e2fsprogs/lib/ext2fs/icount.o new file mode 100755 index 0000000000000000000000000000000000000000..086ef85770d06abf87bd8e4d7f170709270e50de GIT binary patch literal 12680 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 DE7I~v literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/imager.c b/jni/e2fsprogs/lib/ext2fs/imager.c new file mode 100755 index 0000000..23290a6 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/imager.c @@ -0,0 +1,470 @@ +/* + * image.c --- writes out the critical parts of the filesystem as a + * flat file. + * + * Copyright (C) 2000 Theodore Ts'o. + * + * Note: this uses the POSIX IO interfaces, unlike most of the other + * functions in this library. So sue me. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef HAVE_TYPE_SSIZE_T +typedef int ssize_t; +#endif + +/* + * This function returns 1 if the specified block is all zeros + */ +static int check_zero_block(char *buf, int blocksize) +{ + char *cp = buf; + int left = blocksize; + + while (left > 0) { + if (*cp++) + return 0; + left--; + } + return 1; +} + +/* + * Write the inode table out as a single block. + */ +#define BUF_BLOCKS 32 + +errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) +{ + dgrp_t group; + ssize_t left, c, d; + char *buf, *cp; + blk64_t blk; + ssize_t actual; + errcode_t retval; + ext2_loff_t r; + + buf = malloc(fs->blocksize * BUF_BLOCKS); + if (!buf) + return ENOMEM; + + for (group = 0; group < fs->group_desc_count; group++) { + blk = ext2fs_inode_table_loc(fs, group); + if (!blk) { + retval = EXT2_ET_MISSING_INODE_TABLE; + goto errout; + } + left = fs->inode_blocks_per_group; + if ((blk < fs->super->s_first_data_block) || + (blk + left - 1 >= ext2fs_blocks_count(fs->super))) { + retval = EXT2_ET_GDESC_BAD_INODE_TABLE; + goto errout; + } + while (left) { + c = BUF_BLOCKS; + if (c > left) + c = left; + retval = io_channel_read_blk64(fs->io, blk, c, buf); + if (retval) + goto errout; + cp = buf; + while (c) { + if (!(flags & IMAGER_FLAG_SPARSEWRITE)) { + d = c; + goto skip_sparse; + } + /* Skip zero blocks */ + if (check_zero_block(cp, fs->blocksize)) { + c--; + blk++; + left--; + cp += fs->blocksize; + r = ext2fs_llseek(fd, fs->blocksize, + SEEK_CUR); + if (r < 0) { + retval = errno; + goto errout; + } + continue; + } + /* Find non-zero blocks */ + for (d = 1; d < c; d++) { + if (check_zero_block(cp + + d * fs->blocksize, + fs->blocksize)) + break; + } + skip_sparse: + actual = write(fd, cp, d * fs->blocksize); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != d * fs->blocksize) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + blk += d; + left -= d; + cp += d * fs->blocksize; + c -= d; + } + } + } + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Read in the inode table and stuff it into place + */ +errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + dgrp_t group; + ssize_t c, left; + char *buf; + blk64_t blk; + ssize_t actual; + errcode_t retval; + + buf = malloc(fs->blocksize * BUF_BLOCKS); + if (!buf) + return ENOMEM; + + for (group = 0; group < fs->group_desc_count; group++) { + blk = ext2fs_inode_table_loc(fs, group); + if (!blk) { + retval = EXT2_ET_MISSING_INODE_TABLE; + goto errout; + } + left = fs->inode_blocks_per_group; + while (left) { + c = BUF_BLOCKS; + if (c > left) + c = left; + actual = read(fd, buf, fs->blocksize * c); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != fs->blocksize * c) { + retval = EXT2_ET_SHORT_READ; + goto errout; + } + retval = io_channel_write_blk64(fs->io, blk, c, buf); + if (retval) + goto errout; + + blk += c; + left -= c; + } + } + retval = ext2fs_flush_icache(fs); + +errout: + free(buf); + return retval; +} + +/* + * Write out superblock and group descriptors + */ +errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + char *buf, *cp; + ssize_t actual; + errcode_t retval; +#ifdef WORDS_BIGENDIAN + unsigned int groups_per_block; + struct ext2_group_desc *gdp; + int j; +#endif + + if (fs->group_desc == NULL) + return EXT2_ET_NO_GDESC; + + buf = malloc(fs->blocksize); + if (!buf) + return ENOMEM; + + /* + * Write out the superblock + */ + memset(buf, 0, fs->blocksize); +#ifdef WORDS_BIGENDIAN + /* + * We're writing out superblock so let's convert + * it to little endian and then back if needed + */ + ext2fs_swap_super(fs->super); + memcpy(buf, fs->super, SUPERBLOCK_SIZE); + ext2fs_swap_super(fs->super); +#else + memcpy(buf, fs->super, SUPERBLOCK_SIZE); +#endif + actual = write(fd, buf, fs->blocksize); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t) fs->blocksize) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + + /* + * Now write out the block group descriptors + */ + + cp = (char *) fs->group_desc; + +#ifdef WORDS_BIGENDIAN + /* + * Convert group descriptors to little endian and back + * if needed + */ + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); + for (j=0; j < groups_per_block*fs->desc_blocks; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, j); + if (gdp) + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + + actual = write(fd, cp, (ssize_t)fs->blocksize * fs->desc_blocks); + + +#ifdef WORDS_BIGENDIAN + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); + for (j=0; j < groups_per_block*fs->desc_blocks; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, j); + if (gdp) + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t)(fs->blocksize * fs->desc_blocks)) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Read the superblock and group descriptors and overwrite them. + */ +errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + char *buf; + ssize_t actual, size; + errcode_t retval; + + size = (ssize_t)fs->blocksize * (fs->group_desc_count + 1); + buf = malloc(size); + if (!buf) + return ENOMEM; + + /* + * Read it all in. + */ + actual = read(fd, buf, size); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != size) { + retval = EXT2_ET_SHORT_READ; + goto errout; + } + + /* + * Now copy in the superblock and group descriptors + */ + memcpy(fs->super, buf, SUPERBLOCK_SIZE); + + memcpy(fs->group_desc, buf + fs->blocksize, + (ssize_t)fs->blocksize * fs->group_desc_count); + + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Write the block/inode bitmaps. + */ +errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) +{ + ext2fs_generic_bitmap bmap; + errcode_t retval; + ssize_t actual; + size_t c; + __u64 itr, cnt, size, total_size; + char buf[1024]; + + if (flags & IMAGER_FLAG_INODEMAP) { + if (!fs->inode_map) { + retval = ext2fs_read_inode_bitmap(fs); + if (retval) + return retval; + } + bmap = fs->inode_map; + itr = 1; + cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) * + fs->group_desc_count; + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + return retval; + } + bmap = fs->block_map; + itr = fs->super->s_first_data_block; + cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count); + size = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; + } + total_size = size * fs->group_desc_count; + + while (cnt > 0) { + size = sizeof(buf); + if (size > (cnt >> 3)) + size = (cnt >> 3); + if (size == 0) + break; + + retval = ext2fs_get_generic_bmap_range(bmap, itr, + size << 3, buf); + if (retval) + return retval; + + actual = write(fd, buf, size); + if (actual == -1) + return errno; + if (actual != (int) size) + return EXT2_ET_SHORT_READ; + + itr += size << 3; + cnt -= size << 3; + } + + size = total_size % fs->blocksize; + memset(buf, 0, sizeof(buf)); + if (size) { + size = fs->blocksize - size; + while (size) { + c = size; + if (c > (int) sizeof(buf)) + c = sizeof(buf); + actual = write(fd, buf, c); + if (actual < 0) + return errno; + if ((size_t) actual != c) + return EXT2_ET_SHORT_WRITE; + size -= c; + } + } + return 0; +} + + +/* + * Read the block/inode bitmaps. + */ +errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) +{ + ext2fs_generic_bitmap bmap; + errcode_t retval; + __u64 itr, cnt; + char buf[1024]; + unsigned int size; + ssize_t actual; + + if (flags & IMAGER_FLAG_INODEMAP) { + if (!fs->inode_map) { + retval = ext2fs_read_inode_bitmap(fs); + if (retval) + return retval; + } + bmap = fs->inode_map; + itr = 1; + cnt = (__u64)EXT2_INODES_PER_GROUP(fs->super) * + fs->group_desc_count; + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + return retval; + } + bmap = fs->block_map; + itr = fs->super->s_first_data_block; + cnt = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count); + size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + } + + while (cnt > 0) { + size = sizeof(buf); + if (size > (cnt >> 3)) + size = (cnt >> 3); + if (size == 0) + break; + + actual = read(fd, buf, size); + if (actual == -1) + return errno; + if (actual != (int) size) + return EXT2_ET_SHORT_READ; + + retval = ext2fs_set_generic_bmap_range(bmap, itr, + size << 3, buf); + if (retval) + return retval; + + itr += size << 3; + cnt -= size << 3; + } + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/imager.o b/jni/e2fsprogs/lib/ext2fs/imager.o new file mode 100755 index 0000000000000000000000000000000000000000..cdb8eb6873b6562a6760f32776439330a2a9cc24 GIT binary patch literal 7136 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 +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf) +{ + errcode_t retval; +#ifdef WORDS_BIGENDIAN + blk_t *block_nr; + int i; + int limit = fs->blocksize >> 2; +#endif + + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) && + (fs->io != fs->image_io)) + memset(buf, 0, fs->blocksize); + else { + retval = io_channel_read_blk(fs->io, blk, 1, buf); + if (retval) + return retval; + } +#ifdef WORDS_BIGENDIAN + block_nr = (blk_t *) buf; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); +#endif + return 0; +} + +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf) +{ +#ifdef WORDS_BIGENDIAN + blk_t *block_nr; + int i; + int limit = fs->blocksize >> 2; +#endif + + if (fs->flags & EXT2_FLAG_IMAGE_FILE) + return 0; + +#ifdef WORDS_BIGENDIAN + block_nr = (blk_t *) buf; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); +#endif + return io_channel_write_blk(fs->io, blk, 1, buf); +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/ind_block.o b/jni/e2fsprogs/lib/ext2fs/ind_block.o new file mode 100755 index 0000000000000000000000000000000000000000..0bebd1ded4206f972f72057cd064b964b74af793 GIT binary patch literal 1520 zcmbu9&1(};5Wr`%soBtwR%xYDZG!Y*11?Dg$<2pGtsovmK|#8t$<_q(0m-7NEhxl; zUW!4lO1v5H;6boCDa1cOFU51szXB>KOWv#0mW=+MDIg9nC z%=H-SHIOf?v7RFNe}^TwLB94lv*H(6b4OMp9XS-iEnZGJ@)XQfrmg%i)oCqnb!30! z7v`RX$JaqRx83$ZZ`X&l06tJ%)2@cPUbJcb32oB#s@CnVUuaD)J!k>W;A!-$ zP-|oFoe97`uol*)8J>bQ1LX&)E^+FIo@1=HhimF-Z-O<=p5$Rq^?iGuZ{S|$o{-8V z3wOi!^-?)oEQDimHKxXK=t=Wz0i=gG(#D)L8wkNXvKh|5kWK{IQsBhoYtJjM=UpJg zmV)r}2f!(GG4i7r^pgli?YKLEP?X1!>tB*VhZp_~M)_s%9Kf3(j=qB2#f$bi5-6Tz47s!0goSM`>VaC)b4k_E zD+Z{kVm_}I49M&GvTgvf#nrO*pp-RqEn7%yE4gCop1>tNnRZaMP&9P)^0k|%%SIBT zth#zeTP-E?I@sxI3e>VuGLkE(*Yc$2)9NDq#9+RnMtP(Espy;>pR!$ThQk*&u?#$} zeL^=!%zcB5N5x$UUe1LgH!&sv*I)Uii1%DUPKY##-~qI$hWj`weBYxK>=4n8&{xnW zY)2Suj)Eg%mpOC3LsaKE&!_LlDWZSDZlf`3{#{;B%td*0#v)(Lzk$rXHzJ@vHj?j_ JvhT>9{}+LD(x?Cc literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/initialize.c b/jni/e2fsprogs/lib/ext2fs/initialize.c new file mode 100755 index 0000000..edd692b --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/initialize.c @@ -0,0 +1,671 @@ +/* + * initialize.c --- initialize a filesystem handle given superblock + * parameters. Used by mke2fs when initializing a filesystem. + * + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#if defined(__linux__) && defined(EXT2_OS_LINUX) +#define CREATOR_OS EXT2_OS_LINUX +#else +#if defined(__GNU__) && defined(EXT2_OS_HURD) +#define CREATOR_OS EXT2_OS_HURD +#else +#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) +#define CREATOR_OS EXT2_OS_FREEBSD +#else +#if defined(LITES) && defined(EXT2_OS_LITES) +#define CREATOR_OS EXT2_OS_LITES +#else +#define CREATOR_OS EXT2_OS_LINUX /* by default */ +#endif /* defined(LITES) && defined(EXT2_OS_LITES) */ +#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */ +#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */ +#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */ + +/* + * Calculate the number of GDT blocks to reserve for online filesystem growth. + * The absolute maximum number of GDT blocks we can reserve is determined by + * the number of block pointers that can fit into a single block. + */ +static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs) +{ + struct ext2_super_block *sb = fs->super; + unsigned long bpg = sb->s_blocks_per_group; + unsigned int gdpb = EXT2_DESC_PER_BLOCK(sb); + unsigned long max_blocks = 0xffffffff; + unsigned long rsv_groups; + unsigned int rsv_gdb; + + /* We set it at 1024x the current filesystem size, or + * the upper block count limit (2^32), whichever is lower. + */ + if (ext2fs_blocks_count(sb) < max_blocks / 1024) + max_blocks = ext2fs_blocks_count(sb) * 1024; + /* + * ext2fs_div64_ceil() is unnecessary because max_blocks is + * max _GDT_ blocks, which is limited to 32 bits. + */ + rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg); + rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks; + if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb)) + rsv_gdb = EXT2_ADDR_PER_BLOCK(sb); +#ifdef RES_GDT_DEBUG + printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %u\n", + max_blocks, rsv_groups, rsv_gdb); +#endif + + return rsv_gdb; +} + +errcode_t ext2fs_initialize(const char *name, int flags, + struct ext2_super_block *param, + io_manager manager, ext2_filsys *ret_fs) +{ + ext2_filsys fs; + errcode_t retval; + struct ext2_super_block *super; + unsigned int rem; + unsigned int overhead = 0; + unsigned int ipg; + dgrp_t i; + blk64_t free_blocks; + blk_t numblocks; + int rsv_gdt; + int csum_flag; + int bigalloc_flag; + int io_flags; + int has_bg; + unsigned reserved_inos; + char *buf = 0; + char c; + double reserved_ratio; + char *time_env; + + if (!param || !ext2fs_blocks_count(param)) + return EXT2_ET_INVALID_ARGUMENT; + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + memset(fs, 0, sizeof(struct struct_ext2_filsys)); + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; + fs->flags = flags | EXT2_FLAG_RW; + fs->umask = 022; + fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; +#ifdef WORDS_BIGENDIAN + fs->flags |= EXT2_FLAG_SWAP_BYTES; +#endif + + time_env = getenv("E2FSPROGS_FAKE_TIME"); + if (time_env) + fs->now = strtoul(time_env, NULL, 0); + + io_flags = IO_FLAG_RW; + if (flags & EXT2_FLAG_EXCLUSIVE) + io_flags |= IO_FLAG_EXCLUSIVE; + if (flags & EXT2_FLAG_DIRECT_IO) + io_flags |= IO_FLAG_DIRECT_IO; + io_flags |= O_BINARY; + retval = manager->open(name, io_flags, &fs->io); + if (retval) + goto cleanup; + fs->image_io = fs->io; + fs->io->app_data = fs; + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); + if (retval) + goto cleanup; + + strcpy(fs->device_name, name); + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super); + if (retval) + goto cleanup; + fs->super = super; + + memset(super, 0, SUPERBLOCK_SIZE); + +#define set_field(field, default) (super->field = param->field ? \ + param->field : (default)) +#define assign_field(field) (super->field = param->field) + + super->s_magic = EXT2_SUPER_MAGIC; + super->s_state = EXT2_VALID_FS; + + bigalloc_flag = ext2fs_has_feature_bigalloc(param); + + assign_field(s_log_block_size); + + if (bigalloc_flag) { + set_field(s_log_cluster_size, super->s_log_block_size+4); + if (super->s_log_block_size > super->s_log_cluster_size) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + } else + super->s_log_cluster_size = super->s_log_block_size; + + set_field(s_first_data_block, super->s_log_cluster_size ? 0 : 1); + set_field(s_max_mnt_count, 0); + set_field(s_errors, EXT2_ERRORS_DEFAULT); + set_field(s_feature_compat, 0); + set_field(s_feature_incompat, 0); + set_field(s_feature_ro_compat, 0); + set_field(s_default_mount_opts, 0); + set_field(s_first_meta_bg, 0); + set_field(s_raid_stride, 0); /* default stride size: 0 */ + set_field(s_raid_stripe_width, 0); /* default stripe width: 0 */ + set_field(s_log_groups_per_flex, 0); + set_field(s_flags, 0); + assign_field(s_backup_bgs[0]); + assign_field(s_backup_bgs[1]); + + assign_field(s_encoding); + assign_field(s_encoding_flags); + + if (ext2fs_has_feature_casefold(param)) + fs->encoding = ext2fs_load_nls_table(param->s_encoding); + + if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { + retval = EXT2_ET_RO_UNSUPP_FEATURE; + goto cleanup; + } + + set_field(s_rev_level, EXT2_GOOD_OLD_REV); + if (super->s_rev_level >= EXT2_DYNAMIC_REV) { + set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO); + set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE); + if (super->s_inode_size >= sizeof(struct ext2_inode_large)) { + int extra_isize = sizeof(struct ext2_inode_large) - + EXT2_GOOD_OLD_INODE_SIZE; + set_field(s_min_extra_isize, extra_isize); + set_field(s_want_extra_isize, extra_isize); + } + } else { + super->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; + super->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; + } + + set_field(s_checkinterval, 0); + super->s_mkfs_time = super->s_lastcheck = fs->now ? fs->now : time(NULL); + + super->s_creator_os = CREATOR_OS; + + fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(super); + fs->cluster_ratio_bits = super->s_log_cluster_size - + super->s_log_block_size; + + if (bigalloc_flag) { + unsigned long long bpg; + + if (param->s_blocks_per_group && + param->s_clusters_per_group && + ((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) != + param->s_blocks_per_group)) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + if (param->s_clusters_per_group) + assign_field(s_clusters_per_group); + else if (param->s_blocks_per_group) + super->s_clusters_per_group = + param->s_blocks_per_group / + EXT2FS_CLUSTER_RATIO(fs); + else if (super->s_log_cluster_size + 15 < 32) + super->s_clusters_per_group = fs->blocksize * 8; + else + super->s_clusters_per_group = (fs->blocksize - 1) * 8; + if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super)) + super->s_clusters_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super); + bpg = EXT2FS_C2B(fs, + (unsigned long long) super->s_clusters_per_group); + if (bpg >= (((unsigned long long) 1) << 32)) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + super->s_blocks_per_group = bpg; + } else { + set_field(s_blocks_per_group, fs->blocksize * 8); + if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super)) + super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super); + super->s_clusters_per_group = super->s_blocks_per_group; + } + + ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) & + ~((blk64_t) EXT2FS_CLUSTER_MASK(fs))); + ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param)); + if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + + set_field(s_mmp_update_interval, 0); + + /* + * If we're creating an external journal device, we don't need + * to bother with the rest. + */ + if (ext2fs_has_feature_journal_dev(super)) { + fs->group_desc_count = 0; + ext2fs_mark_super_dirty(fs); + *ret_fs = fs; + return 0; + } + +retry: + fs->group_desc_count = (dgrp_t) ext2fs_div64_ceil( + ext2fs_blocks_count(super) - super->s_first_data_block, + EXT2_BLOCKS_PER_GROUP(super)); + if (fs->group_desc_count == 0) { + retval = EXT2_ET_TOOSMALL; + goto cleanup; + } + + set_field(s_desc_size, + ext2fs_has_feature_64bit(super) ? + EXT2_MIN_DESC_SIZE_64BIT : 0); + + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, + EXT2_DESC_PER_BLOCK(super)); + + i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; + + if (ext2fs_has_feature_64bit(super) && + (ext2fs_blocks_count(super) / i) >= (1ULL << 32)) + set_field(s_inodes_count, ~0U); + else + set_field(s_inodes_count, ext2fs_blocks_count(super) / i); + + /* + * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so + * that we have enough inodes for the filesystem(!) + */ + if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1) + super->s_inodes_count = EXT2_FIRST_INODE(super)+1; + + /* + * There should be at least as many inodes as the user + * requested. Figure out how many inodes per group that + * should be. But make sure that we don't allocate more than + * one bitmap's worth of inodes each group. + */ + ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count); + if (ipg > fs->blocksize * 8) { + if (!bigalloc_flag && super->s_blocks_per_group >= 256) { + /* Try again with slightly different parameters */ + super->s_blocks_per_group -= 8; + ext2fs_blocks_count_set(super, + ext2fs_blocks_count(param)); + super->s_clusters_per_group = super->s_blocks_per_group; + goto retry; + } else { + retval = EXT2_ET_TOO_MANY_INODES; + goto cleanup; + } + } + + if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super)) + ipg = EXT2_MAX_INODES_PER_GROUP(super); + +ipg_retry: + super->s_inodes_per_group = ipg; + + /* + * Make sure the number of inodes per group completely fills + * the inode table blocks in the descriptor. If not, add some + * additional inodes/group. Waste not, want not... + */ + fs->inode_blocks_per_group = (((super->s_inodes_per_group * + EXT2_INODE_SIZE(super)) + + EXT2_BLOCK_SIZE(super) - 1) / + EXT2_BLOCK_SIZE(super)); + super->s_inodes_per_group = ((fs->inode_blocks_per_group * + EXT2_BLOCK_SIZE(super)) / + EXT2_INODE_SIZE(super)); + /* + * Finally, make sure the number of inodes per group is a + * multiple of 8. This is needed to simplify the bitmap + * splicing code. + */ + if (super->s_inodes_per_group < 8) + super->s_inodes_per_group = 8; + super->s_inodes_per_group &= ~7; + fs->inode_blocks_per_group = (((super->s_inodes_per_group * + EXT2_INODE_SIZE(super)) + + EXT2_BLOCK_SIZE(super) - 1) / + EXT2_BLOCK_SIZE(super)); + + /* + * adjust inode count to reflect the adjusted inodes_per_group + */ + if ((__u64)super->s_inodes_per_group * fs->group_desc_count > ~0U) { + ipg--; + goto ipg_retry; + } + super->s_inodes_count = super->s_inodes_per_group * + fs->group_desc_count; + super->s_free_inodes_count = super->s_inodes_count; + + /* + * check the number of reserved group descriptor table blocks + */ + if (ext2fs_has_feature_resize_inode(super)) + rsv_gdt = calc_reserved_gdt_blocks(fs); + else + rsv_gdt = 0; + set_field(s_reserved_gdt_blocks, rsv_gdt); + if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) { + retval = EXT2_ET_RES_GDT_BLOCKS; + goto cleanup; + } + /* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */ + if (super->s_reserved_gdt_blocks + fs->desc_blocks > + super->s_blocks_per_group * 3 / 4) { + ext2fs_set_feature_meta_bg(fs->super); + ext2fs_clear_feature_resize_inode(fs->super); + set_field(s_reserved_gdt_blocks, 0); + } + + /* + * Calculate the maximum number of bookkeeping blocks per + * group. It includes the superblock, the block group + * descriptors, the block bitmap, the inode bitmap, the inode + * table, and the reserved gdt blocks. + */ + overhead = (int) (3 + fs->inode_blocks_per_group + + super->s_reserved_gdt_blocks); + + if (ext2fs_has_feature_meta_bg(fs->super)) + overhead++; + else + overhead += fs->desc_blocks; + + /* This can only happen if the user requested too many inodes */ + if (overhead > super->s_blocks_per_group) { + retval = EXT2_ET_TOO_MANY_INODES; + goto cleanup; + } + + /* + * See if the last group is big enough to support the + * necessary data structures. If not, we need to get rid of + * it. We need to recalculate the overhead for the last block + * group, since it might or might not have a superblock + * backup. + */ + overhead = (int) (2 + fs->inode_blocks_per_group); + has_bg = 0; + if (ext2fs_has_feature_sparse_super2(super)) { + /* + * We have to do this manually since + * super->s_backup_bgs hasn't been set up yet. + */ + if (fs->group_desc_count == 2) + has_bg = param->s_backup_bgs[0] != 0; + else + has_bg = param->s_backup_bgs[1] != 0; + } else + has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1); + if (has_bg) + overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks; + rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) % + super->s_blocks_per_group); + if ((fs->group_desc_count == 1) && rem && (rem < overhead)) { + retval = EXT2_ET_TOOSMALL; + goto cleanup; + } + if (rem && (rem < overhead+50)) { + ext2fs_blocks_count_set(super, ext2fs_blocks_count(super) - + rem); + /* + * If blocks count is changed, we need to recalculate + * reserved blocks count not to exceed 50%. + */ + reserved_ratio = 100.0 * ext2fs_r_blocks_count(param) / + ext2fs_blocks_count(param); + ext2fs_r_blocks_count_set(super, reserved_ratio * + ext2fs_blocks_count(super) / 100.0); + + goto retry; + } + + /* + * At this point we know how big the filesystem will be. So + * we can do any and all allocations that depend on the block + * count. + */ + + /* Set up the locations of the backup superblocks */ + if (ext2fs_has_feature_sparse_super2(super)) { + if (super->s_backup_bgs[0] >= fs->group_desc_count) + super->s_backup_bgs[0] = fs->group_desc_count - 1; + if (super->s_backup_bgs[1] >= fs->group_desc_count) + super->s_backup_bgs[1] = fs->group_desc_count - 1; + if (super->s_backup_bgs[0] == super->s_backup_bgs[1]) + super->s_backup_bgs[1] = 0; + if (super->s_backup_bgs[0] > super->s_backup_bgs[1]) { + __u32 t = super->s_backup_bgs[0]; + super->s_backup_bgs[0] = super->s_backup_bgs[1]; + super->s_backup_bgs[1] = t; + } + } + + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); + if (retval) + goto cleanup; + + strcpy(buf, "block bitmap for "); + strcat(buf, fs->device_name); + retval = ext2fs_allocate_subcluster_bitmap(fs, buf, &fs->block_map); + if (retval) + goto cleanup; + + strcpy(buf, "inode bitmap for "); + strcat(buf, fs->device_name); + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); + if (retval) + goto cleanup; + + ext2fs_free_mem(&buf); + + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, + &fs->group_desc); + if (retval) + goto cleanup; + + memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); + + /* + * Reserve the superblock and group descriptors for each + * group, and fill in the correct group statistics for group. + * Note that although the block bitmap, inode bitmap, and + * inode table have not been allocated (and in fact won't be + * by this routine), they are accounted for nevertheless. + * + * If FLEX_BG meta-data grouping is used, only account for the + * superblock and group descriptors (the inode tables and + * bitmaps will be accounted for when allocated). + */ + free_blocks = 0; + csum_flag = ext2fs_has_group_desc_csum(fs); + reserved_inos = super->s_first_ino; + for (i = 0; i < fs->group_desc_count; i++) { + /* + * Don't set the BLOCK_UNINIT group for the last group + * because the block bitmap needs to be padded. + */ + if (csum_flag) { + if (i != fs->group_desc_count - 1) + ext2fs_bg_flags_set(fs, i, + EXT2_BG_BLOCK_UNINIT); + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); + numblocks = super->s_inodes_per_group; + if (reserved_inos) { + if (numblocks > reserved_inos) { + numblocks -= reserved_inos; + reserved_inos = 0; + } else { + reserved_inos -= numblocks; + numblocks = 0; + } + } + ext2fs_bg_itable_unused_set(fs, i, numblocks); + } + numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); + if (fs->super->s_log_groups_per_flex) + numblocks += 2 + fs->inode_blocks_per_group; + + free_blocks += numblocks; + ext2fs_bg_free_blocks_count_set(fs, i, numblocks); + ext2fs_bg_free_inodes_count_set(fs, i, fs->super->s_inodes_per_group); + ext2fs_bg_used_dirs_count_set(fs, i, 0); + ext2fs_group_desc_csum_set(fs, i); + } + free_blocks &= ~EXT2FS_CLUSTER_MASK(fs); + ext2fs_free_blocks_count_set(super, free_blocks); + + c = (char) 255; + if (((int) c) == -1) { + super->s_flags |= EXT2_FLAGS_SIGNED_HASH; + } else { + super->s_flags |= EXT2_FLAGS_UNSIGNED_HASH; + } + + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); + ext2fs_mark_ib_dirty(fs); + + io_channel_set_blksize(fs->io, fs->blocksize); + + *ret_fs = fs; + return 0; +cleanup: + free(buf); + ext2fs_free(fs); + return retval; +} + +errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs, int super_only) +{ + blk64_t blk; + ext2_ino_t ino; + unsigned int group = 0; + unsigned int count = 0; + int total_free = 0; + int group_free = 0; + int last_allocated = 0; + int uninit; + + /* + * First calculate the block statistics + */ + uninit = 1; + for (blk = fs->super->s_first_data_block; + blk < ext2fs_blocks_count(fs->super); blk++) { + if (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk)) { + group_free++; + total_free++; + } else { + uninit = 0; + } + count++; + if ((count == fs->super->s_blocks_per_group) || + (blk == ext2fs_blocks_count(fs->super)-1)) { + ext2fs_bg_free_blocks_count_set(fs, group, + group_free); + if (!super_only) { + if (uninit && blk != + ext2fs_blocks_count(fs->super) - 1) + ext2fs_bg_flags_set(fs, group, + EXT2_BG_BLOCK_UNINIT); + else + ext2fs_bg_flags_clear(fs, group, + EXT2_BG_BLOCK_UNINIT); + } + count = 0; + group_free = 0; + uninit = 1; + group++; + } + } + total_free = EXT2FS_C2B(fs, total_free); + ext2fs_free_blocks_count_set(fs->super, total_free); + + /* + * Next, calculate the inode statistics + */ + group_free = 0; + total_free = 0; + last_allocated = 0; + count = 0; + group = 0; + + /* Protect loop from wrap-around if s_inodes_count maxed */ + for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) { + if (!ext2fs_test_inode_bitmap2(fs->inode_map, ino)) { + group_free++; + total_free++; + } else { + last_allocated = ino; + } + count++; + if ((count == fs->super->s_inodes_per_group) || + (ino == fs->super->s_inodes_count)) { + if (!super_only) { + if (last_allocated) { + ext2fs_bg_flags_clear(fs, group, + EXT2_BG_INODE_UNINIT); + ext2fs_bg_itable_unused_set(fs, group, + fs->super->s_inodes_per_group - + (last_allocated % + fs->super->s_inodes_per_group)); + } else { + ext2fs_bg_flags_set(fs, group, + EXT2_BG_INODE_UNINIT); + ext2fs_bg_itable_unused_set(fs, group, + 0); + } + ext2fs_bg_free_inodes_count_set(fs, group, + group_free); + } + group++; + count = 0; + group_free = 0; + last_allocated = 0; + } + } + fs->super->s_free_inodes_count = total_free; + ext2fs_mark_super_dirty(fs); + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/initialize.o b/jni/e2fsprogs/lib/ext2fs/initialize.o new file mode 100755 index 0000000000000000000000000000000000000000..192123ccc8539f0e62b1372be3fdd1823754073b GIT binary patch literal 15016 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 K;47P(|Nj6n(Bt?3 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/inline.c b/jni/e2fsprogs/lib/ext2fs/inline.c new file mode 100755 index 0000000..ae2ae6e --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/inline.c @@ -0,0 +1,118 @@ +/* + * inline.c --- Includes the inlined functions defined in the header + * files as standalone functions, in case the application program + * is compiled with inlining turned off. + * + * Copyright (C) 1993, 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 /* for posix_memalign() */ +#endif + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif + +#include "ext2_fs.h" +#define INCLUDE_INLINE_FUNCS +#include "ext2fs.h" + +/* + * We used to define this as an inline, but since we are now using + * autoconf-defined #ifdef's, we need to export this as a + * library-provided function exclusively. + */ +errcode_t ext2fs_get_memalign(unsigned long size, + unsigned long align, void *ptr) +{ + errcode_t retval = 0; + void **p = ptr; + + if (align < 8) + align = 8; +#ifdef HAVE_POSIX_MEMALIGN + retval = posix_memalign(p, align, size); + if (retval == ENOMEM) + return EXT2_ET_NO_MEMORY; +#else /* !HAVE_POSIX_MEMALIGN */ +#ifdef HAVE_MEMALIGN + *p = memalign(align, size); + if (*p == NULL) { + if (errno) + return errno; + else + return EXT2_ET_NO_MEMORY; + } +#else /* !HAVE_MEMALIGN */ +#ifdef HAVE_VALLOC + if (align > sizeof(long long)) + *p = valloc(size); + else +#endif + *p = malloc(size); + if ((uintptr_t) *p & (align - 1)) { + free(*p); + *p = 0; + } + if (*p == 0) + return EXT2_ET_NO_MEMORY; +#endif /* HAVE_MEMALIGN */ +#endif /* HAVE_POSIX_MEMALIGN */ + return retval; +} + +#ifdef DEBUG +static int isaligned(void *ptr, unsigned long align) +{ + return (((unsigned long) ptr & (align - 1)) == 0); +} + +static errcode_t test_memalign(unsigned long align) +{ + void *ptr = 0; + errcode_t retval; + + retval = ext2fs_get_memalign(32, align, &ptr); + if (!retval && !isaligned(ptr, align)) + retval = EINVAL; + free(ptr); + printf("tst_memalign(%lu) is %s\n", align, + retval ? error_message(retval) : "OK"); + return retval; +} + +int main(int argc, char **argv) +{ + int err = 0; + + if (test_memalign(4)) + err++; + if (test_memalign(32)) + err++; + if (test_memalign(1024)) + err++; + if (test_memalign(4096)) + err++; + return err; +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/inline.o b/jni/e2fsprogs/lib/ext2fs/inline.o new file mode 100755 index 0000000000000000000000000000000000000000..a29977247fa4a8ea00c4ff8082e3f9f989aa7747 GIT binary patch literal 17072 zcmeI2e{56N700jRFl-1Rq|utTFq<_KNk*f)Lgt8#ZtmFkb=ep^2yDhSH? zz3QE*keZlYs%EoGBeU7X@EwXw1o!x#$S#h|&iI410blUPHV>-uYBjVau==gLm#k9d zGoY#VMIH$Fmef}J)B|Aez-fQkYL*DwOA2f+SF_URndRtvWHzwu zQOj4j4+J9zXZ(R$&;EWwo1T1a)cw12CKTBT{kk*o-O48d-%#ah^$WH0jnr4DS*|9a z4HH@T3+xFz5m;4O9*8|!i>wBosaaK44&$KjRVsPh#hhsaDV>qs=Ry`N|)!eQJ$K;qvThoix#1z<@UL2V~TmRSoZ}$Vn!a{Ly zJ2e=em;AXHz2x^cKDXr=m~(pW_!sW8>CZ|_^B2~HiD_C7yv*UxO#fN6^OM;9y!*uO zgZ0`!Hur`)aCC3z#>@WDjZ3iaT!#Jk=-w#YN8vs)d-+~<0O#5iv@HuUbXKX?U|+Am z^?e5RY1j{E@qP-*=5{rX&HH`UzH8cV44pjY51qUWb)fyx#^_0mg;9U>v{wC^P;i2y;gkS83*EH0>^F|#sp%6 z_Tq1i%|i_7v)1SE%oO+q>+kFo_~aC)XR|+jxBKtE{&*B({0k7Lc$ULB#<=|>FpMc| z)7&oSc6<{1OK2Wk0$-;6A${)owDrN>pwGdhJ~fU$;#>=;p@V_oTQ8zbID`G;b*0*{ zOtvuq_jrCrjoK6Z`82c@`vvE?*S6lax{a9EXGR~64~!@IJrBQSA5Qs0`DaDB&cNKC zhV|tV_{Y!24CqfqC|d%tw!(jBmN zLfzRrBD40G!EYY3F<4LC#tZ_bVg{c>4UE|+*u>vsd%vgev(O%lZ(fsSJ4TfiALuj2 z_?=)2pVjdKF;Y`x#R#0|A!e+;%|hQ|xq^I(wMC${V-~ci!9Kv4$)6`pWAlx)#y3K~ z0R4;OQ@sN6g+-zD)hpCQUOpkqea_{2+~IlU3zfS+yXw}qcdjgVsykwG?*ylAX;I9VyE%?^mcE7pU z{*UKQI7h(;USIOgbHZPkzv%O90DKK3A`_#kbtA@9z&Er7=DFU}vx|o&bbFvJAHmsq z^J=xC#1L+{oE-+mG21?G)*JF$+X@V)^11ait@rS3<&^RP$J8p!=L0c+;n z&}S>MP==Z**t={y&|kd9(UIKj&fIVt>FG&FZydwYqkU_L~5ViQNaVPT<;l4AvZ6mq1?|*c17Qeouq#U8k=7 z$zh)=#=eDeT(fXYtUWll#;VR#tap3(=|p-U+1DFh*HE{vt^q12gFn1{&ume?-Cy$E zQxZ}Ya9^pZQd{x6sWe>FTB>&xVcn)@HgP7nJX$X>HYUB5@& zVUN1g9(7rdy0Ri~?QQU=>+q->_NaT6bQCvs9JCnYd%>el`K|UYWUtzzu9b8f&@9Xw zj?;F-zd?_>qaJl@~8_e^48vZ z(k;~9tsZql9(ALn>p(Y~N+TRsMa?Cl2rYnBP&7%pZd2Eque;&VUKkGXcr9eFnRMub zjC*rl_IuPF_NY7UQI{nh&C7c3KbV*Ga{nk>j15p~Azgz5trcl``gUHR&>zE*F2$finJDNf*HVrm3`* z`?=_9NvM@Nx&n#@Nf);4m2Kty--VA7UrBm6cIflMX&3zk7k<^nP9TVetuqApZJ$TN zF1&%b=})Tz$MNkZeyeo@`(=c5w2qg>`TUd5?R~{O*GziU-SD78f5Pw*2Cq1NK))2h zK@E8W@n+@`i?`PII!pd9hGhKUZl^igU*W>yLc@Jf6&f8;+rh2;-u$u zXbbT>p{b}Zp(g9`g0dBG{wO1j{Q7|W&pTIw;5t0-q<@9VW$hYlby|^A2#%x;9P-rP7vP!_2Jb4+{wpybQ zKTG-w_{NL%uej)O-#~wwNzZZkOXy!Ge|kutG4%Ug^fMIyM-Ba27yVIKchR47q_4M{ zp%TPz8ho1kSxZX+>t7(=PMq7-LVVcZZ$q)$_O71VVF4H9c z;{fTa4E=ksPw4nD_&(?_Cp#aLK4s{Oi1Yr=ak~b%lbsRLpCLP}f6Ybz28|_dRf5^YLYtfw1+Zu0Xx0KX330#IF-y zN%}X5m%+IMudx19>Nmve4Stk3o`djWJ9Y3I>rD}_(xuk^jC{o4caeVFu+vC<(%{Fb z->wj^C;PvHICC0Dc>k#VS-IR2@;Zb0H~Q0T@ISlQd582FLqFr9f1LKsqlO;yA16P* zPx^DDk5jvTMD^CwL(Rkw5+5{pi1=yZm89QD`~vZM;qCj^&v_&prjmv)N5f4q=OJN1G~JMDr?JHvuYJL7^&J5z#7J0;N1j{XR~%97~M zHWxl9cv$FQX*`G2cqhu+PlLiL(#P`FygQ%9(Rse#qdQm!B{= z=jG=O&UyJwgLD2}1?|C$>*YMV#o(MzXAI8y^bvz|K7GdEoKIgdc!bvL3hG?;hx6%8 z2IqX5{bfDp)B6oQ=hNc`=Y0C2!8vc{{fq5$-i&#l>^IJj+YHY6@os~29(>&3obR49 zIOnz34bJ&1w}buUJhh4T9p;>mrVP&c=plo1K6=XFoR5BJaLz|dXn)~)IUn6%aLz~D z4PHj;_&$SkK6=97{iHu{@JZs_KK6(6&MMlEm~(!~`yF%6FEfUo^T;CxZ>IJ7jKMiy z#Joes59f;&OaL%i48l3Z|D%!`nUe1#?8JzQ^HiL7XlrlKyN&5`W zdD0PsbDlJAaL$v?8N8MD-46}Uc@oDdw`-8}DlwQ@-!%~JiKTZ$2cGIrq@(dv9Fo1p}^I2yq5ld^@ zljs2f`)qj>k7Z((>jPZSok=GW(PVE%yWA5SOeZ?+LS2p3k)pl)sB3|K?5SQoEV85c z!CMsRM_nIuEyy`4yPoT_f<}x97f45)9wbMdigJ!Rm0A($P@{GwKLFSns?51i8+0zp zHwiJr2D_5I@n}~vO`&2x?JRjFk?xB+X-vPw{I=H1Ia;D#8S!ay~a~{43-3#4AI_LPa>L1*iyncFU%sUn~l;8hq{<_;WQBU@#NFd z&O|cB<#4}oLmt`AzHdwIV3ozJKG%_-Uy#CSYw^0?zD%O-k;lGsAFLjowgGBFS2C4| zW_I=`_<7N^T$!~rCAy~b<-Bk=;xLUJ%oNPoe2rT% zjt94>v#%FdeVk5=@@@(ird-AW<0<&(Pqo`#sT>!HrbW4dj5 zL_gQrjYDBSsa4D%_F<(}>4f#2>`f(m6Lp=cZXlD+#J0ir&K~@xZF1lTv2E)%@|_+w z+7&i#$fNeYkmLAl?yjH@^`^F-jTCfaezDcVVtcV4bdE;5xF8Vi5@Yp}Vd$jM%a^kV zC!IsA+E#8=rrj@yQTtK%l3crG^w|&Ub~~0B?OsTu+wCk8?RFGUyB*7N?RG5I?RG4Y ztD@c7f@RSt$*qfaL9YMgpjvB(Eh>l}qg)$t7+yoRup-wTxA3MQ7>sHPrWh7{5L-AfHq(rX^RRX>AY$SD1_ zd4ztI$(Q@U==FlFJ4h^I6YEDqwe{Uk`9G$8_)3S;Kl}f=-wBmt{bp~pQoUca%-Emo zKY!1FL;Two!H+J(Z!R;n>%l){^ty>&BvC`bQ7`e^= + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include /* for PATH_MAX */ + +#include "ext2_fs.h" +#include "ext2_ext_attr.h" + +#include "ext2fs.h" +#include "ext2fsP.h" + +struct ext2_inline_data { + ext2_filsys fs; + ext2_ino_t ino; + size_t ea_size; /* the size of inline data in ea area */ + void *ea_data; +}; + +static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data) +{ + struct ext2_xattr_handle *handle; + errcode_t retval; + + retval = ext2fs_xattrs_open(data->fs, data->ino, &handle); + if (retval) + return retval; + + retval = ext2fs_xattrs_read(handle); + if (retval) + goto err; + + retval = ext2fs_xattr_set(handle, "system.data", + data->ea_data, data->ea_size); +err: + (void) ext2fs_xattrs_close(&handle); + return retval; +} + +static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data) +{ + struct ext2_xattr_handle *handle; + errcode_t retval; + + data->ea_size = 0; + data->ea_data = 0; + + retval = ext2fs_xattrs_open(data->fs, data->ino, &handle); + if (retval) + return retval; + + retval = ext2fs_xattrs_read(handle); + if (retval) + goto err; + + retval = ext2fs_xattr_get(handle, "system.data", + (void **)&data->ea_data, &data->ea_size); + if (retval == EXT2_ET_EA_KEY_NOT_FOUND) { + data->ea_size = 0; + data->ea_data = NULL; + retval = 0; + } else if (retval) + goto err; + +err: + (void) ext2fs_xattrs_close(&handle); + return retval; +} + +errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inline_data data; + char empty[1] = { '\0' }; + + data.fs = fs; + data.ino = ino; + data.ea_size = 0; + data.ea_data = empty; + return ext2fs_inline_data_ea_set(&data); +} + +errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size) +{ + struct ext2_inode inode; + struct ext2_inline_data data; + errcode_t retval; + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + + if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) + return EXT2_ET_NO_INLINE_DATA; + + data.fs = fs; + data.ino = ino; + retval = ext2fs_inline_data_ea_get(&data); + if (retval) + return retval; + + *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size; + return ext2fs_free_mem(&data.ea_data); +} + +int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino, + void *priv_data) +{ + struct dir_context *ctx; + struct ext2_inode inode; + struct ext2_dir_entry dirent; + struct ext2_inline_data data; + int ret = BLOCK_ABORT; + e2_blkcnt_t blockcnt = 0; + char *old_buf; + unsigned int old_buflen; + int old_flags; + + ctx = (struct dir_context *)priv_data; + old_buf = ctx->buf; + old_buflen = ctx->buflen; + old_flags = ctx->flags; + ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA; + + ctx->errcode = ext2fs_read_inode(fs, ino, &inode); + if (ctx->errcode) + goto out; + + if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) { + ctx->errcode = EXT2_ET_NO_INLINE_DATA; + goto out; + } + + if (!LINUX_S_ISDIR(inode.i_mode)) { + ctx->errcode = EXT2_ET_NO_DIRECTORY; + goto out; + } + ret = 0; + + /* we first check '.' and '..' dir */ + dirent.inode = ino; + dirent.name_len = 1; + ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent); + dirent.name[0] = '.'; + dirent.name[1] = '\0'; + ctx->buf = (char *)&dirent; + ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); + if (ret & BLOCK_ABORT) + goto out; + + dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]); + dirent.name_len = 2; + ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent); + dirent.name[0] = '.'; + dirent.name[1] = '.'; + dirent.name[2] = '\0'; + ctx->buf = (char *)&dirent; + ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); + if (ret & BLOCK_INLINE_DATA_CHANGED) { + errcode_t err; + + inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode); + err = ext2fs_write_inode(fs, ino, &inode); + if (err) + goto out; + ret &= ~BLOCK_INLINE_DATA_CHANGED; + } + if (ret & BLOCK_ABORT) + goto out; + + ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE; + ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE; +#ifdef WORDS_BIGENDIAN + ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); + if (ctx->errcode) { + ret |= BLOCK_ABORT; + goto out; + } +#endif + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); + if (ret & BLOCK_INLINE_DATA_CHANGED) { +#ifdef WORDS_BIGENDIAN + ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, + ctx->buflen, 0); + if (ctx->errcode) { + ret |= BLOCK_ABORT; + goto out; + } +#endif + ctx->errcode = ext2fs_write_inode(fs, ino, &inode); + if (ctx->errcode) + ret |= BLOCK_ABORT; + ret &= ~BLOCK_INLINE_DATA_CHANGED; + } + if (ret & BLOCK_ABORT) + goto out; + + data.fs = fs; + data.ino = ino; + ctx->errcode = ext2fs_inline_data_ea_get(&data); + if (ctx->errcode) { + ret |= BLOCK_ABORT; + goto out; + } + if (data.ea_size <= 0) + goto out1; + + ctx->buf = data.ea_data; + ctx->buflen = data.ea_size; +#ifdef WORDS_BIGENDIAN + ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); + if (ctx->errcode) { + ret |= BLOCK_ABORT; + goto out1; + } +#endif + + ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); + if (ret & BLOCK_INLINE_DATA_CHANGED) { +#ifdef WORDS_BIGENDIAN + ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, + ctx->buflen, 0); + if (ctx->errcode) { + ret |= BLOCK_ABORT; + goto out1; + } +#endif + ctx->errcode = ext2fs_inline_data_ea_set(&data); + if (ctx->errcode) + ret |= BLOCK_ABORT; + } + +out1: + ext2fs_free_mem(&data.ea_data); +out: + ctx->buf = old_buf; + ctx->buflen = old_buflen; + ctx->flags = old_flags; + ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED); + return ret; +} + +errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_xattr_handle *handle; + errcode_t retval; + + retval = ext2fs_xattrs_open(fs, ino, &handle); + if (retval) + return retval; + + retval = ext2fs_xattrs_read(handle); + if (retval) + goto err; + + retval = ext2fs_xattr_remove(handle, "system.data"); +err: + (void) ext2fs_xattrs_close(&handle); + return retval; +} + +static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino, + char *bbuf, char *ibuf, int size) +{ + struct ext2_dir_entry *dir, *dir2; + struct ext2_dir_entry_tail *t; + errcode_t retval; + int offset; + unsigned int rec_len; + int csum_size = 0; + int filetype = 0; + + if (ext2fs_has_feature_metadata_csum(fs->super)) + csum_size = sizeof(struct ext2_dir_entry_tail); + + /* Create '.' and '..' */ + if (ext2fs_has_feature_filetype(fs->super)) + filetype = EXT2_FT_DIR; + + /* + * Set up entry for '.' + */ + dir = (struct ext2_dir_entry *) bbuf; + dir->inode = ino; + ext2fs_dirent_set_name_len(dir, 1); + ext2fs_dirent_set_file_type(dir, filetype); + dir->name[0] = '.'; + rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1); + dir->rec_len = EXT2_DIR_REC_LEN(1); + + /* + * Set up entry for '..' + */ + dir = (struct ext2_dir_entry *) (bbuf + dir->rec_len); + dir->rec_len = EXT2_DIR_REC_LEN(2); + dir->inode = ext2fs_le32_to_cpu(((__u32 *)ibuf)[0]); + ext2fs_dirent_set_name_len(dir, 2); + ext2fs_dirent_set_file_type(dir, filetype); + dir->name[0] = '.'; + dir->name[1] = '.'; + + /* + * Adjust the last rec_len + */ + offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2); + dir = (struct ext2_dir_entry *) (bbuf + offset); + memcpy(bbuf + offset, ibuf + EXT4_INLINE_DATA_DOTDOT_SIZE, + size - EXT4_INLINE_DATA_DOTDOT_SIZE); + size += EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) - + EXT4_INLINE_DATA_DOTDOT_SIZE; + + do { + dir2 = dir; + retval = ext2fs_get_rec_len(fs, dir, &rec_len); + if (retval) + goto err; + offset += rec_len; + dir = (struct ext2_dir_entry *) (bbuf + offset); + } while (offset < size); + rec_len += fs->blocksize - csum_size - offset; + retval = ext2fs_set_rec_len(fs, rec_len, dir2); + if (retval) + goto err; + + if (csum_size) { + t = EXT2_DIRENT_TAIL(bbuf, fs->blocksize); + ext2fs_initialize_dirent_tail(fs, t); + } + +err: + return retval; +} + +static errcode_t +ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, char *buf, size_t size) +{ + errcode_t retval; + blk64_t blk; + char *blk_buf; + + retval = ext2fs_get_memzero(fs->blocksize, &blk_buf); + if (retval) + return retval; + +#ifdef WORDS_BIGENDIAN + retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE, + size, 0); + if (retval) + goto errout; +#endif + + /* Adjust the rec_len */ + retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size); + if (retval) + goto errout; + /* Allocate a new block */ + retval = ext2fs_new_block2(fs, 0, 0, &blk); + if (retval) + goto errout; + retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino); + if (retval) + goto errout; + + /* Update inode */ + if (ext2fs_has_feature_extents(fs->super)) + inode->i_flags |= EXT4_EXTENTS_FL; + inode->i_flags &= ~EXT4_INLINE_DATA_FL; + retval = ext2fs_iblk_add_blocks(fs, inode, 1); + if (retval) + goto errout; + inode->i_size = fs->blocksize; + retval = ext2fs_bmap2(fs, ino, inode, 0, BMAP_SET, 0, 0, &blk); + if (retval) + goto errout; + retval = ext2fs_write_inode(fs, ino, inode); + if (retval) + goto errout; + ext2fs_block_alloc_stats(fs, blk, +1); + +errout: + ext2fs_free_mem(&blk_buf); + return retval; +} + +static errcode_t +ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, char *buf, size_t size) +{ + ext2_file_t e2_file; + errcode_t retval; + + /* Update inode */ + memset(inode->i_block, 0, sizeof(inode->i_block)); + if (ext2fs_has_feature_extents(fs->super)) { + ext2_extent_handle_t handle; + + inode->i_flags &= ~EXT4_EXTENTS_FL; + retval = ext2fs_extent_open2(fs, ino, inode, &handle); + if (retval) + return retval; + ext2fs_extent_free(handle); + } + inode->i_flags &= ~EXT4_INLINE_DATA_FL; + inode->i_size = 0; + retval = ext2fs_write_inode(fs, ino, inode); + if (retval) + return retval; + + /* Write out the block buffer */ + retval = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file); + if (retval) + return retval; + retval = ext2fs_file_write(e2_file, buf, size, 0); + ext2fs_file_close(e2_file); + return retval; +} + +errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode inode; + struct ext2_inline_data data; + errcode_t retval; + size_t inline_size; + char *inline_buf = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + + if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) + return EXT2_ET_NO_INLINE_DATA; + + data.fs = fs; + data.ino = ino; + retval = ext2fs_inline_data_ea_get(&data); + if (retval) + return retval; + inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE; + retval = ext2fs_get_mem(inline_size, &inline_buf); + if (retval) + goto errout; + + memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE); + if (data.ea_size > 0) { + memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE, + data.ea_data, data.ea_size); + } + + memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); + /* + * NOTE: We must do this write -> ea_remove -> read cycle here because + * removing the inline data EA can free the EA block, which is a change + * that our stack copy of the inode will never see. If that happens, + * we can end up with the EA block and lblk 0 pointing to the same + * pblk, which is bad news. + */ + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) + goto errout; + retval = ext2fs_inline_data_ea_remove(fs, ino); + if (retval) + goto errout; + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + goto errout; + + if (LINUX_S_ISDIR(inode.i_mode)) { + retval = ext2fs_inline_data_dir_expand(fs, ino, &inode, + inline_buf, inline_size); + } else { + retval = ext2fs_inline_data_file_expand(fs, ino, &inode, + inline_buf, inline_size); + } + +errout: + if (inline_buf) + ext2fs_free_mem(&inline_buf); + ext2fs_free_mem(&data.ea_data); + return retval; +} + +/* + * When caller uses this function to retrieve the inline data, it must + * allocate a buffer which has the size of inline data. The size of + * inline data can be know by ext2fs_inline_data_get_size(). + */ +errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t *size) +{ + struct ext2_inode inode_buf; + struct ext2_inline_data data; + errcode_t retval; + + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + + data.fs = fs; + data.ino = ino; + retval = ext2fs_inline_data_ea_get(&data); + if (retval) + return retval; + + memcpy(buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE); + if (data.ea_size > 0) + memcpy((char *) buf + EXT4_MIN_INLINE_DATA_SIZE, + data.ea_data, data.ea_size); + + if (size) + *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size; + ext2fs_free_mem(&data.ea_data); + return 0; +} + +errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + void *buf, size_t size) +{ + struct ext2_inode inode_buf; + struct ext2_inline_data data = { + .fs = fs, + .ino = ino, + }; + errcode_t retval; + size_t free_ea_size, existing_size, free_inode_size; + + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + + if (size <= EXT4_MIN_INLINE_DATA_SIZE) { + memcpy((void *)inode->i_block, buf, size); + } else { + retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size); + if (retval) + return retval; + + retval = ext2fs_inline_data_size(fs, ino, &existing_size); + if (retval) + return retval; + + if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) { + free_inode_size = EXT4_MIN_INLINE_DATA_SIZE - + existing_size; + } else { + free_inode_size = 0; + } + + if (size != existing_size && + size > existing_size + free_ea_size + free_inode_size) + return EXT2_ET_INLINE_DATA_NO_SPACE; + + memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE); + if (size > EXT4_MIN_INLINE_DATA_SIZE) + data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE; + data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE; + } + retval = ext2fs_write_inode(fs, ino, inode); + if (retval) + return retval; + return ext2fs_inline_data_ea_set(&data); +} + +#ifdef DEBUG +#include "e2p/e2p.h" + +/* + * The length of buffer is set to 64 because in inode's i_block member it only + * can save 60 bytes. Thus this value can let the data being saved in extra + * space. + */ +#define BUFF_SIZE (64) + +static errcode_t file_test(ext2_filsys fs) +{ + struct ext2_inode inode; + ext2_ino_t newfile; + errcode_t retval; + size_t size; + char *buf = 0, *cmpbuf = 0; + + /* create a new file */ + retval = ext2fs_new_inode(fs, 2, 010755, 0, &newfile); + if (retval) { + com_err("file_test", retval, "while allocating a new inode"); + return 1; + } + + memset(&inode, 0, sizeof(inode)); + inode.i_flags |= EXT4_INLINE_DATA_FL; + inode.i_size = EXT4_MIN_INLINE_DATA_SIZE; + inode.i_mode = LINUX_S_IFREG; + retval = ext2fs_write_new_inode(fs, newfile, &inode); + if (retval) { + com_err("file_test", retval, "while writing a new inode"); + return 1; + } + + retval = ext2fs_inline_data_init(fs, newfile); + if (retval) { + com_err("file_test", retval, "while init 'system.data'"); + return 1; + } + + retval = ext2fs_inline_data_size(fs, newfile, &size); + if (retval) { + com_err("file_test", retval, "while getting size"); + return 1; + } + + if (size != EXT4_MIN_INLINE_DATA_SIZE) { + fprintf(stderr, + "tst_inline_data: size of inline data is wrong\n"); + return 1; + } + + ext2fs_get_mem(BUFF_SIZE, &buf); + memset(buf, 'a', BUFF_SIZE); + retval = ext2fs_inline_data_set(fs, newfile, 0, buf, BUFF_SIZE); + if (retval) { + com_err("file_test", retval, + "while setting inline data %s", buf); + goto err; + } + + ext2fs_get_mem(BUFF_SIZE, &cmpbuf); + retval = ext2fs_inline_data_get(fs, newfile, 0, cmpbuf, &size); + if (retval) { + com_err("file_test", retval, "while getting inline data"); + goto err; + } + + if (size != BUFF_SIZE) { + fprintf(stderr, + "tst_inline_data: size %zu != buflen %u\n", + size, BUFF_SIZE); + retval = 1; + goto err; + } + + if (memcmp(buf, cmpbuf, BUFF_SIZE)) { + fprintf(stderr, "tst_inline_data: buf != cmpbuf\n"); + retval = 1; + goto err; + } + + retval = ext2fs_punch(fs, newfile, 0, 0, 0, ~0ULL); + if (retval) { + com_err("file_test", retval, "while truncating inode"); + goto err; + } + + /* reload inode and check isize */ + ext2fs_read_inode(fs, newfile, &inode); + if (inode.i_size != 0) { + fprintf(stderr, "tst_inline_data: i_size should be 0\n"); + retval = 1; + } + +err: + if (cmpbuf) + ext2fs_free_mem(&cmpbuf); + if (buf) + ext2fs_free_mem(&buf); + return retval; +} + +static errcode_t dir_test(ext2_filsys fs) +{ + const char *dot_name = "."; + const char *stub_name = "stub"; + const char *parent_name = "test"; + ext2_ino_t parent, dir, tmp; + errcode_t retval; + char dirname[32]; + int i; + + retval = ext2fs_mkdir(fs, 11, 11, stub_name); + if (retval) { + com_err("dir_test", retval, "while creating %s dir", stub_name); + return retval; + } + + retval = ext2fs_mkdir(fs, 11, 0, parent_name); + if (retval) { + com_err("dir_test", retval, + "while creating %s dir", parent_name); + return retval; + } + + retval = ext2fs_lookup(fs, 11, parent_name, strlen(parent_name), + 0, &parent); + if (retval) { + com_err("dir_test", retval, + "while looking up %s dir", parent_name); + return retval; + } + + retval = ext2fs_lookup(fs, parent, dot_name, strlen(dot_name), + 0, &tmp); + if (retval) { + com_err("dir_test", retval, + "while looking up %s dir", parent_name); + return retval; + } + + if (parent != tmp) { + fprintf(stderr, "tst_inline_data: parent (%u) != tmp (%u)\n", + parent, tmp); + return 1; + } + + for (i = 0, dir = 13; i < 4; i++, dir++) { + tmp = 0; + snprintf(dirname, sizeof(dirname), "%d", i); + retval = ext2fs_mkdir(fs, parent, 0, dirname); + if (retval) { + com_err("dir_test", retval, + "while creating %s dir", dirname); + return retval; + } + + retval = ext2fs_lookup(fs, parent, dirname, strlen(dirname), + 0, &tmp); + if (retval) { + com_err("dir_test", retval, + "while looking up %s dir", parent_name); + return retval; + } + + if (dir != tmp) { + fprintf(stderr, + "tst_inline_data: dir (%u) != tmp (%u)\n", + dir, tmp); + return 1; + } + } + + snprintf(dirname, sizeof(dirname), "%d", i); + retval = ext2fs_mkdir(fs, parent, 0, dirname); + if (retval && retval != EXT2_ET_DIR_NO_SPACE) { + com_err("dir_test", retval, "while creating %s dir", dirname); + return retval; + } + + retval = ext2fs_expand_dir(fs, parent); + if (retval) { + com_err("dir_test", retval, "while expanding %s dir", parent_name); + return retval; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + ext2_filsys fs; + struct ext2_super_block param; + errcode_t retval; + + /* setup */ + initialize_ext2_error_table(); + + memset(¶m, 0, sizeof(param)); + ext2fs_blocks_count_set(¶m, 32768); + param.s_inodes_count = 100; + + param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_INLINE_DATA; + param.s_rev_level = EXT2_DYNAMIC_REV; + param.s_inode_size = 256; + + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, + test_io_manager, &fs); + if (retval) { + com_err("setup", retval, + "while initializing filesystem"); + exit(1); + } + + retval = ext2fs_allocate_tables(fs); + if (retval) { + com_err("setup", retval, + "while allocating tables for test filesystem"); + exit(1); + } + + /* initialize inode cache */ + if (!fs->icache) { + ext2_ino_t first_ino = EXT2_FIRST_INO(fs->super); + int i; + + /* we just want to init inode cache. So ignore error */ + ext2fs_create_inode_cache(fs, 16); + if (!fs->icache) { + fprintf(stderr, + "tst_inline_data: init inode cache failed\n"); + exit(1); + } + + /* setup inode cache */ + for (i = 0; i < fs->icache->cache_size; i++) + fs->icache->cache[i].ino = first_ino++; + } + + /* test */ + if (file_test(fs)) { + fprintf(stderr, "tst_inline_data(FILE): FAILED\n"); + return 1; + } + printf("tst_inline_data(FILE): OK\n"); + + if (dir_test(fs)) { + fprintf(stderr, "tst_inline_data(DIR): FAILED\n"); + return 1; + } + printf("tst_inline_data(DIR): OK\n"); + ext2fs_free(fs); + + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/inline_data.o b/jni/e2fsprogs/lib/ext2fs/inline_data.o new file mode 100755 index 0000000000000000000000000000000000000000..9401be2dcada3823013bf825a2a8d8ced3f935cb GIT binary patch literal 11056 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 vq3zd#t1!Nl|IRLUBnH%k^dDWR$7}z+hw+{% +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "e2image.h" + +#define IBLOCK_STATUS_CSUMS_OK 1 +#define IBLOCK_STATUS_INSANE 2 +#define SCAN_BLOCK_STATUS(scan) ((scan)->temp_buffer + (scan)->inode_size) + +struct ext2_struct_inode_scan { + errcode_t magic; + ext2_filsys fs; + ext2_ino_t current_inode; + blk64_t current_block; + dgrp_t current_group; + ext2_ino_t inodes_left; + blk_t blocks_left; + dgrp_t groups_left; + blk_t inode_buffer_blocks; + char * inode_buffer; + int inode_size; + char * ptr; + int bytes_left; + char *temp_buffer; + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data); + void * done_group_data; + int bad_block_ptr; + int scan_flags; + int reserved[6]; +}; + +/* + * This routine flushes the icache, if it exists. + */ +errcode_t ext2fs_flush_icache(ext2_filsys fs) +{ + unsigned i; + + if (!fs->icache) + return 0; + + for (i=0; i < fs->icache->cache_size; i++) + fs->icache->cache[i].ino = 0; + + fs->icache->buffer_blk = 0; + return 0; +} + +/* + * Free the inode cache structure + */ +void ext2fs_free_inode_cache(struct ext2_inode_cache *icache) +{ + unsigned i; + + if (--icache->refcount) + return; + if (icache->buffer) + ext2fs_free_mem(&icache->buffer); + for (i = 0; i < icache->cache_size; i++) + ext2fs_free_mem(&icache->cache[i].inode); + if (icache->cache) + ext2fs_free_mem(&icache->cache); + icache->buffer_blk = 0; + ext2fs_free_mem(&icache); +} + +errcode_t ext2fs_create_inode_cache(ext2_filsys fs, unsigned int cache_size) +{ + unsigned i; + errcode_t retval; + + if (fs->icache) + return 0; + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); + if (retval) + return retval; + + memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); + retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); + if (retval) + goto errout; + + fs->icache->buffer_blk = 0; + fs->icache->cache_last = -1; + fs->icache->cache_size = cache_size; + fs->icache->refcount = 1; + retval = ext2fs_get_array(fs->icache->cache_size, + sizeof(struct ext2_inode_cache_ent), + &fs->icache->cache); + if (retval) + goto errout; + + for (i = 0; i < fs->icache->cache_size; i++) { + retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), + &fs->icache->cache[i].inode); + if (retval) + goto errout; + } + + ext2fs_flush_icache(fs); + return 0; +errout: + ext2fs_free_inode_cache(fs->icache); + fs->icache = 0; + return retval; +} + +errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, + ext2_inode_scan *ret_scan) +{ + ext2_inode_scan scan; + errcode_t retval; + errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + if (fs->blocksize < 1024) + return EXT2_FILSYS_CORRUPTED; /* Should never happen */ + + /* + * If fs->badblocks isn't set, then set it --- since the inode + * scanning functions require it. + */ + if (fs->badblocks == 0) { + /* + * Temporarily save fs->get_blocks and set it to zero, + * for compatibility with old e2fsck's. + */ + save_get_blocks = fs->get_blocks; + fs->get_blocks = 0; + retval = ext2fs_read_bb_inode(fs, &fs->badblocks); + if (retval && fs->badblocks) { + ext2fs_badblocks_list_free(fs->badblocks); + fs->badblocks = 0; + } + fs->get_blocks = save_get_blocks; + } + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); + if (retval) + return retval; + memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); + + scan->magic = EXT2_ET_MAGIC_INODE_SCAN; + scan->fs = fs; + scan->inode_size = EXT2_INODE_SIZE(fs->super); + scan->bytes_left = 0; + scan->current_group = 0; + scan->groups_left = fs->group_desc_count - 1; + scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : + EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS; + scan->current_block = ext2fs_inode_table_loc(scan->fs, + scan->current_group); + if (scan->current_block && + ((scan->current_block < fs->super->s_first_data_block) || + (scan->current_block + fs->inode_blocks_per_group - 1 >= + ext2fs_blocks_count(fs->super)))) { + ext2fs_free_mem(&scan); + return EXT2_ET_GDESC_BAD_INODE_TABLE; + } + + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); + scan->blocks_left = scan->fs->inode_blocks_per_group; + if (ext2fs_has_group_desc_csum(fs)) { + __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group); + if (scan->inodes_left > unused) + scan->inodes_left -= unused; + else + scan->inodes_left = 0; + scan->blocks_left = + (scan->inodes_left + + (fs->blocksize / scan->inode_size - 1)) * + scan->inode_size / fs->blocksize; + } + retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks, + &scan->inode_buffer); + scan->done_group = 0; + scan->done_group_data = 0; + scan->bad_block_ptr = 0; + if (retval) { + ext2fs_free_mem(&scan); + return retval; + } + retval = ext2fs_get_mem(scan->inode_size + scan->inode_buffer_blocks, + &scan->temp_buffer); + if (retval) { + ext2fs_free_mem(&scan->inode_buffer); + ext2fs_free_mem(&scan); + return retval; + } + memset(SCAN_BLOCK_STATUS(scan), 0, scan->inode_buffer_blocks); + if (scan->fs->badblocks && scan->fs->badblocks->num) + scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; + if (ext2fs_has_group_desc_csum(fs)) + scan->scan_flags |= EXT2_SF_DO_LAZY; + *ret_scan = scan; + return 0; +} + +void ext2fs_close_inode_scan(ext2_inode_scan scan) +{ + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return; + + ext2fs_free_mem(&scan->inode_buffer); + scan->inode_buffer = NULL; + ext2fs_free_mem(&scan->temp_buffer); + scan->temp_buffer = NULL; + ext2fs_free_mem(&scan); + return; +} + +void ext2fs_set_inode_callback(ext2_inode_scan scan, + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data), + void *done_group_data) +{ + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return; + + scan->done_group = done_group; + scan->done_group_data = done_group_data; +} + +int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, + int clear_flags) +{ + int old_flags; + + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return 0; + + old_flags = scan->scan_flags; + scan->scan_flags &= ~clear_flags; + scan->scan_flags |= set_flags; + return old_flags; +} + +/* + * This function is called by ext2fs_get_next_inode when it needs to + * get ready to read in a new blockgroup. + */ +static errcode_t get_next_blockgroup(ext2_inode_scan scan) +{ + ext2_filsys fs = scan->fs; + + scan->current_group++; + scan->groups_left--; + + scan->current_block = ext2fs_inode_table_loc(scan->fs, + scan->current_group); + scan->current_inode = scan->current_group * + EXT2_INODES_PER_GROUP(fs->super); + + scan->bytes_left = 0; + scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super); + scan->blocks_left = fs->inode_blocks_per_group; + if (ext2fs_has_group_desc_csum(fs)) { + __u32 unused = ext2fs_bg_itable_unused(fs, scan->current_group); + if (scan->inodes_left > unused) + scan->inodes_left -= unused; + else + scan->inodes_left = 0; + scan->blocks_left = + (scan->inodes_left + + (fs->blocksize / scan->inode_size - 1)) * + scan->inode_size / fs->blocksize; + } + if (scan->current_block && + ((scan->current_block < fs->super->s_first_data_block) || + (scan->current_block + fs->inode_blocks_per_group - 1 >= + ext2fs_blocks_count(fs->super)))) + return EXT2_ET_GDESC_BAD_INODE_TABLE; + return 0; +} + +errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, + int group) +{ + scan->current_group = group - 1; + scan->groups_left = scan->fs->group_desc_count - group; + scan->bad_block_ptr = 0; + return get_next_blockgroup(scan); +} + +/* + * This function is called by get_next_blocks() to check for bad + * blocks in the inode table. + * + * This function assumes that badblocks_list->list is sorted in + * increasing order. + */ +static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, + blk64_t *num_blocks) +{ + blk64_t blk = scan->current_block; + badblocks_list bb = scan->fs->badblocks; + + /* + * If the inode table is missing, then obviously there are no + * bad blocks. :-) + */ + if (blk == 0) + return 0; + + /* Make sure bad_block_ptr is still valid */ + if (scan->bad_block_ptr >= bb->num) { + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; + return 0; + } + + /* + * If the current block is greater than the bad block listed + * in the bad block list, then advance the pointer until this + * is no longer the case. If we run out of bad blocks, then + * we don't need to do any more checking! + */ + while (blk > bb->list[scan->bad_block_ptr]) { + if (++scan->bad_block_ptr >= bb->num) { + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; + return 0; + } + } + + /* + * If the current block is equal to the bad block listed in + * the bad block list, then handle that one block specially. + * (We could try to handle runs of bad blocks, but that + * only increases CPU efficiency by a small amount, at the + * expense of a huge expense of code complexity, and for an + * uncommon case at that.) + */ + if (blk == bb->list[scan->bad_block_ptr]) { + scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; + *num_blocks = 1; + if (++scan->bad_block_ptr >= bb->num) + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; + return 0; + } + + /* + * If there is a bad block in the range that we're about to + * read in, adjust the number of blocks to read so that we we + * don't read in the bad block. (Then the next block to read + * will be the bad block, which is handled in the above case.) + */ + if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) + *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); + + return 0; +} + +static int block_map_looks_insane(ext2_filsys fs, + struct ext2_inode_large *inode) +{ + unsigned int i, bad; + + /* We're only interested in block mapped files, dirs, and symlinks */ + if ((inode->i_flags & EXT4_INLINE_DATA_FL) || + (inode->i_flags & EXT4_EXTENTS_FL)) + return 0; + if (!LINUX_S_ISREG(inode->i_mode) && + !LINUX_S_ISLNK(inode->i_mode) && + !LINUX_S_ISDIR(inode->i_mode)) + return 0; + if (LINUX_S_ISLNK(inode->i_mode) && + EXT2_I_SIZE(inode) <= sizeof(inode->i_block)) + return 0; + + /* Unused inodes probably aren't insane */ + if (inode->i_links_count == 0) + return 0; + + /* See if more than half the block maps are insane */ + for (i = 0, bad = 0; i < EXT2_N_BLOCKS; i++) + if (inode->i_block[i] != 0 && + (inode->i_block[i] < fs->super->s_first_data_block || + inode->i_block[i] >= ext2fs_blocks_count(fs->super))) + bad++; + return bad > EXT2_N_BLOCKS / 2; +} + +static int extent_head_looks_insane(struct ext2_inode_large *inode) +{ + if (!(inode->i_flags & EXT4_EXTENTS_FL) || + ext2fs_extent_header_verify(inode->i_block, + sizeof(inode->i_block)) == 0) + return 0; + return 1; +} + +/* + * Check all the inodes that we just read into the buffer. Record what we + * find here -- currently, we can observe that all checksums are ok; more + * than half the inodes are insane; or no conclusions at all. + */ +static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks) +{ + ext2_ino_t ino, inodes_to_scan; + unsigned int badness, checksum_failures; + unsigned int inodes_in_buf, inodes_per_block; + char *p; + struct ext2_inode_large *inode; + char *block_status; + unsigned int blk, bad_csum; + + if (!(scan->scan_flags & EXT2_SF_WARN_GARBAGE_INODES)) + return; + + inodes_to_scan = scan->inodes_left; + inodes_in_buf = num_blocks * scan->fs->blocksize / scan->inode_size; + if (inodes_to_scan > inodes_in_buf) + inodes_to_scan = inodes_in_buf; + + p = (char *) scan->inode_buffer; + ino = scan->current_inode + 1; + checksum_failures = badness = 0; + block_status = SCAN_BLOCK_STATUS(scan); + memset(block_status, 0, scan->inode_buffer_blocks); + inodes_per_block = EXT2_INODES_PER_BLOCK(scan->fs->super); + + if (inodes_per_block < 2) + return; + +#ifdef WORDS_BIGENDIAN + if (ext2fs_get_mem(EXT2_INODE_SIZE(scan->fs->super), &inode)) + return; +#endif + + while (inodes_to_scan > 0) { + blk = (p - (char *)scan->inode_buffer) / scan->fs->blocksize; + bad_csum = ext2fs_inode_csum_verify(scan->fs, ino, + (struct ext2_inode_large *) p) == 0; + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) p, + 0, EXT2_INODE_SIZE(scan->fs->super)); +#else + inode = (struct ext2_inode_large *) p; +#endif + + /* Is this inode insane? */ + if (bad_csum) { + checksum_failures++; + badness++; + } else if (extent_head_looks_insane(inode) || + block_map_looks_insane(scan->fs, inode)) + badness++; + + /* If more than half are insane, declare the whole block bad */ + if (badness > inodes_per_block / 2) { + unsigned int ino_adj; + + block_status[blk] |= IBLOCK_STATUS_INSANE; + ino_adj = inodes_per_block - + ((ino - 1) % inodes_per_block); + if (ino_adj > inodes_to_scan) + ino_adj = inodes_to_scan; + inodes_to_scan -= ino_adj; + p += scan->inode_size * ino_adj; + ino += ino_adj; + checksum_failures = badness = 0; + continue; + } + + if ((ino % inodes_per_block) == 0) { + if (checksum_failures == 0) + block_status[blk] |= IBLOCK_STATUS_CSUMS_OK; + checksum_failures = badness = 0; + } + inodes_to_scan--; + p += scan->inode_size; + ino++; + }; + +#ifdef WORDS_BIGENDIAN + ext2fs_free_mem(&inode); +#endif +} + +/* + * This function is called by ext2fs_get_next_inode when it needs to + * read in more blocks from the current blockgroup's inode table. + */ +static errcode_t get_next_blocks(ext2_inode_scan scan) +{ + blk64_t num_blocks; + errcode_t retval; + + /* + * Figure out how many blocks to read; we read at most + * inode_buffer_blocks, and perhaps less if there aren't that + * many blocks left to read. + */ + num_blocks = scan->inode_buffer_blocks; + if (num_blocks > scan->blocks_left) + num_blocks = scan->blocks_left; + + /* + * If the past block "read" was a bad block, then mark the + * left-over extra bytes as also being bad. + */ + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { + if (scan->bytes_left) + scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; + scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; + } + + /* + * Do inode bad block processing, if necessary. + */ + if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { + retval = check_for_inode_bad_blocks(scan, &num_blocks); + if (retval) + return retval; + } + + if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || + (scan->current_block == 0)) { + memset(scan->inode_buffer, 0, + (size_t) num_blocks * scan->fs->blocksize); + } else { + retval = io_channel_read_blk64(scan->fs->io, + scan->current_block, + (int) num_blocks, + scan->inode_buffer); + if (retval) + return EXT2_ET_NEXT_INODE_READ; + } + check_inode_block_sanity(scan, num_blocks); + + scan->ptr = scan->inode_buffer; + scan->bytes_left = num_blocks * scan->fs->blocksize; + + scan->blocks_left -= num_blocks; + if (scan->current_block) + scan->current_block += num_blocks; + + return 0; +} + +#if 0 +/* + * Returns 1 if the entire inode_buffer has a non-zero size and + * contains all zeros. (Not just deleted inodes, since that means + * that part of the inode table was used at one point; we want all + * zeros, which means that the inode table is pristine.) + */ +static inline int is_empty_scan(ext2_inode_scan scan) +{ + int i; + + if (scan->bytes_left == 0) + return 0; + + for (i=0; i < scan->bytes_left; i++) + if (scan->ptr[i]) + return 0; + return 1; +} +#endif + +errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode, int bufsize) +{ + errcode_t retval; + int extra_bytes = 0; + int length; + struct ext2_inode_large *iptr = (struct ext2_inode_large *)inode; + char *iblock_status; + unsigned int iblk; + + EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); + length = EXT2_INODE_SIZE(scan->fs->super); + iblock_status = SCAN_BLOCK_STATUS(scan); + + /* + * Do we need to start reading a new block group? + */ + if (scan->inodes_left <= 0) { + force_new_group: + if (scan->done_group) { + retval = (scan->done_group) + (scan->fs, scan, scan->current_group, + scan->done_group_data); + if (retval) + return retval; + } + if (scan->groups_left <= 0) { + *ino = 0; + return 0; + } + retval = get_next_blockgroup(scan); + if (retval) + return retval; + } + /* + * These checks are done outside the above if statement so + * they can be done for block group #0. + */ + if ((scan->scan_flags & EXT2_SF_DO_LAZY) && + (ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT) + )) + goto force_new_group; + if (scan->inodes_left == 0) + goto force_new_group; + if (scan->current_block == 0) { + if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { + goto force_new_group; + } else + return EXT2_ET_MISSING_INODE_TABLE; + } + + + /* + * Have we run out of space in the inode buffer? If so, we + * need to read in more blocks. + */ + if (scan->bytes_left < scan->inode_size) { + if (scan->bytes_left) + memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); + extra_bytes = scan->bytes_left; + + retval = get_next_blocks(scan); + if (retval) + return retval; +#if 0 + /* + * XXX test Need check for used inode somehow. + * (Note: this is hard.) + */ + if (is_empty_scan(scan)) + goto force_new_group; +#endif + } + + if (bufsize < length) { + retval = ext2fs_get_mem(length, &iptr); + if (retval) + return retval; + } + + retval = 0; + iblk = scan->current_inode % EXT2_INODES_PER_GROUP(scan->fs->super) / + EXT2_INODES_PER_BLOCK(scan->fs->super) % + scan->inode_buffer_blocks; + if (extra_bytes) { + memcpy(scan->temp_buffer+extra_bytes, scan->ptr, + scan->inode_size - extra_bytes); + scan->ptr += scan->inode_size - extra_bytes; + scan->bytes_left -= scan->inode_size - extra_bytes; + + /* Verify the inode checksum. */ + if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) && + !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1, + (struct ext2_inode_large *)scan->temp_buffer)) + retval = EXT2_ET_INODE_CSUM_INVALID; + +#ifdef WORDS_BIGENDIAN + memset(iptr, 0, length); + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) iptr, + (struct ext2_inode_large *) scan->temp_buffer, + 0, length); +#else + memcpy(iptr, scan->temp_buffer, length); +#endif + if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; + scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; + } else { + /* Verify the inode checksum. */ + if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) && + !(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1, + (struct ext2_inode_large *)scan->ptr)) + retval = EXT2_ET_INODE_CSUM_INVALID; + +#ifdef WORDS_BIGENDIAN + memset(iptr, 0, length); + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) iptr, + (struct ext2_inode_large *) scan->ptr, + 0, length); +#else + memcpy(iptr, scan->ptr, length); +#endif + scan->ptr += scan->inode_size; + scan->bytes_left -= scan->inode_size; + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; + } + if ((iblock_status[iblk] & IBLOCK_STATUS_INSANE) && + (retval == 0 || retval == EXT2_ET_INODE_CSUM_INVALID)) + retval = EXT2_ET_INODE_IS_GARBAGE; + + scan->inodes_left--; + scan->current_inode++; + *ino = scan->current_inode; + if (iptr != (struct ext2_inode_large *)inode) { + memcpy(inode, iptr, bufsize); + ext2fs_free_mem(&iptr); + } + return retval; +} + +errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode) +{ + return ext2fs_get_next_inode_full(scan, ino, inode, + sizeof(struct ext2_inode)); +} + +/* + * Functions to read and write a single inode. + */ +errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize, + int flags) +{ + blk64_t block_nr; + dgrp_t group; + unsigned long block, offset; + char *ptr; + errcode_t retval; + unsigned i; + int clen, inodes_per_block; + io_channel io; + int length = EXT2_INODE_SIZE(fs->super); + struct ext2_inode_large *iptr; + int cache_slot, fail_csum; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + if (fs->blocksize < 1024) + return EXT2_FILSYS_CORRUPTED; /* Should never happen */ + + /* Check to see if user has an override function */ + if (fs->read_inode && + ((bufsize == sizeof(struct ext2_inode)) || + (EXT2_INODE_SIZE(fs->super) == sizeof(struct ext2_inode)))) { + retval = (fs->read_inode)(fs, ino, inode); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + if ((ino == 0) || (ino > fs->super->s_inodes_count)) + return EXT2_ET_BAD_INODE_NUM; + /* Create inode cache if not present */ + if (!fs->icache) { + retval = ext2fs_create_inode_cache(fs, 4); + if (retval) + return retval; + } + /* Check to see if it's in the inode cache */ + for (i = 0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + memcpy(inode, fs->icache->cache[i].inode, + (bufsize > length) ? length : bufsize); + return 0; + } + } + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); + block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize; + block_nr += (ino - 1) / inodes_per_block; + offset = ((ino - 1) % inodes_per_block) * + EXT2_INODE_SIZE(fs->super); + io = fs->image_io; + } else { + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); + if (group > fs->group_desc_count) + return EXT2_ET_BAD_INODE_NUM; + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * + EXT2_INODE_SIZE(fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); + block_nr = ext2fs_inode_table_loc(fs, group); + if (!block_nr) + return EXT2_ET_MISSING_INODE_TABLE; + if ((block_nr < fs->super->s_first_data_block) || + (block_nr + fs->inode_blocks_per_group - 1 >= + ext2fs_blocks_count(fs->super))) + return EXT2_ET_GDESC_BAD_INODE_TABLE; + block_nr += block; + io = fs->io; + } + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); + + cache_slot = (fs->icache->cache_last + 1) % fs->icache->cache_size; + iptr = (struct ext2_inode_large *)fs->icache->cache[cache_slot].inode; + + ptr = (char *) iptr; + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (block_nr != fs->icache->buffer_blk) { + retval = io_channel_read_blk64(io, block_nr, 1, + fs->icache->buffer); + if (retval) + return retval; + fs->icache->buffer_blk = block_nr; + } + + memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, + clen); + + offset = 0; + length -= clen; + ptr += clen; + block_nr++; + } + length = EXT2_INODE_SIZE(fs->super); + + /* Verify the inode checksum. */ + fail_csum = !ext2fs_inode_csum_verify(fs, ino, iptr); + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr, + (struct ext2_inode_large *) iptr, + 0, length); +#endif + + /* Update the inode cache bookkeeping */ + if (!fail_csum) { + fs->icache->cache_last = cache_slot; + fs->icache->cache[cache_slot].ino = ino; + } + memcpy(inode, iptr, (bufsize > length) ? length : bufsize); + + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !(flags & READ_INODE_NOCSUM) && fail_csum) + return EXT2_ET_INODE_CSUM_INVALID; + + return 0; +} + +errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) +{ + return ext2fs_read_inode2(fs, ino, inode, bufsize, 0); +} + +errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode) +{ + return ext2fs_read_inode2(fs, ino, inode, + sizeof(struct ext2_inode), 0); +} + +errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize, + int flags) +{ + blk64_t block_nr; + dgrp_t group; + unsigned long block, offset; + errcode_t retval = 0; + struct ext2_inode_large *w_inode; + char *ptr; + unsigned i; + int clen; + int length = EXT2_INODE_SIZE(fs->super); + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + /* Check to see if user provided an override function */ + if (fs->write_inode) { + retval = (fs->write_inode)(fs, ino, inode); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + + if ((ino == 0) || (ino > fs->super->s_inodes_count)) + return EXT2_ET_BAD_INODE_NUM; + + /* Prepare our shadow buffer for read/modify/byteswap/write */ + retval = ext2fs_get_mem(length, &w_inode); + if (retval) + return retval; + + if (bufsize < length) { + retval = ext2fs_read_inode2(fs, ino, + (struct ext2_inode *)w_inode, + length, READ_INODE_NOCSUM); + if (retval) + goto errout; + } + + /* Check to see if the inode cache needs to be updated */ + if (fs->icache) { + for (i=0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + memcpy(fs->icache->cache[i].inode, inode, + (bufsize > length) ? length : bufsize); + break; + } + } + } else { + retval = ext2fs_create_inode_cache(fs, 4); + if (retval) + goto errout; + } + memcpy(w_inode, inode, (bufsize > length) ? length : bufsize); + + if (!(fs->flags & EXT2_FLAG_RW)) { + retval = EXT2_ET_RO_FILSYS; + goto errout; + } + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length); +#endif + + if ((flags & WRITE_INODE_NOCSUM) == 0) { + retval = ext2fs_inode_csum_set(fs, ino, w_inode); + if (retval) + goto errout; + } + + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * + EXT2_INODE_SIZE(fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); + block_nr = ext2fs_inode_table_loc(fs, (unsigned) group); + if (!block_nr) { + retval = EXT2_ET_MISSING_INODE_TABLE; + goto errout; + } + if ((block_nr < fs->super->s_first_data_block) || + (block_nr + fs->inode_blocks_per_group - 1 >= + ext2fs_blocks_count(fs->super))) { + retval = EXT2_ET_GDESC_BAD_INODE_TABLE; + goto errout; + } + block_nr += block; + + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); + + ptr = (char *) w_inode; + + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (fs->icache->buffer_blk != block_nr) { + retval = io_channel_read_blk64(fs->io, block_nr, 1, + fs->icache->buffer); + if (retval) + goto errout; + fs->icache->buffer_blk = block_nr; + } + + + memcpy((char *) fs->icache->buffer + (unsigned) offset, + ptr, clen); + + retval = io_channel_write_blk64(fs->io, block_nr, 1, + fs->icache->buffer); + if (retval) + goto errout; + + offset = 0; + ptr += clen; + length -= clen; + block_nr++; + } + + fs->flags |= EXT2_FLAG_CHANGED; +errout: + ext2fs_free_mem(&w_inode); + return retval; +} + +errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) +{ + return ext2fs_write_inode2(fs, ino, inode, bufsize, 0); +} + +errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + return ext2fs_write_inode2(fs, ino, inode, + sizeof(struct ext2_inode), 0); +} + +/* + * This function should be called when writing a new inode. It makes + * sure that extra part of large inodes is initialized properly. + */ +errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + struct ext2_inode *buf; + int size = EXT2_INODE_SIZE(fs->super); + struct ext2_inode_large *large_inode; + errcode_t retval; + __u32 t = fs->now ? fs->now : time(NULL); + + if (!inode->i_ctime) + inode->i_ctime = t; + if (!inode->i_mtime) + inode->i_mtime = t; + if (!inode->i_atime) + inode->i_atime = t; + + if (size == sizeof(struct ext2_inode)) + return ext2fs_write_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); + + buf = malloc(size); + if (!buf) + return ENOMEM; + + memset(buf, 0, size); + *buf = *inode; + + large_inode = (struct ext2_inode_large *) buf; + large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - + EXT2_GOOD_OLD_INODE_SIZE; + if (!large_inode->i_crtime) + large_inode->i_crtime = t; + + retval = ext2fs_write_inode_full(fs, ino, buf, size); + free(buf); + return retval; +} + + +errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) +{ + struct ext2_inode inode; + int i; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ino > fs->super->s_inodes_count) + return EXT2_ET_BAD_INODE_NUM; + + if (fs->get_blocks) { + if (!(*fs->get_blocks)(fs, ino, blocks)) + return 0; + } + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + for (i=0; i < EXT2_N_BLOCKS; i++) + blocks[i] = inode.i_block[i]; + return 0; +} + +errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode inode; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ino > fs->super->s_inodes_count) + return EXT2_ET_BAD_INODE_NUM; + + if (fs->check_directory) { + retval = (fs->check_directory)(fs, ino); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + if (!LINUX_S_ISDIR(inode.i_mode)) + return EXT2_ET_NO_DIRECTORY; + return 0; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/inode.o b/jni/e2fsprogs/lib/ext2fs/inode.o new file mode 100755 index 0000000000000000000000000000000000000000..dd421c03707cd2260a3d82967a30eaae0c27b766 GIT binary patch literal 18992 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/io_manager.c b/jni/e2fsprogs/lib/ext2fs/io_manager.c new file mode 100755 index 0000000..dca6af0 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/io_manager.c @@ -0,0 +1,152 @@ +/* + * io_manager.c --- the I/O manager abstraction + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t io_channel_set_options(io_channel channel, const char *opts) +{ + errcode_t retval = 0; + char *next, *ptr, *options, *arg; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (!opts) + return 0; + + if (!channel->manager->set_option) + return EXT2_ET_INVALID_ARGUMENT; + + options = malloc(strlen(opts)+1); + if (!options) + return EXT2_ET_NO_MEMORY; + strcpy(options, opts); + ptr = options; + + while (ptr && *ptr) { + next = strchr(ptr, '&'); + if (next) + *next++ = 0; + + arg = strchr(ptr, '='); + if (arg) + *arg++ = 0; + + retval = (channel->manager->set_option)(channel, ptr, arg); + if (retval) + break; + ptr = next; + } + free(options); + return retval; +} + +errcode_t io_channel_write_byte(io_channel channel, unsigned long offset, + int count, const void *data) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->write_byte) + return channel->manager->write_byte(channel, offset, + count, data); + + return EXT2_ET_UNIMPLEMENTED; +} + +errcode_t io_channel_read_blk64(io_channel channel, unsigned long long block, + int count, void *data) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->read_blk64) + return (channel->manager->read_blk64)(channel, block, + count, data); + + if ((block >> 32) != 0) + return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64; + + return (channel->manager->read_blk)(channel, (unsigned long) block, + count, data); +} + +errcode_t io_channel_write_blk64(io_channel channel, unsigned long long block, + int count, const void *data) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->write_blk64) + return (channel->manager->write_blk64)(channel, block, + count, data); + + if ((block >> 32) != 0) + return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64; + + return (channel->manager->write_blk)(channel, (unsigned long) block, + count, data); +} + +errcode_t io_channel_discard(io_channel channel, unsigned long long block, + unsigned long long count) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->discard) + return (channel->manager->discard)(channel, block, count); + + return EXT2_ET_UNIMPLEMENTED; +} + +errcode_t io_channel_zeroout(io_channel channel, unsigned long long block, + unsigned long long count) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->zeroout) + return (channel->manager->zeroout)(channel, block, count); + + return EXT2_ET_UNIMPLEMENTED; +} + +errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr) +{ + size_t size; + + if (count == 0) + size = io->block_size; + else if (count > 0) + size = io->block_size * count; + else + size = -count; + + if (io->align > 0) { + if ((unsigned) io->align > size) + size = io->align; + return ext2fs_get_memalign(size, io->align, ptr); + } else + return ext2fs_get_mem(size, ptr); +} + +errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block, + unsigned long long count) +{ + if (!io->manager->cache_readahead) + return EXT2_ET_OP_NOT_SUPPORTED; + + return io->manager->cache_readahead(io, block, count); +} diff --git a/jni/e2fsprogs/lib/ext2fs/io_manager.o b/jni/e2fsprogs/lib/ext2fs/io_manager.o new file mode 100755 index 0000000000000000000000000000000000000000..0757c4d1e9981062407435739a683c1387401fee GIT binary patch literal 3968 zcmcgvUuauZ82@f>V-s83v43r?HdCgQ!LoL2V*|yjYv&NBV@w$cO>fiNrYwKDBy;QL zuu#E1_+WAPG_{32G*7~)Y=OZ#Dl)+r6$XMzS`{*VQSl)`Lj8Rw=j5K2E|}q>->^#A{QF;x|Mc#x1_94aP^LWGY36{a*-Nomf!g{DizvX{wA^rncpDHwc^l$+(fwx(?9v|)Fc^-N<8>fy5-|g_-4x1$PF%S4? z_73o%K?f9nzDe?%!Ee_1mvbWCqc53cznNV8|+43~a=26otsHs)6QuFKS z3nK5Rb5gV|79h>J)&M$XgTSfjB zmItq){`PXN#og+h$`z2)Exd+|`_vIb_E+wmomMUjJa8eeEnC}Ol@q!uL z5ikNLbs5{P+Rs_s3s1!xG@HQgAm7}}KUck+edQ{#ux=i5j?VxldKG%m9Pau9QnteV zOJdBg^d#-R|J~X6;QN5v-+Q!s_#kX?KNa-?PObdA{@hxiNX$-*ZF}8GrN@(rZGHPg zeWCpba07lkjC04xc%$3sY6;SItUClsbREX1zjf$v%cC1UZ1|wjylk`thYq*W_umPg zC3%M!6YrYjU8>mYt@?edCD^O^&99S( z8mNrQe%*Z(-1vIH=#{()X7{(ceowf5D~4)6{{-Afzpd4hn$&O){Ic+OFaCnS@ip{} z0fD0mJ!2Qv8#VjlT!Gp6sT$B#{-}eq`C9x#b?}>Ya6UJVN5vuP2iPt+V0=h!S=0gW z4v9ZyVu7LX&oF0xhfIa22Vm%{0$=ptZ%h0rKFVV7hA{AVR?U5J-PYRgH^ABNQJHE{ z55T7Ifo0&9N+5d*e2s+I~%Jg(H;%w zT&eMhocO@ktFGUJt8mFR4+m9Yxom-3Cmx@Q7o618Km;0e~CKZ{O zq)^I<*`bVcHbdjda3pFc5>709&PgScr!y3aB;#=>ahELZWWvdb47y`l7>T9`+Pg>7 z;W0?!PTY=-k0n?Xa}pjAg%Zh(6MFuoS9Yc|cI2e)(~iZGk?`>8Q5`&!8qYZ4;mM36 zBXy$T(Ucu`Xf)+GI&)+^9kEj*Iux-ZQ74>o>=8SP2O%=JU`E_d*kevA6rm8}%-F+t zPsaJJB|-X*o!qxahuL0uSfJZSLc0l%KH7dZ)GJTszrDD>%By>qp@J;dDgcT{}`p9IGK@5zR| +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "irel.h" + +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_start_iter(ext2_irel irel); +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref); +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); +static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); +static errcode_t ima_free(ext2_irel irel); + +/* + * This data structure stores the array of inode references; there is + * a structure for each inode. + */ +struct inode_reference_entry { + __u16 num; + struct ext2_inode_reference *refs; +}; + +struct irel_ma { + __u32 magic; + ext2_ino_t max_inode; + ext2_ino_t ref_current; + int ref_iter; + ext2_ino_t *orig_map; + struct ext2_inode_relocate_entry *entries; + struct inode_reference_entry *ref_entries; +}; + +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, + ext2_irel *new_irel) +{ + ext2_irel irel = 0; + errcode_t retval; + struct irel_ma *ma = 0; + size_t size; + + *new_irel = 0; + + /* + * Allocate memory structures + */ + retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), + &irel); + if (retval) + goto errout; + memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); + + retval = ext2fs_get_mem(strlen(name)+1, &irel->name); + if (retval) + goto errout; + strcpy(irel->name, name); + + retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma); + if (retval) + goto errout; + memset(ma, 0, sizeof(struct irel_ma)); + irel->priv_data = ma; + + size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); + retval = ext2fs_get_array(max_inode+1, sizeof(ext2_ino_t), + &ma->orig_map); + if (retval) + goto errout; + memset(ma->orig_map, 0, size); + + size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * + (max_inode+1)); + retval = ext2fs_get_array((max_inode+1, + sizeof(struct ext2_inode_relocate_entry), &ma->entries); + if (retval) + goto errout; + memset(ma->entries, 0, size); + + size = (size_t) (sizeof(struct inode_reference_entry) * + (max_inode+1)); + retval = ext2fs_get_mem(max_inode+1, + sizeof(struct inode_reference_entry), &ma->ref_entries); + if (retval) + goto errout; + memset(ma->ref_entries, 0, size); + ma->max_inode = max_inode; + + /* + * Fill in the irel data structure + */ + irel->put = ima_put; + irel->get = ima_get; + irel->get_by_orig = ima_get_by_orig; + irel->start_iter = ima_start_iter; + irel->next = ima_next; + irel->add_ref = ima_add_ref; + irel->start_iter_ref = ima_start_iter_ref; + irel->next_ref = ima_next_ref; + irel->move = ima_move; + irel->delete = ima_delete; + irel->free = ima_free; + + *new_irel = irel; + return 0; + +errout: + ima_free(irel); + return retval; +} + +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent) +{ + struct inode_reference_entry *ref_ent; + struct irel_ma *ma; + errcode_t retval; + size_t size, old_size; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + + /* + * Force the orig field to the correct value; the application + * program shouldn't be messing with this field. + */ + if (ma->entries[(unsigned) old].new == 0) + ent->orig = old; + else + ent->orig = ma->entries[(unsigned) old].orig; + + /* + * If max_refs has changed, reallocate the refs array + */ + ref_ent = ma->ref_entries + (unsigned) old; + if (ref_ent->refs && ent->max_refs != + ma->entries[(unsigned) old].max_refs) { + size = (sizeof(struct ext2_inode_reference) * ent->max_refs); + old_size = (sizeof(struct ext2_inode_reference) * + ma->entries[(unsigned) old].max_refs); + retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); + if (retval) + return retval; + } + + ma->entries[(unsigned) old] = *ent; + ma->orig_map[(unsigned) ent->orig] = old; + return 0; +} + +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + *ent = ma->entries[(unsigned) old]; + return 0; +} + +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + ext2_ino_t ino; + + ma = irel->priv_data; + if (orig > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + ino = ma->orig_map[(unsigned) orig]; + if (ino == 0) + return ENOENT; + *old = ino; + *ent = ma->entries[(unsigned) ino]; + return 0; +} + +static errcode_t ima_start_iter(ext2_irel irel) +{ + irel->current = 0; + return 0; +} + +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + while (++irel->current < ma->max_inode) { + if (ma->entries[(unsigned) irel->current].new == 0) + continue; + *old = irel->current; + *ent = ma->entries[(unsigned) irel->current]; + return 0; + } + *old = 0; + return 0; +} + +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref) +{ + struct irel_ma *ma; + size_t size; + struct inode_reference_entry *ref_ent; + struct ext2_inode_relocate_entry *ent; + errcode_t retval; + + ma = irel->priv_data; + if (ino > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + + ref_ent = ma->ref_entries + (unsigned) ino; + ent = ma->entries + (unsigned) ino; + + /* + * If the inode reference array doesn't exist, create it. + */ + if (ref_ent->refs == 0) { + size = (size_t) ((sizeof(struct ext2_inode_reference) * + ent->max_refs)); + retval = ext2fs_get_array(ent->max_refs, + sizeof(struct ext2_inode_reference), &ref_ent->refs); + if (retval) + return retval; + memset(ref_ent->refs, 0, size); + ref_ent->num = 0; + } + + if (ref_ent->num >= ent->max_refs) + return EXT2_ET_TOO_MANY_REFS; + + ref_ent->refs[(unsigned) ref_ent->num++] = *ref; + return 0; +} + +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (ino > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) ino].new == 0) + return ENOENT; + ma->ref_current = ino; + ma->ref_iter = 0; + return 0; +} + +static errcode_t ima_next_ref(ext2_irel irel, + struct ext2_inode_reference *ref) +{ + struct irel_ma *ma; + struct inode_reference_entry *ref_ent; + + ma = irel->priv_data; + + ref_ent = ma->ref_entries + ma->ref_current; + + if ((ref_ent->refs == NULL) || + (ma->ref_iter >= ref_ent->num)) { + ref->block = 0; + ref->offset = 0; + return 0; + } + *ref = ref_ent->refs[ma->ref_iter++]; + return 0; +} + + +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if ((old > ma->max_inode) || (new > ma->max_inode)) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + + ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; + if (ma->ref_entries[(unsigned) new].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); + ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; + + ma->entries[(unsigned) old].new = 0; + ma->ref_entries[(unsigned) old].num = 0; + ma->ref_entries[(unsigned) old].refs = 0; + + ma->orig_map[ma->entries[new].orig] = new; + return 0; +} + +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + + ma->entries[old].new = 0; + if (ma->ref_entries[(unsigned) old].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); + ma->orig_map[ma->entries[(unsigned) old].orig] = 0; + + ma->ref_entries[(unsigned) old].num = 0; + ma->ref_entries[(unsigned) old].refs = 0; + return 0; +} + +static errcode_t ima_free(ext2_irel irel) +{ + struct irel_ma *ma; + ext2_ino_t ino; + + if (!irel) + return 0; + + ma = irel->priv_data; + + if (ma) { + if (ma->orig_map) + ext2fs_free_mem(&ma->orig_map); + if (ma->entries) + ext2fs_free_mem(&ma->entries); + if (ma->ref_entries) { + for (ino = 0; ino <= ma->max_inode; ino++) { + if (ma->ref_entries[(unsigned) ino].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); + } + ext2fs_free_mem(&ma->ref_entries); + } + ext2fs_free_mem(&ma); + } + if (irel->name) + ext2fs_free_mem(&irel->name); + ext2fs_free_mem(&irel); + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/ismounted.c b/jni/e2fsprogs/lib/ext2fs/ismounted.c new file mode 100755 index 0000000..8fc0b99 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/ismounted.c @@ -0,0 +1,472 @@ +/* + * ismounted.c --- Check to see if the filesystem was mounted + * + * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* define BSD_SOURCE to make sure we get the major() macro */ +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ +#endif + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_LINUX_FD_H +#include +#endif +#ifdef HAVE_LINUX_LOOP_H +#include +#include +#ifdef HAVE_LINUX_MAJOR_H +#include +#endif /* HAVE_LINUX_MAJOR_H */ +#endif /* HAVE_LINUX_LOOP_H */ +#ifdef HAVE_MNTENT_H +#include +#endif +#ifdef HAVE_GETMNTINFO +#include +#include +#include +#endif /* HAVE_GETMNTINFO */ +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#ifdef HAVE_SETMNTENT +/* + * Check to see if a regular file is mounted. + * If /etc/mtab/ is a symlink of /proc/mounts, you will need the following check + * because the name in /proc/mounts is a loopback device not a regular file. + */ +static int check_loop_mounted(const char *mnt_fsname, dev_t mnt_rdev, + dev_t file_dev, ino_t file_ino) +{ +#if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H) + struct loop_info64 loopinfo = {0, }; + int loop_fd, ret; + + if (major(mnt_rdev) == LOOP_MAJOR) { + loop_fd = open(mnt_fsname, O_RDONLY); + if (loop_fd < 0) + return -1; + + ret = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo); + close(loop_fd); + if (ret < 0) + return -1; + + if (file_dev == loopinfo.lo_device && + file_ino == loopinfo.lo_inode) + return 1; + } +#endif /* defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H) */ + return 0; +} + +/* + * Helper function which checks a file in /etc/mtab format to see if a + * filesystem is mounted. Returns an error if the file doesn't exist + * or can't be opened. + */ +static errcode_t check_mntent_file(const char *mtab_file, const char *file, + int *mount_flags, char *mtpt, int mtlen) +{ + struct mntent *mnt; + struct stat st_buf, dir_st_buf; + errcode_t retval = 0; + dev_t file_dev=0, file_rdev=0; + ino_t file_ino=0; + FILE *f; + int fd; + + *mount_flags = 0; + + if ((f = setmntent (mtab_file, "r")) == NULL) { + if (errno == ENOENT) { + if (getenv("EXT2FS_NO_MTAB_OK")) + return 0; + else + return EXT2_ET_NO_MTAB_FILE; + } + return errno; + } + if (stat(file, &st_buf) == 0) { + if (ext2fsP_is_disk_device(st_buf.st_mode)) { +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + file_rdev = st_buf.st_rdev; +#endif /* __GNU__ */ + } else { + file_dev = st_buf.st_dev; + file_ino = st_buf.st_ino; + } + } + while ((mnt = getmntent (f)) != NULL) { + if (mnt->mnt_fsname[0] != '/') + continue; + if (strcmp(file, mnt->mnt_fsname) == 0) { + if (stat(mnt->mnt_dir, &st_buf) != 0) + continue; + if (file_rdev && (file_rdev != st_buf.st_dev)) { +#ifdef DEBUG + printf("Bogus entry in %s! " + "(%s is not mounted on %s)\n", + mtab_file, file, mnt->mnt_dir); +#endif /* DEBUG */ + continue; + } + break; + } + if (stat(mnt->mnt_fsname, &st_buf) == 0) { + if (ext2fsP_is_disk_device(st_buf.st_mode)) { +#ifndef __GNU__ + if (file_rdev && + (file_rdev == st_buf.st_rdev)) { + if (stat(mnt->mnt_dir, + &dir_st_buf) != 0) + continue; + if (file_rdev == dir_st_buf.st_dev) + break; + } + if (check_loop_mounted(mnt->mnt_fsname, + st_buf.st_rdev, file_dev, + file_ino) == 1) + break; +#endif /* __GNU__ */ + } else { + if (file_dev && ((file_dev == st_buf.st_dev) && + (file_ino == st_buf.st_ino))) + break; + } + } + } + + if (mnt == 0) { +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + /* + * Do an extra check to see if this is the root device. We + * can't trust /etc/mtab, and /proc/mounts will only list + * /dev/root for the root filesystem. Argh. Instead we + * check if the given device has the same major/minor number + * as the device that the root directory is on. + */ + if (file_rdev && stat("/", &st_buf) == 0) { + if (st_buf.st_dev == file_rdev) { + *mount_flags = EXT2_MF_MOUNTED; + if (mtpt) + strncpy(mtpt, "/", mtlen); + goto is_root; + } + } +#endif /* __GNU__ */ + goto errout; + } + *mount_flags = EXT2_MF_MOUNTED; + +#ifdef MNTOPT_RO + /* Check to see if the ro option is set */ + if (hasmntopt(mnt, MNTOPT_RO)) + *mount_flags |= EXT2_MF_READONLY; +#endif + + if (mtpt) + strncpy(mtpt, mnt->mnt_dir, mtlen); + /* + * Check to see if we're referring to the root filesystem. + * If so, do a manual check to see if we can open /etc/mtab + * read/write, since if the root is mounted read/only, the + * contents of /etc/mtab may not be accurate. + */ + if (!strcmp(mnt->mnt_dir, "/")) { +is_root: +#define TEST_FILE "/.ismount-test-file" + *mount_flags |= EXT2_MF_ISROOT; + fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600); + if (fd < 0) { + if (errno == EROFS) + *mount_flags |= EXT2_MF_READONLY; + } else + close(fd); + (void) unlink(TEST_FILE); + } + retval = 0; +errout: + endmntent (f); + return retval; +} + +static errcode_t check_mntent(const char *file, int *mount_flags, + char *mtpt, int mtlen) +{ + errcode_t retval; + +#ifdef DEBUG + retval = check_mntent_file("/tmp/mtab", file, mount_flags, + mtpt, mtlen); + if (retval == 0) + return 0; +#endif /* DEBUG */ +#ifdef __linux__ + retval = check_mntent_file("/proc/mounts", file, mount_flags, + mtpt, mtlen); + if (retval == 0) + return 0; +#endif /* __linux__ */ +#if defined(MOUNTED) || defined(_PATH_MOUNTED) +#ifndef MOUNTED +#define MOUNTED _PATH_MOUNTED +#endif /* MOUNTED */ + retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen); + return retval; +#else + *mount_flags = 0; + return 0; +#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */ +} + +#else +#if defined(HAVE_GETMNTINFO) + +static errcode_t check_getmntinfo(const char *file, int *mount_flags, + char *mtpt, int mtlen) +{ + struct statfs *mp; + int len, n; + const char *s1; + char *s2; + + n = getmntinfo(&mp, MNT_NOWAIT); + if (n == 0) + return errno; + + len = sizeof(_PATH_DEV) - 1; + s1 = file; + if (strncmp(_PATH_DEV, s1, len) == 0) + s1 += len; + + *mount_flags = 0; + while (--n >= 0) { + s2 = mp->f_mntfromname; + if (strncmp(_PATH_DEV, s2, len) == 0) { + s2 += len - 1; + *s2 = 'r'; + } + if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { + *mount_flags = EXT2_MF_MOUNTED; + break; + } + ++mp; + } + if (mtpt) + strncpy(mtpt, mp->f_mntonname, mtlen); + return 0; +} +#endif /* HAVE_GETMNTINFO */ +#endif /* HAVE_SETMNTENT */ + +/* + * Check to see if we're dealing with the swap device. + */ +static int is_swap_device(const char *file) +{ + FILE *f; + char buf[1024], *cp; + dev_t file_dev; + struct stat st_buf; + int ret = 0; + + file_dev = 0; +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + if ((stat(file, &st_buf) == 0) && + ext2fsP_is_disk_device(st_buf.st_mode)) + file_dev = st_buf.st_rdev; +#endif /* __GNU__ */ + + if (!(f = fopen("/proc/swaps", "r"))) + return 0; + /* Skip the first line */ + if (!fgets(buf, sizeof(buf), f)) + goto leave; + if (*buf && strncmp(buf, "Filename\t", 9)) + /* Linux <=2.6.19 contained a bug in the /proc/swaps + * code where the header would not be displayed + */ + goto valid_first_line; + + while (fgets(buf, sizeof(buf), f)) { +valid_first_line: + if ((cp = strchr(buf, ' ')) != NULL) + *cp = 0; + if ((cp = strchr(buf, '\t')) != NULL) + *cp = 0; + if (strcmp(buf, file) == 0) { + ret++; + break; + } +#ifndef __GNU__ + if (file_dev && (stat(buf, &st_buf) == 0) && + ext2fsP_is_disk_device(st_buf.st_mode) && + file_dev == st_buf.st_rdev) { + ret++; + break; + } +#endif /* __GNU__ */ + } + +leave: + fclose(f); + return ret; +} + + +/* + * ext2fs_check_mount_point() fills determines if the device is + * mounted or otherwise busy, and fills in mount_flags with one or + * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT, + * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY. If mtpt is + * non-NULL, the directory where the device is mounted is copied to + * where mtpt is pointing, up to mtlen characters. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, + char *mtpt, int mtlen) +{ + errcode_t retval = 0; + int busy = 0; + + if (getenv("EXT2FS_PRETEND_RO_MOUNT")) { + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY; + if (getenv("EXT2FS_PRETEND_ROOTFS")) + *mount_flags = EXT2_MF_ISROOT; + return 0; + } + if (getenv("EXT2FS_PRETEND_RW_MOUNT")) { + *mount_flags = EXT2_MF_MOUNTED; + if (getenv("EXT2FS_PRETEND_ROOTFS")) + *mount_flags = EXT2_MF_ISROOT; + return 0; + } + +#ifdef __linux__ /* This only works on Linux 2.6+ systems */ + { + struct stat st_buf; + + if (stat(device, &st_buf) == 0 && + ext2fsP_is_disk_device(st_buf.st_mode)) { + int fd = open(device, O_RDONLY | O_EXCL); + + if (fd >= 0) { + /* + * The device is not busy so it's + * definitelly not mounted. No need to + * to perform any more checks. + */ + close(fd); + *mount_flags = 0; + return 0; + } else if (errno == EBUSY) { + busy = 1; + } + } + } +#endif + + if (is_swap_device(device)) { + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP; + if (mtpt) + strncpy(mtpt, "", mtlen); + } else { +#ifdef HAVE_SETMNTENT + retval = check_mntent(device, mount_flags, mtpt, mtlen); +#else +#ifdef HAVE_GETMNTINFO + retval = check_getmntinfo(device, mount_flags, mtpt, mtlen); +#else +#if defined(__GNUC__) && !defined(_WIN32) + #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!" +#endif + *mount_flags = 0; +#endif /* HAVE_GETMNTINFO */ +#endif /* HAVE_SETMNTENT */ + } + if (retval) + return retval; + + if (busy) + *mount_flags |= EXT2_MF_BUSY; + + return 0; +} + +/* + * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED, + * EXT2_MF_READONLY, and EXT2_MF_ROOT + * + */ +errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags) +{ + return ext2fs_check_mount_point(file, mount_flags, NULL, 0); +} + +#ifdef DEBUG +int main(int argc, char **argv) +{ + int retval, mount_flags; + char mntpt[80]; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + add_error_table(&et_ext2_error_table); + mntpt[0] = 0; + retval = ext2fs_check_mount_point(argv[1], &mount_flags, + mntpt, sizeof(mntpt)); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_check_if_mounted"); + exit(1); + } + printf("Device %s reports flags %02x\n", argv[1], mount_flags); + if (mount_flags & EXT2_MF_BUSY) + printf("\t%s is apparently in use.\n", argv[1]); + if (mount_flags & EXT2_MF_MOUNTED) + printf("\t%s is mounted.\n", argv[1]); + if (mount_flags & EXT2_MF_SWAP) + printf("\t%s is a swap device.\n", argv[1]); + if (mount_flags & EXT2_MF_READONLY) + printf("\t%s is read-only.\n", argv[1]); + if (mount_flags & EXT2_MF_ISROOT) + printf("\t%s is the root filesystem.\n", argv[1]); + if (mntpt[0]) + printf("\t%s is mounted on %s.\n", argv[1], mntpt); + exit(0); +} +#endif /* DEBUG */ diff --git a/jni/e2fsprogs/lib/ext2fs/ismounted.o b/jni/e2fsprogs/lib/ext2fs/ismounted.o new file mode 100755 index 0000000000000000000000000000000000000000..d14fc83f9861fd24bd01480fbc055b12a5b3b6dc GIT binary patch literal 7232 zcmbtYeQaA-6+h2*R;Nw+UDDB}PN6^w)cs&UCr#s}NlOar$FfxGpqmpMXN{WJY3z-b z4zQF8ZDM~kQ^Y3Lj($wYnI_mDot8)&>&QTr*gx$MLNJiq4$0Aqv<)Qkq=fK0_nl+k zzSKg3E7|Y9-#h1bKJK~aKKq9|@7on}9Ma*?YgD;Yl<3l(mAPxCE-i%Q+;I5H?1}oZ z+1Bt#VUn(t7LZ5F$aCt+3)PZ$VX|>N=8*U1xXsO26RT7LKV9Uk-LpfzGF8yqqVMw9A0D{Bai#@lV_Oc)OyJ~KU=8J*=Oj7Aa`N% z;qjk~k62buIiim1U6ys2f)CBOZ-(#n;3!NU8jm^^Uw9qyd?M^br=0v%*cpZFUChUM*F4PQTi~x7 zKQ|l^-;VLAhP+GGUWnGX9^$@RW!Gc<+0K8H<>wA^#r!M}PE*fZtI---Rzg0p%}wp_ zx))@Rvb^pA3RUtug8b&K^=F+aUMcK)PwILO$ENFGqngeqES&;mjX%SQ>Dd#lV{>80uh(IMFAn-0jTF)AuE9nT zdA$ZZ*Tb=wZiHi>=a^$P4c# z@5R=}@wqj`b?wcqzz1>G?r}Zt7jyt?XVq#E@i&G2I%RvNht$&1YmVPTG!Ojjtkw>E zj6Fo&4014qdGw>7Ts{1^Uw+&S>|elG*5H(%VC-XHoIkoB@xf<)j^5+YJQ_;@cbIo9>-%iFdu^i*;+^OA~x?zu6I z=j?LWUn}I^>^02~$@yqvg|AbP4d!4W>Uks1x7~bR?XIi`>k#hGx6VJWJ|{l4b8L{a zIS9VN*K!ZX*=5$3<#_KjoAYR0KWZTF`{5nvXik+CT zqj_nG<~u@LVsqGM}990*Pt&gADej|eQ7vidh5C2b<^j=>!vRZH%=GP<3f%3 ztJkEb6^0*~j?Q+y8{Lz8W(@O(@z4=kiZ=T!$Tw1wCy-<18)0nGn!f2Ax9qk?AS)4z8;f$y;Ig;pr*VGGpg%d54OP zYd!N>&bi?8W#)O#LkD_#jmg8#gPq%UJ&@Snv9ojM-nK-?zQmq=2ljT-JbYj0t_S9! z4~q0X+3$7_-bJN;w~Ohof59Uzz&4R>;%nRDr3V+2;lMkO84;hO z2^3AIBQM->CK|r!)Ww>>@g9?GfE3PFGoI$}w#BZR3+3u!t{7vvSBw-Io-fCo#;rp> zpYe(P|D(t~hlK;*sqlRjUx&n3?f4$bge$4(9ZC6O-o-aMd&-r-5;6iT6f6L%FxdY=fxL*#tI$W8u8(M?< zjIYP5;1{akzpaA*vos|9^~P5;h{Wn|F+zJlt*#hPeC4zmxuDG-Ism19GBv+2p;4qS@;r}^JOXG=fU!J zoiVkJNpR-J@3!)2vv8aL zkcBstrEz{$!N)CJYk}2nTDYB0SN1vkbEn0BN^p%UCC^3$*SHjayNdkfD)K99d_uO1 z|76OeUvRan>oO>~+EqMf@o>-4ani!=`g|_H&;5nR=>WgtXDuGPKfGh%HvdfvxAT0@ z9ljlocdb7)-+2qS*Xy)}+dQQz_;xu0nctS55nS_mQf){5iRM%BsNg}KPQimb2dnTL zvUu!$eKNrFBk||S0FUBNTRe^GJFdUCaGSpr;Mcfr2KW{K(BiT4zfukljrS?By;^Y1 zo8lV;=e*hdbGwDxb<%I)c3;g29<+N*@Sxo%EFSzeDUVYY9xJ0nB@1t|@U{4pk4Mn| zb_-wci2HSgGX zrabx{O4-~{Iyrcp9!=#^>BlKPl9A#5Eh@>!sy3A7P9+`=}FAz^=1_oGiAT9u(mfDKj4aeeJWU2nI%QsM8a-`kDQs%+M_$bAGFOXr8-}6ixdaD!S5GA{r>=k?6$`M literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/link.c b/jni/e2fsprogs/lib/ext2fs/link.c new file mode 100755 index 0000000..d69b1e3 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/link.c @@ -0,0 +1,646 @@ +/* + * link.c --- create links in a ext2fs directory + * + * Copyright (C) 1993, 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#define EXT2_DX_ROOT_OFF 24 + +struct dx_frame { + void *buf; + blk64_t pblock; + struct ext2_dx_countlimit *head; + struct ext2_dx_entry *entries; + struct ext2_dx_entry *at; +}; + +struct dx_lookup_info { + const char *name; + int namelen; + int hash_alg; + __u32 hash; + unsigned levels; + struct dx_frame frames[EXT4_HTREE_LEVEL]; +}; + +static errcode_t alloc_dx_frame(ext2_filsys fs, struct dx_frame *frame) +{ + return ext2fs_get_mem(fs->blocksize, &frame->buf); +} + +static void dx_release(struct dx_lookup_info *info) +{ + unsigned level; + + for (level = 0; level < info->levels; level++) { + if (info->frames[level].buf == NULL) + break; + ext2fs_free_mem(&(info->frames[level].buf)); + } + info->levels = 0; +} + +static void dx_search_entry(struct dx_frame *frame, int count, __u32 hash) +{ + struct ext2_dx_entry *p, *q, *m; + + p = frame->entries + 1; + q = frame->entries + count - 1; + while (p <= q) { + m = p + (q - p) / 2; + if (ext2fs_le32_to_cpu(m->hash) > hash) + q = m - 1; + else + p = m + 1; + } + frame->at = p - 1; +} + +static errcode_t load_logical_dir_block(ext2_filsys fs, ext2_ino_t dir, + struct ext2_inode *diri, blk64_t block, + blk64_t *pblk, void *buf) +{ + errcode_t errcode; + int ret_flags; + + errcode = ext2fs_bmap2(fs, dir, diri, NULL, 0, block, &ret_flags, + pblk); + if (errcode) + return errcode; + if (ret_flags & BMAP_RET_UNINIT) + return EXT2_ET_DIR_CORRUPTED; + return ext2fs_read_dir_block4(fs, *pblk, buf, 0, dir); +} + +static errcode_t dx_lookup(ext2_filsys fs, ext2_ino_t dir, + struct ext2_inode *diri, struct dx_lookup_info *info) +{ + struct ext2_dx_root_info *root; + errcode_t errcode; + int level = 0; + int count, limit; + int hash_alg; + int hash_flags = diri->i_flags & EXT4_CASEFOLD_FL; + __u32 minor_hash; + struct dx_frame *frame; + + errcode = alloc_dx_frame(fs, &(info->frames[0])); + if (errcode) + return errcode; + info->levels = 1; + + errcode = load_logical_dir_block(fs, dir, diri, 0, + &(info->frames[0].pblock), + info->frames[0].buf); + if (errcode) + goto out_err; + root = (struct ext2_dx_root_info *) ((char *)info->frames[0].buf + + EXT2_DX_ROOT_OFF); + hash_alg = root->hash_version; + if (hash_alg != EXT2_HASH_TEA && hash_alg != EXT2_HASH_HALF_MD4 && + hash_alg != EXT2_HASH_LEGACY) { + errcode = EXT2_ET_DIRHASH_UNSUPP; + goto out_err; + } + if (hash_alg <= EXT2_HASH_TEA && + fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH) + hash_alg += 3; + if (root->indirect_levels >= ext2_dir_htree_level(fs)) { + errcode = EXT2_ET_DIR_CORRUPTED; + goto out_err; + } + info->hash_alg = hash_alg; + + errcode = ext2fs_dirhash2(hash_alg, info->name, info->namelen, + fs->encoding, hash_flags, + fs->super->s_hash_seed, &info->hash, + &minor_hash); + if (errcode) + goto out_err; + + for (level = 0; level <= root->indirect_levels; level++) { + frame = &(info->frames[level]); + if (level > 0) { + errcode = alloc_dx_frame(fs, frame); + if (errcode) + goto out_err; + info->levels++; + + errcode = load_logical_dir_block(fs, dir, diri, + ext2fs_le32_to_cpu(info->frames[level-1].at->block) & 0x0fffffff, + &(frame->pblock), frame->buf); + if (errcode) + goto out_err; + } + errcode = ext2fs_get_dx_countlimit(fs, frame->buf, + &(frame->head), NULL); + if (errcode) + goto out_err; + count = ext2fs_le16_to_cpu(frame->head->count); + limit = ext2fs_le16_to_cpu(frame->head->limit); + frame->entries = (struct ext2_dx_entry *)(frame->head); + if (!count || count > limit) { + errcode = EXT2_ET_DIR_CORRUPTED; + goto out_err; + } + + dx_search_entry(frame, count, info->hash); + } + return 0; +out_err: + dx_release(info); + return errcode; +} + +struct link_struct { + ext2_filsys fs; + const char *name; + int namelen; + ext2_ino_t inode; + int flags; + int done; + unsigned int blocksize; + errcode_t err; + struct ext2_super_block *sb; +}; + +static int link_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entru EXT2FS_ATTR((unused)), + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data) +{ + struct link_struct *ls = (struct link_struct *) priv_data; + struct ext2_dir_entry *next; + unsigned int rec_len, min_rec_len, curr_rec_len; + int ret = 0; + int csum_size = 0; + + if (ls->done) + return DIRENT_ABORT; + + rec_len = EXT2_DIR_REC_LEN(ls->namelen); + + ls->err = ext2fs_get_rec_len(ls->fs, dirent, &curr_rec_len); + if (ls->err) + return DIRENT_ABORT; + + if (ext2fs_has_feature_metadata_csum(ls->fs->super)) + csum_size = sizeof(struct ext2_dir_entry_tail); + /* + * See if the following directory entry (if any) is unused; + * if so, absorb it into this one. + */ + next = (struct ext2_dir_entry *) (buf + offset + curr_rec_len); + if ((offset + (int) curr_rec_len < blocksize - (8 + csum_size)) && + (next->inode == 0) && + (offset + (int) curr_rec_len + (int) next->rec_len <= blocksize)) { + curr_rec_len += next->rec_len; + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent); + if (ls->err) + return DIRENT_ABORT; + ret = DIRENT_CHANGED; + } + + /* + * If the directory entry is used, see if we can split the + * directory entry to make room for the new name. If so, + * truncate it and return. + */ + if (dirent->inode) { + min_rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(dirent)); + if (curr_rec_len < (min_rec_len + rec_len)) + return ret; + rec_len = curr_rec_len - min_rec_len; + ls->err = ext2fs_set_rec_len(ls->fs, min_rec_len, dirent); + if (ls->err) + return DIRENT_ABORT; + next = (struct ext2_dir_entry *) (buf + offset + + dirent->rec_len); + next->inode = 0; + ext2fs_dirent_set_name_len(next, 0); + ext2fs_dirent_set_file_type(next, 0); + ls->err = ext2fs_set_rec_len(ls->fs, rec_len, next); + if (ls->err) + return DIRENT_ABORT; + return DIRENT_CHANGED; + } + + /* + * If we get this far, then the directory entry is not used. + * See if we can fit the request entry in. If so, do it. + */ + if (curr_rec_len < rec_len) + return ret; + dirent->inode = ls->inode; + ext2fs_dirent_set_name_len(dirent, ls->namelen); + strncpy(dirent->name, ls->name, ls->namelen); + if (ext2fs_has_feature_filetype(ls->sb)) + ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7); + + ls->done++; + return DIRENT_ABORT|DIRENT_CHANGED; +} + +static errcode_t add_dirent_to_buf(ext2_filsys fs, e2_blkcnt_t blockcnt, + char *buf, ext2_ino_t dir, + struct ext2_inode *diri, const char *name, + ext2_ino_t ino, int flags, blk64_t *pblkp) +{ + struct dir_context ctx; + struct link_struct ls; + errcode_t retval; + + retval = load_logical_dir_block(fs, dir, diri, blockcnt, pblkp, buf); + if (retval) + return retval; + ctx.errcode = 0; + ctx.func = link_proc; + ctx.dir = dir; + ctx.flags = DIRENT_FLAG_INCLUDE_EMPTY; + ctx.buf = buf; + ctx.priv_data = &ls; + + ls.fs = fs; + ls.name = name; + ls.namelen = strlen(name); + ls.inode = ino; + ls.flags = flags; + ls.done = 0; + ls.sb = fs->super; + ls.blocksize = fs->blocksize; + ls.err = 0; + + ext2fs_process_dir_block(fs, pblkp, blockcnt, 0, 0, &ctx); + if (ctx.errcode) + return ctx.errcode; + if (ls.err) + return ls.err; + if (!ls.done) + return EXT2_ET_DIR_NO_SPACE; + return 0; +} + +struct dx_hash_map { + __u32 hash; + int size; + int off; +}; + +static EXT2_QSORT_TYPE dx_hash_map_cmp(const void *ap, const void *bp) +{ + const struct dx_hash_map *a = ap, *b = bp; + + if (a->hash < b->hash) + return -1; + if (a->hash > b->hash) + return 1; + return 0; +} + +static errcode_t dx_move_dirents(ext2_filsys fs, struct dx_hash_map *map, + int count, void *from, void *to) +{ + struct ext2_dir_entry *de; + int i; + int rec_len = 0; + errcode_t retval; + int csum_size = 0; + void *base = to; + + if (ext2fs_has_feature_metadata_csum(fs->super)) + csum_size = sizeof(struct ext2_dir_entry_tail); + + for (i = 0; i < count; i++) { + de = (struct ext2_dir_entry *) ((char *)from + map[i].off); + rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(de)); + memcpy(to, de, rec_len); + retval = ext2fs_set_rec_len(fs, rec_len, to); + if (retval) + return retval; + to = (char *)to + rec_len; + } + /* + * Update rec_len of the last dir entry to stretch to the end of block + */ + to = (char *)to - rec_len; + rec_len = fs->blocksize - ((char *)to - (char *)base) - csum_size; + retval = ext2fs_set_rec_len(fs, rec_len, to); + if (retval) + return retval; + if (csum_size) + ext2fs_initialize_dirent_tail(fs, + EXT2_DIRENT_TAIL(base, fs->blocksize)); + return 0; +} + +static errcode_t dx_insert_entry(ext2_filsys fs, ext2_ino_t dir, + struct dx_lookup_info *info, int level, + __u32 hash, blk64_t lblk) +{ + int pcount; + struct ext2_dx_entry *top, *new; + + pcount = ext2fs_le16_to_cpu(info->frames[level].head->count); + top = info->frames[level].entries + pcount; + new = info->frames[level].at + 1; + memmove(new + 1, new, (char *)top - (char *)new); + new->hash = ext2fs_cpu_to_le32(hash); + new->block = ext2fs_cpu_to_le32(lblk); + info->frames[level].head->count = ext2fs_cpu_to_le16(pcount + 1); + return ext2fs_write_dir_block4(fs, info->frames[level].pblock, + info->frames[level].buf, 0, dir); +} + +static errcode_t dx_split_leaf(ext2_filsys fs, ext2_ino_t dir, + struct ext2_inode *diri, + struct dx_lookup_info *info, void *buf, + blk64_t leaf_pblk, blk64_t new_lblk, + blk64_t new_pblk) +{ + int hash_flags = diri->i_flags & EXT4_CASEFOLD_FL; + struct ext2_dir_entry *de; + void *buf2; + errcode_t retval = 0; + unsigned int rec_len; + unsigned int offset, move_size; + int i, count = 0; + struct dx_hash_map *map; + int continued; + __u32 minor_hash; + + retval = ext2fs_get_mem(fs->blocksize, &buf2); + if (retval) + return retval; + retval = ext2fs_get_array(fs->blocksize / 12, + sizeof(struct dx_hash_map), &map); + if (retval) { + ext2fs_free_mem(&buf2); + return retval; + } + for (offset = 0; offset < fs->blocksize; offset += rec_len) { + de = (struct ext2_dir_entry *) ((char *)buf + offset); + retval = ext2fs_get_rec_len(fs, de, &rec_len); + if (retval) + goto out; + if (ext2fs_dirent_name_len(de) > 0 && de->inode) { + map[count].off = offset; + map[count].size = rec_len; + retval = ext2fs_dirhash2(info->hash_alg, de->name, + ext2fs_dirent_name_len(de), + fs->encoding, hash_flags, + fs->super->s_hash_seed, + &(map[count].hash), + &minor_hash); + if (retval) + goto out; + count++; + } + } + qsort(map, count, sizeof(struct dx_hash_map), dx_hash_map_cmp); + move_size = 0; + /* Find place to split block */ + for (i = count - 1; i >= 0; i--) { + if (move_size + map[i].size / 2 > fs->blocksize / 2) + break; + move_size += map[i].size; + } + /* Let i be the first entry to move */ + i++; + /* Move selected directory entries to new block */ + retval = dx_move_dirents(fs, map + i, count - i, buf, buf2); + if (retval) + goto out; + retval = ext2fs_write_dir_block4(fs, new_pblk, buf2, 0, dir); + if (retval) + goto out; + /* Repack remaining entries in the old block */ + retval = dx_move_dirents(fs, map, i, buf, buf2); + if (retval) + goto out; + retval = ext2fs_write_dir_block4(fs, leaf_pblk, buf2, 0, dir); + if (retval) + goto out; + /* Update parent node */ + continued = map[i].hash == map[i-1].hash; + retval = dx_insert_entry(fs, dir, info, info->levels - 1, + map[i].hash + continued, new_lblk); +out: + ext2fs_free_mem(&buf2); + ext2fs_free_mem(&map); + return retval; +} + +static errcode_t dx_grow_tree(ext2_filsys fs, ext2_ino_t dir, + struct ext2_inode *diri, + struct dx_lookup_info *info, void *buf, + blk64_t leaf_pblk) +{ + int i; + errcode_t retval; + ext2_off64_t size = EXT2_I_SIZE(diri); + blk64_t lblk, pblk; + struct ext2_dir_entry *de; + struct ext2_dx_countlimit *head; + int csum_size = 0; + int count; + + if (ext2fs_has_feature_metadata_csum(fs->super)) + csum_size = sizeof(struct ext2_dx_tail); + + /* Find level which can accommodate new child */ + for (i = info->levels - 1; i >= 0; i--) + if (ext2fs_le16_to_cpu(info->frames[i].head->count) < + ext2fs_le16_to_cpu(info->frames[i].head->limit)) + break; + /* Need to grow tree depth? */ + if (i < 0 && info->levels >= ext2_dir_htree_level(fs)) + return EXT2_ET_DIR_NO_SPACE; + lblk = size / fs->blocksize; + size += fs->blocksize; + retval = ext2fs_inode_size_set(fs, diri, size); + if (retval) + return retval; + retval = ext2fs_fallocate(fs, + EXT2_FALLOCATE_FORCE_INIT | EXT2_FALLOCATE_ZERO_BLOCKS, + dir, diri, 0, lblk, 1); + if (retval) + return retval; + retval = ext2fs_write_inode(fs, dir, diri); + if (retval) + return retval; + retval = ext2fs_bmap2(fs, dir, diri, NULL, 0, lblk, NULL, &pblk); + if (retval) + return retval; + /* Only leaf addition needed? */ + if (i == (int)info->levels - 1) + return dx_split_leaf(fs, dir, diri, info, buf, leaf_pblk, + lblk, pblk); + + de = buf; + de->inode = 0; + ext2fs_dirent_set_name_len(de, 0); + ext2fs_dirent_set_file_type(de, 0); + retval = ext2fs_set_rec_len(fs, fs->blocksize, de); + if (retval) + return retval; + head = (struct ext2_dx_countlimit *) ((char *)buf + 8); + count = ext2fs_le16_to_cpu(info->frames[i+1].head->count); + /* Growing tree depth? */ + if (i < 0) { + struct ext2_dx_root_info *root; + + memcpy(head, info->frames[0].entries, + count * sizeof(struct ext2_dx_entry)); + head->limit = ext2fs_cpu_to_le16( + (fs->blocksize - (8 + csum_size)) / + sizeof(struct ext2_dx_entry)); + /* head->count gets set by memcpy above to correct value */ + + /* Now update tree root */ + info->frames[0].head->count = ext2fs_cpu_to_le16(1); + info->frames[0].entries[0].block = ext2fs_cpu_to_le32(lblk); + root = (struct ext2_dx_root_info *) + ((char *)info->frames[0].buf + EXT2_DX_ROOT_OFF); + root->indirect_levels++; + } else { + /* Splitting internal node in two */ + int count1 = count / 2; + int count2 = count - count1; + __u32 split_hash = ext2fs_le32_to_cpu(info->frames[i+1].entries[count1].hash); + + memcpy(head, info->frames[i+1].entries + count1, + count2 * sizeof(struct ext2_dx_entry)); + head->count = ext2fs_cpu_to_le16(count2); + head->limit = ext2fs_cpu_to_le16( + (fs->blocksize - (8 + csum_size)) / + sizeof(struct ext2_dx_entry)); + info->frames[i+1].head->count = ext2fs_cpu_to_le16(count1); + + /* Update parent node */ + retval = dx_insert_entry(fs, dir, info, i, split_hash, lblk); + if (retval) + return retval; + + } + /* Writeout split block / updated root */ + retval = ext2fs_write_dir_block4(fs, info->frames[i+1].pblock, + info->frames[i+1].buf, 0, dir); + if (retval) + return retval; + /* Writeout new tree block */ + retval = ext2fs_write_dir_block4(fs, pblk, buf, 0, dir); + if (retval) + return retval; + return 0; +} + +static errcode_t dx_link(ext2_filsys fs, ext2_ino_t dir, + struct ext2_inode *diri, const char *name, + ext2_ino_t ino, int flags) +{ + struct dx_lookup_info dx_info; + errcode_t retval; + void *blockbuf; + unsigned restart = 0; + blk64_t leaf_pblk; + + retval = ext2fs_get_mem(fs->blocksize, &blockbuf); + if (retval) + return retval; + + dx_info.name = name; + dx_info.namelen = strlen(name); +again: + retval = dx_lookup(fs, dir, diri, &dx_info); + if (retval) + goto free_buf; + + retval = add_dirent_to_buf(fs, + ext2fs_le32_to_cpu(dx_info.frames[dx_info.levels-1].at->block) & 0x0fffffff, + blockbuf, dir, diri, name, ino, flags, &leaf_pblk); + /* + * Success or error other than ENOSPC...? We are done. We may need upto + * two tries to add entry. One to split htree node and another to add + * new leaf block. + */ + if (restart >= dx_info.levels || retval != EXT2_ET_DIR_NO_SPACE) + goto free_frames; + retval = dx_grow_tree(fs, dir, diri, &dx_info, blockbuf, leaf_pblk); + if (retval) + goto free_frames; + /* Restart everything now that the tree is larger */ + restart++; + dx_release(&dx_info); + goto again; +free_frames: + dx_release(&dx_info); +free_buf: + ext2fs_free_mem(&blockbuf); + return retval; +} + +/* + * Note: the low 3 bits of the flags field are used as the directory + * entry filetype. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags) +{ + errcode_t retval; + struct link_struct ls; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) + return retval; + + if (inode.i_flags & EXT2_INDEX_FL) + return dx_link(fs, dir, &inode, name, ino, flags); + + ls.fs = fs; + ls.name = name; + ls.namelen = name ? strlen(name) : 0; + ls.inode = ino; + ls.flags = flags; + ls.done = 0; + ls.sb = fs->super; + ls.blocksize = fs->blocksize; + ls.err = 0; + + retval = ext2fs_dir_iterate2(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, + NULL, link_proc, &ls); + if (retval) + return retval; + if (ls.err) + return ls.err; + + if (!ls.done) + return EXT2_ET_DIR_NO_SPACE; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/link.o b/jni/e2fsprogs/lib/ext2fs/link.o new file mode 100755 index 0000000000000000000000000000000000000000..1aa3f87b1a1ff50f270f63d9492c5bf198f96ae5 GIT binary patch literal 12520 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 +#endif + +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#ifdef __MSDOS__ +#include +#endif +#include "et/com_err.h" +#include "ext2fs/ext2_io.h" + +#ifdef __linux__ + +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + +#define my_llseek lseek64 + +#else +#if defined(HAVE_LLSEEK) +#include + +#ifndef HAVE_LLSEEK_PROTOTYPE +extern long long llseek (int fd, long long offset, int origin); +#endif + +#define my_llseek llseek + +#else /* ! HAVE_LLSEEK */ + +#if SIZEOF_LONG == SIZEOF_LONG_LONG || _FILE_OFFSET_BITS+0 == 64 + +#define my_llseek lseek + +#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */ + +#include + +#ifndef __NR__llseek +#define __NR__llseek 140 +#endif + +#ifndef __i386__ +static int _llseek (unsigned int, unsigned long, + unsigned long, ext2_loff_t *, unsigned int); + +static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, + unsigned long, offset_low,ext2_loff_t *,result, + unsigned int, origin); +#endif + +static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin) +{ + ext2_loff_t result; + int retval; + +#ifndef __i386__ + retval = _llseek(fd, ((unsigned long long) offset) >> 32, +#else + retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32), +#endif + ((unsigned long long) offset) & 0xffffffff, + &result, origin); + return (retval == -1 ? (ext2_loff_t) retval : result); +} + +#endif /* SIZE_LONG == SIZEOF_LONG_LONG */ + +#endif /* HAVE_LLSEEK */ +#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */ + +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) +{ +#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG + return my_llseek (fd, offset, origin); +#else + ext2_loff_t result; + static int do_compat = 0; + + if (do_compat) + goto fallback; + + result = my_llseek (fd, offset, origin); + if (result == -1 && errno == ENOSYS) { + /* + * Just in case this code runs on top of an old kernel + * which does not support the llseek system call + */ + do_compat++; + fallback: + if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))) + return lseek(fd, (off_t) offset, origin); + errno = EINVAL; + return -1; + } + return result; +#endif +} + +#else /* !linux */ + +#ifndef EINVAL +#define EINVAL EXT2_ET_INVALID_ARGUMENT +#endif + +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) +{ +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + return lseek64 (fd, offset, origin); +#else + if ((sizeof(off_t) < sizeof(ext2_loff_t)) && + (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) { + errno = EINVAL; + return -1; + } + return lseek (fd, (off_t) offset, origin); +#endif +} + +#endif /* linux */ + + diff --git a/jni/e2fsprogs/lib/ext2fs/llseek.o b/jni/e2fsprogs/lib/ext2fs/llseek.o new file mode 100755 index 0000000000000000000000000000000000000000..9fc712ec1a36a88978a7118682c42a3ef24f7136 GIT binary patch literal 1144 zcmbtTJ4*vW5S~lo3xkTF2vH-L!p0?uK~fls~*N+F!*`oLTQcZb9WSlC%9*eWUY z7ihXb{(v@i3i=N$Ekc}Gcg^JzD+g}pn{VdZ$L!wO-12-t(?FR94^WR33y==fu`Zwv zU07MGz;pE^a9=%#t70Yk_}&d)AH7g2Rx*fn#Ci$Kud63B_gH&X4rX4!%o@4fu|sY< z`}y2hBFz#kEvN63UOQd|?Q~R&grhKl+>qo`U(P zFcE^!TC02zJcpA7mhjE|p5Q}G)0l#3Z{i1#>G#Yp_K(~Ke(J1VQA`FAyo3%%jI3p7FO0L9oH~177D(X*|80a!%r16 zfjO@28e8a(Eb>Ae>*DxN~n>il{Wre= BT_gYi literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/lookup.c b/jni/e2fsprogs/lib/ext2fs/lookup.c new file mode 100755 index 0000000..c1d802c --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/lookup.c @@ -0,0 +1,70 @@ +/* + * lookup.c --- ext2fs directory lookup operations + * + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct lookup_struct { + const char *name; + int len; + ext2_ino_t *inode; + int found; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int lookup_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct lookup_struct *ls = (struct lookup_struct *) priv_data; + + if (ls->len != ext2fs_dirent_name_len(dirent)) + return 0; + if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent))) + return 0; + *ls->inode = dirent->inode; + ls->found++; + return DIRENT_ABORT; +} + + +errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, + int namelen, char *buf, ext2_ino_t *inode) +{ + errcode_t retval; + struct lookup_struct ls; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + ls.name = name; + ls.len = namelen; + ls.inode = inode; + ls.found = 0; + + retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls); + if (retval) + return retval; + + return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND; +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/lookup.o b/jni/e2fsprogs/lib/ext2fs/lookup.o new file mode 100755 index 0000000000000000000000000000000000000000..fe5f695c31bfffb576cac3941b32c894d1c0931c GIT binary patch literal 1832 zcmbVN%}*0i5TEVx(LyCfL?9IwBZq=Z;arw(xqZx8Whhm~O zzlqX7$qTs^%(t4K%zpPOCbqS7A0Uk_J=$yo(`Zx748SYOZP}RDh4v4xl3Uy<*EdAz z#W?}4J6ji@QeE<0NvVb6!q__UNpFbihf<1o)vp)N*m$LSvTMj~3prUmv3gFIk~5@o zU(|;oDLJPAb4kYWOvt)pPXNpIbz$9lX!UhLZXA*m8T7Zf<<)F)VRRiiS==BH@<*=r z-qhlWU^LP@I4lp!!&r#KQ&u3{o&e!akKlDn(1%zj!#|Q9X^D-yyFJT}XLXJZw-g(1 zfiIr{e0ZhMJ<2Eg8EKiS_`P*YQ_PR9_LC%D)WNUPUiTt6cEM{FvK!YCci_kB7j3H_ z)XSE?ZJDhzz!OV1uv1mFqj}I)m*<;6oX@K24RCxP{MbHtk_ETngCZ6@Kkl?8?KSuV zhIN?1f7w61qPyXLD17x)%5A z8mpnrsxxtnf^uFp7LNv)EeAlxGP?f?>RVybebe#~{R~3iynNEe@c+z33={VVRoE)w zJLex^z{S%lSYn8G~hg=Lr84W(Ouv&Ky17>ZpWb*zwtf8?Ne-9fJ=S6WeV;;}>(;q}_ TZG>Q+f%v|*gj6GbYvca{R6`w0 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/mkdir.c b/jni/e2fsprogs/lib/ext2fs/mkdir.c new file mode 100755 index 0000000..437c8ff --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/mkdir.c @@ -0,0 +1,200 @@ +/* + * mkdir.c --- make a directory in the filesystem + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#ifndef EXT2_FT_DIR +#define EXT2_FT_DIR 2 +#endif + +errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, + const char *name) +{ + ext2_extent_handle_t handle; + errcode_t retval; + struct ext2_inode parent_inode, inode; + ext2_ino_t ino = inum; + ext2_ino_t scratch_ino; + blk64_t blk; + char *block = 0; + int inline_data = 0; + int drop_refcount = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* + * Create a new dir with inline data iff this feature is enabled + * and ino >= EXT2_FIRST_INO. + */ + if ((!ino || ino >= EXT2_FIRST_INO(fs->super)) && + ext2fs_has_feature_inline_data(fs->super)) + inline_data = 1; + + /* + * Allocate an inode, if necessary + */ + if (!ino) { + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, + 0, &ino); + if (retval) + goto cleanup; + } + + /* + * Allocate a data block for the directory + */ + memset(&inode, 0, sizeof(struct ext2_inode)); + if (!inline_data) { + retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino, + &inode, + 0), + NULL, &blk); + if (retval) + goto cleanup; + } + + /* + * Create a scratch template for the directory + */ + if (inline_data) + retval = ext2fs_new_dir_inline_data(fs, ino, parent, + inode.i_block); + else + retval = ext2fs_new_dir_block(fs, ino, parent, &block); + if (retval) + goto cleanup; + + /* + * Get the parent's inode, if necessary + */ + if (parent != ino) { + retval = ext2fs_read_inode(fs, parent, &parent_inode); + if (retval) + goto cleanup; + } else + memset(&parent_inode, 0, sizeof(parent_inode)); + + /* + * Create the inode structure.... + */ + inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); + inode.i_uid = inode.i_gid = 0; + if (inline_data) { + inode.i_flags |= EXT4_INLINE_DATA_FL; + inode.i_size = EXT4_MIN_INLINE_DATA_SIZE; + } else { + if (ext2fs_has_feature_extents(fs->super)) + inode.i_flags |= EXT4_EXTENTS_FL; + else + inode.i_block[0] = blk; + inode.i_size = fs->blocksize; + ext2fs_iblk_set(fs, &inode, 1); + } + inode.i_links_count = 2; + + /* + * Write out the inode and inode data block. The inode generation + * number is assigned by write_new_inode, which means that the call + * to write_dir_block must come after that. + */ + retval = ext2fs_write_new_inode(fs, ino, &inode); + if (retval) + goto cleanup; + if (inline_data) { + /* init "system.data" for new dir */ + retval = ext2fs_inline_data_init(fs, ino); + } else { + retval = ext2fs_write_dir_block4(fs, blk, block, 0, ino); + if (retval) + goto cleanup; + + if (ext2fs_has_feature_extents(fs->super)) { + retval = ext2fs_extent_open2(fs, ino, &inode, &handle); + if (retval) + goto cleanup; + retval = ext2fs_extent_set_bmap(handle, 0, blk, 0); + ext2fs_extent_free(handle); + if (retval) + goto cleanup; + } + } + + /* + * Update accounting.... + */ + if (!inline_data) + ext2fs_block_alloc_stats2(fs, blk, +1); + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); + drop_refcount = 1; + + /* + * Link the directory into the filesystem hierarchy + */ + if (name) { + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, + &scratch_ino); + if (!retval) { + retval = EXT2_ET_DIR_EXISTS; + name = 0; + goto cleanup; + } + if (retval != EXT2_ET_FILE_NOT_FOUND) + goto cleanup; + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); + if (retval) + goto cleanup; + } + + /* + * Update parent inode's counts + */ + if (parent != ino) { + /* reload parent inode due to inline data */ + retval = ext2fs_read_inode(fs, parent, &parent_inode); + if (retval) + goto cleanup; + parent_inode.i_links_count++; + retval = ext2fs_write_inode(fs, parent, &parent_inode); + if (retval) + goto cleanup; + } + drop_refcount = 0; + +cleanup: + if (block) + ext2fs_free_mem(&block); + if (drop_refcount) { + if (!inline_data) + ext2fs_block_alloc_stats2(fs, blk, -1); + ext2fs_inode_alloc_stats2(fs, ino, -1, 1); + } + return retval; + +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/mkdir.o b/jni/e2fsprogs/lib/ext2fs/mkdir.o new file mode 100755 index 0000000000000000000000000000000000000000..d757ab165b0ab7e983713d03fff2ff5f13725777 GIT binary patch literal 4232 zcmbtXO-xi*6h1Q#WKg7_)>?mWT;HPh&ddKVWkQyHPkv4V;CF-o-Ses&LQY|#s#y34$y}Ik>$^$B{8k;85 zhQDy*UeoOKc+>2R(NxHc_sr(cPygiyv`qz=NrwU@3fiC5WUW_LC;uM{s3h+VJ-Ms zeh&J;#Mwh;cKLvrg{`3z9>*5z5%fSll_tkV3xNlIDtq%Dhd&M78~1u;t%dDoaS8jJ;cjCY{K7wQc6uDY71uO;%!ALkLF@kcps&kwxeXcf=>9+E zJvf%(7w2kB=4w6ud)`NGao@)|&V3qkJ#L5JD%9S_UA#5cRqJWp?4yY;aJS`WXmsso ze7>Vm&W}&Vl27uwsw1DI>_iRj<3q~6Ec|rt>ml+qC-2MA-70jepp$Pli}|b0{fRng zHM5Jz2Xk-?uhAGnq$&1`^WMq#{Tq#{{J6#T1@pqcytG-a+X}hBV0+1L7M~(_xKDBK z<@Ip|x~lH3!;gSbdVlQG%nZ5ac!=$cpD!%I4(bZ^v0;O8_FcbA3;G-+&4~sRZ=^ESv z*YXy#m@|BBPvP&g=F)mbK7SCtEz38Lw{#ahqaFTo9G?MK{o#V_4{%E4TD(Qr%OTe% zWgO+X_RHAydM3kp`y8*}s8G)hI6DnlX6AztUo|ymW_FIKGj27)wa2k=e-kmG4l=SQ zEaaT`Ch#MuZPm}5nku;yFO6+0zZ1szUKGx`;r_^c>2a&D^1v*vUhTe#UOYKxSii2F zphpY1k38WhS87Xu&LiDWn)3$z~(wg->HI1l7S49}G= z@_f?d*;D7I79hJMK2?py$@;W$s%~H4TGjPU-}sDFb)6qTJw5s3_Z=*jx&fX~);DzH zw}tVKc#jd_FNyQgZCD7tivC`6lNscF0X`_87x6E_DUEQA63;2D>VkO2+d+eB5x3o=i}$ArJh=)u|2VqwL@MBSE8uTb;QzXU{t9p&dvLDS zS&Hxd*z;g~v$GW6r!;(vhF{R|It{<3;afF)R>QSF<>80 z8#SI44d=$D#$Ll&G5>Z2V(!*(?g?s)X*k!I8lP+UP6c9~)9_a`{E3FEp2gw@`J~yO zS2g{^8opb@Cp3JIhTqq4J)h4te6Ob8BKr&5-KXJaHC*>UqT#y#inAI#GUbA;Q*tU? z^`8r6xaxBhOxTf7FlCRVDA*T|M(tRNu;~~`TH#nE9J8(dP%4CVI7LxAnzT2>y^$eH z+Yg44)_@&KT}s#%7(kR%OwpnKa6)Y&@%YfCVYPEKnaAplhK4DbN<{3Kk`5$n+k)Bk zeK^(+U*i3?buk`_C>VYYsddc0Y{8n<8;SP~Q7{%y*}-?;KX)*h3h`cqYY$ojiBQy5 zXQUHsO+ic}3@PApBAl|V3UG;L!VXC%NdzA3qaeacg?cfMMtPPQR=#SPRw6x{E@H=< z^*E2JVY)AoLGjg2`$vL@WgY$B=_2Y@ zKFt!U2HD&?^rD6a)Jq2c@-kNb3v5cQU*x-yTm0=%I`}MOW+_a=vPpMK`##8d$ukf2 z2H8#KD9;D~r-+B%n|QDMSM!2~v0RO|@_?j3ol|=MV!>Ehn&_}RKdcnxto&E-Us$-s jKQDiDR3G7UOsUSR_~S5MZkxH&(!TnAU?2Hx`T73<5hoV( literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/mkjournal.c b/jni/e2fsprogs/lib/ext2fs/mkjournal.c new file mode 100755 index 0000000..54772dd --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/mkjournal.c @@ -0,0 +1,654 @@ +/* + * mkjournal.c --- make a journal for a filesystem + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#include "ext2_fs.h" +#include "e2p/e2p.h" +#include "ext2fs.h" + +#include "kernel-jbd.h" + +/* + * This function automatically sets up the journal superblock and + * returns it as an allocated block. + */ +errcode_t ext2fs_create_journal_superblock2(ext2_filsys fs, + struct ext2fs_journal_params *jparams, + int flags, char **ret_jsb) +{ + errcode_t retval; + journal_superblock_t *jsb; + + if (jparams->num_journal_blocks < JBD2_MIN_JOURNAL_BLOCKS) + return EXT2_ET_JOURNAL_TOO_SMALL; + + if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) + return retval; + + memset (jsb, 0, fs->blocksize); + + jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER); + if (flags & EXT2_MKJOURNAL_V1_SUPER) + jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V1); + else + jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2); + jsb->s_blocksize = htonl(fs->blocksize); + jsb->s_maxlen = htonl(jparams->num_journal_blocks + jparams->num_fc_blocks); + jsb->s_nr_users = htonl(1); + jsb->s_first = htonl(1); + jsb->s_sequence = htonl(1); + jsb->s_num_fc_blks = htonl(jparams->num_fc_blocks); + memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); + /* + * If we're creating an external journal device, we need to + * adjust these fields. + */ + if (ext2fs_has_feature_journal_dev(fs->super)) { + jsb->s_nr_users = 0; + jsb->s_first = htonl(ext2fs_journal_sb_start(fs->blocksize) + 1); + } + + *ret_jsb = (char *) jsb; + return 0; +} + +errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, __u32 num_blocks, + int flags, char **ret_sb) +{ + struct ext2fs_journal_params jparams; + + jparams.num_journal_blocks = num_blocks; + jparams.num_fc_blocks = 0; + + return ext2fs_create_journal_superblock2(fs, &jparams, flags, ret_sb); +} + +/* + * This function writes a journal using POSIX routines. It is used + * for creating external journals and creating journals on live + * filesystems. + */ +static errcode_t write_journal_file(ext2_filsys fs, char *filename, + struct ext2fs_journal_params *jparams, + int flags) +{ + errcode_t retval; + char *buf = 0; + int fd, ret_size; + blk_t i; + + if ((retval = ext2fs_create_journal_superblock2(fs, jparams, flags, + &buf))) + return retval; + + /* Open the device or journal file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + retval = errno; + goto errfree; + } + + /* Write the superblock out */ + retval = EXT2_ET_SHORT_WRITE; + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { + retval = errno; + goto errout; + } + if (ret_size != (int) fs->blocksize) + goto errout; + memset(buf, 0, fs->blocksize); + + if (flags & EXT2_MKJOURNAL_LAZYINIT) + goto success; + + for (i = 1; i < jparams->num_journal_blocks + jparams->num_fc_blocks; i++) { + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { + retval = errno; + goto errout; + } + if (ret_size != (int) fs->blocksize) + goto errout; + } + +success: + retval = 0; +errout: + close(fd); +errfree: + ext2fs_free_mem(&buf); + return retval; +} + +/* + * Convenience function which zeros out _num_ blocks starting at + * _blk_. In case of an error, the details of the error is returned + * via _ret_blk_ and _ret_count_ if they are non-NULL pointers. + * Returns 0 on success, and an error code on an error. + * + * As a special case, if the first argument is NULL, then it will + * attempt to free the static zeroizing buffer. (This is to keep + * programs that check for memory leaks happy.) + */ +#define MAX_STRIDE_LENGTH (4194304 / (int) fs->blocksize) +errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num, + blk64_t *ret_blk, int *ret_count) +{ + int j, count; + static void *buf; + static int stride_length; + errcode_t retval; + + /* If fs is null, clean up the static buffer and return */ + if (!fs) { + if (buf) { + free(buf); + buf = 0; + stride_length = 0; + } + return 0; + } + + /* Deal with zeroing less than 1 block */ + if (num <= 0) + return 0; + + /* Try a zero out command, if supported */ + retval = io_channel_zeroout(fs->io, blk, num); + if (retval == 0) + return 0; + + /* Allocate the zeroizing buffer if necessary */ + if (num > stride_length && stride_length < MAX_STRIDE_LENGTH) { + void *p; + int new_stride = num; + + if (new_stride > MAX_STRIDE_LENGTH) + new_stride = MAX_STRIDE_LENGTH; + p = realloc(buf, fs->blocksize * new_stride); + if (!p) + return EXT2_ET_NO_MEMORY; + buf = p; + stride_length = new_stride; + memset(buf, 0, fs->blocksize * stride_length); + } + /* OK, do the write loop */ + j=0; + while (j < num) { + if (blk % stride_length) { + count = stride_length - (blk % stride_length); + if (count > (num - j)) + count = num - j; + } else { + count = num - j; + if (count > stride_length) + count = stride_length; + } + retval = io_channel_write_blk64(fs->io, blk, count, buf); + if (retval) { + if (ret_count) + *ret_count = count; + if (ret_blk) + *ret_blk = blk; + return retval; + } + j += count; blk += count; + } + return 0; +} + +errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num, + blk_t *ret_blk, int *ret_count) +{ + blk64_t ret_blk2; + errcode_t retval; + + retval = ext2fs_zero_blocks2(fs, blk, num, &ret_blk2, ret_count); + if (retval) + *ret_blk = (blk_t) ret_blk2; + return retval; +} + +/* + * Calculate the initial goal block to be roughly at the middle of the + * filesystem. Pick a group that has the largest number of free + * blocks. + */ +static blk64_t get_midpoint_journal_block(ext2_filsys fs) +{ + dgrp_t group, start, end, i, log_flex; + + group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) - + fs->super->s_first_data_block) / 2); + log_flex = 1U << fs->super->s_log_groups_per_flex; + if (fs->super->s_log_groups_per_flex && (group > log_flex)) { + group = group & ~(log_flex - 1); + while ((group < fs->group_desc_count) && + ext2fs_bg_free_blocks_count(fs, group) == 0) + group++; + if (group == fs->group_desc_count) + group = 0; + start = group; + } else + start = (group > 0) ? group-1 : group; + end = ((group+1) < fs->group_desc_count) ? group+1 : group; + group = start; + for (i = start + 1; i <= end; i++) + if (ext2fs_bg_free_blocks_count(fs, i) > + ext2fs_bg_free_blocks_count(fs, group)) + group = i; + return ext2fs_group_first_block2(fs, group); +} + +/* + * This function creates a journal using direct I/O routines. + */ +static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, + struct ext2fs_journal_params *jparams, + blk64_t goal, int flags) +{ + char *buf; + errcode_t retval; + struct ext2_inode inode; + unsigned long long inode_size; + int falloc_flags = EXT2_FALLOCATE_FORCE_INIT; + blk64_t zblk; + + if ((retval = ext2fs_create_journal_superblock2(fs, jparams, flags, + &buf))) + return retval; + + if ((retval = ext2fs_read_bitmaps(fs))) + goto out2; + + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) + goto out2; + + if (inode.i_blocks > 0) { + retval = EEXIST; + goto out2; + } + + if (goal == ~0ULL) + goal = get_midpoint_journal_block(fs); + + if (ext2fs_has_feature_extents(fs->super)) + inode.i_flags |= EXT4_EXTENTS_FL; + + if (!(flags & EXT2_MKJOURNAL_LAZYINIT)) + falloc_flags |= EXT2_FALLOCATE_ZERO_BLOCKS; + + inode_size = (unsigned long long)fs->blocksize * + (jparams->num_journal_blocks + jparams->num_fc_blocks); + inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); + inode.i_links_count = 1; + inode.i_mode = LINUX_S_IFREG | 0600; + retval = ext2fs_inode_size_set(fs, &inode, inode_size); + if (retval) + goto out2; + + retval = ext2fs_fallocate(fs, falloc_flags, journal_ino, + &inode, goal, 0, + jparams->num_journal_blocks + jparams->num_fc_blocks); + if (retval) + goto out2; + + if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode))) + goto out2; + + retval = ext2fs_bmap2(fs, journal_ino, &inode, NULL, 0, 0, NULL, &zblk); + if (retval) + goto out2; + + retval = io_channel_write_blk64(fs->io, zblk, 1, buf); + if (retval) + goto out2; + + 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); + +out2: + ext2fs_free_mem(&buf); + return retval; +} + +/* + * Find a reasonable journal file size (in blocks) given the number of blocks + * in the filesystem. For very small filesystems, it is not reasonable to + * have a journal that fills more than half of the filesystem. + * + * n.b. comments assume 4k blocks + */ +int ext2fs_default_journal_size(__u64 num_blocks) +{ + if (num_blocks < 2048) + return -1; + if (num_blocks < 32768) /* 128 MB */ + return (1024); /* 4 MB */ + if (num_blocks < 256*1024) /* 1 GB */ + return (4096); /* 16 MB */ + if (num_blocks < 512*1024) /* 2 GB */ + return (8192); /* 32 MB */ + if (num_blocks < 4096*1024) /* 16 GB */ + return (16384); /* 64 MB */ + if (num_blocks < 8192*1024) /* 32 GB */ + return (32768); /* 128 MB */ + if (num_blocks < 16384*1024) /* 64 GB */ + return (65536); /* 256 MB */ + if (num_blocks < 32768*1024) /* 128 GB */ + return (131072); /* 512 MB */ + return 262144; /* 1 GB */ +} + +errcode_t ext2fs_get_journal_params(struct ext2fs_journal_params *params, + ext2_filsys fs) +{ + blk_t total_blks; + int ret; + + memset(params, 0, sizeof(*params)); + if (ext2fs_has_feature_journal_dev(fs->super)) { + total_blks = ext2fs_blocks_count(fs->super); + if (total_blks < JBD2_MIN_JOURNAL_BLOCKS) + return EXT2_ET_JOURNAL_TOO_SMALL; + + if (!ext2fs_has_feature_fast_commit(fs->super)) { + params->num_journal_blocks = total_blks; + params->num_fc_blocks = 0; + return 0; + } + params->num_journal_blocks = ext2fs_blocks_count(fs->super) * + EXT2_JOURNAL_TO_FC_BLKS_RATIO / + (EXT2_JOURNAL_TO_FC_BLKS_RATIO + 1); + if (JBD2_MIN_JOURNAL_BLOCKS > params->num_journal_blocks) + params->num_journal_blocks = JBD2_MIN_JOURNAL_BLOCKS; + params->num_fc_blocks = total_blks - params->num_journal_blocks; + return 0; + } + + ret = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super)); + if (ret < 0) + return EXT2_ET_JOURNAL_TOO_SMALL; + + params->num_journal_blocks = ret; + if (ext2fs_has_feature_fast_commit(fs->super)) + params->num_fc_blocks = params->num_journal_blocks / + EXT2_JOURNAL_TO_FC_BLKS_RATIO; + return 0; +} + +int ext2fs_journal_sb_start(int blocksize) +{ + if (blocksize == EXT2_MIN_BLOCK_SIZE) + return 2; + return 1; +} + +/* + * This function adds a journal device to a filesystem + */ +errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) +{ + struct stat st; + errcode_t retval; + char buf[SUPERBLOCK_SIZE]; + journal_superblock_t *jsb; + int start; + __u32 i, nr_users; + + /* Make sure the device exists and is a block device */ + if (stat(journal_dev->device_name, &st) < 0) + return errno; + + if (!S_ISBLK(st.st_mode)) + return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ + + /* Get the journal superblock */ + start = ext2fs_journal_sb_start(journal_dev->blocksize); + if ((retval = io_channel_read_blk64(journal_dev->io, start, + -SUPERBLOCK_SIZE, + buf))) + return retval; + + jsb = (journal_superblock_t *) buf; + if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) || + (jsb->s_header.h_blocktype != (unsigned) ntohl(JBD2_SUPERBLOCK_V2))) + return EXT2_ET_NO_JOURNAL_SB; + + if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; + + /* Check and see if this filesystem has already been added */ + nr_users = ntohl(jsb->s_nr_users); + if (nr_users > JBD2_USERS_MAX) + return EXT2_ET_CORRUPT_JOURNAL_SB; + for (i=0; i < nr_users; i++) { + if (memcmp(fs->super->s_uuid, + &jsb->s_users[i*16], 16) == 0) + break; + } + if (i >= nr_users) { + memcpy(&jsb->s_users[nr_users*16], + fs->super->s_uuid, 16); + jsb->s_nr_users = htonl(nr_users+1); + } + + /* Writeback the journal superblock */ + if ((retval = io_channel_write_blk64(journal_dev->io, start, + -SUPERBLOCK_SIZE, buf))) + return retval; + + fs->super->s_journal_inum = 0; + fs->super->s_journal_dev = st.st_rdev; + memcpy(fs->super->s_journal_uuid, jsb->s_uuid, + sizeof(fs->super->s_journal_uuid)); + memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks)); + ext2fs_set_feature_journal(fs->super); + ext2fs_mark_super_dirty(fs); + return 0; +} + +/* + * This function adds a journal inode to a filesystem, using either + * POSIX routines if the filesystem is mounted, or using direct I/O + * functions if it is not. + */ +errcode_t ext2fs_add_journal_inode3(ext2_filsys fs, struct ext2fs_journal_params *jparams, + blk64_t goal, int flags) +{ + errcode_t retval; + ext2_ino_t journal_ino; + struct stat st; + char jfile[1024]; + int mount_flags; + int fd = -1; + + if (flags & EXT2_MKJOURNAL_NO_MNT_CHECK) + mount_flags = 0; + else if ((retval = ext2fs_check_mount_point(fs->device_name, + &mount_flags, + jfile, sizeof(jfile)-10))) + return retval; + + if (mount_flags & EXT2_MF_MOUNTED) { +#if HAVE_EXT2_IOCTLS + int f = 0; +#endif + strcat(jfile, "/.journal"); + + /* + * If .../.journal already exists, make sure any + * immutable or append-only flags are cleared. + */ +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) + (void) chflags (jfile, 0); +#else +#if HAVE_EXT2_IOCTLS + fd = open(jfile, O_RDONLY); + if (fd >= 0) { + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); + close(fd); + if (retval) + return errno; + } +#endif +#endif + + /* Create the journal file */ + 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... Ignore it. */ + flags &= ~EXT2_MKJOURNAL_LAZYINIT; + + if ((retval = write_journal_file(fs, jfile, jparams, flags))) + goto errout; + + /* Get inode number of the journal file */ + if (fstat(fd, &st) < 0) { + retval = errno; + goto errout; + } + +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) + retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); +#else +#if HAVE_EXT2_IOCTLS + if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) { + retval = errno; + goto errout; + } + f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); +#endif +#endif + if (retval) { + retval = errno; + goto errout; + } + + if (close(fd) < 0) { + retval = errno; + fd = -1; + goto errout; + } + journal_ino = st.st_ino; + memset(fs->super->s_jnl_blocks, 0, + sizeof(fs->super->s_jnl_blocks)); + } else { + if ((mount_flags & EXT2_MF_BUSY) && + !(fs->flags & EXT2_FLAG_EXCLUSIVE)) { + retval = EBUSY; + goto errout; + } + journal_ino = EXT2_JOURNAL_INO; + if ((retval = write_journal_inode(fs, journal_ino, + jparams, goal, flags))) + return retval; + } + + fs->super->s_journal_inum = journal_ino; + fs->super->s_journal_dev = 0; + memset(fs->super->s_journal_uuid, 0, + sizeof(fs->super->s_journal_uuid)); + ext2fs_set_feature_journal(fs->super); + + ext2fs_mark_super_dirty(fs); + return 0; +errout: + if (fd >= 0) + close(fd); + return retval; +} + +errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks, + blk64_t goal, int flags) +{ + struct ext2fs_journal_params jparams; + + jparams.num_journal_blocks = num_blocks; + jparams.num_fc_blocks = 0; + + return ext2fs_add_journal_inode3(fs, &jparams, goal, flags); +} + +errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags) +{ + return ext2fs_add_journal_inode2(fs, num_blocks, ~0ULL, flags); +} + + +#ifdef DEBUG +main(int argc, char **argv) +{ + errcode_t retval; + char *device_name; + ext2_filsys fs; + + if (argc < 2) { + fprintf(stderr, "Usage: %s filesystem\n", argv[0]); + exit(1); + } + device_name = argv[1]; + + retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, + unix_io_manager, &fs); + if (retval) { + com_err(argv[0], retval, "while opening %s", device_name); + exit(1); + } + + retval = ext2fs_add_journal_inode(fs, JBD2_MIN_JOURNAL_BLOCKS, 0); + if (retval) { + com_err(argv[0], retval, "while adding journal to %s", + device_name); + exit(1); + } + retval = ext2fs_flush(fs); + if (retval) { + printf("Warning, had trouble writing out superblocks.\n"); + } + ext2fs_close_free(&fs); + exit(0); + +} +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/mkjournal.o b/jni/e2fsprogs/lib/ext2fs/mkjournal.o new file mode 100755 index 0000000000000000000000000000000000000000..eab2064a988b33c5ef12aa4eee90d3556cb898ce GIT binary patch literal 12760 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 R@{wg!?xPgLBUkbG{{!t=h^+ts literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/mmp.c b/jni/e2fsprogs/lib/ext2fs/mmp.c new file mode 100755 index 0000000..eb94170 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/mmp.c @@ -0,0 +1,488 @@ +/* + * Helper functions for multiple mount protection (MMP). + * + * Copyright (C) 2011 Whamcloud, Inc. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ +#endif + +#include "config.h" + +#if HAVE_UNISTD_H +#include +#endif +#include + +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" + +#ifndef O_DIRECT +#define O_DIRECT 0 +#endif + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#ifndef CONFIG_MMP +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +#endif + +errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf) +{ +#ifdef CONFIG_MMP + struct mmp_struct *mmp_cmp; + errcode_t retval = 0; + + if ((mmp_blk <= fs->super->s_first_data_block) || + (mmp_blk >= ext2fs_blocks_count(fs->super))) + return EXT2_ET_MMP_BAD_BLOCK; + + /* ext2fs_open() reserves fd0,1,2 to avoid stdio collision, so checking + * mmp_fd <= 0 is OK to validate that the fd is valid. This opens its + * own fd to read the MMP block to ensure that it is using O_DIRECT, + * regardless of how the io_manager is doing reads, to avoid caching of + * the MMP block by the io_manager or the VM. It needs to be fresh. */ + if (fs->mmp_fd <= 0) { + struct stat st; + int flags = O_RDONLY | O_DIRECT; + + /* + * There is no reason for using O_DIRECT if we're working with + * regular file. Disabling it also avoids problems with + * alignment when the device of the host file system has sector + * size larger than blocksize of the fs we're working with. + */ + if (stat(fs->device_name, &st) == 0 && + S_ISREG(st.st_mode)) + flags &= ~O_DIRECT; + + fs->mmp_fd = open(fs->device_name, flags); + if (fs->mmp_fd < 0) { + retval = EXT2_ET_MMP_OPEN_DIRECT; + goto out; + } + } + + if (fs->mmp_cmp == NULL) { + int align = ext2fs_get_dio_alignment(fs->mmp_fd); + + retval = ext2fs_get_memalign(fs->blocksize, align, + &fs->mmp_cmp); + if (retval) + return retval; + } + + if ((blk64_t) 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; + + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_mmp_csum_verify(fs, mmp_cmp)) + retval = EXT2_ET_MMP_CSUM_INVALID; + +#ifdef WORDS_BIGENDIAN + 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 != EXT4_MMP_MAGIC) { + retval = EXT2_ET_MMP_MAGIC_INVALID; + goto out; + } + +out: + return retval; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf) +{ +#ifdef CONFIG_MMP + 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; + + if (fs->super->s_mmp_block < fs->super->s_first_data_block || + fs->super->s_mmp_block > ext2fs_blocks_count(fs->super)) + return EXT2_ET_MMP_BAD_BLOCK; + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_mmp(mmp_s); +#endif + + retval = ext2fs_mmp_csum_set(fs, mmp_s); + if (retval) + return retval; + + /* 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_blk64(fs->io, mmp_blk, -(int)sizeof(struct mmp_struct), buf); + +#ifdef WORDS_BIGENDIAN + ext2fs_swap_mmp(mmp_s); +#endif + + /* Make sure the block gets to disk quickly */ + io_channel_flush(fs->io); + return retval; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +#ifdef HAVE_SRANDOM +#define srand(x) srandom(x) +#define rand() random() +#endif + +unsigned ext2fs_mmp_new_seq(void) +{ +#ifdef CONFIG_MMP + unsigned new_seq; + struct timeval tv; + unsigned long pid = getpid(); + + gettimeofday(&tv, 0); + pid = (pid >> 16) | ((pid & 0xFFFF) << 16); + srand(pid ^ 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 > EXT4_MMP_SEQ_MAX); + + return new_seq; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +#ifdef CONFIG_MMP +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 = EXT4_MMP_MAGIC; + mmp_s->mmp_seq = EXT4_MMP_SEQ_CLEAN; + mmp_s->mmp_time = 0; +#ifdef HAVE_GETHOSTNAME + gethostname((char *) mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename)); +#else + mmp_s->mmp_nodename[0] = '\0'; +#endif + strncpy((char *) 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 < EXT4_MMP_MIN_CHECK_INTERVAL) + mmp_s->mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL; + + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); +out: + return retval; +} +#endif + +errcode_t ext2fs_mmp_update(ext2_filsys fs) +{ + return ext2fs_mmp_update2(fs, 0); +} + +errcode_t ext2fs_mmp_clear(ext2_filsys fs) +{ +#ifdef CONFIG_MMP + errcode_t retval = 0; + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + retval = ext2fs_mmp_reset(fs); + + return retval; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +errcode_t ext2fs_mmp_init(ext2_filsys fs) +{ +#ifdef CONFIG_MMP + struct ext2_super_block *sb = fs->super; + blk64_t mmp_block; + errcode_t retval; + + if (sb->s_mmp_update_interval == 0) + sb->s_mmp_update_interval = EXT4_MMP_UPDATE_INTERVAL; + /* This is probably excessively large, but who knows? */ + else if (sb->s_mmp_update_interval > EXT4_MMP_MAX_UPDATE_INTERVAL) + return EXT2_ET_INVALID_ARGUMENT; + + if (fs->mmp_buf == NULL) { + retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); + if (retval) + goto out; + } + + retval = ext2fs_alloc_block2(fs, 0, fs->mmp_buf, &mmp_block); + if (retval) + goto out; + + sb->s_mmp_block = mmp_block; + + retval = ext2fs_mmp_reset(fs); + if (retval) + goto out; + +out: + return retval; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +#ifndef min +#define min(x, y) ((x) < (y) ? (x) : (y)) +#endif + +/* + * Make sure that the fs is not mounted or being fsck'ed while opening the fs. + */ +errcode_t ext2fs_mmp_start(ext2_filsys fs) +{ +#ifdef CONFIG_MMP + 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 < EXT4_MMP_MIN_CHECK_INTERVAL) + mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL; + + seq = mmp_s->mmp_seq; + if (seq == EXT4_MMP_SEQ_CLEAN) + goto clean_seq; + if (seq == EXT4_MMP_SEQ_FSCK) { + retval = EXT2_ET_MMP_FSCK_ON; + goto mmp_error; + } + + if (seq > EXT4_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(min(mmp_check_interval * 2 + 1, mmp_check_interval + 60)); + + 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(); +#ifdef HAVE_GETHOSTNAME + gethostname((char *) mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename)); +#else + strcpy((char *) mmp_s->mmp_nodename, "unknown host"); +#endif + strncpy((char *) 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(min(2 * mmp_check_interval + 1, mmp_check_interval + 60)); + + 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 = EXT4_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; +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +/* + * 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) +{ +#ifdef CONFIG_MMP + struct mmp_struct *mmp, *mmp_cmp; + errcode_t retval = 0; + + if (!ext2fs_has_feature_mmp(fs->super) || + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP) || + (fs->mmp_buf == NULL) || (fs->mmp_cmp == NULL)) + goto mmp_error; + + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, NULL); + 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; + } + + mmp_cmp->mmp_seq = EXT4_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; + } + + return retval; +#else + if (!ext2fs_has_feature_mmp(fs->super) || + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP)) + return 0; + + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +#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_update2(ext2_filsys fs, int immediately) +{ +#ifdef CONFIG_MMP + struct mmp_struct *mmp, *mmp_cmp; + struct timeval tv; + errcode_t retval = 0; + + if (!ext2fs_has_feature_mmp(fs->super) || + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP)) + return 0; + + gettimeofday(&tv, 0); + if (!immediately && + 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 = EXT4_MMP_SEQ_FSCK; + retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf); + +mmp_error: + return retval; +#else + if (!ext2fs_has_feature_mmp(fs->super) || + !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP)) + return 0; + + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif diff --git a/jni/e2fsprogs/lib/ext2fs/mmp.o b/jni/e2fsprogs/lib/ext2fs/mmp.o new file mode 100755 index 0000000000000000000000000000000000000000..84eb0c241554c2162f9081d768138d0056bec39d GIT binary patch literal 7648 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/namei.c b/jni/e2fsprogs/lib/ext2fs/namei.c new file mode 100755 index 0000000..1064ab5 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/namei.c @@ -0,0 +1,227 @@ +/* + * namei.c --- ext2fs directory lookup operations + * + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +/* #define NAMEI_DEBUG */ + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, + const char *pathname, size_t pathlen, int follow, + int link_count, char *buf, ext2_ino_t *res_inode); + +static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, + ext2_ino_t inode, int link_count, + char *buf, ext2_ino_t *res_inode) +{ + char *pathname; + char *buffer = 0; + errcode_t retval; + struct ext2_inode ei; + blk64_t blk; + +#ifdef NAMEI_DEBUG + printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", + root, dir, inode, link_count); + +#endif + retval = ext2fs_read_inode (fs, inode, &ei); + if (retval) return retval; + if (!LINUX_S_ISLNK (ei.i_mode)) { + *res_inode = inode; + return 0; + } + if (link_count++ >= EXT2FS_MAX_NESTED_LINKS) + return EXT2_ET_SYMLINK_LOOP; + + if (ext2fs_is_fast_symlink(&ei)) + pathname = (char *)&(ei.i_block[0]); + else if (ei.i_flags & EXT4_INLINE_DATA_FL) { + retval = ext2fs_get_memzero(ei.i_size, &buffer); + if (retval) + return retval; + + retval = ext2fs_inline_data_get(fs, inode, + &ei, buffer, NULL); + if (retval) { + ext2fs_free_mem(&buffer); + return retval; + } + pathname = buffer; + } else { + retval = ext2fs_bmap2(fs, inode, &ei, NULL, 0, 0, NULL, &blk); + if (retval) + return retval; + + retval = ext2fs_get_mem(fs->blocksize, &buffer); + if (retval) + return retval; + + retval = io_channel_read_blk64(fs->io, blk, 1, buffer); + if (retval) { + ext2fs_free_mem(&buffer); + return retval; + } + pathname = buffer; + } + + retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, + link_count, buf, res_inode); + if (buffer) + ext2fs_free_mem(&buffer); + return retval; +} + +/* + * This routine interprets a pathname in the context of the current + * directory and the root directory, and returns the inode of the + * containing directory, and a pointer to the filename of the file + * (pointing into the pathname) and the length of the filename. + */ +static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, + const char *pathname, int pathlen, + int link_count, char *buf, + const char **name, int *namelen, + ext2_ino_t *res_inode) +{ + char c; + const char *thisname; + int len; + ext2_ino_t inode; + errcode_t retval; + + if ((c = *pathname) == '/') { + dir = root; + pathname++; + pathlen--; + } + while (1) { + thisname = pathname; + for (len=0; --pathlen >= 0;len++) { + c = *(pathname++); + if (c == '/') + break; + } + if (pathlen < 0) + break; + retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode); + if (retval) return retval; + retval = follow_link (fs, root, dir, inode, + link_count, buf, &dir); + if (retval) return retval; + } + *name = thisname; + *namelen = len; + *res_inode = dir; + return 0; +} + +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, + const char *pathname, size_t pathlen, int follow, + int link_count, char *buf, ext2_ino_t *res_inode) +{ + const char *base_name; + int namelen; + ext2_ino_t dir, inode; + errcode_t retval; + +#ifdef NAMEI_DEBUG + printf("open_namei: root=%lu, dir=%lu, path=%.*s, lc=%d\n", + root, base, pathlen, pathname, link_count); +#endif + retval = dir_namei(fs, root, base, pathname, pathlen, + link_count, buf, &base_name, &namelen, &dir); + if (retval) return retval; + if (!namelen) { /* special case: '/usr/' etc */ + *res_inode=dir; + return 0; + } + retval = ext2fs_lookup (fs, dir, base_name, namelen, buf, &inode); + if (retval) + return retval; + if (follow) { + retval = follow_link(fs, root, dir, inode, link_count, + buf, &inode); + if (retval) + return retval; + } +#ifdef NAMEI_DEBUG + printf("open_namei: (link_count=%d) returns %lu\n", + link_count, inode); +#endif + *res_inode = inode; + return 0; +} + +errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0, + buf, inode); + + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0, + buf, inode); + + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t inode, ext2_ino_t *res_inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode); + + ext2fs_free_mem(&buf); + return retval; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/namei.o b/jni/e2fsprogs/lib/ext2fs/namei.o new file mode 100755 index 0000000000000000000000000000000000000000..26fdc14dc7577b2a9e479c4d293460bc15c8b197 GIT binary patch literal 4544 zcmds3U2IfE6rSDN(yc8m&}z~CY*h>ebp=FzqKP+Yg=$Dc2qqfau1kAMH*9zNvj_zf zo2-dE+DOD0g+*H2?Teb2xSMFG>4OgvBR&{kG)sTrHfn-A-A%0PcjnIQPH(%2@y#LZ z%zSg^obQ}_&Y8aP+<|>=my5~aVqdVrPNIyBRTtJeU+SzJlDQezwWZT*l1nkycwF;Z z7iXGMAH|wdm$W8pBGzanG{5C>>DeurcYg>jd~)04D*ttwvBR)Y+XAc~SR&@N9>bo? zZqd^j&9n9T3>$};vza=UHS6?jg0au(4qrpQS;(8!ESs3=PMH-forqzs#;kQ)*k|LI zNyqgHJw02kr{^m4?7YUNGSzz4gnqMzWpCC)cdW}=)Yy27i)C+U-mMGTnyr<%XOe6U zWWj;-NZZ6C9`jpEr}rh{|M;}#|1qbz5r?wm67~t$SuGZmt&OS6T4U;_7e3V!KR@Et zjd*n?t0vhxPO#e1vc5D>&aw++p`R@L9xl4zlyGwJ;*$T}1Ew6z|rqRJ)t)EVmwEV}~fej^}dc{#9wKk>ZDgW^;?xx0?=o^x(tg%+{&C8HWWlAp58o9DT3~piZnST7$)F1a@b8 zY_9QGJ?i8YOXfXagKG?2%_sFy&)V7z@NXz1dQ1X$lUkQ0^M91bpgUDw%GM`g%kv-` z`c}w#%tAkkKrSO}PBS~_P3%1v*?1z>U>ziTPovJX%r2SF)VD5bu509fF`h5up7iOG z)@hMnh~boa2er$4U0mprKEA-Ycf$V$UguH|=|Emh&1q|<=zA<+eY5q>@!HLG6>{O9 zct0xSS*e~yKg|;Nhmg;A!@EJ@O|jxRA^HdJeX&ld%Yl&(!znEkSMV zH7~Hep0C(Yz-7N(^yVaDO(}j}ik!fEmze2Fc}m$(0=lH1{4GL_=IU6Q^HgM7+}3W6 z!3Oei9Ql~HWnR#2dm=a2h`8YmO2fu_a7+K5%hi$1erE9;^g@Q`L=5!;ALk&8o@_0M zT*wrubNW8~9(=mo!>-XcnXAFwSXT;fkyVR+RqXCs-2DbTOxRmQ@25AEILh8mZ}KAE z8CidY?^EdWtS1x*A8mfk7#;~m!p+{b%?oMZ*tXFdf6sm8wKux zLe^F_*k0MV?!5cM68Ei2?_hfs`{ifGT5zNbxx=>Hm`e(3&$ueR*xI68XGqB2NhjGp zE9AbXxvlD;ROwDtdJihLzZ7zVZZ3DLVEZL^r59Uan|Pw;`G~LJd1e_;A+};F!Mzgp zM{dOd0F4oW<>Ps>vkLwbN8OCa0BasM%-;!o0*Oe2^Ta%f|8D%-Swbjd+*izPT)zPM ziT(2|$AuCF{~GHJ3Lj~|AGpi`MVtkS;3taUdJ&xHkljuZB5C)$zj8) z8V_D!8h@O~lKoe_Fv+p0y%Hobn+BSL2aU@b!6?XhNm-hVJr4`UjnM~y#vGaseE)hcdt;4*Iq9k|Tv z_Z+y)>uCor>-aYZF6*8dC!;(1M*QKxfD!cfMM9y-3FaF%LIGbCN6gm~85l6aQ7IP; zhk{|l-y4Vq{6~#E9EwDa9UqiJIPeb`1E-AP2pfqGhm5e}L~i?r4TB`*J~-m<3yehl zBclT_b4Krx# zz5ZZ0(rYk&*Vn^*;2I4a!8|%Zb1>rX=?{d%M##^lkA#lx+9~fJ83+vSV4He<{AWAc zbkes?#Q48VmBb%O1cXVa|@Mi%V@Du@I9ezdT4ePne!Z?8UTb z3K?OL)KLCPb@Kgg21X*zSiC6&@57loB!4-7hC{hl<=&TuRB#npQ($Us(UrKkzs{lD ssdf&stN9-nMf^4?!=QT + +#include "ext2_fs.h" +#include "ext2fs.h" + +int ext2fs_native_flag(void) +{ +#ifdef WORDS_BIGENDIAN + return EXT2_FLAG_SWAP_BYTES; +#else + return 0; +#endif +} + + + diff --git a/jni/e2fsprogs/lib/ext2fs/native.o b/jni/e2fsprogs/lib/ext2fs/native.o new file mode 100755 index 0000000000000000000000000000000000000000..c84fdd2fca206a88a4ad53de7d870ebd7bc8ccc3 GIT binary patch literal 952 zcmbVKy-EW?5T5fAO<^GxA}A(B3K3kA*rYrJHK151R)UxH+{9?^0(VP@BG~#UzJZoL zg|)BX6X?v{PQ2`CF7W~gsrd;4_$Smjb^F7y%XBppPri##NqCo_sFjNr=(MT(CaD29%Xc^oB8e6@@ zkE9-qmERl6K8RQirBK&?FP5Q#%p?L3iH^0rM7#?L>sO*hM-%E3(J0*Xf5ah%6<-6O zWB&QZN}K!s)IvJ#dCSi;I=>g2ODq^%K%{uPpN_Gw7-Zo3j5Jp)vk&1#UdhR}FU=-# zGk=JB7dNfV45p{u&kkCsCvWPJ2@O+-=bQSZ>Ed|iPm!~0Q-&uxa6M-*ePcWR8++M0 AiU0rr literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/newdir.c b/jni/e2fsprogs/lib/ext2fs/newdir.c new file mode 100755 index 0000000..7f47285 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/newdir.c @@ -0,0 +1,126 @@ +/* + * newdir.c --- create a new directory block + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef EXT2_FT_DIR +#define EXT2_FT_DIR 2 +#endif + +/* + * Create new directory block + */ +errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, + ext2_ino_t parent_ino, char **block) +{ + struct ext2_dir_entry *dir = NULL; + errcode_t retval; + char *buf; + int rec_len; + int filetype = 0; + struct ext2_dir_entry_tail *t; + int csum_size = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + memset(buf, 0, fs->blocksize); + dir = (struct ext2_dir_entry *) buf; + + if (ext2fs_has_feature_metadata_csum(fs->super)) + csum_size = sizeof(struct ext2_dir_entry_tail); + + retval = ext2fs_set_rec_len(fs, fs->blocksize - csum_size, dir); + if (retval) { + ext2fs_free_mem(&buf); + return retval; + } + + if (dir_ino) { + if (ext2fs_has_feature_filetype(fs->super)) + filetype = EXT2_FT_DIR; + /* + * Set up entry for '.' + */ + dir->inode = dir_ino; + ext2fs_dirent_set_name_len(dir, 1); + ext2fs_dirent_set_file_type(dir, filetype); + dir->name[0] = '.'; + rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1); + dir->rec_len = EXT2_DIR_REC_LEN(1); + + /* + * Set up entry for '..' + */ + dir = (struct ext2_dir_entry *) (buf + dir->rec_len); + retval = ext2fs_set_rec_len(fs, rec_len, dir); + if (retval) { + ext2fs_free_mem(&buf); + return retval; + } + dir->inode = parent_ino; + ext2fs_dirent_set_name_len(dir, 2); + ext2fs_dirent_set_file_type(dir, filetype); + dir->name[0] = '.'; + dir->name[1] = '.'; + + } + + if (csum_size) { + t = EXT2_DIRENT_TAIL(buf, fs->blocksize); + ext2fs_initialize_dirent_tail(fs, t); + } + *block = buf; + return 0; +} + +/* + * Create new directory on inline data + */ +errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, + ext2_ino_t dir_ino EXT2FS_ATTR((unused)), + ext2_ino_t parent_ino, __u32 *iblock) +{ + struct ext2_dir_entry *dir = NULL; + errcode_t retval; + int rec_len; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + iblock[0] = ext2fs_cpu_to_le32(parent_ino); + + dir = (struct ext2_dir_entry *)((char *)iblock + + EXT4_INLINE_DATA_DOTDOT_SIZE); + dir->inode = 0; + rec_len = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE; + retval = ext2fs_set_rec_len(fs, rec_len, dir); + if (retval) + goto errout; + +#ifdef WORDS_BIGENDIAN + retval = ext2fs_dirent_swab_out2(fs, (char *)dir, rec_len, 0); + if (retval) + goto errout; +#endif + +errout: + return retval; +} diff --git a/jni/e2fsprogs/lib/ext2fs/newdir.o b/jni/e2fsprogs/lib/ext2fs/newdir.o new file mode 100755 index 0000000000000000000000000000000000000000..7353c18de422e672da47f9fdb6f565acd85db560 GIT binary patch literal 3024 zcmbtWUuauZ82@h4Es5>=XRT|ouE|`r?ZB`O!S-oaR%a2BIwlOj%lJ_mWo#TGg;&)<#O7{h0jotG~lW7}y-JLOxpk z5WLVGF}+eSe5ibbRuS&gQa{xy{bsE|^bOmHJ@ntlzSIkx{ln%S+XSPB*rviba$p&C znY9bR)`(tU`xWEzi3;-K{Tk%T{(i6N8Ajy%_57Kt9=9UnmSjFE{xs|hx2M-9BMrYQ z){GWwk`N1h;8?6%gzsU4yfv%`AS-v1$FZ0%A2h|j)NOjKx3TN;iQxk@uIGo|ov*Z# z$90xF$a{lpZ8g1ehw0r9(jm4LIz!~W3RwYua9GRS5B50{F_**Nk6hv2aP8$G(|g={ zpWzzv+iQ3UHTd(_a~JhKOXK3)(BBoK(JPS;;*a3mknff7C_SijP)+32Vb<8Ew5b(? z)7-P#O`N$nv%FQ^ymY*X`CGjew0^1|qr0ULW+Y_R!Vde}mo0_9cnbK#a+~GRhvi3U zyo|n9j+*1)1Jo7XLtT{+_z?6L2lk3R`n(}$NZ`<8oO3EcZz~?(if=PQeyq_)N~G+}x!Ai-HkX{w#74*Bqwz5uL?<35WBOZx##7o+%w*);lF5j zn}+|R;d?ZEQuLFE{b2N(bW+1Rnkdl^8m{~QL&J6dVR^28|2-P6`#-JW`uSXyePKU( zT<$;9F5uEs@Dt*_g{yfu?ZXSw$o1hH6934DtMj3F)=AlM*I9BYo|sRkos3IqC!KR# z0(N9JXU!zD04*R^#!fp{%E>4ZV_7GmL(uj^b9T;}b!>Mr>sV>WwP$SCwi3C;v~qI} zZV*$kvss4~n|v~pbdz=}dC^h1xOOt7v@^~HhOM)y`NVmOXXafe{>tlbKA&@K@UjLy zh1q1vahDeyCDZC-ktJk}wm5UvY!)>Wfm24jzT+de8Y2l|sMnegKTgYteKu zEbYH;B8`p8U%`DaepLO1P(x!$DzY87MA`RAd<^#f*ev>4#pmQeyzsx|e*6CbBmO&F literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/nls_utf8.c b/jni/e2fsprogs/lib/ext2fs/nls_utf8.c new file mode 100755 index 0000000..b07e66e --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/nls_utf8.c @@ -0,0 +1,1000 @@ +/* + * Copyright (c) 2014 SGI. + * Copyright (c) 2018 Collabora Ltd. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * This code is adapted from the Linux Kernel. We have a + * userspace version here such that the hashes will match that + * implementation. + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +/* Encoding a unicode version number as a single unsigned int. */ +#define UNICODE_MAJ_SHIFT (16) +#define UNICODE_MIN_SHIFT (8) + +#define UNICODE_AGE(MAJ, MIN, REV) \ + (((unsigned int)(MAJ) << UNICODE_MAJ_SHIFT) | \ + ((unsigned int)(MIN) << UNICODE_MIN_SHIFT) | \ + ((unsigned int)(REV))) + +/* Needed in struct utf8cursor below. */ +#define UTF8HANGULLEAF (12) + +/* + * Cursor structure used by the normalizer. + */ +struct utf8cursor { + const struct utf8data *data; + const char *s; + const char *p; + const char *ss; + const char *sp; + unsigned int len; + unsigned int slen; + short int ccc; + short int nccc; + unsigned char hangul[UTF8HANGULLEAF]; +}; + +/* + * Initialize a utf8cursor to normalize a string. + * Returns 0 on success. + * Returns -1 on failure. + */ +// extern int utf8cursor(struct utf8cursor *u8c, const struct utf8data *data, +// const char *s); +// extern int utf8ncursor(struct utf8cursor *u8c, const struct utf8data *data, +// const char *s, size_t len); + +/* + * Get the next byte in the normalization. + * Returns a value > 0 && < 256 on success. + * Returns 0 when the end of the normalization is reached. + * Returns -1 if the string being normalized is not valid UTF-8. + */ +// extern int utf8byte(struct utf8cursor *u8c); + + +struct utf8data { + unsigned int maxage; + unsigned int offset; +}; + +#define __INCLUDED_FROM_UTF8NORM_C__ +#include "utf8data.h" +#undef __INCLUDED_FROM_UTF8NORM_C__ + +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof(array[0])) + +#if 0 +/* Highest unicode version supported by the data tables. */ +static int utf8version_is_supported(uint8_t maj, uint8_t min, uint8_t rev) +{ + int i = ARRAY_SIZE(utf8agetab) - 1; + unsigned int sb_utf8version = UNICODE_AGE(maj, min, rev); + + while (i >= 0 && utf8agetab[i] != 0) { + if (sb_utf8version == utf8agetab[i]) + return 1; + i--; + } + return 0; +} +#endif + +#if 0 +static int utf8version_latest(void) +{ + return utf8vers; +} +#endif + +/* + * UTF-8 valid ranges. + * + * The UTF-8 encoding spreads the bits of a 32bit word over several + * bytes. This table gives the ranges that can be held and how they'd + * be represented. + * + * 0x00000000 0x0000007F: 0xxxxxxx + * 0x00000000 0x000007FF: 110xxxxx 10xxxxxx + * 0x00000000 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx + * 0x00000000 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 0x00000000 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 0x00000000 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * There is an additional requirement on UTF-8, in that only the + * shortest representation of a 32bit value is to be used. A decoder + * must not decode sequences that do not satisfy this requirement. + * Thus the allowed ranges have a lower bound. + * + * 0x00000000 0x0000007F: 0xxxxxxx + * 0x00000080 0x000007FF: 110xxxxx 10xxxxxx + * 0x00000800 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx + * 0x00010000 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 0x00200000 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 0x04000000 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * Actual unicode characters are limited to the range 0x0 - 0x10FFFF, + * 17 planes of 65536 values. This limits the sequences actually seen + * even more, to just the following. + * + * 0 - 0x7F: 0 - 0x7F + * 0x80 - 0x7FF: 0xC2 0x80 - 0xDF 0xBF + * 0x800 - 0xFFFF: 0xE0 0xA0 0x80 - 0xEF 0xBF 0xBF + * 0x10000 - 0x10FFFF: 0xF0 0x90 0x80 0x80 - 0xF4 0x8F 0xBF 0xBF + * + * Within those ranges the surrogates 0xD800 - 0xDFFF are not allowed. + * + * Note that the longest sequence seen with valid usage is 4 bytes, + * the same a single UTF-32 character. This makes the UTF-8 + * representation of Unicode strictly smaller than UTF-32. + * + * The shortest sequence requirement was introduced by: + * Corrigendum #1: UTF-8 Shortest Form + * It can be found here: + * http://www.unicode.org/versions/corrigendum1.html + * + */ + +/* + * Return the number of bytes used by the current UTF-8 sequence. + * Assumes the input points to the first byte of a valid UTF-8 + * sequence. + */ +static inline int utf8clen(const char *s) +{ + unsigned char c = *s; + + return 1 + (c >= 0xC0) + (c >= 0xE0) + (c >= 0xF0); +} + +/* + * Decode a 3-byte UTF-8 sequence. + */ +static unsigned int +utf8decode3(const char *str) +{ + unsigned int uc; + + uc = *str++ & 0x0F; + uc <<= 6; + uc |= *str++ & 0x3F; + uc <<= 6; + uc |= *str++ & 0x3F; + + return uc; +} + +/* + * Encode a 3-byte UTF-8 sequence. + */ +static int +utf8encode3(char *str, unsigned int val) +{ + str[2] = (val & 0x3F) | 0x80; + val >>= 6; + str[1] = (val & 0x3F) | 0x80; + val >>= 6; + str[0] = val | 0xE0; + + return 3; +} + +/* + * utf8trie_t + * + * A compact binary tree, used to decode UTF-8 characters. + * + * Internal nodes are one byte for the node itself, and up to three + * bytes for an offset into the tree. The first byte contains the + * following information: + * NEXTBYTE - flag - advance to next byte if set + * BITNUM - 3 bit field - the bit number to tested + * OFFLEN - 2 bit field - number of bytes in the offset + * if offlen == 0 (non-branching node) + * RIGHTPATH - 1 bit field - set if the following node is for the + * right-hand path (tested bit is set) + * TRIENODE - 1 bit field - set if the following node is an internal + * node, otherwise it is a leaf node + * if offlen != 0 (branching node) + * LEFTNODE - 1 bit field - set if the left-hand node is internal + * RIGHTNODE - 1 bit field - set if the right-hand node is internal + * + * Due to the way utf8 works, there cannot be branching nodes with + * NEXTBYTE set, and moreover those nodes always have a righthand + * descendant. + */ +typedef const unsigned char utf8trie_t; +#define BITNUM 0x07 +#define NEXTBYTE 0x08 +#define OFFLEN 0x30 +#define OFFLEN_SHIFT 4 +#define RIGHTPATH 0x40 +#define TRIENODE 0x80 +#define RIGHTNODE 0x40 +#define LEFTNODE 0x80 + +/* + * utf8leaf_t + * + * The leaves of the trie are embedded in the trie, and so the same + * underlying datatype: unsigned char. + * + * leaf[0]: The unicode version, stored as a generation number that is + * an index into utf8agetab[]. With this we can filter code + * points based on the unicode version in which they were + * defined. The CCC of a non-defined code point is 0. + * leaf[1]: Canonical Combining Class. During normalization, we need + * to do a stable sort into ascending order of all characters + * with a non-zero CCC that occur between two characters with + * a CCC of 0, or at the begin or end of a string. + * The unicode standard guarantees that all CCC values are + * between 0 and 254 inclusive, which leaves 255 available as + * a special value. + * Code points with CCC 0 are known as stoppers. + * leaf[2]: Decomposition. If leaf[1] == 255, then leaf[2] is the + * start of a NUL-terminated string that is the decomposition + * of the character. + * The CCC of a decomposable character is the same as the CCC + * of the first character of its decomposition. + * Some characters decompose as the empty string: these are + * characters with the Default_Ignorable_Code_Point property. + * These do affect normalization, as they all have CCC 0. + * + * The decompositions in the trie have been fully expanded, with the + * exception of Hangul syllables, which are decomposed algorithmically. + * + * Casefolding, if applicable, is also done using decompositions. + * + * The trie is constructed in such a way that leaves exist for all + * UTF-8 sequences that match the criteria from the "UTF-8 valid + * ranges" comment above, and only for those sequences. Therefore a + * lookup in the trie can be used to validate the UTF-8 input. + */ +typedef const unsigned char utf8leaf_t; + +#define LEAF_GEN(LEAF) ((LEAF)[0]) +#define LEAF_CCC(LEAF) ((LEAF)[1]) +#define LEAF_STR(LEAF) ((const char *)((LEAF) + 2)) + +#define MINCCC (0) +#define MAXCCC (254) +#define STOPPER (0) +#define DECOMPOSE (255) + +/* Marker for hangul syllable decomposition. */ +#define HANGUL ((char)(255)) +/* Size of the synthesized leaf used for Hangul syllable decomposition. */ +#define UTF8HANGULLEAF (12) + +/* + * Hangul decomposition (algorithm from Section 3.12 of Unicode 6.3.0) + * + * AC00;;Lo;0;L;;;;;N;;;;; + * D7A3;;Lo;0;L;;;;;N;;;;; + * + * SBase = 0xAC00 + * LBase = 0x1100 + * VBase = 0x1161 + * TBase = 0x11A7 + * LCount = 19 + * VCount = 21 + * TCount = 28 + * NCount = 588 (VCount * TCount) + * SCount = 11172 (LCount * NCount) + * + * Decomposition: + * SIndex = s - SBase + * + * LV (Canonical/Full) + * LIndex = SIndex / NCount + * VIndex = (Sindex % NCount) / TCount + * LPart = LBase + LIndex + * VPart = VBase + VIndex + * + * LVT (Canonical) + * LVIndex = (SIndex / TCount) * TCount + * TIndex = (Sindex % TCount) + * LVPart = SBase + LVIndex + * TPart = TBase + TIndex + * + * LVT (Full) + * LIndex = SIndex / NCount + * VIndex = (Sindex % NCount) / TCount + * TIndex = (Sindex % TCount) + * LPart = LBase + LIndex + * VPart = VBase + VIndex + * if (TIndex == 0) { + * d = + * } else { + * TPart = TBase + TIndex + * d = + * } + */ + +/* Constants */ +#define SB (0xAC00) +#define LB (0x1100) +#define VB (0x1161) +#define TB (0x11A7) +#define LC (19) +#define VC (21) +#define TC (28) +#define NC (VC * TC) +#define SC (LC * NC) + +/* Algorithmic decomposition of hangul syllable. */ +static utf8leaf_t * +utf8hangul(const char *str, unsigned char *hangul) +{ + unsigned int si; + unsigned int li; + unsigned int vi; + unsigned int ti; + unsigned char *h; + + /* Calculate the SI, LI, VI, and TI values. */ + si = utf8decode3(str) - SB; + li = si / NC; + vi = (si % NC) / TC; + ti = si % TC; + + /* Fill in base of leaf. */ + h = hangul; + LEAF_GEN(h) = 2; + LEAF_CCC(h) = DECOMPOSE; + h += 2; + + /* Add LPart, a 3-byte UTF-8 sequence. */ + h += utf8encode3((char *)h, li + LB); + + /* Add VPart, a 3-byte UTF-8 sequence. */ + h += utf8encode3((char *)h, vi + VB); + + /* Add TPart if required, also a 3-byte UTF-8 sequence. */ + if (ti) + h += utf8encode3((char *)h, ti + TB); + + /* Terminate string. */ + h[0] = '\0'; + + return hangul; +} + +/* + * Use trie to scan s, touching at most len bytes. + * Returns the leaf if one exists, NULL otherwise. + * + * A non-NULL return guarantees that the UTF-8 sequence starting at s + * is well-formed and corresponds to a known unicode code point. The + * shorthand for this will be "is valid UTF-8 unicode". + */ +static utf8leaf_t *utf8nlookup(const struct utf8data *data, + unsigned char *hangul, const char *s, size_t len) +{ + utf8trie_t *trie; + int offlen; + int offset; + int mask; + int node; + + if (!data) + return NULL; + if (len == 0) + return NULL; + + trie = utf8data + data->offset; + node = 1; + while (node) { + offlen = (*trie & OFFLEN) >> OFFLEN_SHIFT; + if (*trie & NEXTBYTE) { + if (--len == 0) + return NULL; + s++; + } + mask = 1 << (*trie & BITNUM); + if (*s & mask) { + /* Right leg */ + if (offlen) { + /* Right node at offset of trie */ + node = (*trie & RIGHTNODE); + offset = trie[offlen]; + while (--offlen) { + offset <<= 8; + offset |= trie[offlen]; + } + trie += offset; + } else if (*trie & RIGHTPATH) { + /* Right node after this node */ + node = (*trie & TRIENODE); + trie++; + } else { + /* No right node. */ + return NULL; + } + } else { + /* Left leg */ + if (offlen) { + /* Left node after this node. */ + node = (*trie & LEFTNODE); + trie += offlen + 1; + } else if (*trie & RIGHTPATH) { + /* No left node. */ + return NULL; + } else { + /* Left node after this node */ + node = (*trie & TRIENODE); + trie++; + } + } + } + /* + * Hangul decomposition is done algorithmically. These are the + * codepoints >= 0xAC00 and <= 0xD7A3. Their UTF-8 encoding is + * always 3 bytes long, so s has been advanced twice, and the + * start of the sequence is at s-2. + */ + if (LEAF_CCC(trie) == DECOMPOSE && LEAF_STR(trie)[0] == HANGUL) + trie = utf8hangul(s - 2, hangul); + return trie; +} + +/* + * Use trie to scan s. + * Returns the leaf if one exists, NULL otherwise. + * + * Forwards to utf8nlookup(). + */ +static utf8leaf_t *utf8lookup(const struct utf8data *data, + unsigned char *hangul, const char *s) +{ + return utf8nlookup(data, hangul, s, (size_t)-1); +} + +#if 0 +/* + * Maximum age of any character in s. + * Return -1 if s is not valid UTF-8 unicode. + * Return 0 if only non-assigned code points are used. + */ +static int utf8agemax(const struct utf8data *data, const char *s) +{ + utf8leaf_t *leaf; + int age = 0; + int leaf_age; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + + while (*s) { + leaf = utf8lookup(data, hangul, s); + if (!leaf) + return -1; + + leaf_age = utf8agetab[LEAF_GEN(leaf)]; + if (leaf_age <= data->maxage && leaf_age > age) + age = leaf_age; + s += utf8clen(s); + } + return age; +} +#endif + +#if 0 +/* + * Minimum age of any character in s. + * Return -1 if s is not valid UTF-8 unicode. + * Return 0 if non-assigned code points are used. + */ +static int utf8agemin(const struct utf8data *data, const char *s) +{ + utf8leaf_t *leaf; + int age; + int leaf_age; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + age = data->maxage; + while (*s) { + leaf = utf8lookup(data, hangul, s); + if (!leaf) + return -1; + leaf_age = utf8agetab[LEAF_GEN(leaf)]; + if (leaf_age <= data->maxage && leaf_age < age) + age = leaf_age; + s += utf8clen(s); + } + return age; +} +#endif + +#if 0 +/* + * Maximum age of any character in s, touch at most len bytes. + * Return -1 if s is not valid UTF-8 unicode. + */ +static int utf8nagemax(const struct utf8data *data, const char *s, size_t len) +{ + utf8leaf_t *leaf; + int age = 0; + int leaf_age; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + + while (len && *s) { + leaf = utf8nlookup(data, hangul, s, len); + if (!leaf) + return -1; + leaf_age = utf8agetab[LEAF_GEN(leaf)]; + if (leaf_age <= data->maxage && leaf_age > age) + age = leaf_age; + len -= utf8clen(s); + s += utf8clen(s); + } + return age; +} +#endif + +#if 0 +/* + * Maximum age of any character in s, touch at most len bytes. + * Return -1 if s is not valid UTF-8 unicode. + */ +static int utf8nagemin(const struct utf8data *data, const char *s, size_t len) +{ + utf8leaf_t *leaf; + int leaf_age; + int age; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + age = data->maxage; + while (len && *s) { + leaf = utf8nlookup(data, hangul, s, len); + if (!leaf) + return -1; + leaf_age = utf8agetab[LEAF_GEN(leaf)]; + if (leaf_age <= data->maxage && leaf_age < age) + age = leaf_age; + len -= utf8clen(s); + s += utf8clen(s); + } + return age; +} +#endif + +#if 0 +/* + * Length of the normalization of s. + * Return -1 if s is not valid UTF-8 unicode. + * + * A string of Default_Ignorable_Code_Point has length 0. + */ +static ssize_t utf8len(const struct utf8data *data, const char *s) +{ + utf8leaf_t *leaf; + size_t ret = 0; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + while (*s) { + leaf = utf8lookup(data, hangul, s); + if (!leaf) + return -1; + if (utf8agetab[LEAF_GEN(leaf)] > data->maxage) + ret += utf8clen(s); + else if (LEAF_CCC(leaf) == DECOMPOSE) + ret += strlen(LEAF_STR(leaf)); + else + ret += utf8clen(s); + s += utf8clen(s); + } + return ret; +} +#endif + +#if 0 +/* + * Length of the normalization of s, touch at most len bytes. + * Return -1 if s is not valid UTF-8 unicode. + */ +static ssize_t utf8nlen(const struct utf8data *data, const char *s, size_t len) +{ + utf8leaf_t *leaf; + size_t ret = 0; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + while (len && *s) { + leaf = utf8nlookup(data, hangul, s, len); + if (!leaf) + return -1; + if (utf8agetab[LEAF_GEN(leaf)] > data->maxage) + ret += utf8clen(s); + else if (LEAF_CCC(leaf) == DECOMPOSE) + ret += strlen(LEAF_STR(leaf)); + else + ret += utf8clen(s); + len -= utf8clen(s); + s += utf8clen(s); + } + return ret; +} +#endif + +/* + * Set up an utf8cursor for use by utf8byte(). + * + * u8c : pointer to cursor. + * data : const struct utf8data to use for normalization. + * s : string. + * len : length of s. + * + * Returns -1 on error, 0 on success. + */ +static int utf8ncursor(struct utf8cursor *u8c, const struct utf8data *data, + const char *s, size_t len) +{ + if (!data) + return -1; + if (!s) + return -1; + u8c->data = data; + u8c->s = s; + u8c->p = NULL; + u8c->ss = NULL; + u8c->sp = NULL; + u8c->len = len; + u8c->slen = 0; + u8c->ccc = STOPPER; + u8c->nccc = STOPPER; + /* Check we didn't clobber the maximum length. */ + if (u8c->len != len) + return -1; + /* The first byte of s may not be an utf8 continuation. */ + if (len > 0 && (*s & 0xC0) == 0x80) + return -1; + return 0; +} + +#if 0 +/* + * Set up an utf8cursor for use by utf8byte(). + * + * u8c : pointer to cursor. + * data : const struct utf8data to use for normalization. + * s : NUL-terminated string. + * + * Returns -1 on error, 0 on success. + */ +static int utf8cursor(struct utf8cursor *u8c, const struct utf8data *data, + const char *s) +{ + return utf8ncursor(u8c, data, s, (unsigned int)-1); +} +#endif + +/* + * Get one byte from the normalized form of the string described by u8c. + * + * Returns the byte cast to an unsigned char on success, and -1 on failure. + * + * The cursor keeps track of the location in the string in u8c->s. + * When a character is decomposed, the current location is stored in + * u8c->p, and u8c->s is set to the start of the decomposition. Note + * that bytes from a decomposition do not count against u8c->len. + * + * Characters are emitted if they match the current CCC in u8c->ccc. + * Hitting end-of-string while u8c->ccc == STOPPER means we're done, + * and the function returns 0 in that case. + * + * Sorting by CCC is done by repeatedly scanning the string. The + * values of u8c->s and u8c->p are stored in u8c->ss and u8c->sp at + * the start of the scan. The first pass finds the lowest CCC to be + * emitted and stores it in u8c->nccc, the second pass emits the + * characters with this CCC and finds the next lowest CCC. This limits + * the number of passes to 1 + the number of different CCCs in the + * sequence being scanned. + * + * Therefore: + * u8c->p != NULL -> a decomposition is being scanned. + * u8c->ss != NULL -> this is a repeating scan. + * u8c->ccc == -1 -> this is the first scan of a repeating scan. + */ +static int utf8byte(struct utf8cursor *u8c) +{ + utf8leaf_t *leaf; + int ccc; + + for (;;) { + /* Check for the end of a decomposed character. */ + if (u8c->p && *u8c->s == '\0') { + u8c->s = u8c->p; + u8c->p = NULL; + } + + /* Check for end-of-string. */ + if (!u8c->p && (u8c->len == 0 || *u8c->s == '\0')) { + /* There is no next byte. */ + if (u8c->ccc == STOPPER) + return 0; + /* End-of-string during a scan counts as a stopper. */ + ccc = STOPPER; + goto ccc_mismatch; + } else if ((*u8c->s & 0xC0) == 0x80) { + /* This is a continuation of the current character. */ + if (!u8c->p) + u8c->len--; + return (unsigned char)*u8c->s++; + } + + /* Look up the data for the current character. */ + if (u8c->p) { + leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s); + } else { + leaf = utf8nlookup(u8c->data, u8c->hangul, + u8c->s, u8c->len); + } + + /* No leaf found implies that the input is a binary blob. */ + if (!leaf) + return -1; + + ccc = LEAF_CCC(leaf); + /* Characters that are too new have CCC 0. */ + if (utf8agetab[LEAF_GEN(leaf)] > u8c->data->maxage) { + ccc = STOPPER; + } else if (ccc == DECOMPOSE) { + u8c->len -= utf8clen(u8c->s); + u8c->p = u8c->s + utf8clen(u8c->s); + u8c->s = LEAF_STR(leaf); + /* Empty decomposition implies CCC 0. */ + if (*u8c->s == '\0') { + if (u8c->ccc == STOPPER) + continue; + ccc = STOPPER; + goto ccc_mismatch; + } + + leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s); + if (!leaf) + return -1; + ccc = LEAF_CCC(leaf); + } + + /* + * If this is not a stopper, then see if it updates + * the next canonical class to be emitted. + */ + if (ccc != STOPPER && u8c->ccc < ccc && ccc < u8c->nccc) + u8c->nccc = ccc; + + /* + * Return the current byte if this is the current + * combining class. + */ + if (ccc == u8c->ccc) { + if (!u8c->p) + u8c->len--; + return (unsigned char)*u8c->s++; + } + + /* Current combining class mismatch. */ +ccc_mismatch: + if (u8c->nccc == STOPPER) { + /* + * Scan forward for the first canonical class + * to be emitted. Save the position from + * which to restart. + */ + u8c->ccc = MINCCC - 1; + u8c->nccc = ccc; + u8c->sp = u8c->p; + u8c->ss = u8c->s; + u8c->slen = u8c->len; + if (!u8c->p) + u8c->len -= utf8clen(u8c->s); + u8c->s += utf8clen(u8c->s); + } else if (ccc != STOPPER) { + /* Not a stopper, and not the ccc we're emitting. */ + if (!u8c->p) + u8c->len -= utf8clen(u8c->s); + u8c->s += utf8clen(u8c->s); + } else if (u8c->nccc != MAXCCC + 1) { + /* At a stopper, restart for next ccc. */ + u8c->ccc = u8c->nccc; + u8c->nccc = MAXCCC + 1; + u8c->s = u8c->ss; + u8c->p = u8c->sp; + u8c->len = u8c->slen; + } else { + /* All done, proceed from here. */ + u8c->ccc = STOPPER; + u8c->nccc = STOPPER; + u8c->sp = NULL; + u8c->ss = NULL; + u8c->slen = 0; + } + } +} + +#if 0 +/* + * Look for the correct const struct utf8data for a unicode version. + * Returns NULL if the version requested is too new. + * + * Two normalization forms are supported: nfdi and nfdicf. + * + * nfdi: + * - Apply unicode normalization form NFD. + * - Remove any Default_Ignorable_Code_Point. + * + * nfdicf: + * - Apply unicode normalization form NFD. + * - Remove any Default_Ignorable_Code_Point. + * - Apply a full casefold (C + F). + */ +static const struct utf8data *utf8nfdi(unsigned int maxage) +{ + int i = ARRAY_SIZE(utf8nfdidata) - 1; + + while (maxage < utf8nfdidata[i].maxage) + i--; + if (maxage > utf8nfdidata[i].maxage) + return NULL; + return &utf8nfdidata[i]; +} +#endif + +static const struct utf8data *utf8nfdicf(unsigned int maxage) +{ + int i = ARRAY_SIZE(utf8nfdicfdata) - 1; + + while (maxage < utf8nfdicfdata[i].maxage) + i--; + if (maxage > utf8nfdicfdata[i].maxage) + return NULL; + return &utf8nfdicfdata[i]; +} + +static int utf8_casefold(const struct ext2fs_nls_table *table, + const unsigned char *str, size_t len, + unsigned char *dest, size_t dlen) +{ + const struct utf8data *data = utf8nfdicf(table->version); + struct utf8cursor cur; + size_t nlen = 0; + + if (utf8ncursor(&cur, data, (const char *) str, len) < 0) + goto invalid_seq; + + for (nlen = 0; nlen < dlen; nlen++) { + int c = utf8byte(&cur); + + dest[nlen] = c; + if (!c) + return nlen; + if (c == -1) + break; + } + + return -ENAMETOOLONG; + +invalid_seq: + if (dlen < len) + return -ENAMETOOLONG; + + /* Signal invalid sequence */ + return -EINVAL; +} + +static int utf8_validate(const struct ext2fs_nls_table *table, + char *s, size_t len, char **pos) +{ + const struct utf8data *data = utf8nfdicf(table->version); + utf8leaf_t *leaf; + unsigned char hangul[UTF8HANGULLEAF]; + + if (!data) + return -1; + while (len && *s) { + leaf = utf8nlookup(data, hangul, s, len); + if (!leaf) { + *pos = s; + return 1; + } + len -= utf8clen(s); + s += utf8clen(s); + } + return 0; +} + +static int utf8_casefold_cmp(const struct ext2fs_nls_table *table, + const unsigned char *str1, size_t len1, + const unsigned char *str2, size_t len2) +{ + const struct utf8data *data = utf8nfdicf(table->version); + int c1, c2; + struct utf8cursor cur1, cur2; + + if (utf8ncursor(&cur1, data, (const char *) str1, len1) < 0) + return -1; + if (utf8ncursor(&cur2, data, (const char *) str2, len2) < 0) + return -1; + + do { + c1 = utf8byte(&cur1); + c2 = utf8byte(&cur2); + + if (c1 < 0 || c2 < 0) + return -1; + if (c1 != c2) + return c1 - c2; + } while (c1); + + return 0; +} + +static const struct ext2fs_nls_ops utf8_ops = { + .casefold = utf8_casefold, + .validate = utf8_validate, + .casefold_cmp = utf8_casefold_cmp, +}; + +static const struct ext2fs_nls_table nls_utf8 = { + .ops = &utf8_ops, + .version = UNICODE_AGE(12, 1, 0), +}; + +const struct ext2fs_nls_table *ext2fs_load_nls_table(int encoding) +{ + if (encoding == EXT4_ENC_UTF8_12_1) + return &nls_utf8; + + return NULL; +} + +int ext2fs_check_encoded_name(const struct ext2fs_nls_table *table, + char *name, size_t len, char **pos) +{ + return table->ops->validate(table, name, len, pos); +} + +int ext2fs_casefold_cmp(const struct ext2fs_nls_table *table, + const unsigned char *str1, size_t len1, + const unsigned char *str2, size_t len2) +{ + return table->ops->casefold_cmp(table, str1, len1, str2, len2); +} diff --git a/jni/e2fsprogs/lib/ext2fs/nls_utf8.o b/jni/e2fsprogs/lib/ext2fs/nls_utf8.o new file mode 100755 index 0000000000000000000000000000000000000000..b4a4205b5746b8add7200f7d480d9d41bb727cdf GIT binary patch literal 71832 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

qQhd6;KjvZc;bT&_ zZg86q%JbmXuXWMSfU{rUjCf|j*)Q@r@mUa`1@W=-U_Fj4ijVRo@zHozQ}{NxpZ`1H ze*W)+TV6Wu0l4L*{1DvN=Ol$+ivMKDbsTle{6I{cbt5kWH~(i*8+)h%XZ@dsPqp(Q zuN5Dyf1~i{g)w+*cmBTs{|@I*-YGun-y>Z2rGoSS75EpOKl!BisQ;?-`6PVSoDcbW ziqF3D;oq}7a6aURDL&`U=LKIED|+F4$S+fTDt|D(&(EtGaQ6KT@UI2u{2{LsAFW%1 z@aIe4n^Sm~a9wvp;EdrPL;A^OP>`iD@@O>owed<)#>iPp2bC+5w*`~rM> z!0AKY2kw1J&WC@$bH@3Q&!+e+I-gG=o+al)zMSH-=Y0MQKKssx{2;~W%=vuf>temm zoe%j%ick4Jzgg#RgHHuG>r7q=?(5v(d@i0JeH)z*c~go{oA4LNy6zTUCcF=v^W>d~ zKMT(I$%n*8=Uc(~@OzS?^C6#fdj4I~DW@l&2KRM45dI~S*M;+c?5krvFP%Sm=3Vi) z_pcB>9VN+q132sUH0ss}&bpB|iI3K;+xh$?e0rP@d0&dpr1SYH_)Iw;^63B;w*v7>;V+WBDtqIb*+<4- z1p)%dM!pXrM)I4^eR99=Na1fpD!) zS$`(EG5#F<%fT5xc?G!nmxup&s}+7i7#3;|Qjo|brZ*qG6UEXG=CvO4w`L+qy ze7nToPRXa(Y`Vo?d5`$K_<7ff4GI5J;Zxwumwyj<8l3r(mz-7_XHmG;XAj)=pBvv#g4_P1{1BY^zVhp1jgG*XFZr?4^WUSLI6e7==%<490zXFOknc*?*T4|zSf)kpWYHs|ws)VbaHkavjBN3W+zrW4%i`7z;L;QsrW zEI8wT4dNdHXZ+*^aEo8BL#CV$*YC9RAuox~1Hp^81>w4`mz@7MBF<&!Prl;xZ-#!= z>B-l@{k+{2uJd+R{GT6!=ephlx4J3c2RDCR*GIxDqz>oc>7o;?LzpMNgu0o*Ll5Ec!Tgt;myLoTzI?iuMoZ<{1>HeYv9bQ z{{`{jIymzp-*9@)|4pYS-*WmR_-{Ks`3|^W7kk3BzemE?B(F>1zaqSRFupMVUlQIY z+-kwwtnez~i^8o&yd4WypUOK?VdJV#t?;iBpFZJwUYiyEa?x)IuNJ;1{1w6vh3ov8 zABu5uKHR}PUjXNPAYTNxy!3O&o^ZWxKNS8-iKlA#x<2N`+obRs;VZ)J8iKcV;hNW> zaQ(b<2JZKPb8x>8RQ*sK$zuEh2Mv$);H=xfMBN&|SvT@V@p)E!nuY5;Zv{7hyN=o_ zi*ITJ=XDf$XNtZnML(0GpH0!9h<-AJ!k;^zf-_(8GjOY$eqL+68}l%3zYEA)H#qD0 z@(1IQ9&q}T_c{GzFv>bT`H<7sJs97RcY5*yxW%d8Z%hi;eocY1U;O@g8l3$ipLKeE z|2*gPbvqNT*O{5Zb-u5YeA|TA3!f4G^}-t-zxKKD`9-*1r*#R}aSOs< zFaGP`R{y8MP;GIz%m%pa^UAlx=Rxt=2e<3MkHEto4#4d?Q28-9`~G(Hmr%`;$#$&uzPaU@$ob#bQ$}$z;oDbx6Df;>pePfEgDMjCzqVG!4R~E15 zvwg0a#OInSaQ^!s@*dIKb=Tjbo_*k~CwU&+&+`JfpXZa#|M3^a_@{-?&Dkn_i?T`|I91n;H%D`d=1>kx#@gf1fMPELw+Pa56S$jnuz0b zo>#!98k~J0uLZYw9u}V|@v-^9+cY@m19?gGHXkZ+UIRaWS%} z$vhE*qd$2SIOAa*s-2#^2HelX2Iun?m_LoqhrCIA7Nl-1&WCkqbw1>6;-h`(az32@ z-Oh)+C&ef4eBOb)3eJbTnBp_-e0Y6Waz5lUPX7ZKch>32=fJHmTF(XXvH7!t{dp0b zpQFiFL~rwl@vMS#{*bRZ{WFMj-Ra3UzA#ZZ}e-C}L z)06i({TlRHrzf9v`VHvkoSuBq={KQYa(eQ8aI4RUWnCN!pA&vA{2AewDZJ8}8gAzQ z$@nz6ZxjAVIL2EM-0H9U&m_3tf2KumPr1*Oz}YYI6{lyNSDl`G4cy|_^}Y%2uQRv6 z{dMLpIOo+T(3d@M#!0>pZsY3pWW|%QQpUCZRVln4oa6oj#%%!Sxa8BKe<}>sfyR_X zuY3mF;%N&1@iq_c>$3pv>$42bIKPNESHKx3`6{@t&$@73*XP3DC~+nq_CnA;&N53f z+J8r;WOD_rBu3;#^CPVP(K9GCz8Wd@w%lFy3I&x+5o^I_jt zoDcbGicb|5C*x^D9jd_@4|xr^)nP&6X#}_We_VJIxYb{I3pmH+?|-&}b6oN^a2xk8 z#lH{SkDCSe;}*o{(cs0~1-Qk7r^%s9yzu)~`47i;GJalXR)8~p@@jC4-(uyhS$uTd z7H~gqm*{P4;eOZ+&T+|m!2P&q!u5Pn@h@X!rq}aDEx2D_b>Mz|HGs1|JnuJxGfwg* zr|-Z#Y<7C`7I2GG_tiGxx*j`)>-lR*_#@JngA`u=Be6crYZ7r*fHN=hN^pzwQ*3&8 ztaU!`g-@OHA+JyIX%ZisKlK=+S$veYgZn;qfcrjni@(jcS;W~R{>uBneP2r8e%u*w zKkgzp>%5F{m%v$P@?~&8?uqa}KyB=yW;(v`@zjF*cpAVN&$Ec95uEXmH-Y6HpLQf_S#TnHTvsxXZ?baEo7gGdRcP-??i6=eXpp;C|dG;abmW@wZE)Rs=Ky&hJsl7gO|0 zDf%^V->-FW->)t4w|(_psPi^B^CjN__x(C{KK#2mC(eibRD85wmG6rMF@LRF6}a_f zDoFVEbZWr){Q!AgioPL5-;|+>#f#zWri^bfo$ z4&LMRhrn5X@@a6tUP|D8 zz08Tf)qer;&x135@&#}||F?x}{5#@r@$X>%?13|W@?&rx{|UH{|6Kev{tIv)|0TGO zzv=_A@5aA5{Ks20xb;`-UjxqgS^rw`X%U|~=fiyKoez1l=q)e)J<}F&=0)BLZt?57 z=nx;fjw(lDUEmhK@;=eqxW9z?kOk+sUY5zCw&gUZQM6Ye=orOyuAeX^S1oQV_@7jejE8#fHPn6N^l$Z zS>$97)x!0>QwwhKd_?qh;1-YaMsUXSr--Ksobix1gIhdLi+`W<$$U*bm~}qnL*k?J zwkSTf?rJf{6u9+8`Hbjo{_yW<&Vn<3@;Pune>R2x6~?rOJ#gROeQ@93BXHL9rKrO( zIO8Ed0e?<^KNy3c5C0xz4LE(sYr%b9``|wQ18^VzB{;|BzYopK#&|d`c@;SIb;!5c z>B(!reZFE%XPo30;66_N@|kh1XE};!TG~^ZQ2fvY&|07(c&%C@}(5sG#3LfJ)S0DOL(jJ z9|`|f;g`a-FO@jinE$tleopuiYG4oB!u97|yTUcjI-G>e|C8dA`DlFM=W`jjpU;)x zoDct_KEA&SoP8m$2DfqbygViRt&;D&^Z)qkqyK{QCtq~>{{sDz(~~cQTReJRUKOtE zXlOo;Z~8Wga~hm=_#=#40%sk_XPo};p`Uen@;PuH=YnvJb6xmnW5_q|?f<=J>xj2n zJR$#?S47b0_@98+fZP8A>G^nW4^57D;B}AZs9nkNGw@Z%=P}5Erfp0s01b*uHG%mi%%3~hPcL}`4@h$Ks$B)2! z954NF^esBR3_k1lHu#3)Jvh1TIX(q`;`ky@hA+OE*Cu$im_j!)xyvD@(_@Pgx8 z;0umld^pCj<@hu%%1#__#C2Qcm)?wj=;`>n-tkrNR>yb2yB+8Me`eb8`j1Bc%e*hqgqNS@$;L;d5u zgW=%B*v-R_PmC7(dxuAci@gJ*BgGJ2CZe%iKG#2JLZy2L{5_%G|mg?nXv~RpH6r$*_BjUHQdkC-uabK^Y2vyMN&BMBz&I zoY^`Wj#+U=$1}-RF&g%i@yu`-W2k>*B$u}iSUSU_BUdK2NSJ-7MgKjPBpEQ7e3|g> zY?$6*#bcp`stw!?rMZ_2yGvY`8JY~*^hxS$)?u-aW`{?@GQGl~9}hcR7%fcXZEG7G z&y3z>bH_7bE430bq_}lOa_?^M(8QgbE%fmW)^cxrg|77HL-b~vOeOP3V)ppmW5Yoc zCnS_%>F36t036Rm1z2_8!|1Gf#z8FdnAr z=-AaZ6b2saPe2d^p4^Z3-p&p6KQSC$Te}i=jgZ^DyW!Llo1E(%8yyYXS$I7@HgNqS z*-;aW_v9uEp^s4*mc)=nIF>vP+n9r+;oOlQ9+{ZzeIgfPiBmhwb(`Jec7h_)^*0{Z z&yC}{9PW2~Ae?%}*yP?D3T~}7b;8b_yAwv87zt}HOyYa}BmMT;&NTXZVkA4NuVHwf zci8%|xkx8VgzxspVqT#V<6*V*hQ)B(LJ7SM+dv4PwaAZ-h9zm0%!UUPO$!jt8p+u{ zK8y^6$FR@aLwL_XI0f5Nyf2)h!+_ybJ8}DJuSvE@3al*Q-B0DlMl-!OHAY4=q48l> zg#y?fGm#Gs9!-+Ex{`Q&A`~nnaW(B?LvPz;G(0leAD?gqC(Fi;a1Pu&)5lpGwu9WA z;gQU}ySaG96P}0o2ZzH_4?~R>awD0+!9}i!hH#qC;LNmNAT>6d=@wuI~N5^efwIlW_JiR)J z+%M+Ad~PzFsPA_up0w^{2JDn%d+hCr!Hg}bUVAd0TXZw`olyTY=%a zdw3w%TNrxME|Ug|HZSgT+#k~3gb6VguFI2m2D{$mNmx62{hqKee3)Bza#6t*Iv6gd zWKg^A91e}S4#QoXW68$->rQUOPCL1)X7DuB8$Vw#mFHYuOccVp$wiZ7d(0FD@}uLq z%wT-LEPu}X;?c0P-8M1TK0bk5Uyb-JsTGdH5n`edf4foy=lh7A2PtdU^{N@m8vkb~r^O&tz+kAY34f zjfMq|bEt~6A2!4dhno$#J{&%QvLb$FYFev`!umVvQ>M;;#N4QV2|_%S58>WdfPy<`0&cXIYwb)ffdej*#5$BVdd zrDmVEdnd-jf{PbpVY?qsUd7MA_^f)x;^)k(^;xTjqmiPtfqjCaQ$#&;XnALOr8cFL1pUU99LelEKb42FdeHuJHtKCB5b!uU1L z{WRCn;JcnH(Zopd9qD}y{vStT@@~+0;XgVULb`i3i2J@Y`H-57c%`u2_$G-)`Tme0 z4%oRmKYHitJytxN{Ouy_Ve46P_Yh~7&BljrJruq|P2TxXW2SEM7JoF1FO2{H9;RQG z$>2wCHw;=|9Di{5+ON8SGx#y-75we+%ou)*bH!WnY#ToZ=K=g!jW3hmWj5A&MdFi- zKaY>K_JjLydrA1uBEpXuGSvpd?H5A)rofLm6J~d1KN+7M#fPhVKmLnCe)j%{uN3jg zG2Z{dhMNasH1R!lMa@%^mdOsKyf+s2yy9lH;|qk-QGv>2zu IfByad2M~m;>;M1& literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/mke2fs/util.c b/jni/e2fsprogs/mke2fs/util.c new file mode 100755 index 0000000..3e83169 --- /dev/null +++ b/jni/e2fsprogs/mke2fs/util.c @@ -0,0 +1,330 @@ +/* + * util.c --- helper functions used by tune2fs and mke2fs + * + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifdef _WIN32 +#define _POSIX +#define __USE_MINGW_ALARM +#endif + +#include "config.h" +#include +#include +#include +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LINUX_MAJOR_H +#include +#endif +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#include "et/com_err.h" +#include "e2p/e2p.h" +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "support/nls-enable.h" +#include "support/devname.h" +#include "blkid/blkid.h" +#include "util.h" + +char *journal_location_string = NULL; + +#ifndef HAVE_STRCASECMP +int strcasecmp (char *s1, char *s2) +{ + while (*s1 && *s2) { + int ch1 = *s1++, ch2 = *s2++; + if (isupper (ch1)) + ch1 = tolower (ch1); + if (isupper (ch2)) + ch2 = tolower (ch2); + if (ch1 != ch2) + return ch1 - ch2; + } + return *s1 ? 1 : *s2 ? -1 : 0; +} +#endif + +/* + * Given argv[0], return the program name. + */ +char *get_progname(char *argv_zero) +{ + char *cp; + + cp = strrchr(argv_zero, '/'); + if (!cp ) + return argv_zero; + else + return cp+1; +} + +static jmp_buf alarm_env; + +static void alarm_signal(int signal EXT2FS_ATTR((unused))) +{ + longjmp(alarm_env, 1); +} + +void proceed_question(int delay) +{ + char buf[256]; + const char *short_yes = _("yY"); + const char *english_yes = "yY"; + + fflush(stdout); + fflush(stderr); + if (delay > 0) { + if (setjmp(alarm_env)) { + signal(SIGALRM, SIG_IGN); + printf("%s", _("\n")); + return; + } + signal(SIGALRM, alarm_signal); + printf(_("Proceed anyway (or wait %d seconds to proceed) ? (y,N) "), + delay); + alarm(delay); + } else + fputs(_("Proceed anyway? (y,N) "), stdout); + buf[0] = 0; + if (!fgets(buf, sizeof(buf), stdin) || + strchr(_("nN"), buf[0]) || + !(strchr(short_yes, buf[0]) || + strchr(english_yes, buf[0]))) { + putc('\n', stdout); + exit(1); + } + signal(SIGALRM, SIG_IGN); +} + +void check_mount(const char *device, int force, const char *type) +{ + errcode_t retval; + int mount_flags; + + retval = ext2fs_check_if_mounted(device, &mount_flags); + if (retval) { + com_err("ext2fs_check_if_mount", retval, + _("while determining whether %s is mounted."), + device); + return; + } + if (mount_flags & EXT2_MF_MOUNTED) { + fprintf(stderr, _("%s is mounted; "), device); + if (force >= 2) { + fputs(_("mke2fs forced anyway. Hope /etc/mtab is " + "incorrect.\n"), stderr); + return; + } + abort_mke2fs: + fprintf(stderr, _("will not make a %s here!\n"), type); + exit(1); + } + if (mount_flags & EXT2_MF_BUSY) { + fprintf(stderr, _("%s is apparently in use by the system; "), + device); + if (force >= 2) { + fputs(_("mke2fs forced anyway.\n"), stderr); + return; + } + goto abort_mke2fs; + } +} + +void parse_journal_opts(const char *opts) +{ + char *buf, *token, *next, *p, *arg; + int len; + int journal_usage = 0; + + len = strlen(opts); + buf = malloc(len+1); + if (!buf) { + fputs(_("Couldn't allocate memory to parse journal " + "options!\n"), stderr); + exit(1); + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p+1; + } + arg = strchr(token, '='); + if (arg) { + *arg = 0; + arg++; + } +#if 0 + printf("Journal option=%s, argument=%s\n", token, + arg ? arg : "NONE"); +#endif + if (strcmp(token, "device") == 0) { + journal_device = get_devname(NULL, arg, NULL); + if (!journal_device) { + if (arg) + fprintf(stderr, _("\nCould not find " + "journal device matching %s\n"), + arg); + journal_usage++; + continue; + } + } else if (strcmp(token, "size") == 0) { + if (!arg) { + journal_usage++; + continue; + } + journal_size = strtoul(arg, &p, 0); + if (*p) + journal_usage++; + } else if (strcmp(token, "fast_commit_size") == 0) { + if (!arg) { + journal_usage++; + continue; + } + journal_fc_size = strtoul(arg, &p, 0); + if (*p) + journal_usage++; + } else if (!strcmp(token, "location")) { + if (!arg) { + journal_usage++; + continue; + } + journal_location_string = strdup(arg); + } else if (strcmp(token, "v1_superblock") == 0) { + journal_flags |= EXT2_MKJOURNAL_V1_SUPER; + continue; + } else + journal_usage++; + } + if (journal_usage) { + fputs(_("\nBad 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" + "\tlocation=\n\n" + "The journal size must be between " + "1024 and 10240000 filesystem blocks.\n\n"), stderr); + free(buf); + exit(1); + } + free(buf); +} + +static inline int jsize_to_blks(ext2_filsys fs, int size) +{ + return (size * 1024) / (fs->blocksize / 1024); +} + +/* Fast commit size is in KBs */ +static inline int fcsize_to_blks(ext2_filsys fs, int size) +{ + return (size * 1024) / (fs->blocksize); +} + +/* + * Determine the number of journal blocks to use, either via + * user-specified # of megabytes, or via some intelligently selected + * defaults. + * + * Find a reasonable journal file size (in blocks) given the number of blocks in + * the filesystem. For very small filesystems, it is not reasonable to have a + * journal that fills more than half of the filesystem. + */ +void figure_journal_size(struct ext2fs_journal_params *jparams, + int requested_j_size, int requested_fc_size, ext2_filsys fs) +{ + int total_blocks, ret; + + ret = ext2fs_get_journal_params(jparams, fs); + if (ret) { + fputs(_("\nFilesystem too small for a journal\n"), stderr); + return; + } + + if (requested_j_size > 0 || + (ext2fs_has_feature_fast_commit(fs->super) && requested_fc_size > 0)) { + if (requested_j_size > 0) + jparams->num_journal_blocks = + jsize_to_blks(fs, requested_j_size); + if (ext2fs_has_feature_fast_commit(fs->super) && + requested_fc_size > 0) + jparams->num_fc_blocks = + fcsize_to_blks(fs, requested_fc_size); + else if (!ext2fs_has_feature_fast_commit(fs->super)) + jparams->num_fc_blocks = 0; + total_blocks = jparams->num_journal_blocks + jparams->num_fc_blocks; + if (total_blocks < 1024 || total_blocks > 10240000) { + fprintf(stderr, _("\nThe total requested journal " + "size is %d blocks; it must be\n" + "between 1024 and 10240000 blocks. " + "Aborting.\n"), + total_blocks); + exit(1); + } + if ((unsigned int) total_blocks > ext2fs_free_blocks_count(fs->super) / 2) { + fputs(_("\nTotal journal size too big for filesystem.\n"), + stderr); + exit(1); + } + } +} + +void print_check_message(int mnt, unsigned int check) +{ + if (mnt < 0) + mnt = 0; + if (!mnt && !check) + return; + printf(_("This filesystem will be automatically " + "checked every %d mounts or\n" + "%g days, whichever comes first. " + "Use tune2fs -c or -i to override.\n"), + mnt, ((double) check) / (3600 * 24)); +} + +void dump_mmp_msg(struct mmp_struct *mmp, const char *msg) +{ + + if (msg) + printf("MMP check failed: %s\n", msg); + if (mmp) { + time_t t = mmp->mmp_time; + + printf("MMP error info: node: %.*s, device: %.*s, updated: %s", + EXT2_LEN_STR(mmp->mmp_nodename), + EXT2_LEN_STR(mmp->mmp_bdevname), ctime(&t)); + } +} diff --git a/jni/e2fsprogs/mke2fs/util.o b/jni/e2fsprogs/mke2fs/util.o new file mode 100755 index 0000000000000000000000000000000000000000..c3822ed39068ce83cff0ad8e4b438ed389d7cfa8 GIT binary patch literal 11056 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 literal 0 HcmV?d00001 diff --git a/out/Makefile b/out/Makefile deleted file mode 100755 index 4f51c95..0000000 --- a/out/Makefile +++ /dev/null @@ -1,152 +0,0 @@ -# By YZBruh - -# Copyright 2024 Partition Manager -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##### -# sub-make for installing-uninstalling -##### - -THIS_IS := out - -# include needed variables -include ../Makefile.inc --include $(BUILD)/config/INS_STAT.mk --include $(BUILD)/config/UNINS_STAT.mk - -INSTALL_PROGRESS_LIST := \ - really_termux \ - welcome \ - check_ins_stat \ - deb_installer \ - really_builded \ - install_binary - -UNINSTALL_PROGRESS_LIST := \ - really_termux \ - welcome \ - check_unins_stat \ - uninstall_$(TARGET) - -# create an empty target -all: - $(P) "" - -# installer -.PHONY: install -install: $(INSTALL_PROGRESS_LIST) - -# uninstaller -.PHONY: uninstall -uninstall: $(UNINSTALL_PROGRESS_LIST) - -install_binary: - $(E) " - Installing binary..." - if cp $(BINARY_DIR)/$(TARGET) /data/data/com.termux/files/usr/bin/$(TARGET); then \ - $(E_NS) " - Setting up permissions..."; \ - else \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi; \ - if chmod 777 $(TERMUX_BIN)/$(TARGET); then \ - $(E_NS) " - Saving current status..."; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi; \ - $(P) " - Success.\n\n"; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - $(E_NS) "UNINSTALLED_SUCCESS := " > $(BUILD)/config/UNINS_STAT.mk - @ exit 0 - -uninstall_$(TARGET): - if [ -f $(TERMUX_USR)/share/man/man8/$(TARGET).8.gz ]; then \ - $(E_NS) " - It was found to be established by $(TARGET)'s deb pack. It's removed with apt..."; \ - apt remove -y $(TARGET) || exit 1; \ - $(P) " - Success.\n\n"; \ - $(E_NS) "UNINSTALLED_SUCCESS := true" > $(BUILD)/config/UNINS_STAT.mk; \ - $(E_NS) "INSTALL_SUCCESS := " > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) " - It was found that pmt was manually established (with this makefile or copying). Manually removed..."; \ - if rm $(TERMUX_BIN)/$(TARGET); then \ - $(P) " - Success.\n\n"; \ - $(E_NS) "UNINSTALLED_SUCCESS := true" > $(BUILD)/config/UNINS_STAT.mk; \ - $(E_NS) "INSTALL_SUCCESS := " > $(BUILD)/config/INS_STAT.mk; \ - else \ - $(E_NS) "UNINSTALLED_SUCCESS := false" > $(BUILD)/config/UNINS_STAT.mk; \ - exit 1; \ - fi; \ - fi - -deb_installer: - if [ -f $(DEB_DIR)/*.deb ]; then \ - $(E_NS) " - The created deb pack was found. It's setup..."; \ - cd $(DEB_DIR) || exit 1; \ - apt install ./*.deb || exit 1; \ - if [ ! "$?" = "0" ]; then \ - cd $(CUR_DIR); \ - $(P) " - Success.\n\n"; \ - $(E_NS) "INSTALL_SUCCESS := true" > $(BUILD)/config/INS_STAT.mk; \ - $(E_NS) "UNINSTALLED_SUCCESS := " > $(BUILD)/config/UNINS_STAT.mk; \ - cd ..; \ - exit 0; \ - else \ - cd $(CUR_DIR); \ - $(P) " - $(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) installing failed!\n"; \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - cd ..; \ - exit 1; \ - fi; \ - fi - -check_ins_stat: - @ if [ ! "$(INSTALL_SUCCESS)" = "true" ] && [ ! "$(INSTALL_SUCCESS)" = "" ]; then \ - $(P) " - $(YELLOW)$(BOLD)Warning:$(BOLD_RESET)$(RESET) a previously-stayed failed installation process found\n"; \ - fi - -check_unins_stat: - @ if [ ! "$(UNINSTALL_SUCCESS)" = "true" ] && [ ! "$(UNINSTALL_SUCCESS)" = "" ]; then \ - $(P) " - $(YELLOW)$(BOLD)Warning:$(BOLD_RESET)$(RESET) a previously-stayed failed uninstallation process found\n"; \ - fi - -welcome: - $(E) " ----------- $(TARGET) $(PROG)er ----------- " - @ if [ "$(PROG)" = "uninstall" ]; then \ - if [ ! -f $(TERMUX_BIN)/$(TARGET) ]; then \ - $(E_NS) " - $(TARGET) already $(PROG)ed"; \ - exit 1; \ - fi; \ - fi - @ if [ "$(PROG)" = "install" ]; then \ - if [ -f $(TERMUX_BIN)/$(TARGET) ]; then \ - $(E_NS) " - $(TARGET) already $(PROG)ed"; \ - exit 1; \ - fi; \ - fi - -really_termux: - @ if [ ! -f $(TERMUX_BIN)/termux-open ]; then \ - $(P) "$(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) This function is only available on Termux.\n"; \ - exit 1; \ - fi - -really_builded: - if [ ! -f $(BINARY_DIR)/$(TARGET) ]; then \ - $(P) " - $(RED)$(BOLD)Error:$(BOLD_RESET)$(RESET) Package not builded! Please build package and try again \n"; \ - $(E_NS) "INSTALL_SUCCESS := false" > $(BUILD)/config/INS_STAT.mk; \ - exit 1; \ - fi - -# end diff --git a/pmt-termux.sh b/pmt-termux.sh index ffc5f36..6e26af9 100755 --- a/pmt-termux.sh +++ b/pmt-termux.sh @@ -3,7 +3,8 @@ # By YZBruh | ShawkTeam # Variables -LOCAL_VERSION="2.8.0" +LOCAL_VERSION="2.9.0" +LOCAL_RELDATE="" LOCAL_OWNER="ShawkTeam" LOCAL_REPO="pmt" LOCAL_RELEASE_TAG="${LOCAL_VERSION}" @@ -59,10 +60,7 @@ function view_help() printc " uninstall, -u Uninstall Partition Manager." printc " status, -s Display install/uninstall status." printc " --setup, -S Setup required packages." - printc " --package If you already have a debug package, make\n setup by specifying this way." - printc " --binary Setup binary instead of the deb pack." - printc " --compress-algorithm [ALGO] Speficy custom algorithm for extracting package (if only custom package specified)." - printc "Supported algorithms: xz, gzip, zip, 7z, tar, tar.xz, tar.gz\n" + printc " --package If you already have a pmt package, make\n setup by specifying this way." printc "Report bugs to " exit 0 @@ -71,7 +69,7 @@ function view_help() # Script really operated termux proclamation? function really_termux() { - ls "${LOCAL_PREFIX}/bin" | grep "termux" &>/dev/null \ + basename -a ${LOCAL_PREFIX}/bin/* | grep "termux" &>/dev/null \ || abort "Are you sure you're in termux?" } @@ -116,6 +114,14 @@ function check_status() exit 0 } +# check xz-utils install status +function check_xz() +{ + # The outflow of the APT is not controlled in use + [ -f ${LOCAL_PREFIX}/bin/xz ] \ + || abort "xz-utils not installed! Run setup command." +} + # Check internet connection function net_control() { @@ -126,21 +132,20 @@ function net_control() # Download Partition Manager function download() { - local URL + local URL="https://github.com/${LOCAL_OWNER}/${LOCAL_REPO}/releases/tag/${LOCAL_RELEASE_TAG}/download/pmt-${LOCAL_ARCH}-${LOCAL_RELDATE}.xz" + local URL_MANDOC="https://github.com/${LOCAL_OWNER}/${LOCAL_REPO}/releases/tag/${LOCAL_RELEASE_TAG}/download/mandoc.gz" - if [ "${BINARY}" = 1 -a "${PACKAGE}" != 1 ]; then - URL="https://github.com/${LOCAL_OWNER}/${LOCAL_REPO}/releases/tag/${LOCAL_RELEASE_TAG}/download/pmt-${LOCAL_ARCH}.xz" - else - URL="https://github.com/${LOCAL_OWNER}/${LOCAL_REPO}/releases/tag/${LOCAL_RELEASE_TAG}/download/pmt-${LOCAL_ARCH}.deb" - fi - - print "Downloading: \`${URL}'" - - curl -L "${URL}" -o "${LOCAL_TMPDIR}/pmt-${LOCAL_ARCH}.deb" &>/dev/null \ + print "Downloading: 'pmt-${LOCAL_ARCH}-${LOCAL_RELDATE}.xz'..." + curl -L "${URL}" -o "${LOCAL_TMPDIR}/pmt-${LOCAL_ARCH}.xz" &>/dev/null \ || abort "Download failed!" - chmod -R 777 "${LOCAL_TMPDIR}" \ - || warning "Cannot set mode '777' on installed sources." + HAVE_MANDOC=true + print "Downloading mandoc..." + curl -L "${URL_MANDOC}" -o "${LOCAL_TMPDIR}/pmt.8.gz" &>/dev/null \ + || warning "Download failed! (mandoc)" + + chmod -R 755 "${LOCAL_TMPDIR}" &>/dev/null \ + || warning "Cannot set mode '777' on downloaded files." } # For installing required packages @@ -149,14 +154,11 @@ function setup_packages() net_control print "Updating mirrors..." - if ! pkg update &>/dev/null || [ "$?" != 0 ]; then - abort "Updating failed!" - fi + pkg update &>/dev/null || abort "Updating failed!" - print "Installing: 'xz-utils, p7zip'" - if ! pkg install -y xz-utils p7zip || [ "$?" != 0 ]; then - abort "Installing failed!" - fi + print "Installing xz-utils..." + pkg install -y xz-utils &>/dev/null \ + || abort "Installing failed!" print "Success." exit 0 @@ -165,56 +167,45 @@ function setup_packages() # Install deb package function install_fn() { - local mydir="$(pwd)" + local mydir="${PWD}" [ "${LOCAL_PACKAGE}" = "" ] || local bname=$(basename ${LOCAL_PACKAGE}) - [ "${PACKAGE}" = 1 ] && \ + ${PACKAGE} && \ if [ ! -f "${LOCAL_PACKAGE}" ]; then [ -d "${LOCAL_PACKAGE}" ] \ && abort "\`${LOCAL_PACKAGE}': is directory." abort "\`${LOCAL_PACKAGE}': no such file." else - cp "${LOCAL_PACKAGE}" "${LOCAL_TMPDIR}" + cp "${LOCAL_PACKAGE}" "${LOCAL_TMPDIR}/pmt-${LOCAL_ARCH}.xz" fi cd "${LOCAL_TMPDIR}" - [ "${BINARY}" = 1 -a "${NONE_ALGO}" != 1 ] \ - && print "Extracting '${bname}'..." && \ - if eval "${ALGO_DEC} ${ALGO_FLAGS} ${LOCAL_TMPDIR}/${bname}" &>/dev/null; then - rm -f "${bname}" + print "Extracting package..." + if xz -d "$(basename *.xz)" ; then + rm -f "pmt*.xz" else - abort "Failed! Try speficing algorithm." + abort "Failed! Cannot extract pmt package." fi - [ "$(basename *)" = "*" ] \ - && abort "Deb pack or binary file was not found!" + [ -z $(basename "pmt-*") ] \ + && abort "Extracted binary file was not found!" + mv "$(basename pmt-*)" pmt - bname=$(basename *) - - if [ "${BINARY}" = 1 ]; then - mv "${bname}" pmt &>/dev/null - - print "Copying..." - cp pmt "${LOCAL_PREFIX}/bin/pmt" &>/dev/null \ - || abort "Copying failed" - - print "Setting up permissions..." - chmod 777 "${LOCAL_PREFIX}/bin/pmt" &>/dev/null \ - || abort "Cannot set permissions!" - - print "Success." - return + print "Installing..." + cp pmt "${LOCAL_PREFIX}/bin/pmt" &>/dev/null \ + || abort "Installing failed!" + + if ${HAVE_MANDOC}; then + print "Installing mandoc (force)..." + cp -f pmt.8.gz ${LOCAL_PREFIX}/share/man/man8 &>/dev/null + chmod 755 ${LOCAL_PREFIX}/share/man/man8/pmt.8.gz &>/dev/null fi - print "Installing Partition Manager with APT..." - if ! apt -y install ./pmt-${LOCAL_ARCH}.deb; then - warning "Installing failed with APT. Trying installing with dpkg..." - - dpkg install pmt-${LOCAL_ARCH}.deb &>/dev/null \ - || abort "Cannot install Partition Manager!" - fi + print "Setting up permissions for binary..." + chmod 755 "${LOCAL_PREFIX}/bin/pmt" &>/dev/null \ + || abort "Failed to set permissions!" print "Success." cd "${mydir}" @@ -223,27 +214,21 @@ function install_fn() # Uninstall deb package function uninstall_fn() { - [ "${BINARY}" = 1 ] \ - && print "Removing binary..." && \ + print "Uninstalling Partition Manager..." && \ if rm "${LOCAL_PREFIX}/bin/pmt" &>/dev/null; then print "Success." - return else abort "Failed!" fi - print "Uninstalling Partition Manager with APT..." - if ! apt -y remove pmt &>/dev/null; then - warning "Uninstalling failed with APT. Trying uninstalling with dpkg..." - - dpkg remove pmt &>/dev/null \ - || abort "Cannot uninstall Partition Manager!" - fi - - print "Success." + rm -f ${LOCAL_PREFIX}/share/man/man8/pmt.8.gz } -trap "abort Interrput; cleanup" SIGINT +trap "abort Interrupt." SIGINT +trap "cleanup" SIGQUIT +PACKAGE=false +ALREADY_SHIFT=false +HAVE_MANDOC=false # set -x # Process arguments @@ -267,73 +252,48 @@ while (($# >= 1)); do setup_packages ;; --package) - PACKAGE=1 + PACKAGE=true + [ -z ${2} ] \ + && printc "Option '--package' requires an argument (file)." \ + && exit 1 LOCAL_PACKAGE="${2}" - ;; - --binary) - BINARY=1 - ;; - --not-compressed) - NOT_COMP=1 - ;; - --compress-algorithm) - ALGO_SPEC=1 - [ -z "${2}" ] \ - && abort "'--compress-algorithm' requires an argument." - case "${2}" in - xz|gzip|zip|7z|tar|tar.xz|tar.gz) - if echo "${2}" | grep "tar." &>/dev/null; then - ALGO_DEC="tar" - ALGO_FLAGS="-xf" - elif [ "${2}" = "zip" ]; then - ALGO_DEC="unzip" - ALGO_FLAGS= - elif [ "${2}" = "7z" ]; then - ALGO_DEC="7z" - ALGO_FLAGS="x" - else - ALGO_DEC="${2}" - ALGO_FLAGS="-d" - fi - ;; - none) - NONE_ALGO=1 - ;; - *) - abort "Unknown compress algorithm: ${2}" - ;; - esac + ALREADY_SHIFT=true && shift 1 ;; --help) view_help ;; + *) + if echo ${1} | grep "-" &>/dev/null; then + if ! echo ${1} | grep ".xz" &>/dev/null; then + printc "Unknown option: ${1}" \ + exit 1 + else + break; + fi + else + break + fi + ;; esac - shift 1 + ${ALREADY_SHIFT} || shift 1 done ### Main ### [ -z "${1}" -a "${SOME_SPEC}" != 1 ] && view_help script_head - -[ -z "${LOCAL_PACKAGE}" -a "${PACKAGE}" = 1 ] \ -&& abort "'--package' requires an argument (file)." - really_termux gen_tempdir -[ -z "${ALGO_DEC}" ] && ALGO_DEC="xz" && ALGO_FLAGS="-d" -[ "${ALGO_SPEC}" = 1 -a "${PACKAGE}" != 1 ] \ -&& abort "Compression algorithm cannot be specified without package specification option." - if [ "${PROCESS}" = 1 ]; then [ -f "${LOCAL_PREFIX}/bin/pmt" ] \ && abort "Partition Manager already installed." - [ "${PACKAGE}" = 1 ] || net_control + ${PACKAGE} || net_control + check_xz get_architecture print "Starting install process..." - [ "${PACKAGE}" = 1 ] || download + ${PACKAGE} || download install_fn elif [ "${PROCESS}" = 2 ]; then [ ! -f "${LOCAL_PREFIX}/bin/pmt" ] \

P(y^$wp*$)_==uI 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 +#include +#include + +#pragma warning(pop) + + +// +// Some native APIs. +// + +NTSYSAPI +ULONG +NTAPI +RtlNtStatusToDosError( + IN NTSTATUS Status + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtClose( + IN HANDLE Handle + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtOpenFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtFlushBuffersFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtReadFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtWriteFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtDeviceIoControlFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtFsControlFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtDelayExecution( + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Interval + ); + + +#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +// +// useful macros +// + +#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0))) + + +// +// Include Win32 error codes. +// + +#include + +// +// standard stuff +// + +#include +#include +#include +#include +#include + +#include +#include "ext2_fs.h" +#include + +#include "et/com_err.h" +#include "ext2fs/ext2fs.h" +#include "ext2fs/ext2_err.h" + + + + +// +// For checking structure magic numbers... +// + + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +#define EXT2_ET_MAGIC_NT_IO_CHANNEL 0x10ed + + +// +// Private data block +// + +typedef struct _NT_PRIVATE_DATA { + int magic; + HANDLE Handle; + int Flags; + PCHAR Buffer; + __u32 BufferBlockNumber; + ULONG BufferSize; + BOOLEAN OpenedReadonly; + BOOLEAN Written; +}NT_PRIVATE_DATA, *PNT_PRIVATE_DATA; + + + +// +// Standard interface prototypes +// + +static errcode_t nt_open(const char *name, int flags, io_channel *channel); +static errcode_t nt_close(io_channel channel); +static errcode_t nt_set_blksize(io_channel channel, int blksize); +static errcode_t nt_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t nt_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t nt_flush(io_channel channel); + +static struct struct_io_manager struct_nt_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "NT I/O Manager", + .open = nt_open, + .close = nt_close, + .set_blksize = nt_set_blksize, + .read_blk = nt_read_blk, + .write_blk = nt_write_blk, + .flush = nt_flush +}; + +// +// function to get API +// + +io_manager nt_io_manager() +{ + return &struct_nt_manager; +} + + + + + +// +// This is a code to convert Win32 errors to unix errno +// + +typedef struct { + ULONG WinError; + int errnocode; +}ERROR_ENTRY; + +static ERROR_ENTRY ErrorTable[] = { + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, + { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, + { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, + { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } +}; + + + + +static +unsigned +_MapDosError ( + IN ULONG WinError + ) +{ + int i; + + // + // Lookup + // + + for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) + { + if (WinError == ErrorTable[i].WinError) + { + return ErrorTable[i].errnocode; + } + } + + // + // not in table. Check ranges + // + + if ((WinError >= ERROR_WRITE_PROTECT) && + (WinError <= ERROR_SHARING_BUFFER_EXCEEDED)) + { + return EACCES; + } + else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) && + (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN)) + { + return ENOEXEC; + } + else + { + return EINVAL; + } +} + + + + + + + +// +// Function to map NT status to dos error. +// + +static +__inline +unsigned +_MapNtStatus( + IN NTSTATUS Status + ) +{ + return _MapDosError(RtlNtStatusToDosError(Status)); +} + + + + + +// +// Helper functions to make things easier +// + +static +NTSTATUS +_OpenNtName( + IN PCSTR Name, + IN BOOLEAN Readonly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL + ) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + WCHAR Buffer[512]; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + // + // Make Unicode name from input string + // + + UnicodeString.Buffer = &Buffer[0]; + UnicodeString.Length = 0; + UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!! + + RtlInitAnsiString(&AnsiString, Name); + + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + + if(!NT_SUCCESS(Status)) + { + return Status; // Unmappable character? + } + + // + // Initialize object + // + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + // + // Try to open it in initial mode + // + + if(ARGUMENT_PRESENT(OpenedReadonly)) + { + *OpenedReadonly = Readonly; + } + + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + + if(!NT_SUCCESS(Status)) + { + // + // Maybe was just mounted? wait 0.5 sec and retry. + // + + LARGE_INTEGER Interval; + Interval.QuadPart = -5000000; // 0.5 sec. from now + + NtDelayExecution(FALSE, &Interval); + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + + // + // Try to satisfy mode + // + + if((STATUS_ACCESS_DENIED == Status) && !Readonly) + { + if(ARGUMENT_PRESENT(OpenedReadonly)) + { + *OpenedReadonly = TRUE; + } + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + } + } + + + + // + // done + // + + return Status; +} + + +static +NTSTATUS +_OpenDriveLetter( + IN CHAR Letter, + IN BOOLEAN ReadOnly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL + ) +{ + CHAR Buffer[100]; + + sprintf(Buffer, "\\DosDevices\\%c:", Letter); + + return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly); +} + + +// +// Flush device +// + +static +__inline +NTSTATUS +_FlushDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFlushBuffersFile(Handle, &IoStatusBlock); +} + + +// +// lock drive +// + +static +__inline +NTSTATUS +_LockDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0); +} + + +// +// unlock drive +// + +static +__inline +NTSTATUS +_UnlockDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0); +} + +static +__inline +NTSTATUS +_DismountDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); +} + + +// +// is mounted +// + +static +__inline +BOOLEAN +_IsMounted( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0); + return (BOOLEAN)(STATUS_SUCCESS == Status); +} + + +static +__inline +NTSTATUS +_CloseDisk( + IN HANDLE Handle + ) +{ + return NtClose(Handle); +} + + + + +// +// Make NT name from any recognized name +// + +static +PCSTR +_NormalizeDeviceName( + IN PCSTR Device, + IN PSTR NormalizedDeviceNameBuffer + ) +{ + int PartitionNumber = -1; + UCHAR DiskNumber; + PSTR p; + + + // + // Do not try to parse NT name + // + + if('\\' == *Device) + return Device; + + + + // + // Strip leading '/dev/' if any + // + + if(('/' == *(Device)) && + ('d' == *(Device + 1)) && + ('e' == *(Device + 2)) && + ('v' == *(Device + 3)) && + ('/' == *(Device + 4))) + { + Device += 5; + } + + if('\0' == *Device) + { + return NULL; + } + + + // + // forms: hda[n], fd[n] + // + + if('d' != *(Device + 1)) + { + return NULL; + } + + if('h' == *Device) + { + if((*(Device + 2) < 'a') || (*(Device + 2) > ('a' + 9)) || + ((*(Device + 3) != '\0') && + ((*(Device + 4) != '\0') || + ((*(Device + 3) < '0') || (*(Device + 3) > '9')) + ) + ) + ) + { + return NULL; + } + + DiskNumber = (UCHAR)(*(Device + 2) - 'a'); + + if(*(Device + 3) != '\0') + { + PartitionNumber = (*(Device + 3) - '0'); + } + + } + else if('f' == *Device) + { + // + // 3-d letter should be a digit. + // + + if((*(Device + 3) != '\0') || + (*(Device + 2) < '0') || (*(Device + 2) > '9')) + { + return NULL; + } + + DiskNumber = (UCHAR)(*(Device + 2) - '0'); + + } + else + { + // + // invalid prefix + // + + return NULL; + } + + + + // + // Prefix + // + + strcpy(NormalizedDeviceNameBuffer, "\\Device\\"); + + // + // Media name + // + + switch(*Device) + { + + case 'f': + strcat(NormalizedDeviceNameBuffer, "Floppy0"); + break; + + case 'h': + strcat(NormalizedDeviceNameBuffer, "Harddisk0"); + break; + } + + + p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; + *p = (CHAR)(*p + DiskNumber); + + + // + // Partition nr. + // + + if(PartitionNumber >= 0) + { + strcat(NormalizedDeviceNameBuffer, "\\Partition0"); + + p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; + *p = (CHAR)(*p + PartitionNumber); + } + + + return NormalizedDeviceNameBuffer; +} + + + + +static +VOID +_GetDeviceSize( + IN HANDLE h, + OUT unsigned __int64 *FsSize + ) +{ + PARTITION_INFORMATION pi; + DISK_GEOMETRY gi; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + + // + // Zero it + // + + *FsSize = 0; + + // + // Call driver + // + + RtlZeroMemory(&pi, sizeof(PARTITION_INFORMATION)); + + Status = NtDeviceIoControlFile( + h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO, + &pi, sizeof(PARTITION_INFORMATION), + &pi, sizeof(PARTITION_INFORMATION)); + + + if(NT_SUCCESS(Status)) + { + *FsSize = pi.PartitionLength.QuadPart; + } + else if(STATUS_INVALID_DEVICE_REQUEST == Status) + { + // + // No partitions: get device info. + // + + RtlZeroMemory(&gi, sizeof(DISK_GEOMETRY)); + + Status = NtDeviceIoControlFile( + h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, + &gi, sizeof(DISK_GEOMETRY), + &gi, sizeof(DISK_GEOMETRY)); + + + if(NT_SUCCESS(Status)) + { + *FsSize = + gi.BytesPerSector * + gi.SectorsPerTrack * + gi.TracksPerCylinder * + gi.Cylinders.QuadPart; + } + + } +} + + + +// +// Open device by name. +// + +static +BOOLEAN +_Ext2OpenDevice( + IN PCSTR Name, + IN BOOLEAN ReadOnly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL, + OUT unsigned *Errno OPTIONAL + ) +{ + CHAR NormalizedDeviceName[512]; + NTSTATUS Status; + + if(NULL == Name) + { + // + // Set not found + // + + if(ARGUMENT_PRESENT(Errno)) + *Errno = ENOENT; + + return FALSE; + } + + + if((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') && + (':' == *(Name + 1)) && ('\0' == *(Name + 2))) + { + Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly); + } + else + { + // + // Make name + // + + Name = _NormalizeDeviceName(Name, NormalizedDeviceName); + + if(NULL == Name) + { + // + // Set not found + // + + if(ARGUMENT_PRESENT(Errno)) + *Errno = ENOENT; + + return FALSE; + } + + // + // Try to open it + // + + Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly); + } + + + if(!NT_SUCCESS(Status)) + { + if(ARGUMENT_PRESENT(Errno)) + *Errno = _MapNtStatus(Status); + + return FALSE; + } + + return TRUE; +} + + +// +// Raw block io. Sets dos errno +// + +static +BOOLEAN +_BlockIo( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + IN OUT PCHAR Buffer, + IN BOOLEAN Read, + OUT unsigned* Errno + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + // + // Should be aligned + // + + ASSERT(0 == (Bytes % 512)); + ASSERT(0 == (Offset.LowPart % 512)); + + + // + // perform io + // + + if(Read) + { + Status = NtReadFile(Handle, NULL, NULL, NULL, + &IoStatusBlock, Buffer, Bytes, &Offset, NULL); + } + else + { + Status = NtWriteFile(Handle, NULL, NULL, NULL, + &IoStatusBlock, Buffer, Bytes, &Offset, NULL); + } + + + // + // translate error + // + + if(NT_SUCCESS(Status)) + { + *Errno = 0; + return TRUE; + } + + *Errno = _MapNtStatus(Status); + + return FALSE; +} + + + +__inline +BOOLEAN +_RawWrite( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + OUT const CHAR* Buffer, + OUT unsigned* Errno + ) +{ + return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno); +} + +__inline +BOOLEAN +_RawRead( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + IN PCHAR Buffer, + OUT unsigned* Errno + ) +{ + return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno); +} + + + +__inline +BOOLEAN +_SetPartType( + IN HANDLE Handle, + IN UCHAR Type + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return STATUS_SUCCESS == NtDeviceIoControlFile( + Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_PARTITION_INFO, + &Type, sizeof(Type), + NULL, 0); +} + + + +//--------------------- interface part + +// +// Interface functions. +// Is_mounted is set to 1 if the device is mounted, 0 otherwise +// + +errcode_t +ext2fs_check_if_mounted(const char *file, int *mount_flags) +{ + HANDLE h; + BOOLEAN Readonly; + + *mount_flags = 0; + + if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) + { + return 0; + } + + + __try{ + *mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0; + } + __finally{ + _CloseDisk(h); + } + + return 0; +} + + + +// +// Returns the number of blocks in a partition +// + +static __int64 FsSize = 0; +static char knowndevice[1024] = ""; + + +errcode_t +ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks) +{ + HANDLE h; + BOOLEAN Readonly; + + if((0 == FsSize) || (0 != strcmp(knowndevice, file))) + { + + if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) + { + return 0; + } + + + __try{ + + // + // Get size + // + + _GetDeviceSize(h, &FsSize); + strcpy(knowndevice, file); + } + __finally{ + _CloseDisk(h); + } + + } + + *retblocks = (blk_t)(unsigned __int64)(FsSize / blocksize); + UNREFERENCED_PARAMETER(file); + return 0; +} + + + + + + +// +// Table elements +// + + +static +errcode_t +nt_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + PNT_PRIVATE_DATA NtData = NULL; + errcode_t Errno = 0; + + // + // Check name + // + + if (NULL == name) + { + return EXT2_ET_BAD_DEVICE_NAME; + } + + __try{ + + // + // Allocate channel handle + // + + io = (io_channel) malloc(sizeof(struct struct_io_channel)); + + if (NULL == io) + { + Errno = ENOMEM; + __leave; + } + + RtlZeroMemory(io, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + + NtData = (PNT_PRIVATE_DATA)malloc(sizeof(NT_PRIVATE_DATA)); + + if (NULL == NtData) + { + Errno = ENOMEM; + __leave; + } + + + io->manager = nt_io_manager(); + io->name = malloc(strlen(name) + 1); + if (NULL == io->name) + { + Errno = ENOMEM; + __leave; + } + + strcpy(io->name, name); + io->private_data = NtData; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + // + // Initialize data + // + + RtlZeroMemory(NtData, sizeof(NT_PRIVATE_DATA)); + + NtData->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL; + NtData->BufferBlockNumber = 0xffffffff; + NtData->BufferSize = 1024; + NtData->Buffer = malloc(NtData->BufferSize); + + if (NULL == NtData->Buffer) + { + Errno = ENOMEM; + __leave; + } + + // + // Open it + // + + if(!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &NtData->Handle, &NtData->OpenedReadonly, &Errno)) + { + __leave; + } + + + // + // get size + // + + _GetDeviceSize(NtData->Handle, &FsSize); + strcpy(knowndevice, name); + + + // + // Lock/dismount + // + + if(!NT_SUCCESS(_LockDrive(NtData->Handle)) /*|| !NT_SUCCESS(_DismountDrive(NtData->Handle))*/) + { + NtData->OpenedReadonly = TRUE; + } + + // + // Done + // + + *channel = io; + + + } + __finally{ + + if(0 != Errno) + { + // + // Cleanup + // + + if (NULL != io) + { + free(io->name); + free(io); + } + + if (NULL != NtData) + { + if(NULL != NtData->Handle) + { + _UnlockDrive(NtData->Handle); + _CloseDisk(NtData->Handle); + } + + free(NtData->Buffer); + free(NtData); + } + } + } + + return Errno; +} + + +// +// Close api +// + +static +errcode_t +nt_close(io_channel channel) +{ + PNT_PRIVATE_DATA NtData = NULL; + + if(NULL == channel) + { + return 0; + } + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if (--channel->refcount > 0) + { + return 0; + } + + free(channel->name); + free(channel); + + if (NULL != NtData) + { + if(NULL != NtData->Handle) + { + _DismountDrive(NtData->Handle); + _UnlockDrive(NtData->Handle); + _CloseDisk(NtData->Handle); + } + + free(NtData->Buffer); + free(NtData); + } + + return 0; +} + + + +// +// set block size +// + +static +errcode_t +nt_set_blksize(io_channel channel, int blksize) +{ + PNT_PRIVATE_DATA NtData = NULL; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if (channel->block_size != blksize) + { + channel->block_size = blksize; + + free(NtData->Buffer); + NtData->BufferBlockNumber = 0xffffffff; + NtData->BufferSize = channel->block_size; + ASSERT(0 == (NtData->BufferSize % 512)); + + NtData->Buffer = malloc(NtData->BufferSize); + + if (NULL == NtData->Buffer) + { + return ENOMEM; + } + + } + + return 0; +} + + +// +// read block +// + +static +errcode_t +nt_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + PVOID BufferToRead; + ULONG SizeToRead; + ULONG Size; + LARGE_INTEGER Offset; + PNT_PRIVATE_DATA NtData = NULL; + unsigned Errno = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + // + // If it's in the cache, use it! + // + + if ((1 == count) && + (block == NtData->BufferBlockNumber) && + (NtData->BufferBlockNumber != 0xffffffff)) + { + memcpy(buf, NtData->Buffer, channel->block_size); + return 0; + } + + Size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size); + + Offset.QuadPart = block * channel->block_size; + + // + // If not fit to the block + // + + if(Size <= NtData->BufferSize) + { + // + // Update the cache + // + + NtData->BufferBlockNumber = block; + BufferToRead = NtData->Buffer; + SizeToRead = NtData->BufferSize; + } + else + { + SizeToRead = Size; + BufferToRead = buf; + ASSERT(0 == (SizeToRead % channel->block_size)); + } + + if(!_RawRead(NtData->Handle, Offset, SizeToRead, BufferToRead, &Errno)) + { + + if (channel->read_error) + { + return (channel->read_error)(channel, block, count, buf, + Size, 0, Errno); + } + else + { + return Errno; + } + } + + + if(BufferToRead != buf) + { + ASSERT(Size <= SizeToRead); + memcpy(buf, BufferToRead, Size); + } + + return 0; +} + + +// +// write block +// + +static +errcode_t +nt_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + ULONG SizeToWrite; + LARGE_INTEGER Offset; + PNT_PRIVATE_DATA NtData = NULL; + unsigned Errno = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if(NtData->OpenedReadonly) + { + return EACCES; + } + + if (count == 1) + { + SizeToWrite = channel->block_size; + } + else + { + NtData->BufferBlockNumber = 0xffffffff; + + if (count < 0) + { + SizeToWrite = (ULONG)(-count); + } + else + { + SizeToWrite = (ULONG)(count * channel->block_size); + } + } + + + ASSERT(0 == (SizeToWrite % 512)); + Offset.QuadPart = block * channel->block_size; + + if(!_RawWrite(NtData->Handle, Offset, SizeToWrite, buf, &Errno)) + { + if (channel->write_error) + { + return (channel->write_error)(channel, block, count, buf, + SizeToWrite, 0, Errno); + } + else + { + return Errno; + } + } + + + // + // Stash a copy. + // + + if(SizeToWrite >= NtData->BufferSize) + { + NtData->BufferBlockNumber = block; + memcpy(NtData->Buffer, buf, NtData->BufferSize); + } + + NtData->Written = TRUE; + + return 0; + +} + + + +// +// Flush data buffers to disk. Since we are currently using a +// write-through cache, this is a no-op. +// + +static +errcode_t +nt_flush(io_channel channel) +{ + PNT_PRIVATE_DATA NtData = NULL; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if(NtData->OpenedReadonly) + { + return 0; // EACCESS; + } + + + // + // Flush file buffers. + // + + _FlushDrive(NtData->Handle); + + + // + // Test and correct partition type. + // + + if(NtData->Written) + { + _SetPartType(NtData->Handle, 0x83); + } + + return 0; +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/openfs.c b/jni/e2fsprogs/lib/ext2fs/openfs.c new file mode 100755 index 0000000..fd56a9a --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/openfs.c @@ -0,0 +1,590 @@ +/* + * openfs.c --- open an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" + +#include "ext2fs.h" +#include "e2image.h" + +blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block, + dgrp_t i) +{ + int bg; + int has_super = 0, group_zero_adjust = 0; + blk64_t ret_blk; + + /* + * On a bigalloc FS with 1K blocks, block 0 is reserved for non-ext4 + * stuff, so adjust for that if we're being asked for group 0. + */ + if (i == 0 && fs->blocksize == 1024 && EXT2FS_CLUSTER_RATIO(fs) > 1) + group_zero_adjust = 1; + + if (!ext2fs_has_feature_meta_bg(fs->super) || + (i < fs->super->s_first_meta_bg)) + return group_block + i + 1 + group_zero_adjust; + + bg = EXT2_DESC_PER_BLOCK(fs->super) * i; + if (ext2fs_bg_has_super(fs, bg)) + has_super = 1; + ret_blk = ext2fs_group_first_block2(fs, bg); + /* + * If group_block is not the normal value, we're trying to use + * the backup group descriptors and superblock --- so use the + * alternate location of the second block group in the + * metablock group. Ideally we should be testing each bg + * descriptor block individually for correctness, but we don't + * have the infrastructure in place to do that. + */ + if (group_block != fs->super->s_first_data_block && + ((ret_blk + has_super + fs->super->s_blocks_per_group) < + ext2fs_blocks_count(fs->super))) { + ret_blk += fs->super->s_blocks_per_group; + + /* + * If we're going to jump forward a block group, make sure + * that we adjust has_super to account for the next group's + * backup superblock (or lack thereof). + */ + if (ext2fs_bg_has_super(fs, bg + 1)) + has_super = 1; + else + has_super = 0; + } + return ret_blk + has_super + group_zero_adjust; +} + +blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) +{ + return ext2fs_descriptor_block_loc2(fs, group_block, i); +} + +errcode_t ext2fs_open(const char *name, int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs) +{ + return ext2fs_open2(name, 0, flags, superblock, block_size, + manager, ret_fs); +} + +static void block_sha_map_free_entry(void *data) +{ + free(data); + return; +} + +/* + * Note: if superblock is non-zero, block-size must also be non-zero. + * Superblock and block_size can be zero to use the default size. + * + * Valid flags for ext2fs_open() + * + * EXT2_FLAG_RW - Open the filesystem for read/write. + * 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. + * EXT2_FLAG_64BITS - Allow 64-bit bitfields (needed for large + * filesystems) + */ +errcode_t ext2fs_open2(const char *name, const char *io_options, + int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs) +{ + ext2_filsys fs; + errcode_t retval; + unsigned long i, first_meta_bg; + __u32 features; + unsigned int blocks_per_group, io_flags; + blk64_t group_block, blk; + char *dest, *cp; + int group_zero_adjust = 0; + unsigned int inode_size; + __u64 groups_cnt; +#ifdef WORDS_BIGENDIAN + unsigned int groups_per_block; + struct ext2_group_desc *gdp; + int j; +#endif + char *time_env; + int csum_retries = 0; + + EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + memset(fs, 0, sizeof(struct struct_ext2_filsys)); + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; + fs->flags = flags; + /* don't overwrite sb backups unless flag is explicitly cleared */ + fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; + fs->umask = 022; + + time_env = getenv("E2FSPROGS_FAKE_TIME"); + if (time_env) + fs->now = strtoul(time_env, NULL, 0); + + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); + if (retval) + goto cleanup; + strcpy(fs->device_name, name); + cp = strchr(fs->device_name, '?'); + if (!io_options && cp) { + *cp++ = 0; + io_options = cp; + } + + io_flags = 0; + if (flags & EXT2_FLAG_RW) + io_flags |= IO_FLAG_RW; + if (flags & EXT2_FLAG_EXCLUSIVE) + io_flags |= IO_FLAG_EXCLUSIVE; + if (flags & EXT2_FLAG_DIRECT_IO) + io_flags |= IO_FLAG_DIRECT_IO; + if (flags & EXT2_FLAG_THREADS) + io_flags |= IO_FLAG_THREADS; + retval = manager->open(fs->device_name, io_flags, &fs->io); + if (retval) + goto cleanup; + if (io_options && + (retval = io_channel_set_options(fs->io, io_options))) + goto cleanup; + fs->image_io = fs->io; + fs->io->app_data = fs; + retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super); + if (retval) + goto cleanup; + if (flags & EXT2_FLAG_IMAGE_FILE) { + retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), + &fs->image_header); + if (retval) + goto cleanup; + retval = io_channel_read_blk(fs->io, 0, + -(int)sizeof(struct ext2_image_hdr), + fs->image_header); + if (retval) + goto cleanup; + if (ext2fs_le32_to_cpu(fs->image_header->magic_number) != EXT2_ET_MAGIC_E2IMAGE) + return EXT2_ET_MAGIC_E2IMAGE; + superblock = 1; + block_size = ext2fs_le32_to_cpu(fs->image_header->fs_blocksize); + } + + /* + * If the user specifies a specific block # for the + * superblock, then he/she must also specify the block size! + * Otherwise, read the master superblock located at offset + * SUPERBLOCK_OFFSET from the start of the partition. + * + * Note: we only save a backup copy of the superblock if we + * are reading the superblock from the primary superblock location. + */ + if (superblock) { + if (!block_size) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + io_channel_set_blksize(fs->io, block_size); + group_block = superblock; + fs->orig_super = 0; + } else { + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); + superblock = 1; + group_block = 0; + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); + if (retval) + goto cleanup; + } +retry: + retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, + fs->super); + if (retval) + goto cleanup; + if (fs->orig_super) + memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); + + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) { + retval = 0; + if (!ext2fs_verify_csum_type(fs, fs->super)) + retval = EXT2_ET_UNKNOWN_CSUM; + if (!ext2fs_superblock_csum_verify(fs, fs->super)) { + if (csum_retries++ < 3) + goto retry; + retval = EXT2_ET_SB_CSUM_INVALID; + } + } + +#ifdef WORDS_BIGENDIAN + fs->flags |= EXT2_FLAG_SWAP_BYTES; + ext2fs_swap_super(fs->super); +#else + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + retval = EXT2_ET_UNIMPLEMENTED; + goto cleanup; + } +#endif + + if (fs->super->s_magic != EXT2_SUPER_MAGIC) + retval = EXT2_ET_BAD_MAGIC; + if (retval) + goto cleanup; + + if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) { + retval = EXT2_ET_REV_TOO_HIGH; + goto cleanup; + } + + /* + * Check for feature set incompatibility + */ + if (!(flags & EXT2_FLAG_FORCE)) { + features = fs->super->s_feature_incompat; +#ifdef EXT2_LIB_SOFTSUPP_INCOMPAT + if (flags & EXT2_FLAG_SOFTSUPP_FEATURES) + features &= ~EXT2_LIB_SOFTSUPP_INCOMPAT; +#endif + if (features & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + + features = fs->super->s_feature_ro_compat; +#ifdef EXT2_LIB_SOFTSUPP_RO_COMPAT + if (flags & EXT2_FLAG_SOFTSUPP_FEATURES) + features &= ~EXT2_LIB_SOFTSUPP_RO_COMPAT; +#endif + if ((flags & EXT2_FLAG_RW) && + (features & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { + retval = EXT2_ET_RO_UNSUPP_FEATURE; + goto cleanup; + } + + if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && + ext2fs_has_feature_journal_dev(fs->super)) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + } + + if ((fs->super->s_log_block_size > + (unsigned) (EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) || + (fs->super->s_log_cluster_size > + (unsigned) (EXT2_MAX_CLUSTER_LOG_SIZE - EXT2_MIN_CLUSTER_LOG_SIZE)) || + (fs->super->s_log_block_size > fs->super->s_log_cluster_size) || + (fs->super->s_log_groups_per_flex > 31)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + + /* + * bigalloc requires cluster-aware bitfield operations, which at the + * moment means we need EXT2_FLAG_64BITS. + */ + if (ext2fs_has_feature_bigalloc(fs->super) && + !(flags & EXT2_FLAG_64BITS)) { + retval = EXT2_ET_CANT_USE_LEGACY_BITMAPS; + goto cleanup; + } + + if (!ext2fs_has_feature_bigalloc(fs->super) && + (fs->super->s_log_block_size != fs->super->s_log_cluster_size)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(fs->super); + inode_size = EXT2_INODE_SIZE(fs->super); + if ((inode_size < EXT2_GOOD_OLD_INODE_SIZE) || + (inode_size > fs->blocksize) || + (inode_size & (inode_size - 1))) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + + /* Enforce the block group descriptor size */ + if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) && + ext2fs_has_feature_64bit(fs->super)) { + unsigned desc_size = fs->super->s_desc_size; + + if ((desc_size < EXT2_MIN_DESC_SIZE_64BIT) || + (desc_size > EXT2_MAX_DESC_SIZE) || + (desc_size & (desc_size - 1)) != 0) { + retval = EXT2_ET_BAD_DESC_SIZE; + goto cleanup; + } + } + + fs->cluster_ratio_bits = fs->super->s_log_cluster_size - + fs->super->s_log_block_size; + if (EXT2_BLOCKS_PER_GROUP(fs->super) != + EXT2_CLUSTERS_PER_GROUP(fs->super) << fs->cluster_ratio_bits) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) * + EXT2_INODE_SIZE(fs->super) + + EXT2_BLOCK_SIZE(fs->super) - 1) / + EXT2_BLOCK_SIZE(fs->super)); + if (block_size) { + if (block_size != fs->blocksize) { + retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE; + goto cleanup; + } + } + /* + * Set the blocksize to the filesystem's blocksize. + */ + io_channel_set_blksize(fs->io, fs->blocksize); + + /* + * If this is an external journal device, don't try to read + * the group descriptors, because they're not there. + */ + if (ext2fs_has_feature_journal_dev(fs->super)) { + fs->group_desc_count = 0; + *ret_fs = fs; + return 0; + } + + if (EXT2_INODES_PER_GROUP(fs->super) == 0) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + /* Precompute the FS UUID to seed other checksums */ + ext2fs_init_csum_seed(fs); + + /* + * Read group descriptors + */ + blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); + if (blocks_per_group < 8 || + blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || + fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) || + EXT2_DESC_PER_BLOCK(fs->super) == 0 || + fs->super->s_first_data_block >= ext2fs_blocks_count(fs->super)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + groups_cnt = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) - + fs->super->s_first_data_block, + blocks_per_group); + if (groups_cnt >> 32) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->group_desc_count = groups_cnt; + if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) && + (__u64)fs->group_desc_count * EXT2_INODES_PER_GROUP(fs->super) != + fs->super->s_inodes_count) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, + EXT2_DESC_PER_BLOCK(fs->super)); + if (ext2fs_has_feature_meta_bg(fs->super) && + (fs->super->s_first_meta_bg > fs->desc_blocks) && + !(flags & EXT2_FLAG_IGNORE_SB_ERRORS)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + if (flags & EXT2_FLAG_SUPER_ONLY) + goto skip_read_bg; + retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, + &fs->group_desc); + if (retval) + goto cleanup; + if (!group_block) + group_block = fs->super->s_first_data_block; + /* + * On a FS with a 1K blocksize, block 0 is reserved for bootloaders + * so we must increment block numbers to any group 0 items. + * + * However, we cannot touch group_block directly because in the meta_bg + * case, the ext2fs_descriptor_block_loc2() function will interpret + * group_block != s_first_data_block to mean that we want to access the + * backup group descriptors. This is not what we want if the caller + * set superblock == 0 (i.e. auto-detect the superblock), which is + * what's going on here. + */ + if (group_block == 0 && fs->blocksize == 1024) + group_zero_adjust = 1; + dest = (char *) fs->group_desc; +#ifdef WORDS_BIGENDIAN + groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); +#endif + if (ext2fs_has_feature_meta_bg(fs->super) && + !(flags & EXT2_FLAG_IMAGE_FILE)) { + first_meta_bg = fs->super->s_first_meta_bg; + if (first_meta_bg > fs->desc_blocks) + first_meta_bg = fs->desc_blocks; + } else + first_meta_bg = fs->desc_blocks; + if (first_meta_bg) { + retval = io_channel_read_blk(fs->io, group_block + + group_zero_adjust + 1, + first_meta_bg, dest); + if (retval) + goto cleanup; +#ifdef WORDS_BIGENDIAN + gdp = (struct ext2_group_desc *) dest; + for (j=0; j < groups_per_block*first_meta_bg; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, j); + if (gdp) + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + dest += fs->blocksize*first_meta_bg; + } + + for (i = first_meta_bg ; i < fs->desc_blocks; i++) { + blk = ext2fs_descriptor_block_loc2(fs, group_block, i); + io_channel_cache_readahead(fs->io, blk, 1); + } + + for (i=first_meta_bg ; i < fs->desc_blocks; i++) { + blk = ext2fs_descriptor_block_loc2(fs, group_block, i); + retval = io_channel_read_blk64(fs->io, blk, 1, dest); + if (retval) + goto cleanup; +#ifdef WORDS_BIGENDIAN + for (j=0; j < groups_per_block; j++) { + gdp = ext2fs_group_desc(fs, fs->group_desc, + i * groups_per_block + j); + if (gdp) + ext2fs_swap_group_desc2(fs, gdp); + } +#endif + dest += fs->blocksize; + } + + fs->stride = fs->super->s_raid_stride; + + /* + * If recovery is from backup superblock, Clear _UNININT flags & + * reset bg_itable_unused to zero + */ + if (superblock > 1 && ext2fs_has_group_desc_csum(fs)) { + dgrp_t group; + + for (group = 0; group < fs->group_desc_count; group++) { + ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); + ext2fs_bg_itable_unused_set(fs, group, 0); + /* The checksum will be reset later, but fix it here + * anyway to avoid printing a lot of spurious errors. */ + ext2fs_group_desc_csum_set(fs, group); + } + if (fs->flags & EXT2_FLAG_RW) + ext2fs_mark_super_dirty(fs); + } +skip_read_bg: + if (ext2fs_has_feature_mmp(fs->super) && + !(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; + } + } + + if (fs->flags & EXT2_FLAG_SHARE_DUP) { + fs->block_sha_map = ext2fs_hashmap_create(ext2fs_djb2_hash, + block_sha_map_free_entry, 4096); + if (!fs->block_sha_map) { + retval = EXT2_ET_NO_MEMORY; + goto cleanup; + } + ext2fs_set_feature_shared_blocks(fs->super); + } + + if (ext2fs_has_feature_casefold(fs->super)) + fs->encoding = ext2fs_load_nls_table(fs->super->s_encoding); + + fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; + *ret_fs = fs; + + return 0; +cleanup: + if (!(flags & EXT2_FLAG_NOFREE_ON_ERROR)) { + ext2fs_free(fs); + fs = NULL; + } + *ret_fs = fs; + return retval; +} + +/* + * Set/get the filesystem data I/O channel. + * + * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true. + */ +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io) +{ + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + if (old_io) { + *old_io = (fs->image_io == fs->io) ? 0 : fs->io; + } + return 0; +} + +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io) +{ + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + fs->io = new_io ? new_io : fs->image_io; + return 0; +} + +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io) +{ + errcode_t err; + + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + err = io_channel_set_blksize(new_io, fs->blocksize); + if (err) + return err; + if ((new_io == fs->image_io) || (new_io == fs->io)) + return 0; + if ((fs->image_io != fs->io) && + fs->image_io) + io_channel_close(fs->image_io); + if (fs->io) + io_channel_close(fs->io); + fs->io = fs->image_io = new_io; + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW | + EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; + fs->flags &= ~EXT2_FLAG_IMAGE_FILE; + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/openfs.o b/jni/e2fsprogs/lib/ext2fs/openfs.o new file mode 100755 index 0000000000000000000000000000000000000000..1a81f45b43bfc9c78835d9c424baf832320d22a1 GIT binary patch literal 11736 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 b<8@g672{nZB + +static char spaces[80], backspaces[80]; +static time_t last_update; + +struct ext2fs_progress_ops ext2fs_numeric_progress_ops = { + .init = ext2fs_numeric_progress_init, + .update = ext2fs_numeric_progress_update, + .close = ext2fs_numeric_progress_close, +}; + +static int int_log10(unsigned int arg) +{ + int l; + + for (l=0; arg ; l++) + arg = arg / 10; + return l; +} + +void ext2fs_numeric_progress_init(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *label, __u64 max) +{ + /* + * The PRINT_PROGRESS flag turns on or off ALL + * progress-related messages, whereas the SKIP_PROGRESS + * environment variable prints the start and end messages but + * not the numeric countdown in the middle. + */ + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS)) + return; + + memset(spaces, ' ', sizeof(spaces)-1); + spaces[sizeof(spaces)-1] = 0; + memset(backspaces, '\b', sizeof(backspaces)-1); + backspaces[sizeof(backspaces)-1] = 0; + + memset(progress, 0, sizeof(*progress)); + if (getenv("E2FSPROGS_SKIP_PROGRESS")) + progress->skip_progress++; + + + /* + * Figure out how many digits we need + */ + progress->max = max; + progress->log_max = int_log10(max); + + if (label) { + fputs(label, stdout); + fflush(stdout); + } + last_update = 0; +} + +void ext2fs_numeric_progress_update(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + __u64 val) +{ + time_t now; + + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS)) + return; + if (progress->skip_progress) + return; + now = time(0); + if (now == last_update) + return; + last_update = now; + + printf("%*llu/%*llu", progress->log_max, (unsigned long long) val, + progress->log_max, (unsigned long long) progress->max); + fprintf(stdout, "%.*s", (2*progress->log_max)+1, backspaces); +} + +void ext2fs_numeric_progress_close(ext2_filsys fs, + struct ext2fs_numeric_progress_struct * progress, + const char *message) +{ + if (!(fs->flags & EXT2_FLAG_PRINT_PROGRESS)) + return; + fprintf(stdout, "%.*s", (2*progress->log_max)+1, spaces); + fprintf(stdout, "%.*s", (2*progress->log_max)+1, backspaces); + if (message) + fputs(message, stdout); +} diff --git a/jni/e2fsprogs/lib/ext2fs/progress.o b/jni/e2fsprogs/lib/ext2fs/progress.o new file mode 100755 index 0000000000000000000000000000000000000000..119b6296ffd83a57a5b18d0bf4c646bb639f702c GIT binary patch literal 4120 zcmbtXUuc_E6hB|S%q6z#pLKJ(&81>1Tg9xclT}dou-TU3rlp;*hhdhbU;kkKlzd;u z<`e_n!}iv}9(?dmlsz=!!yX0_@IlzieA`5%4^y%V64{fmK?5uCoSSpn>urL9Cw%vu z`@84=y}9}F$&nLB1C|9s7JLUAGeH5C+c#uKi4JT-&HAWyZ|zdBv}Rk^iVKm|uk6U` z*9-erfA4|X(n4Z2)a{gKVDT{e+;JG6m2lywl{ToMi$#2{RklLS3KqsuzFytx)K=P@ zTI5aZ_4V~mT(@|=v$3{hCsrdC)FN9p{E&SG;11bU zBe`OS1`23Hz90s`S*&3?R0d11XF%ykCf5czotpNbv%M%9C{DP|bs9Kg6C zEBr7CaEkQyk}a?8#~jFy6?V!i*h7+Sl!*r$`Kn%%PpOOQp!G27#i1}B`Z&BNfc-+> zi!b25*vM1J$%f*sU3#m8bv5d=s`e>sk*r%p+WccXB*!a80CK3~G zA0JDQIDTYe0{REi>G^|dg#PG&2arl9v(vrj-MlxO%k~b9M2Dgy0A1|W`fwbqkM>!6 z+9S}1*t3l9z{DWdF&1xszUzy?=fS{}_Q+Vg1AhAzl%B(S72>gu!F9bm?U6xE56_>X zJ2b{RoOQjM?GcCdC?*{wq7yX4I=TX}4w72ZV_XTsU-f1RHUu`oC#jw$cpgy;o?6!* zV=2qH%!QAlp8$To=MXAi)cut8i^z%aj3_#&;s$y4PiAXzWo1C=Z{#C5aT~VkQziE+ z{mpo=Mypd!RW@5B_!X65e9ltAMed|dV{5%1|Dae`mN`6 znsMe%e?jc9~_$N5`))PWg1ROl+BD`XSw};rCe{G4LwmH#B|f zo9z1%%hPVQ^^I$mL% z@|4^uL@(c8W}bbFn|a0=H}gEfxS8iEO<(`MoYwSp{0!q}o(02?)O*?RBlwjTem-N| zthdOxS?`kOM?dGhJwUIvoiaflVwv!r8s4Sh&uRExmbaijhf+w)z~%l+8@SwC*9}~L zmtflU-RyaY=G}BM>bnbW@&&LvYHcyq~=i@MpI??#Wk^WH0-k0?w{rRTjFbd;aX z`csfjdVXSlZZhe+Ej|9raw?tkT<~WzE?4KyB&PC7oJtAN6hu8g?6^#Q{s zp>Hz!8V!eNc$J1>8ivqYjugmr2&b5DBAuHa8ic+J(LwI>|7N(~_-?t03Vd0Q% zdzp8kakKc#{7MpMMT$>)X8ei@L V|Da8=Nk7i#M($tAk?u#+{%=)|;7R}h literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/punch.c b/jni/e2fsprogs/lib/ext2fs/punch.c new file mode 100755 index 0000000..e2543e1 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/punch.c @@ -0,0 +1,513 @@ +/* + * punch.c --- deallocate blocks allocated to an inode + * + * Copyright (C) 2010 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#undef PUNCH_DEBUG + +/* + * This function returns 1 if the specified block is all zeros + */ +static int check_zero_block(char *buf, int blocksize) +{ + char *cp = buf; + int left = blocksize; + + while (left > 0) { + if (*cp++) + return 0; + left--; + } + return 1; +} + +/* + * This clever recursive function handles i_blocks[] as well as + * indirect, double indirect, and triple indirect blocks. It iterates + * over the entries in the i_blocks array or indirect blocks, and for + * each one, will recursively handle any indirect blocks and then + * frees and deallocates the blocks. + */ +static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode, + char *block_buf, blk_t *p, int level, + blk64_t start, blk64_t count, int max) +{ + errcode_t retval; + blk_t b; + int i; + blk64_t offset, incr; + int freed = 0; + +#ifdef PUNCH_DEBUG + printf("Entering ind_punch, level %d, start %llu, count %llu, " + "max %d\n", level, start, count, max); +#endif + incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super) - 2) * level); + for (i = 0, offset = 0; i < max; i++, p++, offset += incr) { + if (offset >= start + count) + break; + if (*p == 0 || (offset+incr) <= start) + continue; + b = *p; + if (level > 0) { + blk_t start2; +#ifdef PUNCH_DEBUG + printf("Reading indirect block %u\n", b); +#endif + retval = ext2fs_read_ind_block(fs, b, block_buf); + if (retval) + return retval; + start2 = (start > offset) ? start - offset : 0; + retval = ind_punch(fs, inode, block_buf + fs->blocksize, + (blk_t *) block_buf, level - 1, + start2, count - offset, + fs->blocksize >> 2); + if (retval) + return retval; + retval = ext2fs_write_ind_block(fs, b, block_buf); + if (retval) + return retval; + if (!check_zero_block(block_buf, fs->blocksize)) + continue; + } +#ifdef PUNCH_DEBUG + printf("Freeing block %u (offset %llu)\n", b, offset); +#endif + ext2fs_block_alloc_stats(fs, b, -1); + *p = 0; + freed++; + } +#ifdef PUNCH_DEBUG + printf("Freed %d blocks\n", freed); +#endif + return ext2fs_iblk_sub_blocks(fs, inode, freed); +} + +#define BLK_T_MAX ((blk_t)~0ULL) +static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode, + char *block_buf, blk64_t start, blk64_t end) +{ + errcode_t retval; + char *buf = 0; + int level; + int num = EXT2_NDIR_BLOCKS; + blk_t *bp = inode->i_block; + blk_t addr_per_block; + blk64_t max = EXT2_NDIR_BLOCKS; + blk_t count; + + /* Check start/end don't overflow the 2^32-1 indirect block limit */ + if (start > BLK_T_MAX) + return 0; + if (end >= BLK_T_MAX || end - start + 1 >= BLK_T_MAX) + count = BLK_T_MAX - start; + else + count = end - start + 1; + + if (!block_buf) { + retval = ext2fs_get_array(3, fs->blocksize, &buf); + if (retval) + return retval; + block_buf = buf; + } + + addr_per_block = (blk_t)fs->blocksize >> 2; + + for (level = 0; level < 4; level++, max *= (blk64_t)addr_per_block) { +#ifdef PUNCH_DEBUG + printf("Main loop level %d, start %llu count %u " + "max %llu num %d\n", level, start, count, max, num); +#endif + if (start < max) { + retval = ind_punch(fs, inode, block_buf, bp, level, + start, count, num); + if (retval) + goto errout; + if (count > max) + count -= max - start; + else + break; + start = 0; + } else + start -= max; + bp += num; + if (level == 0) { + num = 1; + max = 1; + } + } + retval = 0; +errout: + if (buf) + ext2fs_free_mem(&buf); + return retval; +} +#undef BLK_T_MAX + +#ifdef PUNCH_DEBUG + +#define dbg_printf(f, a...) printf(f, ## a) + +static void dbg_print_extent(char *desc, struct ext2fs_extent *extent) +{ + if (desc) + printf("%s: ", desc); + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ", + extent->e_lblk, extent->e_lblk + extent->e_len - 1, + extent->e_len, extent->e_pblk); + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF) + fputs("LEAF ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fputs("UNINIT ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + fputs("2ND_VISIT ", stdout); + if (!extent->e_flags) + fputs("(none)", stdout); + fputc('\n', stdout); + +} +#else +#define dbg_print_extent(desc, ex) do { } while (0) +#define dbg_printf(f, a...) do { } while (0) +#endif + +/* Free a range of blocks, respecting cluster boundaries */ +static errcode_t punch_extent_blocks(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + blk64_t lfree_start, blk64_t free_start, + __u32 free_count, int *freed) +{ + blk64_t pblk; + int freed_now = 0; + __u32 cluster_freed; + errcode_t retval = 0; + + if (free_start < fs->super->s_first_data_block || + (free_start + free_count) >= ext2fs_blocks_count(fs->super)) + return EXT2_ET_BAD_BLOCK_NUM; + + /* No bigalloc? Just free each block. */ + if (EXT2FS_CLUSTER_RATIO(fs) == 1) { + *freed += free_count; + while (free_count-- > 0) + ext2fs_block_alloc_stats2(fs, free_start++, -1); + return retval; + } + + /* + * Try to free up to the next cluster boundary. We assume that all + * blocks in a logical cluster map to blocks from the same physical + * cluster, and that the offsets within the [pl]clusters match. + */ + if (free_start & EXT2FS_CLUSTER_MASK(fs)) { + retval = ext2fs_map_cluster_block(fs, ino, inode, + lfree_start, &pblk); + if (retval) + goto errout; + if (!pblk) { + ext2fs_block_alloc_stats2(fs, free_start, -1); + freed_now++; + } + cluster_freed = EXT2FS_CLUSTER_RATIO(fs) - + (free_start & EXT2FS_CLUSTER_MASK(fs)); + if (cluster_freed > free_count) + cluster_freed = free_count; + free_count -= cluster_freed; + free_start += cluster_freed; + lfree_start += cluster_freed; + } + + /* Free whole clusters from the middle of the range. */ + while (free_count > 0 && free_count >= (unsigned) EXT2FS_CLUSTER_RATIO(fs)) { + ext2fs_block_alloc_stats2(fs, free_start, -1); + freed_now++; + cluster_freed = EXT2FS_CLUSTER_RATIO(fs); + free_count -= cluster_freed; + free_start += cluster_freed; + lfree_start += cluster_freed; + } + + /* Try to free the last cluster. */ + if (free_count > 0) { + retval = ext2fs_map_cluster_block(fs, ino, inode, + lfree_start, &pblk); + if (retval) + goto errout; + if (!pblk) { + ext2fs_block_alloc_stats2(fs, free_start, -1); + freed_now++; + } + } + +errout: + *freed += freed_now; + return retval; +} + +static errcode_t ext2fs_punch_extent(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + blk64_t start, blk64_t end) +{ + ext2_extent_handle_t handle = 0; + struct ext2fs_extent extent; + errcode_t retval; + blk64_t free_start, next, lfree_start; + __u32 free_count, newlen; + int freed = 0; + int op; + + retval = ext2fs_extent_open2(fs, ino, inode, &handle); + if (retval) + return retval; + /* + * Find the extent closest to the start of the punch range. We don't + * check the return value because _goto() sets the current node to the + * next-lowest extent if 'start' is in a hole, and doesn't set a + * current node if there was a real error reading the extent tree. + * In that case, _get() will error out. + * + * Note: If _get() returns 'no current node', that simply means that + * there aren't any blocks mapped past this point in the file, so we're + * done. + */ + ext2fs_extent_goto(handle, start); + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); + if (retval == EXT2_ET_NO_CURRENT_NODE) { + retval = 0; + goto errout; + } else if (retval) + goto errout; + while (1) { + op = EXT2_EXTENT_NEXT_LEAF; + dbg_print_extent("main loop", &extent); + next = extent.e_lblk + extent.e_len; + dbg_printf("start %llu, end %llu, next %llu\n", + (unsigned long long) start, + (unsigned long long) end, + (unsigned long long) next); + if (start <= extent.e_lblk) { + /* + * Have we iterated past the end of the punch region? + * If so, we can stop. + */ + if (end < extent.e_lblk) + break; + dbg_printf("Case #%d\n", 1); + /* Start of deleted region before extent; + adjust beginning of extent */ + free_start = extent.e_pblk; + lfree_start = extent.e_lblk; + if (next > end) + free_count = end - extent.e_lblk + 1; + else + free_count = extent.e_len; + extent.e_len -= free_count; + extent.e_lblk += free_count; + extent.e_pblk += free_count; + } else if (end >= next-1) { + /* + * Is the punch region beyond this extent? This can + * happen if start is already inside a hole. Try to + * advance to the next extent if this is the case. + */ + if (start >= next) + goto next_extent; + /* End of deleted region after extent; + adjust end of extent */ + dbg_printf("Case #%d\n", 2); + newlen = start - extent.e_lblk; + free_start = extent.e_pblk + newlen; + lfree_start = extent.e_lblk + newlen; + free_count = extent.e_len - newlen; + extent.e_len = newlen; + } else { + struct ext2fs_extent newex; + + dbg_printf("Case #%d\n", 3); + /* The hard case; we need to split the extent */ + newex.e_pblk = extent.e_pblk + + (end + 1 - extent.e_lblk); + newex.e_lblk = end + 1; + newex.e_len = next - end - 1; + newex.e_flags = extent.e_flags; + + extent.e_len = start - extent.e_lblk; + free_start = extent.e_pblk + extent.e_len; + lfree_start = extent.e_lblk + extent.e_len; + free_count = end - start + 1; + + dbg_print_extent("inserting", &newex); + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &newex); + if (retval) + goto errout; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto errout; + /* + * Now pointing at inserted extent; so go back. + * + * We cannot use EXT2_EXTENT_PREV to go back; note the + * subtlety in the comment for fix_parents(). + */ + retval = ext2fs_extent_goto(handle, extent.e_lblk); + if (retval) + goto errout; + } + if (extent.e_len) { + dbg_print_extent("replacing", &extent); + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto errout; + retval = ext2fs_extent_fix_parents(handle); + } else { + struct ext2fs_extent newex; + blk64_t old_lblk, next_lblk; + dbg_printf("deleting current extent%s\n", ""); + + /* + * Save the location of the next leaf, then slip + * back to the current extent. + */ + retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, + &newex); + if (retval) + goto errout; + old_lblk = newex.e_lblk; + + retval = ext2fs_extent_get(handle, + EXT2_EXTENT_NEXT_LEAF, + &newex); + if (retval == EXT2_ET_EXTENT_NO_NEXT) + next_lblk = old_lblk; + else if (retval) + goto errout; + else + next_lblk = newex.e_lblk; + + retval = ext2fs_extent_goto(handle, old_lblk); + if (retval) + goto errout; + + /* Now delete the extent. */ + retval = ext2fs_extent_delete(handle, 0); + if (retval) + goto errout; + + retval = ext2fs_extent_fix_parents(handle); + if (retval && retval != EXT2_ET_NO_CURRENT_NODE) + goto errout; + retval = 0; + + /* + * Jump forward to the next extent. If there are + * errors, the ext2fs_extent_get down below will + * capture them for us. + */ + (void)ext2fs_extent_goto(handle, next_lblk); + op = EXT2_EXTENT_CURRENT; + } + if (retval) + goto errout; + dbg_printf("Free start %llu, free count = %u\n", + free_start, free_count); + retval = punch_extent_blocks(fs, ino, inode, lfree_start, + free_start, free_count, &freed); + if (retval) + goto errout; + next_extent: + retval = ext2fs_extent_get(handle, op, + &extent); + if (retval == EXT2_ET_EXTENT_NO_NEXT || + retval == EXT2_ET_NO_CURRENT_NODE) + break; + if (retval) + goto errout; + } + dbg_printf("Freed %d blocks\n", freed); + retval = ext2fs_iblk_sub_blocks(fs, inode, freed); +errout: + ext2fs_extent_free(handle); + return retval; +} + +static errcode_t ext2fs_punch_inline_data(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + blk64_t start, + blk64_t end EXT2FS_ATTR((unused))) +{ + errcode_t retval; + + /* + * In libext2fs ext2fs_punch is based on block unit. So that + * means that if start > 0 we don't need to do nothing. Due + * to this we will remove all inline data in ext2fs_punch() + * now. + */ + if (start > 0) + return 0; + + memset((char *)inode->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); + inode->i_size = 0; + retval = ext2fs_write_inode(fs, ino, inode); + if (retval) + return retval; + + return ext2fs_inline_data_ea_remove(fs, ino); +} + +/* + * Deallocate all logical _blocks_ starting at start to end, inclusive. + * If end is ~0ULL, then this is effectively truncate. + */ +errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, blk64_t start, + blk64_t end) +{ + errcode_t retval; + struct ext2_inode inode_buf; + + if (start > end) + return EINVAL; + + /* Read inode structure if necessary */ + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + if (inode->i_flags & EXT4_INLINE_DATA_FL) + return ext2fs_punch_inline_data(fs, ino, inode, start, end); + else if (inode->i_flags & EXT4_EXTENTS_FL) + retval = ext2fs_punch_extent(fs, ino, inode, start, end); + else + retval = ext2fs_punch_ind(fs, inode, block_buf, start, end); + if (retval) + return retval; + +#ifdef PUNCH_DEBUG + printf("%u: write inode size now %lu blocks %u\n", + ino, EXT2_I_SIZE(inode), inode->i_blocks); +#endif + return ext2fs_write_inode(fs, ino, inode); +} diff --git a/jni/e2fsprogs/lib/ext2fs/punch.o b/jni/e2fsprogs/lib/ext2fs/punch.o new file mode 100755 index 0000000000000000000000000000000000000000..299355453b3faa36755973634a8ea27b252c1f5b GIT binary patch literal 7576 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 Kyjj}A^Zx@7YdaDE literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/qcow2.c b/jni/e2fsprogs/lib/ext2fs/qcow2.c new file mode 100755 index 0000000..2082417 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/qcow2.c @@ -0,0 +1,272 @@ +/* + * qcow2.c --- Functions to generate qcow2 formatted disk images. This + * format is used originally by QEMU for virtual machines, and stores the + * filesystem data on disk in a packed format to avoid creating sparse + * image files that need lots of seeking to read and write. + * + * The qcow2 format supports zlib compression, but that is not yet + * implemented. + * + * It is possible to directly mount a qcow2 image using qemu-nbd: + * + * [root]# modprobe nbd max_part=63 + * [root]# qemu-nbd -c /dev/nbd0 image.img + * [root]# mount /dev/nbd0p1 /mnt/qemu + * + * Format details at http://people.gnome.org/~markmc/qcow-image-format.html + * + * Copyright (C) 2010 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include +#include +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ext2fs/ext2fs.h" +#include "qcow2.h" + +/* Functions for converting qcow2 image into raw image */ + +struct ext2_qcow2_hdr *qcow2_read_header(int fd) +{ + void *buffer = NULL; + struct ext2_qcow2_hdr *hdr = NULL; + size_t size; + errcode_t ret; + + ret = ext2fs_get_mem(sizeof(struct ext2_qcow2_hdr), &buffer); + if (ret) + return NULL; + memset(buffer, 0, sizeof(struct ext2_qcow2_hdr)); + + if (ext2fs_llseek(fd, 0, SEEK_SET < 0)) { + ext2fs_free_mem(&buffer); + return NULL; + } + + size = read(fd, buffer, sizeof(struct ext2_qcow2_hdr)); + if (size != sizeof(struct ext2_qcow2_hdr)) { + ext2fs_free_mem(&buffer); + return NULL; + } + + hdr = (struct ext2_qcow2_hdr *)(buffer); + + if ((ext2fs_be32_to_cpu(hdr->magic) != QCOW_MAGIC) || + (ext2fs_be32_to_cpu(hdr->version) != 2)) { + ext2fs_free_mem(&hdr); + return NULL; + } + + return hdr; +} + +static int qcow2_read_l1_table(struct ext2_qcow2_image *img) +{ + int fd = img->fd; + size_t size, l1_size = img->l1_size * sizeof(blk64_t); + blk64_t *table; + errcode_t ret; + + ret = ext2fs_get_memzero(l1_size, &table); + if (ret) + return ret; + + if (ext2fs_llseek(fd, img->l1_offset, SEEK_SET) < 0) { + ext2fs_free_mem(&table); + return errno; + } + + size = read(fd, table, l1_size); + if (size != l1_size) { + ext2fs_free_mem(&table); + return errno; + } + + img->l1_table = table; + + return 0; +} + +static int qcow2_read_l2_table(struct ext2_qcow2_image *img, + __u64 offset, blk64_t **l2_table) +{ + int fd = img->fd; + size_t size; + + assert(*l2_table); + + if (ext2fs_llseek(fd, offset, SEEK_SET) < 0) + return errno; + + size = read(fd, *l2_table, img->cluster_size); + if (size != img->cluster_size) + return errno; + + return 0; +} + +static int qcow2_copy_data(int fdin, int fdout, __u64 off_in, + __u64 off_out, void *buf, size_t count) +{ + size_t size; + + assert(buf); + + if (ext2fs_llseek(fdout, off_out, SEEK_SET) < 0) + return errno; + + if (ext2fs_llseek(fdin, off_in, SEEK_SET) < 0) + return errno; + + size = read(fdin, buf, count); + if (size != count) + return errno; + + size = write(fdout, buf, count); + if (size != count) + return errno; + + return 0; +} + + +int qcow2_write_raw_image(int qcow2_fd, int raw_fd, + struct ext2_qcow2_hdr *hdr) +{ + struct ext2_qcow2_image img; + errcode_t ret = 0; + unsigned int l1_index, l2_index; + __u64 offset; + blk64_t *l1_table, *l2_table = NULL; + void *copy_buf = NULL; + size_t size; + unsigned int max_l1_size; + + if (hdr->crypt_method) + return -QCOW_ENCRYPTED; + + img.fd = qcow2_fd; + img.hdr = hdr; + img.l2_cache = NULL; + img.l1_table = NULL; + img.cluster_bits = ext2fs_be32_to_cpu(hdr->cluster_bits); + if (img.cluster_bits < 9 || img.cluster_bits > 31) + return -QCOW_CORRUPTED; + img.cluster_size = 1 << img.cluster_bits; + img.l1_size = ext2fs_be32_to_cpu(hdr->l1_size); + img.l1_offset = ext2fs_be64_to_cpu(hdr->l1_table_offset); + img.l2_size = 1 << (img.cluster_bits - 3); + img.image_size = ext2fs_be64_to_cpu(hdr->size); + + if (img.l1_offset & (img.cluster_size - 1)) + return -QCOW_CORRUPTED; + + max_l1_size = (img.image_size >> ((2 * img.cluster_bits) - 3)) + + img.cluster_size; + if (img.l1_size > max_l1_size) + return -QCOW_CORRUPTED; + + ret = ext2fs_get_memzero(img.cluster_size, &l2_table); + if (ret) + goto out; + + ret = ext2fs_get_memzero(1 << img.cluster_bits, ©_buf); + if (ret) + goto out; + + if (ext2fs_llseek(raw_fd, 0, SEEK_SET) < 0) { + ret = errno; + goto out; + } + + ret = qcow2_read_l1_table(&img); + if (ret) + goto out; + + l1_table = img.l1_table; + /* Walk through l1 table */ + for (l1_index = 0; l1_index < img.l1_size; l1_index++) { + __u64 off_out; + + offset = ext2fs_be64_to_cpu(l1_table[l1_index]) & + ~QCOW_OFLAG_COPIED; + + if ((offset > img.image_size) || + (offset <= 0)) + continue; + + if (offset & QCOW_OFLAG_COMPRESSED) { + ret = -QCOW_COMPRESSED; + goto out; + } + + ret = qcow2_read_l2_table(&img, offset, &l2_table); + if (ret) + break; + + /* Walk through l2 table and copy data blocks into raw image */ + for (l2_index = 0; l2_index < img.l2_size; l2_index++) { + offset = ext2fs_be64_to_cpu(l2_table[l2_index]) & + ~QCOW_OFLAG_COPIED; + + if (offset == 0) + continue; + + off_out = ((__u64)l1_index * img.l2_size) + + l2_index; + off_out <<= img.cluster_bits; + ret = qcow2_copy_data(qcow2_fd, raw_fd, offset, + off_out, copy_buf, img.cluster_size); + if (ret) + goto out; + } + } + + /* Resize the output image to the filesystem size */ + if (ext2fs_llseek(raw_fd, img.image_size - 1, SEEK_SET) < 0) { + ret = errno; + goto out; + } + + ((char *)copy_buf)[0] = 0; + size = write(raw_fd, copy_buf, 1); + if (size != 1) { + ret = errno; + goto out; + } + +out: + if (copy_buf) + ext2fs_free_mem(©_buf); + if (img.l1_table) + ext2fs_free_mem(&img.l1_table); + if (l2_table) + ext2fs_free_mem(&l2_table); + return ret; +} diff --git a/jni/e2fsprogs/lib/ext2fs/qcow2.h b/jni/e2fsprogs/lib/ext2fs/qcow2.h new file mode 100755 index 0000000..b649c9c --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/qcow2.h @@ -0,0 +1,114 @@ +/* + * qcow2.h --- structures and function prototypes for qcow2.c to generate + * qcow2 formatted disk images. This format is used originally by QEMU + * for virtual machines, and stores the filesystem data on disk in a + * packed format to avoid creating sparse image files that need lots of + * seeking to read and write. + * + * The qcow2 format supports zlib compression, but that is not yet + * implemented. + * + * It is possible to directly mount a qcow2 image using qemu-nbd: + * + * [root]# modprobe nbd max_part=63 + * [root]# qemu-nbd -c /dev/nbd0 image.img + * [root]# mount /dev/nbd0p1 /mnt/qemu + * + * Format details at http://people.gnome.org/~markmc/qcow-image-format.html + * + * Copyright (C) 2010 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* Number of l2 tables in memory before writeback */ +#define L2_CACHE_PREALLOC 512 + + +#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) +#define QCOW_VERSION 2 +#define QCOW_OFLAG_COPIED (1ULL << 63) +#define QCOW_OFLAG_COMPRESSED (1ULL << 62) + +#define QCOW_COMPRESSED 1 +#define QCOW_ENCRYPTED 2 +#define QCOW_CORRUPTED 3 + +struct ext2_qcow2_hdr { + __u32 magic; + __u32 version; + + __u64 backing_file_offset; + __u32 backing_file_size; + + __u32 cluster_bits; + __u64 size; + __u32 crypt_method; + + __u32 l1_size; + __u64 l1_table_offset; + + __u64 refcount_table_offset; + __u32 refcount_table_clusters; + + __u32 nb_snapshots; + __u64 snapshots_offset; +}; + +typedef struct ext2_qcow2_l2_table L2_CACHE_HEAD; + +struct ext2_qcow2_l2_table { + __u32 l1_index; + __u64 offset; + __u64 *data; + L2_CACHE_HEAD *next; +}; + +struct ext2_qcow2_l2_cache { + L2_CACHE_HEAD *used_head; + L2_CACHE_HEAD *used_tail; + L2_CACHE_HEAD *free_head; + __u32 free; + __u32 count; + __u64 next_offset; +}; + +struct ext2_qcow2_refcount { + __u64 *refcount_table; + __u64 refcount_table_offset; + __u64 refcount_block_offset; + + __u32 refcount_table_clusters; + __u32 refcount_table_index; + __u32 refcount_block_index; + + __u16 *refcount_block; +}; + +struct ext2_qcow2_image { + int fd; + struct ext2_qcow2_hdr *hdr; + struct ext2_qcow2_l2_cache *l2_cache; + struct ext2_qcow2_refcount refcount; + __u32 cluster_size; + __u32 cluster_bits; + __u32 l1_size; + __u32 l2_size; + + __u64 *l1_table; + __u64 l2_offset; + __u64 l1_offset; + __u64 image_size; +}; + +/* Function prototypes */ + +/* qcow2.c */ + +/* Functions for converting qcow2 image into raw image */ +struct ext2_qcow2_hdr *qcow2_read_header(int); +int qcow2_write_raw_image(int, int, struct ext2_qcow2_hdr *); + diff --git a/jni/e2fsprogs/lib/ext2fs/qcow2.o b/jni/e2fsprogs/lib/ext2fs/qcow2.o new file mode 100755 index 0000000000000000000000000000000000000000..9418fec550d8b8827042722edd3329a63804fb42 GIT binary patch literal 5752 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 + (C) 2002 David Woodhouse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + linux/lib/rbtree.c +*/ + +#include "rbtree.h" + +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *right = node->rb_right; + struct rb_node *parent = ext2fs_rb_parent(node); + + if ((node->rb_right = right->rb_left)) + ext2fs_rb_set_parent(right->rb_left, node); + right->rb_left = node; + + ext2fs_rb_set_parent(right, parent); + + if (parent) + { + if (node == parent->rb_left) + parent->rb_left = right; + else + parent->rb_right = right; + } + else + root->rb_node = right; + ext2fs_rb_set_parent(node, right); +} + +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *left = node->rb_left; + struct rb_node *parent = ext2fs_rb_parent(node); + + if ((node->rb_left = left->rb_right)) + ext2fs_rb_set_parent(left->rb_right, node); + left->rb_right = node; + + ext2fs_rb_set_parent(left, parent); + + if (parent) + { + if (node == parent->rb_right) + parent->rb_right = left; + else + parent->rb_left = left; + } + else + root->rb_node = left; + ext2fs_rb_set_parent(node, left); +} + +void ext2fs_rb_insert_color(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *parent, *gparent; + + while ((parent = ext2fs_rb_parent(node)) && ext2fs_rb_is_red(parent)) + { + gparent = ext2fs_rb_parent(parent); + + if (parent == gparent->rb_left) + { + { + register struct rb_node *uncle = gparent->rb_right; + if (uncle && ext2fs_rb_is_red(uncle)) + { + ext2fs_rb_set_black(uncle); + ext2fs_rb_set_black(parent); + ext2fs_rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_right == node) + { + register struct rb_node *tmp; + __rb_rotate_left(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + ext2fs_rb_set_black(parent); + ext2fs_rb_set_red(gparent); + __rb_rotate_right(gparent, root); + } else { + { + register struct rb_node *uncle = gparent->rb_left; + if (uncle && ext2fs_rb_is_red(uncle)) + { + ext2fs_rb_set_black(uncle); + ext2fs_rb_set_black(parent); + ext2fs_rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_left == node) + { + register struct rb_node *tmp; + __rb_rotate_right(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + ext2fs_rb_set_black(parent); + ext2fs_rb_set_red(gparent); + __rb_rotate_left(gparent, root); + } + } + + ext2fs_rb_set_black(root->rb_node); +} + +static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, + struct rb_root *root) +{ + struct rb_node *other; + + while ((!node || ext2fs_rb_is_black(node)) && node != root->rb_node) + { + if (parent->rb_left == node) + { + other = parent->rb_right; + if (ext2fs_rb_is_red(other)) + { + ext2fs_rb_set_black(other); + ext2fs_rb_set_red(parent); + __rb_rotate_left(parent, root); + other = parent->rb_right; + } + if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) && + (!other->rb_right || ext2fs_rb_is_black(other->rb_right))) + { + ext2fs_rb_set_red(other); + node = parent; + parent = ext2fs_rb_parent(node); + } + else + { + if (!other->rb_right || ext2fs_rb_is_black(other->rb_right)) + { + ext2fs_rb_set_black(other->rb_left); + ext2fs_rb_set_red(other); + __rb_rotate_right(other, root); + other = parent->rb_right; + } + ext2fs_rb_set_color(other, ext2fs_rb_color(parent)); + ext2fs_rb_set_black(parent); + ext2fs_rb_set_black(other->rb_right); + __rb_rotate_left(parent, root); + node = root->rb_node; + break; + } + } + else + { + other = parent->rb_left; + if (ext2fs_rb_is_red(other)) + { + ext2fs_rb_set_black(other); + ext2fs_rb_set_red(parent); + __rb_rotate_right(parent, root); + other = parent->rb_left; + } + if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) && + (!other->rb_right || ext2fs_rb_is_black(other->rb_right))) + { + ext2fs_rb_set_red(other); + node = parent; + parent = ext2fs_rb_parent(node); + } + else + { + if (!other->rb_left || ext2fs_rb_is_black(other->rb_left)) + { + ext2fs_rb_set_black(other->rb_right); + ext2fs_rb_set_red(other); + __rb_rotate_left(other, root); + other = parent->rb_left; + } + ext2fs_rb_set_color(other, ext2fs_rb_color(parent)); + ext2fs_rb_set_black(parent); + ext2fs_rb_set_black(other->rb_left); + __rb_rotate_right(parent, root); + node = root->rb_node; + break; + } + } + } + if (node) + ext2fs_rb_set_black(node); +} + +void ext2fs_rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *child, *parent; + int color; + + if (!node->rb_left) + child = node->rb_right; + else if (!node->rb_right) + child = node->rb_left; + else + { + struct rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + node = left; + + if (ext2fs_rb_parent(old)) { + if (ext2fs_rb_parent(old)->rb_left == old) + ext2fs_rb_parent(old)->rb_left = node; + else + ext2fs_rb_parent(old)->rb_right = node; + } else + root->rb_node = node; + + child = node->rb_right; + parent = ext2fs_rb_parent(node); + color = ext2fs_rb_color(node); + + if (parent == old) { + parent = node; + } else { + if (child) + ext2fs_rb_set_parent(child, parent); + parent->rb_left = child; + + node->rb_right = old->rb_right; + ext2fs_rb_set_parent(old->rb_right, node); + } + + node->rb_parent_color = old->rb_parent_color; + node->rb_left = old->rb_left; + ext2fs_rb_set_parent(old->rb_left, node); + + goto color; + } + + parent = ext2fs_rb_parent(node); + color = ext2fs_rb_color(node); + + if (child) + ext2fs_rb_set_parent(child, parent); + if (parent) + { + if (parent->rb_left == node) + parent->rb_left = child; + else + parent->rb_right = child; + } + else + root->rb_node = child; + + color: + if (color == RB_BLACK) + __rb_erase_color(child, parent, root); +} + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct rb_node *ext2fs_rb_first(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} + +struct rb_node *ext2fs_rb_last(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} + +struct rb_node *ext2fs_rb_next(struct rb_node *node) +{ + struct rb_node *parent; + + if (ext2fs_rb_parent(node) == node) + return NULL; + + /* If we have a right-hand child, go down and then left as far + as we can. */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node=node->rb_left; + return (struct rb_node *)node; + } + + /* No right-hand children. Everything down and left is + smaller than us, so any 'next' node must be in the general + direction of our parent. Go up the tree; any time the + ancestor is a right-hand child of its parent, keep going + up. First time it's a left-hand child of its parent, said + parent is our 'next' node. */ + while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_right) + node = parent; + + return parent; +} + +struct rb_node *ext2fs_rb_prev(struct rb_node *node) +{ + struct rb_node *parent; + + if (ext2fs_rb_parent(node) == node) + return NULL; + + /* If we have a left-hand child, go down and then right as far + as we can. */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node=node->rb_right; + return (struct rb_node *)node; + } + + /* No left-hand children. Go up till we find an ancestor which + is a right-hand child of its parent */ + while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_left) + node = parent; + + return parent; +} + +void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root) +{ + struct rb_node *parent = ext2fs_rb_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + if (parent) { + if (victim == parent->rb_left) + parent->rb_left = new; + else + parent->rb_right = new; + } else { + root->rb_node = new; + } + if (victim->rb_left) + ext2fs_rb_set_parent(victim->rb_left, new); + if (victim->rb_right) + ext2fs_rb_set_parent(victim->rb_right, new); + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} diff --git a/jni/e2fsprogs/lib/ext2fs/rbtree.h b/jni/e2fsprogs/lib/ext2fs/rbtree.h new file mode 100755 index 0000000..790f5c1 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/rbtree.h @@ -0,0 +1,183 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop dramatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + Some example of insert and search follows here. The search is a plain + normal search over an ordered tree. The insert instead must be implemented + in two steps: First, the code must insert the element in order as a red leaf + in the tree, and then the support library function rb_insert_color() must + be called. Such function will do the not trivial work to rebalance the + rbtree, if necessary. + +----------------------------------------------------------------------- +static inline struct page * rb_search_page_cache(struct inode * inode, + unsigned long offset) +{ + struct rb_node * n = inode->i_rb_page_cache.rb_node; + struct page * page; + + while (n) + { + page = rb_entry(n, struct page, rb_page_cache); + + if (offset < page->offset) + n = n->rb_left; + else if (offset > page->offset) + n = n->rb_right; + else + return page; + } + return NULL; +} + +static inline struct page * __rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct rb_node ** p = &inode->i_rb_page_cache.rb_node; + struct rb_node * parent = NULL; + struct page * page; + + while (*p) + { + parent = *p; + page = rb_entry(parent, struct page, rb_page_cache); + + if (offset < page->offset) + p = &(*p)->rb_left; + else if (offset > page->offset) + p = &(*p)->rb_right; + else + return page; + } + + rb_link_node(node, parent, p); + + return NULL; +} + +static inline struct page * rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct page * ret; + if ((ret = __rb_insert_page_cache(inode, offset, node))) + goto out; + rb_insert_color(node, &inode->i_rb_page_cache); + out: + return ret; +} +----------------------------------------------------------------------- +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +#include +#include +#include "compiler.h" + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +struct rb_node +{ + uintptr_t rb_parent_color; +#define RB_RED 0 +#define RB_BLACK 1 + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + struct rb_node *rb_node; +}; + + +#define ext2fs_rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define ext2fs_rb_color(r) ((r)->rb_parent_color & 1) +#define ext2fs_rb_is_red(r) (!ext2fs_rb_color(r)) +#define ext2fs_rb_is_black(r) ext2fs_rb_color(r) +#define ext2fs_rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define ext2fs_rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) + +static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p; +} +static inline void ext2fs_rb_set_color(struct rb_node *rb, int color) +{ + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; +} + +#define RB_ROOT (struct rb_root) { NULL, } +#define ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member) + +static inline int ext2fs_rb_empty_root(struct rb_root *root) +{ + return root->rb_node == NULL; +} + +static inline int ext2fs_rb_empty_node(struct rb_node *node) +{ + return ext2fs_rb_parent(node) == node; +} + +static inline void ext2fs_rb_clear_node(struct rb_node *node) +{ + ext2fs_rb_set_parent(node, node); +} + +extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *); +extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *ext2fs_rb_next(struct rb_node *); +extern struct rb_node *ext2fs_rb_prev(struct rb_node *); +extern struct rb_node *ext2fs_rb_first(const struct rb_root *); +extern struct rb_node *ext2fs_rb_last(const struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void ext2fs_rb_link_node(struct rb_node * node, + struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent_color = (uintptr_t)parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +#endif /* _LINUX_RBTREE_H */ diff --git a/jni/e2fsprogs/lib/ext2fs/rbtree.o b/jni/e2fsprogs/lib/ext2fs/rbtree.o new file mode 100755 index 0000000000000000000000000000000000000000..b744656b8d31b3bd8ca2af3dfadb9775469779fd GIT binary patch literal 5920 zcmc&%Ux=L56~EtnJI)NdZW0qs@K0ui1U916M6mUt!iT$BABqG~Xd&!mcJn2>bhEpD zI|Oy5MpjE6e9%Q`AN;dvq0F=|QWU%3gVI6+`d}dRtz}1~d`o;#p)doE)8FshduG1* zc2=Vi`oZqK_uO;OIlptxJ?GAI5B>b%jOQ8sJoB#Ut(0oa*v-9pAk)C)!P!~$F1J^* z_4b7K%KB=tdC@O6aeiNIwcN~mK`Z~?U$50x4>k+t{9{|Y%tqcbZ`=JTyYB^G#{1vA zHO3z4@vdNFc8~dS9}i{t2b;Cksb<}uY91*-u2;BvXWl$6e4ypCK`Y*G@E5dZeXE0W z+7M^VPsqo=EzrhkmlynH+%qku*CBf#9kPYqdTvemYoOJD^&g$ie%eIcb-`P>`n+dt zS_l22Uv5qt^D24by{1K<&=>LE0CVdn>i;gf*P)woUxZx5VIOVD!yoV;{u0dnfD{6gzb9g#CnKA5LH&zJBaCLN5Jw1~zc4!5;-+O=D=UJXA-1zVg0b z{%7ZJ26>vPw^xniX~Wqhd6TpD<(U`Awb+L*bC^49<5{eY%PG(e=ob;oAuxNd4j!yEcRw&TPpF4j6nt$ui*TA_?p`*R> zU>(@L86)hCcf#m$m-_oKf=-MdI$w7&!Y;-5_nk1}Ebr$wj5yoH<1jORUD^PQe@}^I!$p^KJi~glPxMYT;g`4RH`c5M_#f@Ye5$#Hwd4kIz&E_>av!iZ zSTjc+bo`24cwnon;R9I%C)av+?!%dJ=gx4DLU$=3H)MgEii7 z*z+f;5%5cA!rfP&x$M{5xWC#vKS3Su`J`7n7*p+`$OG3OkxQuQ%q8NDbE!UhhvS32 zNxxJ^wQt&c!ra%`)snpu@fsJ|sa`35g3d%wTnDWITmJZU=eMlKQdc2Y{0KSJAL|`* zYspjJ+9>*wPklUClP7j~DT}!*HYIdZAMa%HF4X*D^M1yVx^|FzDPwi3jRn{^2=5@B zn~+Pqe;9z5d*TD@yS0X&zw4aq6*k8NSKs@Cb{1e~TEF`BIP|c;(;viI1-1x(qKCeP zuYaf*E+{4^SN-#UjUjCrkU!gEIKYQH<&DO$)pj|Xz&j|0*=va*Wb72f1F0DLh#zgs z%3DfmkJMq(Yz^I>C+(GqdI!Bv>dh+Z&2TU7aSn6ToeQoHc2G<3RuUajk6_y+^&#sM z@#2j1GOYQAr0z}RSqJZ=@1+C&@6&2-zwM_UAbVRW?cQE|DfYD zz6-9=m*0vLcK6|QIJ!8KzE1ezx^P0rb>kfH*8T*(P1fhwH?0_bQSota;QN^VCttz6 z9d(_x@s_tEY4AB>COIH_=qs1&T=U)00N;MxLHbX4;J-c|tjRO#c$kB7)_ebfG4K2X z%p=;-_vY4~kDTcCeDtQR-1&_`J>SgCR~F8UoeQJoxy6OCWA~SimC&cmZuw1ZjQ7lA z#(ValciTwO90Kitqt`N+Opcy>WaN(BZ)9E{@?Xx36i+@fYX1E%;R_reeiM-IsPbh# z8Yv#NY{EBtjeIXVzSpeY<0{X80eX*Hfp|ZfzdF9794AM2&yE_=^Rc4`LqZR_=f{Ue zib3yu)A60+I5|3&IWcM|cQ=B>FHJ{`+2G9?I~Bel+kC zdojL+Khl5d=;C+KUUPJ_3ln_Ge^~5s!tIv)9}_xmRqA^Y>zg27KehL=qc08F9my9= z4?Fs^! zpSWkaTABG(;*fBeQWVZtO5tqzbW}MTCbpw+X}&TOmKPRJg(jM=MqyZ*F{R~dRIN;7 zeEKZML#Imj^4~FY=&6!k78|PX^`CWY`z$61*3FY+_yN!FEvKIYOH%s${{ZLvRB`|S literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/read_bb.c b/jni/e2fsprogs/lib/ext2fs/read_bb.c new file mode 100755 index 0000000..e58b7cb --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/read_bb.c @@ -0,0 +1,102 @@ +/* + * read_bb --- read the bad blocks inode + * + * Copyright (C) 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct read_bb_record { + ext2_badblocks_list bb_list; + errcode_t err; +}; + +/* + * Helper function for ext2fs_read_bb_inode() + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int mark_bad_block(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct read_bb_record *rb = (struct read_bb_record *) priv_data; + + if (blockcnt < 0) + return 0; + + if ((*block_nr < fs->super->s_first_data_block) || + (*block_nr >= ext2fs_blocks_count(fs->super))) + return 0; /* Ignore illegal blocks */ + + rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr); + if (rb->err) + return BLOCK_ABORT; + return 0; +} + +/* + * Reads the current bad blocks from the bad blocks inode. + */ +errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list) +{ + errcode_t retval; + struct read_bb_record rb; + struct ext2_inode inode; + blk_t numblocks; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!*bb_list) { + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); + if (retval) + return retval; + numblocks = inode.i_blocks; + if (!(ext2fs_has_feature_huge_file(fs->super) && + (inode.i_flags & EXT4_HUGE_FILE_FL))) + numblocks = numblocks / (fs->blocksize / 512); + numblocks += 20; + if (numblocks < 50) + numblocks = 50; + if (numblocks > 50000) + numblocks = 500; + retval = ext2fs_badblocks_list_create(bb_list, numblocks); + if (retval) + return retval; + } + + rb.bb_list = *bb_list; + rb.err = 0; + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_READ_ONLY, + 0, mark_bad_block, &rb); + if (retval) + return retval; + + return rb.err; +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/read_bb.o b/jni/e2fsprogs/lib/ext2fs/read_bb.o new file mode 100755 index 0000000000000000000000000000000000000000..b26247c25d8272587e8a67179ab1a7bf07c93fb0 GIT binary patch literal 2392 zcmbtUO>7%Q6n^7%8gJvIF=zsuC=aI85rVV{`jPfm8YMc@zCX9+)Fu;=yCcTt&Rl$L$1s*xH)ykNP(TR^ zL?;EYgdN0$9i(a>-^t(q_TQK=AJm9mhyLkp!w!akPXZt6r62>W4lLH$Z_%a^;*lU#FHOIzo(>q_NTE`UJCvE8hthe1<5w<)dhK9m?&2EW?ea~-`E7TEHf!w^)Z6iHJk&1EmTT>w^#NCYfin=r z84$}WMzZnw!nwxX9t!Rysk+rq)%zXbcG%!!?6HGIYW%=^{j`x>e*)v`!j%TjNp;O| z8uA_V@*d{Yf@q!m{Jac@p}>JON!9%NY74Ye2oL>fDUs zT&;puwGt-cOVG;GF1> zCus=S8HH~_kVdHJ#&tj6 zlIT9J^CYY6O}m!w&H9A@`H6~?nJ#6gDo(aEQ}oHomI?(AlY(2Gax!kN=_adK@;&R7 zOK&_`@!jmy9@ot&`gFeHJK3`5`kvaun{+11Zo$*BlWxVCfPbd!Ig>M2J!c|6z2^im z=j4l}+(9IhIS3-5@P2MCN0OPzSXr_ve%W_37~d=K7_QIB`(7Ejou|Q^B_G2yIBPwv z+VsDN-=Tmz<*=zwAfe8I4ro~thcVXr#n_6lrOt&~;#)sx%w^0z2vavMeKy>G(qeeB z6pw8B-WtH1HCh`osET?NzOd>1^~m?5o`>U}Ke8!@W3MTGOPORV{(M*zbDh72Jxq?O ie_ho-rUIGAJ=T0({}!;;y_s@T?LV%H +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Reads a list of bad blocks from a FILE * + */ +errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void *priv_data, + void (*invalid)(ext2_filsys fs, + blk_t blk, + char *badstr, + void *priv_data)) +{ + errcode_t retval; + unsigned long long blockno; + int count; + char buf[128]; + + if (fs) + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!*bb_list) { + retval = ext2fs_badblocks_list_create(bb_list, 10); + if (retval) + return retval; + } + + while (!feof (f)) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + count = sscanf(buf, "%llu", &blockno); + if (count <= 0) + continue; + /* Badblocks isn't going to be updated for 64bit */ + if (blockno >> 32) + return EOVERFLOW; + if (fs && + ((blockno < fs->super->s_first_data_block) || + (blockno >= ext2fs_blocks_count(fs->super)))) { + if (invalid) + (invalid)(fs, (blk64_t) blockno, buf, priv_data); + continue; + } + retval = ext2fs_badblocks_list_add(*bb_list, (blk64_t) blockno); + if (retval) + return retval; + } + return 0; +} + +struct compat_struct { + void (*invalid)(ext2_filsys, blk_t); +}; + +static void call_compat_invalid(ext2_filsys fs, blk_t blk, + char *badstr EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct compat_struct *st; + + st = (struct compat_struct *) priv_data; + if (st->invalid) + (st->invalid)(fs, blk); +} + + +/* + * Reads a list of bad blocks from a FILE * + */ +errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void (*invalid)(ext2_filsys fs, blk_t blk)) +{ + struct compat_struct st; + + st.invalid = invalid; + + return ext2fs_read_bb_FILE2(fs, f, bb_list, &st, + call_compat_invalid); +} + + diff --git a/jni/e2fsprogs/lib/ext2fs/read_bb_file.o b/jni/e2fsprogs/lib/ext2fs/read_bb_file.o new file mode 100755 index 0000000000000000000000000000000000000000..7383a44673ebd6824edc729fd37c0aa80fe5e8fe GIT binary patch literal 2616 zcmbVNQD_`x5T4z=n7ibXrrKyijCaxqNx*F`BJ`~*X={q14@IHSht1}0uXl9suHJ5I zH3bXln?CeF#1|zBLIQ#>6;J3xAwKxpD#aHiwhAeI(IS`yk8|eV`7ghlI|K)I|Cw)Q zzJF%^|MuQJv2;?`G?1df*RW?v6rkC^r&~g`U;rcATgIK%>hNZ3&1h^G+MS(22w@yT zZ4^TNAcV#cgozY{$#E-8>Tnae5A6)1PPS%+Gut2DE&ulAh&`5&Tx8u1e1 z(~}TZ5$og~jPj7{D~SPOuV~lKU|Am!H}pZ6?6bn}Algsxp-o)pn5&aJit(6d4ZzD1 z(-GVDp`ndLoXZgHbqaF@4shdnfW~LoFXgUpO*A*Q&NY)7yy?jv+U;jVpV(uvwfwzW zODT2jF4b}r`Q$7X6H2W#7o5)w_BAtVeM7TZ)1ui>d{uiq25K`{WKSNWaxWw z$&?kAG=&%KEauE&{x8PB?BO9RypMf?cI+PYev4~PA!nBA7IDd0!T%p~?Zf;pI6s5E z$yvgr6}DDSZ{j^^+&1icZJb$a)!1xpL1TR_v-_!$*}Z=N!UuS7sJ91)p|OL#t*_bW zv(aaT37q$JoHy0cT3y&gj_zCwnWoA`JUe18Vm8s;V_Wbq*iG5H%KL)nT>{8^PW62D zvRn7dwQ4qZ)XbT9U?W%riT2JJ(5^nGO{6n0jrN#80p@g6jt~E?Ev6?&KG8o;7-M=m zgXS>&{1dvS$jz}!v>qR}WN47iSZW;JB_U_&t;Fe;5*UT-dw-5d0{&?4b0A;<75Q%& z!~=sa_*(+i;VP$yS~%6f9pdtr0QTdL1&+5QCO-;W`M9v3X7!{}kC-cBui+!lfJ4P{ ztOq{R1E(|S#*^-Wzt;o*7ICUm)+f#svG?&InZUUYM5=gGJPF~0kt*KXtP@T(NcoeM zrw~`Cx6Alw43{5o;u(@8xL!w_gz(`=74Kga{D6WN_`GRfQsw!V7^i(z++&>hQwqoj) z>~i(8JbA<` zhc(p-PT&w-&dkBo6?0CG@qe#3G1KUhz41f@j^KHz5;K9q2;=ZhsKwe3d>^DE{zaf% z!YmoU>sh|!_+KW3?h;WYBeV0J{TpoxnP*%shqx*Aw?aOq>#SME;*%Wb{HG~Nk$C +#include +#include +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Iterate through the groups which hold BACKUP superblock/GDT copies in an + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before + * calling this for the first time. In a sparse filesystem it will be the + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... + */ +static unsigned int list_backups(ext2_filsys fs, unsigned int *three, + unsigned int *five, unsigned int *seven) +{ + unsigned int *min = three; + int mult = 3; + unsigned int ret; + + if (ext2fs_has_feature_sparse_super2(fs->super)) { + if (*min == 1) { + *min += 1; + if (fs->super->s_backup_bgs[0]) + return fs->super->s_backup_bgs[0]; + } + if (*min == 2) { + *min += 1; + if (fs->super->s_backup_bgs[1]) + return fs->super->s_backup_bgs[1]; + } + return fs->group_desc_count; + } + if (!ext2fs_has_feature_sparse_super(fs->super)) { + ret = *min; + *min += 1; + return ret; + } + + if (*five < *min) { + min = five; + mult = 5; + } + if (*seven < *min) { + min = seven; + mult = 7; + } + + ret = *min; + *min *= mult; + + return ret; +} + +/* + * This code assumes that the reserved blocks have already been marked in-use + * during ext2fs_initialize(), so that they are not allocated for other + * uses before we can add them to the resize inode (which has to come + * after the creation of the inode table). + */ +errcode_t ext2fs_create_resize_inode(ext2_filsys fs) +{ + errcode_t retval, retval2; + struct ext2_super_block *sb; + struct ext2_inode inode; + __u32 *dindir_buf, *gdt_buf; + unsigned long long apb, inode_size; + /* FIXME-64 - can't deal with extents */ + blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; + int dindir_dirty = 0, inode_dirty = 0, sb_blk = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + sb = fs->super; + + retval = ext2fs_get_array(2, fs->blocksize, &dindir_buf); + if (retval) + return retval; + gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); + + retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); + if (retval) + goto out_free; + + /* + * File systems with a blocksize of 1024 and bigalloc have + * sb->s_first_data_block of 0; yet the superblock is still at + * block #1. We compensate for it here. + */ + sb_blk = sb->s_first_data_block; + if (fs->blocksize == 1024 && sb_blk == 0) + sb_blk = 1; + + /* Maximum possible file size (we only use double indirect blocks) */ + apb = EXT2_ADDR_PER_BLOCK(sb); + if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) { +#ifdef RES_GDT_DEBUG + printf("reading GDT dindir %u\n", dindir_blk); +#endif + retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); + if (retval) + goto out_inode; + } else { + blk_t goal = sb_blk + fs->desc_blocks + + sb->s_reserved_gdt_blocks + 2 + + fs->inode_blocks_per_group; + + retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk); + if (retval) + goto out_free; + inode.i_mode = LINUX_S_IFREG | 0600; + inode.i_links_count = 1; + inode.i_block[EXT2_DIND_BLOCK] = dindir_blk; + ext2fs_iblk_set(fs, &inode, 1); + memset(dindir_buf, 0, fs->blocksize); +#ifdef RES_GDT_DEBUG + printf("allocated GDT dindir %u\n", dindir_blk); +#endif + dindir_dirty = inode_dirty = 1; + inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS; + inode_size *= fs->blocksize; + retval = ext2fs_inode_size_set(fs, &inode, inode_size); + if (retval) + goto out_free; + inode.i_ctime = fs->now ? fs->now : time(0); + } + + for (rsv_off = 0, gdt_off = fs->desc_blocks, + gdt_blk = sb_blk + 1 + fs->desc_blocks; + rsv_off < sb->s_reserved_gdt_blocks; + rsv_off++, gdt_off++, gdt_blk++) { + unsigned int three = 1, five = 5, seven = 7; + unsigned int grp, last = 0; + int gdt_dirty = 0; + + gdt_off %= apb; + if (!dindir_buf[gdt_off]) { + /* FIXME XXX XXX + blk_t new_blk; + + retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk); + if (retval) + goto out_free; + if (new_blk != gdt_blk) { + // XXX free block + retval = -1; // XXX + } + */ + gdt_dirty = dindir_dirty = inode_dirty = 1; + memset(gdt_buf, 0, fs->blocksize); + dindir_buf[gdt_off] = gdt_blk; + ext2fs_iblk_add_blocks(fs, &inode, 1); +#ifdef RES_GDT_DEBUG + printf("added primary GDT block %u at %u[%u]\n", + gdt_blk, dindir_blk, gdt_off); +#endif + } else if (dindir_buf[gdt_off] == gdt_blk) { +#ifdef RES_GDT_DEBUG + printf("reading primary GDT block %u\n", gdt_blk); +#endif + retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); + if (retval) + goto out_dindir; + } else { +#ifdef RES_GDT_DEBUG + printf("bad primary GDT %u != %u at %u[%u]\n", + dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off); +#endif + retval = EXT2_ET_RESIZE_INODE_CORRUPT; + goto out_dindir; + } + + while ((grp = list_backups(fs, &three, &five, &seven)) < + fs->group_desc_count) { + blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; + + if (!gdt_buf[last]) { +#ifdef RES_GDT_DEBUG + printf("added backup GDT %u grp %u@%u[%u]\n", + expect, grp, gdt_blk, last); +#endif + gdt_buf[last] = expect; + ext2fs_iblk_add_blocks(fs, &inode, 1); + gdt_dirty = inode_dirty = 1; + } else if (gdt_buf[last] != expect) { +#ifdef RES_GDT_DEBUG + printf("bad backup GDT %u != %u at %u[%u]\n", + gdt_buf[last], expect, gdt_blk, last); +#endif + retval = EXT2_ET_RESIZE_INODE_CORRUPT; + goto out_dindir; + } + last++; + } + if (gdt_dirty) { +#ifdef RES_GDT_DEBUG + printf("writing primary GDT block %u\n", gdt_blk); +#endif + retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); + if (retval) + goto out_dindir; + } + } + +out_dindir: + if (dindir_dirty) { + retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); + if (!retval) + retval = retval2; + } +out_inode: +#ifdef RES_GDT_DEBUG + printf("inode.i_blocks = %u, i_size = %lu\n", inode.i_blocks, + EXT2_I_SIZE(&inode)); +#endif + if (inode_dirty) { + inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); + retval2 = ext2fs_write_new_inode(fs, EXT2_RESIZE_INO, &inode); + if (!retval) + retval = retval2; + } +out_free: + ext2fs_free_mem(&dindir_buf); + return retval; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/res_gdt.o b/jni/e2fsprogs/lib/ext2fs/res_gdt.o new file mode 100755 index 0000000000000000000000000000000000000000..16200173b0f7189f6c1feb635a5ce7051b4f391b GIT binary patch literal 4472 zcmbtYTWl0n82)Fsh1s_BLaQhUZIzfV#+3qwCP)}93IbX!DjLvrX{YU`H`rZ-a*0j! zLFGXzMDPMuF|qif4;q;l1M*Ug4?>JjXtqlXGv!Hqu#>b|zyHiR?R2{vNIYccocYdw z{m%cNX?XL=ZBGR>jnvTS2by_PC{a_z%-Rr3gF=wZHWy!+I#hjb@+`Simx_i)&e9dT znp|2yZgvM*+3onXkfkp$TwOEVaQefm@xQ*grE8&^X`&b4tH!A|+y>xXz#FQ_eNUqr z8(0WB;VR4;xk5i|SYttbg+YT?Gr_mUt)QKGI7Q-4LdX)V)z@`m3 zUUPh$cj#Wo4-U45>Mt+0gP|4r5##u~$U_fZ{@7keu6@I>>`t;qHCm(eM0}lwl|k&e zxvKbT5Z}wvkJB<}i5!=_4VW096ptg zI?2Hpcp9r9H?;Ctt5dBFgpsGSNgHqwqjSTvcRzAcv8EBXI=2kYZ7f*3g7?NM43~Kk z`lt^Fb>gfu+;RNEM@l{sGsoOWL(W?G<2nG}&YLr#Ac zKINH;GXX}x(xv1ULoN*t*bcu7{!1Z$a^?)PZDff!z^xNSyg2W0F;$8Dfaw>*N9~=S zJlC_`#ylfd@Q+&W{%N6CC!#hs5o!fB(oB}k^9JWu2Yi5O!|D&eH=AofqeiGgW7{nECSgVR?@IqN;J& z5IVp!@KcEQU9d9`KjvZdrtE9<=u5zu+gbHptqo;@+R*iXXy^mk&*^pK-4~7UPkQ$k z#U6L#%qx7OR;(>t+x6i1NXZh!SZY54jt~>-!{bPs;mCOed1LP;_VVQ|&IEO6gTHdb z=eNVU%t6|BSNU_QSNX7C)Ps$4yqwK0vR4~(d-*oJvF~YqP(Q*R>W=F{tho+gL#$D2 z9q=Q#++kP^f!o|0#iZ`Y?^#FOxy866aW2ZIu(jQ=x{79OiTW@2fh1Q#4PW1<%jTnm^^E^Q-`*n!?$SYLNNM!wpqhB zsp#Ak>S{PxJMsBj%O*1TCS9)}cjT?tCT#S07x!HS`Y;%sU>hcC??SQ68@-P^n|a<_ zACTWDU=1Et)u4HLI`s5soY-t&3v0b_ej(w^{x-e7Ds zFqOk&$YD^`z4VD(Ehi^-yVTQN4qb5@#q$>*zQBjq$RlBSl;!kT>BD`0`qSG!+FZCKkxkFO_;50X z$S4)>HD#t|SF|G$!>eS%^U-JShehP2;5Imc?}RDxoV6w0voN-!o$aYe8%2_-L@Kr$ z^FS}p(t4qcSJCqJhAD04Skz7KqNx{3Z=N~G5HQ&IdTKna0 zDMx-Vk1YR}1?&5Jk5wk5{waR(ja;*n*vprHljQ$(smprIvC>!h +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "e2image.h" + +#ifdef HAVE_PTHREAD +typedef pthread_mutex_t mutex_t; + +static void unix_pthread_mutex_lock(mutex_t *mutex) +{ + if (mutex) + pthread_mutex_lock(mutex); +} +static void unix_pthread_mutex_unlock(mutex_t *mutex) +{ + if (mutex) + pthread_mutex_unlock(mutex); +} +#else +typedef int mutex_t; +#define unix_pthread_mutex_lock(mutex_t) do {} while (0) +#define unix_pthread_mutex_unlock(mutex_t) do {} while (0) +#endif + +static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) +{ + dgrp_t i; + unsigned int j; + int block_nbytes, inode_nbytes; + unsigned int nbits; + errcode_t retval; + char *block_buf = NULL, *inode_buf = NULL; + int csum_flag; + blk64_t blk; + blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); + ext2_ino_t ino_itr = 1; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + csum_flag = ext2fs_has_group_desc_csum(fs); + + inode_nbytes = block_nbytes = 0; + if (do_block) { + block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; + retval = io_channel_alloc_buf(fs->io, 0, &block_buf); + if (retval) + goto errout; + memset(block_buf, 0xff, fs->blocksize); + } + if (do_inode) { + inode_nbytes = (size_t) + ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); + retval = io_channel_alloc_buf(fs->io, 0, &inode_buf); + if (retval) + goto errout; + memset(inode_buf, 0xff, fs->blocksize); + } + + for (i = 0; i < fs->group_desc_count; i++) { + if (!do_block) + goto skip_block_bitmap; + + if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) + ) + goto skip_this_block_bitmap; + + retval = ext2fs_get_block_bitmap_range2(fs->block_map, + blk_itr, block_nbytes << 3, block_buf); + if (retval) + goto errout; + + if (i == fs->group_desc_count - 1) { + /* Force bitmap padding for the last group */ + nbits = EXT2FS_NUM_B2C(fs, + ((ext2fs_blocks_count(fs->super) + - (__u64) fs->super->s_first_data_block) + % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super))); + if (nbits) + for (j = nbits; j < fs->blocksize * 8; j++) + ext2fs_set_bit(j, block_buf); + } + + retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf, + block_nbytes); + if (retval) + return retval; + ext2fs_group_desc_csum_set(fs, i); + fs->flags |= EXT2_FLAG_DIRTY; + + blk = ext2fs_block_bitmap_loc(fs, i); + if (blk && blk < ext2fs_blocks_count(fs->super)) { + retval = io_channel_write_blk64(fs->io, blk, 1, + block_buf); + if (retval) { + retval = EXT2_ET_BLOCK_BITMAP_WRITE; + goto errout; + } + } + skip_this_block_bitmap: + blk_itr += block_nbytes << 3; + skip_block_bitmap: + + if (!do_inode) + continue; + + if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) + ) + goto skip_this_inode_bitmap; + + retval = ext2fs_get_inode_bitmap_range2(fs->inode_map, + ino_itr, inode_nbytes << 3, inode_buf); + if (retval) + goto errout; + + retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf, + inode_nbytes); + if (retval) + goto errout; + ext2fs_group_desc_csum_set(fs, i); + fs->flags |= EXT2_FLAG_DIRTY; + + blk = ext2fs_inode_bitmap_loc(fs, i); + if (blk && blk < ext2fs_blocks_count(fs->super)) { + retval = io_channel_write_blk64(fs->io, blk, 1, + inode_buf); + if (retval) { + retval = EXT2_ET_INODE_BITMAP_WRITE; + goto errout; + } + } + skip_this_inode_bitmap: + ino_itr += inode_nbytes << 3; + + } + if (do_block) { + fs->flags &= ~EXT2_FLAG_BB_DIRTY; + ext2fs_free_mem(&block_buf); + } + if (do_inode) { + fs->flags &= ~EXT2_FLAG_IB_DIRTY; + ext2fs_free_mem(&inode_buf); + } + return 0; +errout: + if (inode_buf) + ext2fs_free_mem(&inode_buf); + if (block_buf) + ext2fs_free_mem(&block_buf); + return retval; +} + +static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs) +{ + dgrp_t i; + blk64_t blk; + ext2fs_block_bitmap bmap = fs->block_map; + + for (i = 0; i < fs->group_desc_count; i++) { + if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)) + continue; + + ext2fs_reserve_super_and_bgd(fs, i, bmap); + + /* + * Mark the blocks used for the inode table + */ + blk = ext2fs_inode_table_loc(fs, i); + if (blk) + ext2fs_mark_block_bitmap_range2(bmap, blk, + fs->inode_blocks_per_group); + + /* + * Mark block used for the block bitmap + */ + blk = ext2fs_block_bitmap_loc(fs, i); + if (blk && blk < ext2fs_blocks_count(fs->super)) + ext2fs_mark_block_bitmap2(bmap, blk); + + /* + * Mark block used for the inode bitmap + */ + blk = ext2fs_inode_bitmap_loc(fs, i); + if (blk && blk < ext2fs_blocks_count(fs->super)) + ext2fs_mark_block_bitmap2(bmap, blk); + } + return 0; +} + +static int bitmap_tail_verify(unsigned char *bitmap, int first, int last) +{ + int i; + + for (i = first; i <= last; i++) + if (bitmap[i] != 0xff) + return 0; + return 1; +} + +static errcode_t read_bitmaps_range_prepare(ext2_filsys fs, int flags) +{ + errcode_t retval; + int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; + int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; + char *buf; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if ((block_nbytes > (int) fs->blocksize) || + (inode_nbytes > (int) fs->blocksize)) + return EXT2_ET_CORRUPT_SUPERBLOCK; + + fs->write_bitmaps = ext2fs_write_bitmaps; + + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); + if (retval) + return retval; + + if (flags & EXT2FS_BITMAPS_BLOCK) { + if (fs->block_map) + ext2fs_free_block_bitmap(fs->block_map); + strcpy(buf, "block bitmap for "); + strcat(buf, fs->device_name); + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); + if (retval) + goto cleanup; + } + + if (flags & EXT2FS_BITMAPS_INODE) { + if (fs->inode_map) + ext2fs_free_inode_bitmap(fs->inode_map); + strcpy(buf, "inode bitmap for "); + strcat(buf, fs->device_name); + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); + if (retval) + goto cleanup; + } + ext2fs_free_mem(&buf); + return retval; + +cleanup: + if (flags & EXT2FS_BITMAPS_BLOCK) { + ext2fs_free_block_bitmap(fs->block_map); + fs->block_map = 0; + } + if (flags & EXT2FS_BITMAPS_INODE) { + ext2fs_free_inode_bitmap(fs->inode_map); + fs->inode_map = 0; + } + ext2fs_free_mem(&buf); + return retval; +} + +static errcode_t read_bitmaps_range_start(ext2_filsys fs, int flags, + dgrp_t start, dgrp_t end, + mutex_t *mutex, + int *tail_flags) +{ + dgrp_t i; + char *block_bitmap = 0, *inode_bitmap = 0; + errcode_t retval = 0; + int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; + int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; + int csum_flag; + unsigned int cnt; + blk64_t blk; + blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); + blk64_t blk_cnt; + ext2_ino_t ino_itr = 1; + ext2_ino_t ino_cnt; + + csum_flag = ext2fs_has_group_desc_csum(fs); + + if (flags & EXT2FS_BITMAPS_BLOCK) { + retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap); + if (retval) + goto cleanup; + } else { + block_nbytes = 0; + } + + if (flags & EXT2FS_BITMAPS_INODE) { + retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap); + if (retval) + goto cleanup; + } else { + inode_nbytes = 0; + } + + /* io should be null */ + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize); + ino_cnt = fs->super->s_inodes_count; + while (inode_bitmap && ino_cnt > 0) { + retval = io_channel_read_blk64(fs->image_io, blk++, + 1, inode_bitmap); + if (retval) + goto cleanup; + cnt = fs->blocksize << 3; + if (cnt > ino_cnt) + cnt = ino_cnt; + retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, + ino_itr, cnt, inode_bitmap); + if (retval) + goto cleanup; + ino_itr += cnt; + ino_cnt -= cnt; + } + blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) / + fs->blocksize); + blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, + fs->group_desc_count); + while (block_bitmap && blk_cnt > 0) { + retval = io_channel_read_blk64(fs->image_io, blk++, + 1, block_bitmap); + if (retval) + goto cleanup; + cnt = fs->blocksize << 3; + if (cnt > blk_cnt) + cnt = blk_cnt; + retval = ext2fs_set_block_bitmap_range2(fs->block_map, + blk_itr, cnt, block_bitmap); + if (retval) + goto cleanup; + blk_itr += cnt; + blk_cnt -= cnt; + } + goto cleanup; + } + + blk_itr += ((blk64_t)start * (block_nbytes << 3)); + ino_itr += ((blk64_t)start * (inode_nbytes << 3)); + for (i = start; i <= end; i++) { + if (block_bitmap) { + blk = ext2fs_block_bitmap_loc(fs, i); + if ((csum_flag && + ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && + ext2fs_group_desc_csum_verify(fs, i)) || + (blk >= ext2fs_blocks_count(fs->super))) + blk = 0; + if (blk) { + retval = io_channel_read_blk64(fs->io, blk, + 1, block_bitmap); + if (retval) { + retval = EXT2_ET_BLOCK_BITMAP_READ; + goto cleanup; + } + /* verify block bitmap checksum */ + if (!(fs->flags & + EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_block_bitmap_csum_verify(fs, i, + block_bitmap, block_nbytes)) { + retval = + EXT2_ET_BLOCK_BITMAP_CSUM_INVALID; + goto cleanup; + } + if (!bitmap_tail_verify((unsigned char *) block_bitmap, + block_nbytes, fs->blocksize - 1)) + *tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM; + } else + memset(block_bitmap, 0, block_nbytes); + cnt = block_nbytes << 3; + unix_pthread_mutex_lock(mutex); + retval = ext2fs_set_block_bitmap_range2(fs->block_map, + blk_itr, cnt, block_bitmap); + unix_pthread_mutex_unlock(mutex); + if (retval) + goto cleanup; + blk_itr += block_nbytes << 3; + } + if (inode_bitmap) { + blk = ext2fs_inode_bitmap_loc(fs, i); + if ((csum_flag && + ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && + ext2fs_group_desc_csum_verify(fs, i)) || + (blk >= ext2fs_blocks_count(fs->super))) + blk = 0; + if (blk) { + retval = io_channel_read_blk64(fs->io, blk, + 1, inode_bitmap); + if (retval) { + retval = EXT2_ET_INODE_BITMAP_READ; + goto cleanup; + } + + /* verify inode bitmap checksum */ + if (!(fs->flags & + EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_inode_bitmap_csum_verify(fs, i, + inode_bitmap, inode_nbytes)) { + retval = + EXT2_ET_INODE_BITMAP_CSUM_INVALID; + goto cleanup; + } + if (!bitmap_tail_verify((unsigned char *) inode_bitmap, + inode_nbytes, fs->blocksize - 1)) + *tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM; + } else + memset(inode_bitmap, 0, inode_nbytes); + cnt = inode_nbytes << 3; + unix_pthread_mutex_lock(mutex); + retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, + ino_itr, cnt, inode_bitmap); + unix_pthread_mutex_unlock(mutex); + if (retval) + goto cleanup; + ino_itr += inode_nbytes << 3; + } + } + +cleanup: + if (inode_bitmap) + ext2fs_free_mem(&inode_bitmap); + if (block_bitmap) + ext2fs_free_mem(&block_bitmap); + return retval; +} + +static errcode_t read_bitmaps_range_end(ext2_filsys fs, int flags, + int tail_flags) +{ + errcode_t retval; + + /* Mark group blocks for any BLOCK_UNINIT groups */ + if (flags & EXT2FS_BITMAPS_BLOCK) { + retval = mark_uninit_bg_group_blocks(fs); + if (retval) + return retval; + fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM; + } + if (flags & EXT2FS_BITMAPS_INODE) + fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM; + fs->flags |= tail_flags; + + return 0; +} + +static void read_bitmaps_cleanup_on_error(ext2_filsys fs, int flags) +{ + if (flags & EXT2FS_BITMAPS_BLOCK) { + ext2fs_free_block_bitmap(fs->block_map); + fs->block_map = 0; + } + if (flags & EXT2FS_BITMAPS_INODE) { + ext2fs_free_inode_bitmap(fs->inode_map); + fs->inode_map = 0; + } +} + +static errcode_t read_bitmaps_range(ext2_filsys fs, int flags, + dgrp_t start, dgrp_t end) +{ + errcode_t retval; + int tail_flags = 0; + + retval = read_bitmaps_range_prepare(fs, flags); + if (retval) + return retval; + + retval = read_bitmaps_range_start(fs, flags, start, end, + NULL, &tail_flags); + if (retval == 0) + retval = read_bitmaps_range_end(fs, flags, tail_flags); + if (retval) + read_bitmaps_cleanup_on_error(fs, flags); + return retval; +} + +#ifdef HAVE_PTHREAD +struct read_bitmaps_thread_info { + ext2_filsys rbt_fs; + int rbt_flags; + dgrp_t rbt_grp_start; + dgrp_t rbt_grp_end; + errcode_t rbt_retval; + pthread_mutex_t *rbt_mutex; + int rbt_tail_flags; +}; + +static void *read_bitmaps_thread(void *data) +{ + struct read_bitmaps_thread_info *rbt = data; + + rbt->rbt_retval = read_bitmaps_range_start(rbt->rbt_fs, rbt->rbt_flags, + rbt->rbt_grp_start, rbt->rbt_grp_end, + rbt->rbt_mutex, &rbt->rbt_tail_flags); + return NULL; +} +#endif + +errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) +{ +#ifdef HAVE_PTHREAD + pthread_attr_t attr; + pthread_t *thread_ids = NULL; + struct read_bitmaps_thread_info *thread_infos = NULL; + pthread_mutex_t rbt_mutex = PTHREAD_MUTEX_INITIALIZER; + errcode_t retval; + errcode_t rc; + unsigned flexbg_size = 1U << fs->super->s_log_groups_per_flex; + dgrp_t average_group; + int i, tail_flags = 0; +#endif + + if (flags & ~EXT2FS_BITMAPS_VALID_FLAGS) + return EXT2_ET_INVALID_ARGUMENT; + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + + if (flags & EXT2FS_BITMAPS_WRITE) + return write_bitmaps(fs, flags & EXT2FS_BITMAPS_INODE, + flags & EXT2FS_BITMAPS_BLOCK); + +#ifdef HAVE_PTHREAD + if (((fs->io->flags & CHANNEL_FLAGS_THREADS) == 0) || + (num_threads == 1) || (fs->flags & EXT2_FLAG_IMAGE_FILE)) + goto fallback; + +#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) + if (num_threads < 0) + num_threads = sysconf(_SC_NPROCESSORS_CONF); +#endif + /* + * Guess for now; eventually we should probably define + * ext2fs_get_num_cpus() and teach it how to get this info on + * MacOS, FreeBSD, etc. + * ref: https://stackoverflow.com/questions/150355 + */ + if (num_threads < 0) + num_threads = 4; + + if ((unsigned) num_threads > fs->group_desc_count) + num_threads = fs->group_desc_count; + average_group = fs->group_desc_count / num_threads; + if (ext2fs_has_feature_flex_bg(fs->super)) { + average_group = (average_group / flexbg_size) * flexbg_size; + } + if ((num_threads <= 1) || (average_group == 0)) + goto fallback; + + io_channel_set_options(fs->io, "cache=off"); + retval = pthread_attr_init(&attr); + if (retval) + return retval; + + thread_ids = calloc(sizeof(pthread_t), num_threads); + if (!thread_ids) + return ENOMEM; + + thread_infos = calloc(sizeof(struct read_bitmaps_thread_info), + num_threads); + if (!thread_infos) + goto out; + + retval = read_bitmaps_range_prepare(fs, flags); + if (retval) + goto out; + +// fprintf(stdout, "Multiple threads triggered to read bitmaps\n"); + for (i = 0; i < num_threads; i++) { + thread_infos[i].rbt_fs = fs; + thread_infos[i].rbt_flags = flags; + thread_infos[i].rbt_mutex = &rbt_mutex; + thread_infos[i].rbt_tail_flags = 0; + if (i == 0) + thread_infos[i].rbt_grp_start = 0; + else + thread_infos[i].rbt_grp_start = average_group * i + 1; + + if (i == num_threads - 1) + thread_infos[i].rbt_grp_end = fs->group_desc_count - 1; + else + thread_infos[i].rbt_grp_end = average_group * (i + 1); + retval = pthread_create(&thread_ids[i], &attr, + &read_bitmaps_thread, &thread_infos[i]); + if (retval) + break; + } + for (i = 0; i < num_threads; i++) { + if (!thread_ids[i]) + break; + rc = pthread_join(thread_ids[i], NULL); + if (rc && !retval) + retval = rc; + rc = thread_infos[i].rbt_retval; + if (rc && !retval) + retval = rc; + tail_flags |= thread_infos[i].rbt_tail_flags; + } +out: + rc = pthread_attr_destroy(&attr); + if (rc && !retval) + retval = rc; + free(thread_infos); + free(thread_ids); + + if (retval == 0) + retval = read_bitmaps_range_end(fs, flags, tail_flags); + if (retval) + read_bitmaps_cleanup_on_error(fs, flags); + /* XXX should save and restore cache setting */ + io_channel_set_options(fs->io, "cache=on"); + return retval; +fallback: +#endif /* HAVE_PTHREAD */ + return read_bitmaps_range(fs, flags, 0, fs->group_desc_count - 1); +} + +errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) +{ + return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_INODE, -1); +} + +errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) +{ + return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_BLOCK, -1); +} + +errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) +{ + return write_bitmaps(fs, 1, 0); +} + +errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) +{ + return write_bitmaps(fs, 0, 1); +} + +errcode_t ext2fs_read_bitmaps(ext2_filsys fs) +{ + int flags = 0; + + if (!fs->inode_map) + flags |= EXT2FS_BITMAPS_INODE; + if (!fs->block_map) + flags |= EXT2FS_BITMAPS_BLOCK; + if (flags == 0) + return 0; + return ext2fs_rw_bitmaps(fs, flags, -1); +} + +errcode_t ext2fs_write_bitmaps(ext2_filsys fs) +{ + int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs); + int do_block = fs->block_map && ext2fs_test_bb_dirty(fs); + + if (!do_inode && !do_block) + return 0; + + return write_bitmaps(fs, do_inode, do_block); +} diff --git a/jni/e2fsprogs/lib/ext2fs/rw_bitmaps.o b/jni/e2fsprogs/lib/ext2fs/rw_bitmaps.o new file mode 100755 index 0000000000000000000000000000000000000000..b7abdd11736a331587b2de834641c735c70352a8 GIT binary patch literal 15504 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 + * (copied from libtomcrypt and then relicensed under GPLv2) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif +#include "ext2fs.h" + +static const __u32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) +#define RORc(x, y) ( ((((__u32)(x)&0xFFFFFFFFUL)>>(__u32)((y)&31)) | ((__u32)(x)<<(__u32)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + +#define STORE64H(x, y) \ + do { \ + (y)[0] = (unsigned char)(((x)>>56)&255);\ + (y)[1] = (unsigned char)(((x)>>48)&255);\ + (y)[2] = (unsigned char)(((x)>>40)&255);\ + (y)[3] = (unsigned char)(((x)>>32)&255);\ + (y)[4] = (unsigned char)(((x)>>24)&255);\ + (y)[5] = (unsigned char)(((x)>>16)&255);\ + (y)[6] = (unsigned char)(((x)>>8)&255);\ + (y)[7] = (unsigned char)((x)&255); } while(0) + +#define STORE32H(x, y) \ + do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) + +#define LOAD32H(x, y) \ + do { x = ((__u32)((y)[0] & 255)<<24) | \ + ((__u32)((y)[1] & 255)<<16) | \ + ((__u32)((y)[2] & 255)<<8) | \ + ((__u32)((y)[3] & 255)); } while(0) + +struct sha256_state { + __u64 length; + __u32 state[8], curlen; + unsigned char buf[64]; +}; + +/* This is a highly simplified version from libtomcrypt */ +struct hash_state { + struct sha256_state sha256; +}; + +static void sha256_compress(struct hash_state * md, const unsigned char *buf) +{ + __u32 S[8], W[64], t0, t1; + __u32 t; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha256.state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha256.state[i] = md->sha256.state[i] + S[i]; + } +} + +static void sha256_init(struct hash_state * md) +{ + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0x6A09E667UL; + md->sha256.state[1] = 0xBB67AE85UL; + md->sha256.state[2] = 0x3C6EF372UL; + md->sha256.state[3] = 0xA54FF53AUL; + md->sha256.state[4] = 0x510E527FUL; + md->sha256.state[5] = 0x9B05688CUL; + md->sha256.state[6] = 0x1F83D9ABUL; + md->sha256.state[7] = 0x5BE0CD19UL; +} + +#define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#define SHA256_BLOCKSIZE 64 +static void sha256_process(struct hash_state * md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + + while (inlen > 0) { + if (md->sha256.curlen == 0 && inlen >= SHA256_BLOCKSIZE) { + sha256_compress(md, in); + md->sha256.length += SHA256_BLOCKSIZE * 8; + in += SHA256_BLOCKSIZE; + inlen -= SHA256_BLOCKSIZE; + } else { + n = MIN(inlen, (SHA256_BLOCKSIZE - md->sha256.curlen)); + memcpy(md->sha256.buf + md->sha256.curlen, in, (size_t)n); + md->sha256.curlen += n; + in += n; + inlen -= n; + if (md->sha256.curlen == SHA256_BLOCKSIZE) { + sha256_compress(md, md->sha256.buf); + md->sha256.length += 8*SHA256_BLOCKSIZE; + md->sha256.curlen = 0; + } + } + } +} + + +static void sha256_done(struct hash_state * md, unsigned char *out) +{ + int i; + + /* increase the length of the message */ + md->sha256.length += md->sha256.curlen * 8; + + /* append the '1' bit */ + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha256.curlen > 56) { + while (md->sha256.curlen < 64) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + sha256_compress(md, md->sha256.buf); + md->sha256.curlen = 0; + } + + /* pad up to 56 bytes of zeroes */ + while (md->sha256.curlen < 56) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha256.length, md->sha256.buf+56); + sha256_compress(md, md->sha256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->sha256.state[i], out+(4*i)); + } +} + +void ext2fs_sha256(const unsigned char *in, unsigned long in_size, + unsigned char out[EXT2FS_SHA256_LENGTH]) +{ + struct hash_state md; + + sha256_init(&md); + sha256_process(&md, in, in_size); + sha256_done(&md, out); +} + +#ifdef UNITTEST +static const struct { + char *msg; + unsigned char hash[32]; +} tests[] = { + { "", + { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 } + }, + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, +}; + +int main(int argc, char **argv) +{ + int i; + int errors = 0; + unsigned char tmp[32]; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + unsigned char *msg = (unsigned char *) tests[i].msg; + int len = strlen(tests[i].msg); + + ext2fs_sha256(msg, len, tmp); + printf("SHA256 test message %d: ", i); + if (memcmp(tmp, tests[i].hash, 32) != 0) { + printf("FAILED\n"); + errors++; + } else + printf("OK\n"); + } + return errors; +} + +#endif /* UNITTEST */ diff --git a/jni/e2fsprogs/lib/ext2fs/sha256.o b/jni/e2fsprogs/lib/ext2fs/sha256.o new file mode 100755 index 0000000000000000000000000000000000000000..3c4a158e96215bf8763d536b88e5a10a68e1f448 GIT binary patch literal 4392 zcmbtYdu&tJ89&#~<6h@Y0yGODL}ZGcfFZDqL|und!blwYz$sf1T|*X3^L{uMOGa5U z0uv*xT4x}EC@3MIyoN;AB4TYy2}lq!qzzTA%KA{K_~SZ3Thne@+%5Hf-#zErj+_25 z?I7Rpe82BI-{W`AJ$86y`_3O3B#G%mV%Jzm(^1BT5<_#FHnlMmJOkZ^dkcq@;e~Am zPhWS|e7`Yk{zCWa`RTRHGi_x4IL1y+8*Tpn?yC6<#;W-ZLH)(~S215WR6dLtp6kY{ z4+7iRz3EuyS7UAdEDQ5$Qeu7|boK6=4s*$6msw$6(ue+X%Aq!1bD0ykUe$Qbv9krhixXjsHHxHa~ z$S;q&%->~R)Wz#FO6b)%yl|5Rd;Khl`N3D3nq>3K5}W&ti9JX95c-uZHt%r*D-7AC zIirEw`(W<}A76umVa&}Et(QG!^g9GxmL$&*xa4uAITd++Ao7rZ9%3tUm%}2N8hl12 zPnML~3yjC6H7a}iXQ*HDa4Fpy$ z9NIPNn+*ILh8May{}1%qsjjxnO6qL}pAes@mH0&5QGDv)Hv_Kh(JZANd8lUv zy~@d54)_%ZYkt7mEJj{4)e*$e%MsCwhGG4ZaS<~M@xDO)w9n*AJ$IvLnuqrojE$WC zYwTccbaoax-jg$Jy;|=ciT9%6ts(qWI9?mV&xGUqLio9G{P_^xAC5m8!Y_s6Wg&bx zh!<=1U6zWe_Hb@+woe9<_}=3jdF5=@b|NNX53-rZm(=BzJL|^e!;e+UnQR%IyIJ_3 zU|o)i!*LnrJNZQ#r;B`(7x|K(Wg@@F94+>Ik*~b8ud>+J^3PwsC)d>#>G|zi%)B0R z0@He<{JeCx-*LJG8s5JNn+jDDzJbGXH}C<`1Nb-cxz+Q{tSdgV9IUsCXYwFHNcjCzhUf=F)lA$Z`i)9 zau!%a`Oc9BF468bl9uH$ zmGqrpNw<$!h$CPcH;{Hq9PeR0?*ZQ*Q;Y1?>D=xN*|E1hzQ+-t;%q7LKEk{~inpUD z6V}_s_Yb)1@+yqIVUd`}(nuMIh*Vm$6+E++9+Q9cyDcAPX2aN7$l9qx5 z-bW$t1M#L7*>|tt_B|2yT&$IF7V3A35r_e>{BUg})y6A9U>c;pwJZ1w)g$#w)j9 z+4Js~anrYUcn06!RWlXylEspC%ycccC_BUYpQd$Br6v?rKG$w?{=rm#(0b>_ua2#A z_4cdpUZ^vF8gHkoz4vlr&U|pJF!3L)ef7yJCN8GSjaydl{CQdK)jwYO z-rMo3itQsGKK;zpn|r@(vDW_W$m{NwnoAvN9g|08!|hkU3XH!o+xYCoe+~G@zvyVY z#cCR>n_pUU(CKQgYiV9nP-HEz7HPj>8A}#Y`h|l@FRzv|;=OZ%E8De z>EiKwP5mam3b+CPG(Irz)BG4C9tnRWbgf^^er&{ClO1= zk8K*Mz;Oo#N1DKwN8rRKjcDMZ?ATfk2XVcg7b0+-@1qg8&iC&kaGh_~wzuoHR#!_6sn+Hex6``g>D}ww z-PJV>x_N&~vr~k2)>a*GRW~_>$y&p#?QWO5`e%@xO`3GI?5}oLvkHbPHXUfM;`v$5 ze(Pp>Y@$a2%jvLg6wUk};thGJmRAA4%my6GdTc1sB1m9!{4# zVA1D6CrrK)>%%dcNBY(ZEV6!v{~(|-$wly~_pbvrm@LI#hv2V6I1(N7mh0>FdmMjz UeS + * (copied from libtomcrypt and then relicensed under GPLv2) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + + +#include "config.h" +#if HAVE_SYS_TYPES_H +#include +#endif +#include "ext2fs.h" + +/* the K array */ +#define CONST64(n) n +static const __u64 K[80] = { + CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), + CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), + CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), + CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), + CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), + CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), + CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), + CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), + CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), + CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), + CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), + CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), + CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), + CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), + CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), + CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), + CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), + CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), + CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), + CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), + CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), + CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), + CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), + CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), + CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), + CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), + CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), + CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), + CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), + CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), + CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), + CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), + CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), + CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), + CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), + CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), + CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), + CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), + CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), + CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) +#define RND(a,b,c,d,e,f,g,h,i)\ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];\ + t1 = Sigma0(a) + Maj(a, b, c);\ + d += t0;\ + h = t0 + t1; +#define STORE64H(x, y) \ + do { \ + (y)[0] = (unsigned char)(((x)>>56)&255);\ + (y)[1] = (unsigned char)(((x)>>48)&255);\ + (y)[2] = (unsigned char)(((x)>>40)&255);\ + (y)[3] = (unsigned char)(((x)>>32)&255);\ + (y)[4] = (unsigned char)(((x)>>24)&255);\ + (y)[5] = (unsigned char)(((x)>>16)&255);\ + (y)[6] = (unsigned char)(((x)>>8)&255);\ + (y)[7] = (unsigned char)((x)&255); } while(0) + +#define LOAD64H(x, y)\ + do {x = \ + (((__u64)((y)[0] & 255)) << 56) |\ + (((__u64)((y)[1] & 255)) << 48) |\ + (((__u64)((y)[2] & 255)) << 40) |\ + (((__u64)((y)[3] & 255)) << 32) |\ + (((__u64)((y)[4] & 255)) << 24) |\ + (((__u64)((y)[5] & 255)) << 16) |\ + (((__u64)((y)[6] & 255)) << 8) |\ + (((__u64)((y)[7] & 255)));\ + } while(0) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((__u64)(y)&CONST64(63))) | \ + ((x)<<((__u64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +struct sha512_state { + __u64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +}; + +/* This is a highly simplified version from libtomcrypt */ +struct hash_state { + struct sha512_state sha512; +}; + +static void sha512_compress(struct hash_state * md, const unsigned char *buf) +{ + __u64 S[8], W[80], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha512.state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD64H(W[i], buf + (8*i)); + } + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + + Gamma0(W[i - 15]) + W[i - 16]; + } + + for (i = 0; i < 80; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha512.state[i] = md->sha512.state[i] + S[i]; + } +} + +static void sha512_init(struct hash_state * md) +{ + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); + md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); + md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); + md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); + md->sha512.state[4] = CONST64(0x510e527fade682d1); + md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); + md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); + md->sha512.state[7] = CONST64(0x5be0cd19137e2179); +} + +static void sha512_done(struct hash_state * md, unsigned char *out) +{ + int i; + + /* increase the length of the message */ + md->sha512.length += md->sha512.curlen * CONST64(8); + + /* append the '1' bit */ + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 112 bytes we append zeros then + * compress. Then we can fall back to padding zeros and length encoding + * like normal. */ + if (md->sha512.curlen > 112) { + while (md->sha512.curlen < 128) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + sha512_compress(md, md->sha512.buf); + md->sha512.curlen = 0; + } + + /* pad up to 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB + * of the length. We assume that you won't hash > 2^64 bits of data. */ + while (md->sha512.curlen < 120) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha512.length, md->sha512.buf + 120); + sha512_compress(md, md->sha512.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->sha512.state[i], out+(8 * i)); + } +} + +#define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#define SHA512_BLOCKSIZE 128 +static void sha512_process(struct hash_state * md, + const unsigned char *in, + unsigned long inlen) +{ + unsigned long n; + + while (inlen > 0) { + if (md->sha512.curlen == 0 && inlen >= SHA512_BLOCKSIZE) { + sha512_compress(md, in); + md->sha512.length += SHA512_BLOCKSIZE * 8; + in += SHA512_BLOCKSIZE; + inlen -= SHA512_BLOCKSIZE; + } else { + n = MIN(inlen, (SHA512_BLOCKSIZE - md->sha512.curlen)); + memcpy(md->sha512.buf + md->sha512.curlen, + in, (size_t)n); + md->sha512.curlen += n; + in += n; + inlen -= n; + if (md->sha512.curlen == SHA512_BLOCKSIZE) { + sha512_compress(md, md->sha512.buf); + md->sha512.length += SHA512_BLOCKSIZE * 8; + md->sha512.curlen = 0; + } + } + } +} + +void ext2fs_sha512(const unsigned char *in, unsigned long in_size, + unsigned char out[EXT2FS_SHA512_LENGTH]) +{ + struct hash_state md; + + sha512_init(&md); + sha512_process(&md, in, in_size); + sha512_done(&md, out); +} + +#ifdef UNITTEST +static const struct { + char *msg; + unsigned char hash[64]; +} tests[] = { + { "", + { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, + 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, + 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, + 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, + 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e } + }, + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, +}; + +int main(int argc, char **argv) +{ + int i; + int errors = 0; + unsigned char tmp[64]; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + unsigned char *msg = (unsigned char *) tests[i].msg; + int len = strlen(tests[i].msg); + + ext2fs_sha512(msg, len, tmp); + printf("SHA512 test message %d: ", i); + if (memcmp(tmp, tests[i].hash, 64) != 0) { + printf("FAILED\n"); + errors++; + } else + printf("OK\n"); + } + return errors; +} + +#endif /* UNITTEST */ diff --git a/jni/e2fsprogs/lib/ext2fs/sha512.o b/jni/e2fsprogs/lib/ext2fs/sha512.o new file mode 100755 index 0000000000000000000000000000000000000000..5673065f8b5baa13f1c024360e8c2660f49555d4 GIT binary patch literal 7280 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 +#include +#include +#include +#include +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#if !defined(ENABLE_LIBSPARSE) +static errcode_t sparse_open(const char *name EXT2FS_ATTR((unused)), + int flags EXT2FS_ATTR((unused)), + io_channel *channel EXT2FS_ATTR((unused))) +{ + return EXT2_ET_UNIMPLEMENTED; +} +static errcode_t sparse_close(io_channel channel EXT2FS_ATTR((unused))) +{ + return EXT2_ET_UNIMPLEMENTED; +} +static struct struct_io_manager struct_sparse_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Android sparse I/O Manager", + .open = sparse_open, + .close = sparse_close, +}; +static struct struct_io_manager struct_sparsefd_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Android sparse fd I/O Manager", + .open = sparse_open, + .close = sparse_close, +}; +#else +#include + +struct sparse_map { + int fd; + char **blocks; + int block_size; + uint64_t blocks_count; + char *file; + struct sparse_file *sparse_file; + io_channel channel; +}; + +struct sparse_io_params { + int fd; + char *file; + uint64_t blocks_count; + unsigned int block_size; +}; + +static errcode_t sparse_write_blk(io_channel channel, unsigned long block, + int count, const void *buf); + +static void free_sparse_blocks(struct sparse_map *sm) +{ + uint64_t i; + + for (i = 0; i < sm->blocks_count; ++i) + free(sm->blocks[i]); + free(sm->blocks); + sm->blocks = NULL; +} + +static int sparse_import_segment(void *priv, const void *data, size_t len, + unsigned int block, unsigned int nr_blocks) +{ + struct sparse_map *sm = priv; + + /* Ignore chunk headers, only write the data */ + if (!nr_blocks || len % sm->block_size) + return 0; + + return sparse_write_blk(sm->channel, block, nr_blocks, data); +} + +static errcode_t io_manager_import_sparse(struct sparse_io_params *params, + struct sparse_map *sm, io_channel io) +{ + int fd; + errcode_t retval; + struct sparse_file *sparse_file; + + if (params->fd < 0) { + fd = open(params->file, O_RDONLY); + if (fd < 0) { + retval = -1; + goto err_open; + } + } else + fd = params->fd; + sparse_file = sparse_file_import(fd, false, false); + if (!sparse_file) { + retval = -1; + goto err_sparse; + } + + sm->block_size = sparse_file_block_size(sparse_file); + sm->blocks_count = (sparse_file_len(sparse_file, 0, 0) - 1) + / sm->block_size + 1; + sm->blocks = calloc(sm->blocks_count, sizeof(char*)); + if (!sm->blocks) { + retval = -1; + goto err_alloc; + } + io->block_size = sm->block_size; + + retval = sparse_file_foreach_chunk(sparse_file, true, false, + sparse_import_segment, sm); + + if (retval) + free_sparse_blocks(sm); +err_alloc: + sparse_file_destroy(sparse_file); +err_sparse: + close(fd); +err_open: + return retval; +} + +static errcode_t io_manager_configure(struct sparse_io_params *params, + int flags, io_channel io) +{ + errcode_t retval; + uint64_t img_size; + struct sparse_map *sm = calloc(1, sizeof(*sm)); + if (!sm) + return EXT2_ET_NO_MEMORY; + + sm->file = params->file; + sm->channel = io; + io->private_data = sm; + retval = io_manager_import_sparse(params, sm, io); + if (retval) { + if (!params->block_size || !params->blocks_count) { + retval = EINVAL; + goto err_params; + } + sm->block_size = params->block_size; + sm->blocks_count = params->blocks_count; + sm->blocks = calloc(params->blocks_count, sizeof(void*)); + if (!sm->blocks) { + retval = EXT2_ET_NO_MEMORY; + goto err_alloc; + } + } + io->block_size = sm->block_size; + img_size = (uint64_t)sm->block_size * sm->blocks_count; + + if (flags & IO_FLAG_RW) { + sm->sparse_file = sparse_file_new(sm->block_size, img_size); + if (!sm->sparse_file) { + retval = EXT2_ET_NO_MEMORY; + goto err_alloc; + } + if (params->fd < 0) { + sm->fd = open(params->file, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, + 0644); + if (sm->fd < 0) { + retval = errno; + goto err_open; + } + } else + sm->fd = params->fd; + } else { + sm->fd = -1; + sm->sparse_file = NULL; + } + return 0; + +err_open: + sparse_file_destroy(sm->sparse_file); +err_alloc: + free_sparse_blocks(sm); +err_params: + free(sm); + return retval; +} + +static errcode_t sparse_open_channel(struct sparse_io_params *sparse_params, + int flags, io_channel *channel) +{ + errcode_t retval; + io_channel io; + + io = calloc(1, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + io->block_size = 0; + io->refcount = 1; + + retval = io_manager_configure(sparse_params, flags, io); + if (retval) { + free(io); + return retval; + } + + *channel = io; + return 0; +} + +static errcode_t read_sparse_argv(const char *name, bool is_fd, + struct sparse_io_params *sparse_params) +{ + int ret; + sparse_params->fd = -1; + sparse_params->block_size = 0; + sparse_params->blocks_count = 0; + + sparse_params->file = malloc(strlen(name) + 1); + if (!sparse_params->file) { + fprintf(stderr, "failed to alloc %zu\n", strlen(name) + 1); + return EXT2_ET_NO_MEMORY; + } + + if (is_fd) { + ret = sscanf(name, "(%d):%llu:%u", &sparse_params->fd, + (unsigned long long *)&sparse_params->blocks_count, + &sparse_params->block_size); + } else { + ret = sscanf(name, "(%[^)])%*[:]%llu%*[:]%u", sparse_params->file, + (unsigned long long *)&sparse_params->blocks_count, + &sparse_params->block_size); + } + + if (ret < 1) { + free(sparse_params->file); + return EINVAL; + } + return 0; +} + +static errcode_t sparse_open(const char *name, int flags, io_channel *channel) +{ + errcode_t retval; + struct sparse_io_params sparse_params; + + retval = read_sparse_argv(name, false, &sparse_params); + if (retval) + return EXT2_ET_BAD_DEVICE_NAME; + + retval = sparse_open_channel(&sparse_params, flags, channel); + if (retval) + return retval; + (*channel)->manager = sparse_io_manager; + + return retval; +} + +static errcode_t sparsefd_open(const char *name, int flags, io_channel *channel) +{ + errcode_t retval; + struct sparse_io_params sparse_params; + + retval = read_sparse_argv(name, true, &sparse_params); + if (retval) + return EXT2_ET_BAD_DEVICE_NAME; + + retval = sparse_open_channel(&sparse_params, flags, channel); + if (retval) + return retval; + (*channel)->manager = sparsefd_io_manager; + + return retval; +} + +static errcode_t sparse_merge_blocks(struct sparse_map *sm, uint64_t start, + uint64_t num) +{ + char *buf; + uint64_t i; + unsigned int block_size = sm->block_size; + errcode_t retval = 0; + + buf = calloc(num, block_size); + if (!buf) { + fprintf(stderr, "failed to alloc %llu\n", + (unsigned long long)num * block_size); + return EXT2_ET_NO_MEMORY; + } + + for (i = 0; i < num; i++) { + memcpy(buf + i * block_size, sm->blocks[start + i] , block_size); + free(sm->blocks[start + i]); + sm->blocks[start + i] = NULL; + } + + /* free_sparse_blocks will release this buf. */ + sm->blocks[start] = buf; + + retval = sparse_file_add_data(sm->sparse_file, sm->blocks[start], + block_size * num, start); + + return retval; +} + +static errcode_t sparse_close_channel(io_channel channel) +{ + uint64_t i; + errcode_t retval = 0; + struct sparse_map *sm = channel->private_data; + + if (sm->sparse_file) { + int64_t chunk_start = (sm->blocks[0] == NULL) ? -1 : 0; + for (i = 0; i < sm->blocks_count; ++i) { + if (!sm->blocks[i] && chunk_start != -1) { + retval = sparse_merge_blocks(sm, chunk_start, i - chunk_start); + chunk_start = -1; + } else if (sm->blocks[i] && chunk_start == -1) { + chunk_start = i; + } + if (retval) + goto ret; + } + if (chunk_start != -1) { + retval = sparse_merge_blocks(sm, chunk_start, + sm->blocks_count - chunk_start); + if (retval) + goto ret; + } + retval = sparse_file_write(sm->sparse_file, sm->fd, + /*gzip*/0, /*sparse*/1, /*crc*/0); + } + +ret: + if (sm->sparse_file) + sparse_file_destroy(sm->sparse_file); + free_sparse_blocks(sm); + free(sm->file); + free(sm); + free(channel); + return retval; +} + +static errcode_t sparse_close(io_channel channel) +{ + errcode_t retval; + struct sparse_map *sm = channel->private_data; + int fd = sm->fd; + + retval = sparse_close_channel(channel); + if (fd >= 0) + close(fd); + + return retval; +} + +static errcode_t sparse_set_blksize(io_channel channel, int blksize) +{ + channel->block_size = blksize; + return 0; +} + +static blk64_t block_to_sparse_block(blk64_t block, blk64_t *offset, + io_channel channel, struct sparse_map *sm) +{ + int ratio; + blk64_t ret = block; + + ratio = sm->block_size / channel->block_size; + ret /= ratio; + *offset = (block % ratio) * channel->block_size; + + return ret; +} + +static errcode_t check_block_size(io_channel channel, struct sparse_map *sm) +{ + if (sm->block_size >= channel->block_size) + return 0; + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; +} + +static errcode_t sparse_read_blk64(io_channel channel, blk64_t block, + int count, void *buf) +{ + int i; + char *out = buf; + blk64_t offset = 0, cur_block; + struct sparse_map *sm = channel->private_data; + + if (check_block_size(channel, sm)) + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; + + if (count < 0) { //partial read + count = -count; + cur_block = block_to_sparse_block(block, &offset, channel, sm); + if (sm->blocks[cur_block]) + memcpy(out, (sm->blocks[cur_block]) + offset, count); + else + memset(out, 0, count); + } else { + for (i = 0; i < count; ++i) { + cur_block = block_to_sparse_block(block + i, &offset, + channel, sm); + if (sm->blocks[cur_block]) + memcpy(out + (i * channel->block_size), + sm->blocks[cur_block] + offset, + channel->block_size); + else if (sm->blocks) + memset(out + (i * channel->block_size), 0, + channel->block_size); + } + } + return 0; +} + +static errcode_t sparse_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + return sparse_read_blk64(channel, block, count, buf); +} + +static errcode_t sparse_write_blk64(io_channel channel, blk64_t block, + int count, const void *buf) +{ + int i; + blk64_t offset = 0, cur_block; + const char *in = buf; + struct sparse_map *sm = channel->private_data; + + if (check_block_size(channel, sm)) + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; + + if (count < 0) { //partial write + count = -count; + cur_block = block_to_sparse_block(block, &offset, channel, + sm); + if (!sm->blocks[cur_block]) { + sm->blocks[cur_block] = calloc(1, sm->block_size); + if (!sm->blocks[cur_block]) + return EXT2_ET_NO_MEMORY; + } + memcpy(sm->blocks[cur_block] + offset, in, count); + } else { + for (i = 0; i < count; ++i) { + if (block + i >= sm->blocks_count) + return 0; + cur_block = block_to_sparse_block(block + i, &offset, + channel, sm); + if (!sm->blocks[cur_block]) { + sm->blocks[cur_block] = + calloc(1, sm->block_size); + if (!sm->blocks[cur_block]) + return EXT2_ET_NO_MEMORY; + } + memcpy(sm->blocks[cur_block] + offset, + in + (i * channel->block_size), + channel->block_size); + } + } + return 0; +} + +static errcode_t sparse_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + return sparse_write_blk64(channel, block, count, buf); +} + +static errcode_t sparse_discard(io_channel channel __attribute__((unused)), + blk64_t blk, unsigned long long count) +{ + blk64_t cur_block, offset; + struct sparse_map *sm = channel->private_data; + + if (check_block_size(channel, sm)) + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; + + for (unsigned long long i = 0; i < count; ++i) { + if (blk + i >= sm->blocks_count) + return 0; + cur_block = block_to_sparse_block(blk + i, &offset, channel, + sm); + if (!sm->blocks[cur_block]) + continue; + free(sm->blocks[cur_block]); + sm->blocks[cur_block] = NULL; + } + return 0; +} + +static errcode_t sparse_zeroout(io_channel channel, blk64_t blk, + unsigned long long count) +{ + return sparse_discard(channel, blk, count); +} + +static errcode_t sparse_flush(io_channel channel __attribute__((unused))) +{ + return 0; +} + +static errcode_t sparse_set_option(io_channel channel __attribute__((unused)), + const char *option __attribute__((unused)), + const char *arg __attribute__((unused))) +{ + return 0; +} + +static errcode_t sparse_cache_readahead( + io_channel channel __attribute__((unused)), + blk64_t blk __attribute__((unused)), + unsigned long long count __attribute__((unused))) +{ + return 0; +} + +static struct struct_io_manager struct_sparse_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Android sparse I/O Manager", + .open = sparse_open, + .close = sparse_close, + .set_blksize = sparse_set_blksize, + .read_blk = sparse_read_blk, + .write_blk = sparse_write_blk, + .flush = sparse_flush, + .write_byte = NULL, + .set_option = sparse_set_option, + .get_stats = NULL, + .read_blk64 = sparse_read_blk64, + .write_blk64 = sparse_write_blk64, + .discard = sparse_discard, + .cache_readahead = sparse_cache_readahead, + .zeroout = sparse_zeroout, +}; + +static struct struct_io_manager struct_sparsefd_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Android sparse fd I/O Manager", + .open = sparsefd_open, + .close = sparse_close, + .set_blksize = sparse_set_blksize, + .read_blk = sparse_read_blk, + .write_blk = sparse_write_blk, + .flush = sparse_flush, + .write_byte = NULL, + .set_option = sparse_set_option, + .get_stats = NULL, + .read_blk64 = sparse_read_blk64, + .write_blk64 = sparse_write_blk64, + .discard = sparse_discard, + .cache_readahead = sparse_cache_readahead, + .zeroout = sparse_zeroout, +}; + +#endif + +io_manager sparse_io_manager = &struct_sparse_manager; +io_manager sparsefd_io_manager = &struct_sparsefd_manager; diff --git a/jni/e2fsprogs/lib/ext2fs/sparse_io.o b/jni/e2fsprogs/lib/ext2fs/sparse_io.o new file mode 100755 index 0000000000000000000000000000000000000000..5ec99b3c6a185ab19668f6873953fc1b9b6fd8ca GIT binary patch literal 2336 zcmd^=KWGzi6vy8sttl!of@qFhCvy zx{!{90xaxE?W!`XunQx5_u<{gJ+S%d0KEKMfKB-Rczxl^^IymxuI26by;<~U`D~vT zx<^;iirdH9uHSvycf+9Jno-LMBhS2W{IYq`@ts941kF`<2fR>QcKk*2wiiZ?z&Fbk zt87&ON_=FDyH~-ucgUF7eHiv38)t5k&K1q;#Xg&2uKaVw(iP-?d!C?k1b+6mipfK6 z2)jsf8E$gKSEa-89pn^mDt|iflQ=dY&lF%Iu>fhx1+Ob(n9n1pI=?w^u+FHYC;C=d z!~Binnaj@^ua%DRC>7e5z1Ua!NyHK6-}uKxxG4Pu?M%z0`-?ogda}P1Pu%1j=|{Yf zse_B49;rXUzOf9?)-P$?Jb{22Q8!EOY0 zldnUc)ZGCVhqr36&A~}zmSRG})g7~gmgj@z2eD_JyL9bX6g#z>(yz80L>^e7x9nKn zl3fp-rYF8eVAa5i;xKk@px$XJRiUmEJ22^5GxRz^uW5Rfu~I-j$|~bvL$ce?x01=b7EGiU!rJ3SjMU zqctAW*{2?oKhFFEDz%vAvB(l1wo?LFWjdmC7s%GP<0q1`~Z!u*00L@FW*J$N4b(O>-Peg-WyS}p&gzu3H?jZ^Zx*&NwgpU literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/swapfs.c b/jni/e2fsprogs/lib/ext2fs/swapfs.c new file mode 100755 index 0000000..5e6b22f --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/swapfs.c @@ -0,0 +1,490 @@ +/* + * swapfs.c --- swap ext2 filesystem data structures + * + * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" +#include + +void ext2fs_swap_super(struct ext2_super_block * sb) +{ + int i; + + sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); + sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); + sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); + sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); + sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); + sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); + sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); + sb->s_log_cluster_size = ext2fs_swab32(sb->s_log_cluster_size); + sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); + sb->s_clusters_per_group = ext2fs_swab32(sb->s_clusters_per_group); + sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); + sb->s_mtime = ext2fs_swab32(sb->s_mtime); + sb->s_wtime = ext2fs_swab32(sb->s_wtime); + sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); + sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); + sb->s_magic = ext2fs_swab16(sb->s_magic); + sb->s_state = ext2fs_swab16(sb->s_state); + sb->s_errors = ext2fs_swab16(sb->s_errors); + sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); + sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); + sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); + sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); + sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); + sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); + sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); + sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); + sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); + sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); + sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); + sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); + sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); + /* sb->s_uuid is __u8 and does not need swabbing */ + /* sb->s_volume_name is char and does not need swabbing */ + /* sb->s_last_mounted is char and does not need swabbing */ + sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); + /* sb->s_prealloc_blocks is __u8 and does not need swabbing */ + /* sb->s_prealloc_dir_blocks is __u8 and does not need swabbing */ + sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); + /* sb->s_journal_uuid is __u8 and does not need swabbing */ + sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); + sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); + sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); + for (i = 0; i < 4; i++) + sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); + /* sb->s_def_hash_version is __u8 and does not need swabbing */ + /* sb->s_jnl_backup_type is __u8 and does not need swabbing */ + sb->s_desc_size = ext2fs_swab16(sb->s_desc_size); + sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); + sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); + sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); + /* if journal backup is for a valid extent-based journal... */ + 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; + } + for (; i < 17; i++) + sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); + sb->s_blocks_count_hi = ext2fs_swab32(sb->s_blocks_count_hi); + sb->s_r_blocks_count_hi = ext2fs_swab32(sb->s_r_blocks_count_hi); + sb->s_free_blocks_hi = ext2fs_swab32(sb->s_free_blocks_hi); + 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_raid_stride = ext2fs_swab16(sb->s_raid_stride); + sb->s_mmp_update_interval = ext2fs_swab16(sb->s_mmp_update_interval); + sb->s_mmp_block = ext2fs_swab64(sb->s_mmp_block); + sb->s_raid_stripe_width = ext2fs_swab32(sb->s_raid_stripe_width); + /* sb->s_log_groups_per_flex is __u8 and does not need swabbing */ + /* sb->s_checksum_type is __u8 and does not need swabbing */ + /* sb->s_encryption_level is __u8 and does not need swabbing */ + /* sb->s_reserved_pad is __u8 and does not need swabbing */ + 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); + sb->s_snapshot_r_blocks_count = + ext2fs_swab64(sb->s_snapshot_r_blocks_count); + sb->s_snapshot_list = ext2fs_swab32(sb->s_snapshot_list); + sb->s_error_count = ext2fs_swab32(sb->s_error_count); + sb->s_first_error_time = ext2fs_swab32(sb->s_first_error_time); + sb->s_first_error_ino = ext2fs_swab32(sb->s_first_error_ino); + sb->s_first_error_block = ext2fs_swab64(sb->s_first_error_block); + /* sb->s_first_error_func is __u8 and does not need swabbing */ + sb->s_last_error_time = ext2fs_swab32(sb->s_last_error_time); + sb->s_last_error_ino = ext2fs_swab32(sb->s_last_error_ino); + sb->s_last_error_block = ext2fs_swab64(sb->s_last_error_block); + /* sb->s_last_error_func is __u8 and does not need swabbing */ + /* sb->s_mount_opts is __u8 and does not need swabbing */ + sb->s_usr_quota_inum = ext2fs_swab32(sb->s_usr_quota_inum); + sb->s_grp_quota_inum = ext2fs_swab32(sb->s_grp_quota_inum); + sb->s_overhead_clusters = ext2fs_swab32(sb->s_overhead_clusters); + sb->s_backup_bgs[0] = ext2fs_swab32(sb->s_backup_bgs[0]); + sb->s_backup_bgs[1] = ext2fs_swab32(sb->s_backup_bgs[1]); + /* sb->s_encrypt_algos is __u8 and does not need swabbing */ + /* sb->s_encrypt_pw_salt is __u8 and does not need swabbing */ + sb->s_lpf_ino = ext2fs_swab32(sb->s_lpf_ino); + sb->s_prj_quota_inum = ext2fs_swab32(sb->s_prj_quota_inum); + sb->s_checksum_seed = ext2fs_swab32(sb->s_checksum_seed); + /* s_*_time_hi are __u8 and does not need swabbing */ + sb->s_encoding = ext2fs_swab16(sb->s_encoding); + sb->s_encoding_flags = ext2fs_swab16(sb->s_encoding_flags); + /* catch when new fields are used from s_reserved */ + EXT2FS_BUILD_BUG_ON(sizeof(sb->s_reserved) != 95 * sizeof(__le32)); + sb->s_checksum = ext2fs_swab32(sb->s_checksum); +} + +void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp) +{ + struct ext4_group_desc *gdp4 = (struct ext4_group_desc *)gdp; + + /* Do the 32-bit parts first */ + gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); + gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); + gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); + gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); + gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); + gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); + gdp->bg_flags = ext2fs_swab16(gdp->bg_flags); + gdp->bg_exclude_bitmap_lo = ext2fs_swab32(gdp->bg_exclude_bitmap_lo); + gdp->bg_block_bitmap_csum_lo = + ext2fs_swab16(gdp->bg_block_bitmap_csum_lo); + gdp->bg_inode_bitmap_csum_lo = + ext2fs_swab16(gdp->bg_inode_bitmap_csum_lo); + gdp->bg_itable_unused = ext2fs_swab16(gdp->bg_itable_unused); + gdp->bg_checksum = ext2fs_swab16(gdp->bg_checksum); + /* If we're 32-bit, we're done */ + if (fs == NULL || EXT2_DESC_SIZE(fs->super) < EXT2_MIN_DESC_SIZE_64BIT) + return; + + /* Swap the 64-bit parts */ + gdp4->bg_block_bitmap_hi = ext2fs_swab32(gdp4->bg_block_bitmap_hi); + gdp4->bg_inode_bitmap_hi = ext2fs_swab32(gdp4->bg_inode_bitmap_hi); + gdp4->bg_inode_table_hi = ext2fs_swab32(gdp4->bg_inode_table_hi); + gdp4->bg_free_blocks_count_hi = + ext2fs_swab16(gdp4->bg_free_blocks_count_hi); + gdp4->bg_free_inodes_count_hi = + ext2fs_swab16(gdp4->bg_free_inodes_count_hi); + gdp4->bg_used_dirs_count_hi = + ext2fs_swab16(gdp4->bg_used_dirs_count_hi); + gdp4->bg_itable_unused_hi = ext2fs_swab16(gdp4->bg_itable_unused_hi); + gdp4->bg_exclude_bitmap_hi = ext2fs_swab16(gdp4->bg_exclude_bitmap_hi); + gdp4->bg_block_bitmap_csum_hi = + ext2fs_swab16(gdp4->bg_block_bitmap_csum_hi); + gdp4->bg_inode_bitmap_csum_hi = + ext2fs_swab16(gdp4->bg_inode_bitmap_csum_hi); + EXT2FS_BUILD_BUG_ON(sizeof(gdp4->bg_reserved) != sizeof(__u32)); +} + +void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) +{ + ext2fs_swap_group_desc2(0, gdp); +} + + +void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header, + struct ext2_ext_attr_header *from_header) +{ + int n; + + to_header->h_magic = ext2fs_swab32(from_header->h_magic); + to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); + to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); + to_header->h_hash = ext2fs_swab32(from_header->h_hash); + to_header->h_checksum = ext2fs_swab32(from_header->h_checksum); + for (n = 0; n < 3; n++) + to_header->h_reserved[n] = + ext2fs_swab32(from_header->h_reserved[n]); +} + +void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry, + struct ext2_ext_attr_entry *from_entry) +{ + to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs); + 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); +} + +void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) +{ + struct ext2_ext_attr_header *from_header = + (struct ext2_ext_attr_header *)from; + struct ext2_ext_attr_header *to_header = + (struct ext2_ext_attr_header *)to; + struct ext2_ext_attr_entry *from_entry, *to_entry; + char *from_end = (char *)from_header + bufsize; + + if (to_header != from_header) + memcpy(to_header, from_header, bufsize); + + if (has_header) { + ext2fs_swap_ext_attr_header(to_header, from_header); + + from_entry = (struct ext2_ext_attr_entry *)(from_header+1); + to_entry = (struct ext2_ext_attr_entry *)(to_header+1); + } else { + from_entry = (struct ext2_ext_attr_entry *)from_header; + to_entry = (struct ext2_ext_attr_entry *)to_header; + } + + while ((char *)from_entry < from_end && + (char *)EXT2_EXT_ATTR_NEXT(from_entry) <= from_end && + *(__u32 *)from_entry) { + ext2fs_swap_ext_attr_entry(to_entry, from_entry); + from_entry = EXT2_EXT_ATTR_NEXT(from_entry); + to_entry = EXT2_EXT_ATTR_NEXT(to_entry); + } +} + +void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + int bufsize) +{ + unsigned i, extra_isize, attr_magic; + int has_extents = 0, has_inline_data = 0, islnk = 0, fast_symlink = 0; + unsigned int inode_size; + __u32 *eaf, *eat; + + /* + * Note that t and f may point to the same address. That's why + * if (hostorder) condition is executed before swab calls and + * if (!hostorder) afterwards. + */ + if (hostorder) { + islnk = LINUX_S_ISLNK(f->i_mode); + fast_symlink = ext2fs_is_fast_symlink(EXT2_INODE(f)); + has_extents = (f->i_flags & EXT4_EXTENTS_FL) != 0; + has_inline_data = (f->i_flags & EXT4_INLINE_DATA_FL) != 0; + } + + t->i_mode = ext2fs_swab16(f->i_mode); + t->i_uid = ext2fs_swab16(f->i_uid); + t->i_size = ext2fs_swab32(f->i_size); + t->i_atime = ext2fs_swab32(f->i_atime); + t->i_ctime = ext2fs_swab32(f->i_ctime); + t->i_mtime = ext2fs_swab32(f->i_mtime); + t->i_dtime = ext2fs_swab32(f->i_dtime); + t->i_gid = ext2fs_swab16(f->i_gid); + t->i_links_count = ext2fs_swab16(f->i_links_count); + t->i_file_acl = ext2fs_swab32(f->i_file_acl); + t->i_blocks = ext2fs_swab32(f->i_blocks); + t->i_flags = ext2fs_swab32(f->i_flags); + t->i_size_high = ext2fs_swab32(f->i_size_high); + + if (!hostorder) { + islnk = LINUX_S_ISLNK(t->i_mode); + fast_symlink = ext2fs_is_fast_symlink(EXT2_INODE(t)); + has_extents = (t->i_flags & EXT4_EXTENTS_FL) != 0; + has_inline_data = (t->i_flags & EXT4_INLINE_DATA_FL) != 0; + } + + /* + * Extent data and inline data are swapped on access, not here + */ + if (!has_extents && !has_inline_data && (!islnk || !fast_symlink)) { + for (i = 0; i < EXT2_N_BLOCKS; i++) + t->i_block[i] = ext2fs_swab32(f->i_block[i]); + } else if (t != f) { + for (i = 0; i < EXT2_N_BLOCKS; i++) + t->i_block[i] = f->i_block[i]; + } + t->i_generation = ext2fs_swab32(f->i_generation); + t->i_faddr = ext2fs_swab32(f->i_faddr); + + switch (fs->super->s_creator_os) { + case EXT2_OS_LINUX: + t->osd1.linux1.l_i_version = + ext2fs_swab32(f->osd1.linux1.l_i_version); + t->osd2.linux2.l_i_blocks_hi = + ext2fs_swab16(f->osd2.linux2.l_i_blocks_hi); + t->osd2.linux2.l_i_file_acl_high = + ext2fs_swab16(f->osd2.linux2.l_i_file_acl_high); + t->osd2.linux2.l_i_uid_high = + ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); + t->osd2.linux2.l_i_gid_high = + ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); + t->osd2.linux2.l_i_checksum_lo = + ext2fs_swab16(f->osd2.linux2.l_i_checksum_lo); + break; + case EXT2_OS_HURD: + t->osd1.hurd1.h_i_translator = + ext2fs_swab32 (f->osd1.hurd1.h_i_translator); + t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; + t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; + t->osd2.hurd2.h_i_mode_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); + t->osd2.hurd2.h_i_uid_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); + t->osd2.hurd2.h_i_gid_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); + t->osd2.hurd2.h_i_author = + ext2fs_swab32 (f->osd2.hurd2.h_i_author); + break; + default: + break; + } + + if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) + return; /* no i_extra_isize field */ + + if (hostorder) + extra_isize = f->i_extra_isize; + t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); + if (!hostorder) + 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 */ + return; + } + if (extra_isize & 3) + return; /* Illegal inode extra_isize */ + + inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize; + if (inode_includes(inode_size, i_checksum_hi)) + t->i_checksum_hi = ext2fs_swab16(f->i_checksum_hi); + if (inode_includes(inode_size, i_ctime_extra)) + t->i_ctime_extra = ext2fs_swab32(f->i_ctime_extra); + if (inode_includes(inode_size, i_mtime_extra)) + t->i_mtime_extra = ext2fs_swab32(f->i_mtime_extra); + if (inode_includes(inode_size, i_atime_extra)) + t->i_atime_extra = ext2fs_swab32(f->i_atime_extra); + if (inode_includes(inode_size, i_crtime)) + t->i_crtime = ext2fs_swab32(f->i_crtime); + if (inode_includes(inode_size, i_crtime_extra)) + t->i_crtime_extra = ext2fs_swab32(f->i_crtime_extra); + if (inode_includes(inode_size, i_version_hi)) + t->i_version_hi = ext2fs_swab32(f->i_version_hi); + if (inode_includes(inode_size, i_projid)) + t->i_projid = ext2fs_swab32(f->i_projid); + /* catch new static fields added after i_projid */ + EXT2FS_BUILD_BUG_ON(sizeof(struct ext2_inode_large) != 160); + + i = sizeof(struct ext2_inode) + extra_isize + sizeof(__u32); + if (bufsize < (int) i) + return; /* no space for EA magic */ + + eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + + extra_isize); + + attr_magic = *eaf; + if (!hostorder) + attr_magic = ext2fs_swab32(attr_magic); + + if (attr_magic != EXT2_EXT_ATTR_MAGIC) + return; /* it seems no magic here */ + + eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + + extra_isize); + *eat = ext2fs_swab32(*eaf); + + /* convert EA(s) */ + ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), + bufsize - sizeof(struct ext2_inode) - + extra_isize - sizeof(__u32), 0); + +} + +void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, + struct ext2_inode *f, int hostorder) +{ + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, + (struct ext2_inode_large *) f, hostorder, + 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); + mmp->mmp_checksum = ext2fs_swab32(mmp->mmp_checksum); +} + +errcode_t ext2fs_dirent_swab_in(ext2_filsys fs, char *buf, int flags) +{ + return ext2fs_dirent_swab_in2(fs, buf, fs->blocksize, flags); +} + +errcode_t ext2fs_dirent_swab_in2(ext2_filsys fs, char *buf, + size_t size, int flags) +{ + errcode_t retval; + char *p, *end; + struct ext2_dir_entry *dirent; + unsigned int name_len, rec_len, left; + + p = (char *) buf; + end = (char *) buf + size; + left = size; + while (p < end-8) { + dirent = (struct ext2_dir_entry *) p; + dirent->inode = ext2fs_swab32(dirent->inode); + dirent->rec_len = ext2fs_swab16(dirent->rec_len); + dirent->name_len = ext2fs_swab16(dirent->name_len); + name_len = dirent->name_len; + if (flags & EXT2_DIRBLOCK_V2_STRUCT) + dirent->name_len = ext2fs_swab16(dirent->name_len); + retval = ext2fs_get_rec_len(fs, dirent, &rec_len); + if (retval) + return retval; + if ((rec_len < 8) || (rec_len % 4)) { + rec_len = 8; + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; + } else if (((name_len & 0xFF) + 8) > rec_len) + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; + if (rec_len > left) + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; + left -= rec_len; + p += rec_len; + } + + return 0; +} + +errcode_t ext2fs_dirent_swab_out(ext2_filsys fs, char *buf, int flags) +{ + return ext2fs_dirent_swab_out2(fs, buf, fs->blocksize, flags); +} + +errcode_t ext2fs_dirent_swab_out2(ext2_filsys fs, char *buf, + size_t size, int flags) +{ + errcode_t retval; + char *p, *end; + unsigned int rec_len; + struct ext2_dir_entry *dirent; + + p = buf; + end = buf + size; + while (p < end) { + dirent = (struct ext2_dir_entry *) p; + retval = ext2fs_get_rec_len(fs, dirent, &rec_len); + if (retval) + return retval; + if ((rec_len < 8) || + (rec_len % 4)) { + ext2fs_free_mem(&buf); + return EXT2_ET_DIR_CORRUPTED; + } + p += rec_len; + dirent->inode = ext2fs_swab32(dirent->inode); + dirent->rec_len = ext2fs_swab16(dirent->rec_len); + dirent->name_len = ext2fs_swab16(dirent->name_len); + if (rec_len > size) + return EXT2_ET_DIR_CORRUPTED; + size -= rec_len; + + if (flags & EXT2_DIRBLOCK_V2_STRUCT) + dirent->name_len = ext2fs_swab16(dirent->name_len); + } + + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/swapfs.o b/jni/e2fsprogs/lib/ext2fs/swapfs.o new file mode 100755 index 0000000000000000000000000000000000000000..faf6ad439b9c8b040d7e35d742502582b5dbfb50 GIT binary patch literal 13160 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 +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef HAVE_STRNLEN +/* + * Incredibly, libc5 doesn't appear to have strnlen. So we have to + * provide our own. + */ +static int my_strnlen(const char * s, int count) +{ + const char *cp = s; + + while (count-- && *cp) + cp++; + return cp - s; +} +#define strnlen(str, x) my_strnlen((str),(x)) +#endif + +errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, + const char *name, const char *target) +{ + errcode_t retval; + struct ext2_inode inode; + ext2_ino_t scratch_ino; + blk64_t blk; + int fastlink, inlinelink; + unsigned int target_len; + char *block_buf = 0; + int drop_refcount = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* + * The Linux kernel doesn't allow for links longer than a block + * (counting the NUL terminator) + */ + target_len = strnlen(target, fs->blocksize + 1); + if (target_len >= fs->blocksize) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + + /* + * Allocate a data block for slow links + */ + retval = ext2fs_get_mem(fs->blocksize, &block_buf); + if (retval) + goto cleanup; + memset(block_buf, 0, fs->blocksize); + strncpy(block_buf, target, fs->blocksize); + + memset(&inode, 0, sizeof(struct ext2_inode)); + fastlink = (target_len < sizeof(inode.i_block)); + if (!fastlink) { + retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino, + &inode, + 0), + NULL, &blk); + if (retval) + goto cleanup; + } + + /* + * Allocate an inode, if necessary + */ + if (!ino) { + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFLNK | 0755, + 0, &ino); + if (retval) + goto cleanup; + } + + /* + * Create the inode structure.... + */ + inode.i_mode = LINUX_S_IFLNK | 0777; + inode.i_uid = inode.i_gid = 0; + inode.i_links_count = 1; + ext2fs_inode_size_set(fs, &inode, target_len); + /* The time fields are set by ext2fs_write_new_inode() */ + + inlinelink = !fastlink && ext2fs_has_feature_inline_data(fs->super); + if (fastlink) { + /* Fast symlinks, target stored in inode */ + strcpy((char *)&inode.i_block, target); + } else if (inlinelink) { + /* Try inserting an inline data symlink */ + inode.i_flags |= EXT4_INLINE_DATA_FL; + retval = ext2fs_write_new_inode(fs, ino, &inode); + if (retval) + goto cleanup; + retval = ext2fs_inline_data_set(fs, ino, &inode, block_buf, + target_len); + if (retval) { + inode.i_flags &= ~EXT4_INLINE_DATA_FL; + inlinelink = 0; + goto need_block; + } + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + goto cleanup; + } else { +need_block: + /* Slow symlinks, target stored in the first block */ + ext2fs_iblk_set(fs, &inode, 1); + if (ext2fs_has_feature_extents(fs->super)) { + /* + * The extent bmap is setup after the inode and block + * have been written out below. + */ + inode.i_flags |= EXT4_EXTENTS_FL; + } + } + + /* + * Write out the inode and inode data block. The inode generation + * number is assigned by write_new_inode, which means that the + * operations using ino must come after it. + */ + if (inlinelink) + retval = ext2fs_write_inode(fs, ino, &inode); + else + retval = ext2fs_write_new_inode(fs, ino, &inode); + if (retval) + goto cleanup; + + if (!fastlink && !inlinelink) { + retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL, + &blk); + if (retval) + goto cleanup; + + retval = io_channel_write_blk64(fs->io, blk, 1, block_buf); + if (retval) + goto cleanup; + } + + /* + * Update accounting.... + */ + if (!fastlink && !inlinelink) + ext2fs_block_alloc_stats2(fs, blk, +1); + ext2fs_inode_alloc_stats2(fs, ino, +1, 0); + drop_refcount = 1; + + /* + * Link the symlink into the filesystem hierarchy + */ + if (name) { + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, + &scratch_ino); + if (!retval) { + retval = EXT2_ET_FILE_EXISTS; + goto cleanup; + } + if (retval != EXT2_ET_FILE_NOT_FOUND) + goto cleanup; + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_SYMLINK); + if (retval) + goto cleanup; + } + drop_refcount = 0; + +cleanup: + if (block_buf) + ext2fs_free_mem(&block_buf); + if (drop_refcount) { + if (!fastlink && !inlinelink) + ext2fs_block_alloc_stats2(fs, blk, -1); + ext2fs_inode_alloc_stats2(fs, ino, -1, 0); + } + return retval; +} + +/* + * Test whether an inode is a fast symlink. + * + * A fast symlink has its symlink data stored in inode->i_block. + */ +int ext2fs_is_fast_symlink(struct ext2_inode *inode) +{ + return LINUX_S_ISLNK(inode->i_mode) && EXT2_I_SIZE(inode) && + EXT2_I_SIZE(inode) < sizeof(inode->i_block); +} diff --git a/jni/e2fsprogs/lib/ext2fs/symlink.o b/jni/e2fsprogs/lib/ext2fs/symlink.o new file mode 100755 index 0000000000000000000000000000000000000000..6d28256f33a304859754537d41c64018e18b0331 GIT binary patch literal 4632 zcmbtWO>9(E6h3dJ)6U3`v=oc{b+nCbF;1YOkf`xRQCJYv289H}>$H8)N$01`48j1> zk{Y8MlZM8a;13{+(r7RdV`pWPvS2AJhzljt7Gx&I1?a+;KEAo zt}MfQ(_77aVagcstr)s4WWh6dm+ltZzFbqZz}qtOSAFyh`(png#87JDJetnA;R6#h z(4F-+j|*FV8ZR`N&J5mXhrK!b!I|xiK|iS37B;62Oq_pVw2N(C=%s6lKaO-k-1nfb zI8B2?>BZ5m(k$gdG}KjUq5RxRBR6-4avl8MWaQX3pMi?I)MAR*N^O+iY0SsRd1qPp z8x0a2F4iFrkP*Jx`0S{mxWAkithXo*C2$CzqY=(AbAE~QwI8_)%*$}DN~ci=Monkw zG|oom&?`n9Ub)7k+$_$JW4ML0V_R;$qO6G`d<1j;h9Z2-f$MUYooc$Oo<4(Y1AZzl z=E(VdoMe5V22_rIM4Xc(<71!3vQGBNy6VR{Kz=KEQZc(Zg#Lr0;-lC8Vb(!?_SeYs zgRh`k^WBtrV_&~HxQE9#>cFW#XFZTt1 z@bJO+SGd!+{v}T}GEdxZMf}L?n5^4EOPQO%cbNGxpR5}`W0gmbocd@8WlN*(oHDNR zsbXwLJlw-8va3wz{u$GGaH8uXz8fQxe(T2E%XF=Pd=`|?~1S=F!Lq&=}5rOsnEFSVUR)0mjy@W;F78IXvj&KJbG4x z;zzylX!20_9Xp+grIO*z+ajAI+mN6Y`0+4~cad>&gRypLGqvM=wLpo?S}e9NpY-io zx<33_%@?(w2mRsNrOg1A(=RuFZRBk!8|HcY@)i5I!C?6|zhi{?q2XD6#~9)VaNjW~ zc#JH9siC`b)wccQTLeEQpvCydu;as@hzD9>sfqh4@NSM1BP^ao>x2nZr)x9`TncM@ ze_-99@lk$01+H?eiPKpRyww8_df@1}RqY4Bvzp&F|mPolNpg>PSF z{G{OzRZt>)N5o+HB^utU;Y&4~Ke#;H@`D<_tSlm)?`ybzJFjZE_OG_QFJ=3B{!YrP z$bRvCsEn^QoExmnj$4c1oKHSADG8g{yvf%!RAErc5^7JDB4s$#W!a$D@&~eJo3n-c%xCC$p5W z6B#>8z&a0RtXNNcz|!B7sXp7v#E#>kNhRa4q;2&@vr!%Hk7lfcb~Jk=ZCkJh>ltM? zo=OcI8Dt`HJ1O|^ES(;*vleKm*Mn)>Uhp1E_E|AOc%VJpp~eYEUG0Y}rZtZjL~f{>C-+fhl8r2j}S zMG$Q^+JiZl;8{kiXDK$HNQ$Mb-u`GZX~(UyV;se^Ta;E$Jk>j3MdO$(1d+{js-1FX zs_pb7qJtGN4nr8}q}INOcx=xKmCfu4y|^I(@dbl>24n6o zx~Zh<)S^7gYg_@j*D+>Rkn*A+oAsdd&);ue^2|f^67B`;-<=Cn`qg_E>nZ+f=I?-7 z^S&Byxp*twExTUoyV6Aar2dCWQO=6Lf>%SoTKuoe{C8`5oMWZ0;{O2pZr`ke|Fz3Q L9xn4{UAO)}oj`oo literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/tdb.c b/jni/e2fsprogs/lib/ext2fs/tdb.c new file mode 100755 index 0000000..b07b291 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tdb.c @@ -0,0 +1,4174 @@ +/* +URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb/common +Rev: 23590 +Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007) +*/ + /* + trivial database library - standalone version + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Jeremy Allison 2000-2006 + Copyright (C) Paul `Rusty' Russell 2000 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef CONFIG_STAND_ALONE +#define HAVE_MMAP +#define HAVE_STRDUP +#define HAVE_SYS_MMAN_H +#define HAVE_UTIME_H +#define HAVE_UTIME +#endif +#ifndef __FreeBSD__ +#define _XOPEN_SOURCE 600 +#endif + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#include +#include +#include +#ifdef HAVE_UTIME_H +#include +#endif +#include +#include +#include + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +static char *rep_strdup(const char *s) +{ + char *ret; + int length; + + if (!s) + return NULL; + length = strlen(s); + ret = malloc(length + 1); + if (ret) { + strncpy(ret, s, length); + ret[length] = '\0'; + } + return ret; +} +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +typedef int bool; + +#include "tdb.h" + +static TDB_DATA tdb_null; + +#ifndef u32 +#define u32 unsigned +#endif + +typedef u32 tdb_len_t; +typedef u32 tdb_off_t; + +#ifndef offsetof +#define offsetof(t,f) ((unsigned int)&((t *)0)->f) +#endif + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_ALIGNMENT 4 +#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) +#define DEFAULT_HASH_SIZE 131 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) +#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1) +#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) +#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) +#define TDB_PAD_BYTE 0x42 +#define TDB_PAD_U32 0x42424242 + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) tdb->log.log_fn x + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 +#define TRANSACTION_LOCK 8 + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) + +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) + + +/* the body of the database is made of one list_struct for the free space + plus a separate data list for each hash value */ +struct list_struct { + tdb_off_t next; /* offset of the next record in the list */ + tdb_len_t rec_len; /* total byte length of record */ + tdb_len_t key_len; /* byte length of key */ + tdb_len_t data_len; /* byte length of data */ + u32 full_hash; /* the full 32 bit hash of the key */ + u32 magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + u32 totalsize; (tailer) + } + */ +}; + + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + u32 version; /* version of the code */ + u32 hash_size; /* number of hash entries */ + tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ + tdb_off_t recovery_start; /* offset of transaction recovery region */ + tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ + tdb_off_t reserved[29]; +}; + +struct tdb_lock_type { + int list; + u32 count; + u32 ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + u32 off; + u32 hash; + int lock_rw; +}; + + +struct tdb_methods { + int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); + int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); + void (*next_hash_chain)(struct tdb_context *, u32 *); + int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); + int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); + int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t); +}; + +struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len_t map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + int traverse_read; /* read-only traversal */ + struct tdb_lock_type global_lock; + int num_lockrecs; + struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + u32 flags; /* the flags passed to tdb_open */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + struct tdb_logging_context log; + unsigned int (*hash_fn)(TDB_DATA *key); + int open_flags; /* flags used in the open - needed by reopen */ + unsigned int num_locks; /* number of chain locks held */ + const struct tdb_methods *methods; + struct tdb_transaction *transaction; + int page_size; + int max_dead_records; + bool have_transaction_lock; + tdb_len_t real_map_size; /* how much space has been mapped */ +}; + + +/* + internal prototypes +*/ +static int tdb_munmap(struct tdb_context *tdb); +static void tdb_mmap(struct tdb_context *tdb); +static int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); +static int tdb_unlock(struct tdb_context *tdb, int list, int ltype); +static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); +static int tdb_transaction_lock(struct tdb_context *tdb, int ltype); +static int tdb_transaction_unlock(struct tdb_context *tdb); +static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); +static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); +static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); +static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +static void *tdb_convert(void *buf, u32 size); +static int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +static tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec); +static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +static int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); +static int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); +static int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +static int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +static int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec); +static unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); +static int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec); +static void tdb_io_init(struct tdb_context *tdb); +static int tdb_expand(struct tdb_context *tdb, tdb_off_t size); +static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, + struct list_struct *rec); + + +/* file: error.c */ + +enum TDB_ERROR tdb_error(struct tdb_context *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_EINVAL, "Invalid parameter"}, + {TDB_ERR_NOEXIST, "Record does not exist"}, + {TDB_ERR_RDONLY, "write not permitted"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(struct tdb_context *tdb) +{ + u32 i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + +/* file: lock.c */ + +#define TDB_MARK_LOCK 0x80000000 + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). + + note that a len of zero means lock to end of file +*/ +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = len; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + /* Generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", + tdb->fd, offset, rw_type, lck_type, (int)len)); + } + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + + +/* + upgrade a read lock to a write lock. This needs to be handled in a + special way as some OSes (such as solaris) have too conservative + deadlock detection and claim a deadlock when progress can be + made. For those OSes we may loop for a while. +*/ +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) +{ + int count = 1000; + while (count--) { + struct timeval tv; + if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset)); + return -1; +} + + +/* lock a list in the database. list -1 is the alloc list */ +static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) +{ + struct tdb_lock_type *new_lck; + int i; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* a global lock allows us to avoid per chain locks */ + if (tdb->global_lock.count && + ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + return 0; + } + + if (tdb->global_lock.count) { + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].list == list) { + if (tdb->lockrecs[i].count == 0) { + /* + * Can't happen, see tdb_unlock(). It should + * be an assert. + */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " + "lck->count == 0 for list %d", list)); + } + /* + * Just increment the in-memory struct, posix locks + * don't stack. + */ + tdb->lockrecs[i].count++; + return 0; + } + } + + new_lck = (struct tdb_lock_type *)realloc( + tdb->lockrecs, + sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1)); + if (new_lck == NULL) { + errno = ENOMEM; + return -1; + } + tdb->lockrecs = new_lck; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (!mark_lock && + tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, + 0, 1)) { + return -1; + } + + tdb->num_locks++; + + tdb->lockrecs[tdb->num_lockrecs].list = list; + tdb->lockrecs[tdb->num_lockrecs].count = 1; + tdb->lockrecs[tdb->num_lockrecs].ltype = ltype; + tdb->num_lockrecs += 1; + + return 0; +} + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_lock(struct tdb_context *tdb, int list, int ltype) +{ + int ret; + ret = _tdb_lock(tdb, list, ltype, F_SETLKW); + if (ret) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " + "ltype=%d (%s)\n", list, ltype, strerror(errno))); + } + return ret; +} + +/* lock a list in the database. list -1 is the alloc list. non-blocking lock */ +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) +{ + return _tdb_lock(tdb, list, ltype, F_SETLK); +} + + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +int tdb_unlock(struct tdb_context *tdb, int list, int ltype) +{ + int ret = -1; + int i; + struct tdb_lock_type *lck = NULL; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* a global lock allows us to avoid per chain locks */ + if (tdb->global_lock.count && + ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + return 0; + } + + if (tdb->global_lock.count) { + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].list == list) { + lck = &tdb->lockrecs[i]; + break; + } + } + + if ((lck == NULL) || (lck->count == 0)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); + return -1; + } + + if (lck->count > 1) { + lck->count--; + return 0; + } + + /* + * This lock has count==1 left, so we need to unlock it in the + * kernel. We don't bother with decrementing the in-memory array + * element, we're about to overwrite it with the last array element + * anyway. + */ + + if (mark_lock) { + ret = 0; + } else { + ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, + F_SETLKW, 0, 1); + } + tdb->num_locks--; + + /* + * Shrink the array by overwriting the element just unlocked with the + * last array element. + */ + + if (tdb->num_lockrecs > 1) { + *lck = tdb->lockrecs[tdb->num_lockrecs-1]; + } + tdb->num_lockrecs -= 1; + + /* + * We don't bother with realloc when the array shrinks, but if we have + * a completely idle tdb we should get rid of the locked array. + */ + + if (tdb->num_lockrecs == 0) { + SAFE_FREE(tdb->lockrecs); + } + + if (ret) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + +/* + get the transaction lock + */ +int tdb_transaction_lock(struct tdb_context *tdb, int ltype) +{ + if (tdb->have_transaction_lock || tdb->global_lock.count) { + return 0; + } + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, + F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + tdb->have_transaction_lock = 1; + return 0; +} + +/* + release the transaction lock + */ +int tdb_transaction_unlock(struct tdb_context *tdb) +{ + int ret; + if (!tdb->have_transaction_lock) { + return 0; + } + ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + if (ret == 0) { + tdb->have_transaction_lock = 0; + } + return ret; +} + + + + +/* lock/unlock entire database */ +static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) +{ + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + + if (tdb->global_lock.count && tdb->global_lock.ltype == (u32)ltype) { + tdb->global_lock.count++; + return 0; + } + + if (tdb->global_lock.count) { + /* a global lock of a different type exists */ + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (tdb->num_locks != 0) { + /* can't combine global and chain locks */ + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (!mark_lock && + tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op, + 0, 4*tdb->header.hash_size)) { + if (op == F_SETLKW) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno))); + } + return -1; + } + + tdb->global_lock.count = 1; + tdb->global_lock.ltype = ltype; + + return 0; +} + + + +/* unlock entire db */ +static int _tdb_unlockall(struct tdb_context *tdb, int ltype) +{ + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) { + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (tdb->global_lock.ltype != (u32)ltype || + tdb->global_lock.count == 0) { + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + if (tdb->global_lock.count > 1) { + tdb->global_lock.count--; + return 0; + } + + if (!mark_lock && + tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, + 0, 4*tdb->header.hash_size)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno))); + return -1; + } + + tdb->global_lock.count = 0; + tdb->global_lock.ltype = 0; + + return 0; +} + +/* lock entire database with write lock */ +int tdb_lockall(struct tdb_context *tdb) +{ + return _tdb_lockall(tdb, F_WRLCK, F_SETLKW); +} + +/* lock entire database with write lock - mark only */ +int tdb_lockall_mark(struct tdb_context *tdb) +{ + return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW); +} + +/* unlock entire database with write lock - unmark only */ +int tdb_lockall_unmark(struct tdb_context *tdb) +{ + return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK); +} + +/* lock entire database with write lock - nonblocking variant */ +int tdb_lockall_nonblock(struct tdb_context *tdb) +{ + return _tdb_lockall(tdb, F_WRLCK, F_SETLK); +} + +/* unlock entire database with write lock */ +int tdb_unlockall(struct tdb_context *tdb) +{ + return _tdb_unlockall(tdb, F_WRLCK); +} + +/* lock entire database with read lock */ +int tdb_lockall_read(struct tdb_context *tdb) +{ + return _tdb_lockall(tdb, F_RDLCK, F_SETLKW); +} + +/* lock entire database with read lock - nonblock variant */ +int tdb_lockall_read_nonblock(struct tdb_context *tdb) +{ + return _tdb_lockall(tdb, F_RDLCK, F_SETLK); +} + +/* unlock entire database with read lock */ +int tdb_unlockall_read(struct tdb_context *tdb) +{ + return _tdb_unlockall(tdb, F_RDLCK); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +/* lock/unlock one hash chain, non-blocking. This is meant to be used + to reduce contention - it cannot guarantee how many records will be + locked */ +int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +/* mark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); +} + +/* unmark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); +} + +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + + + +/* record lock stops delete underneath */ +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0; +} + +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1); +} + +/* fcntl locks don't stack: avoid unlocking someone else's */ +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + u32 count = 0; + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0); +} + +/* file: io.c */ + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (fstat(tdb->fd, &st) == -1) { + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (st.st_size < (off_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + if (len == 0) { + return 0; + } + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) { + memcpy(off + (char *)tdb->map_ptr, buf, len); + } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + return 0; +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +void *tdb_convert(void *buf, u32 size) +{ + u32 i, *p = (u32 *)buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} + + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { + return -1; + } + + if (tdb->map_ptr) { + memcpy(buf, off + (char *)tdb->map_ptr, len); + } else { + ssize_t ret = pread(tdb->fd, buf, len, off); + if (ret != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d " + "len=%d ret=%d (%s) map_size=%d\n", + (int)off, (int)len, (int)ret, strerror(errno), + (int)tdb->map_size)); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + } + if (cv) { + tdb_convert(buf, len); + } + return 0; +} + + + +/* + do an unlocked scan of the hash table heads to find the next non-zero head. The value + will then be confirmed with the lock held +*/ +static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + if (tdb->map_ptr) { + for (;h < tdb->header.hash_size;h++) { + if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + u32 off=0; + for (;h < tdb->header.hash_size;h++) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { + break; + } + } + } + (*chain) = h; +} + + +int tdb_munmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret = munmap(tdb->map_ptr, tdb->real_map_size); + if (ret != 0) + return ret; + tdb->real_map_size = 0; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +void tdb_mmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->real_map_size = 0; + tdb->map_ptr = NULL; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + tdb->real_map_size = tdb->map_size; + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) +{ + char buf[1024]; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (ftruncate(tdb->fd, size+addition) == -1) { + char b = 0; + if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } + } + + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ + memset(buf, TDB_PAD_BYTE, sizeof(buf)); + while (addition) { + int n = addition>sizeof(buf)?sizeof(buf):addition; + int ret = pwrite(tdb->fd, buf, n, size); + if (ret != n) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", + n, strerror(errno))); + return -1; + } + addition -= n; + size += n; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +int tdb_expand(struct tdb_context *tdb, tdb_off_t size) +{ + struct list_struct rec; + tdb_off_t offset; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 10 more records, and round + the database up to a multiple of the page size */ + size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr = (char *)realloc(tdb->map_ptr, + tdb->map_size); + if (!new_map_ptr) { + tdb->map_size -= size; + goto fail; + } + tdb->map_ptr = new_map_ptr; + } else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +/* read/write a tdb_off_t */ +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} + +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + tdb_off_t off = *d; + return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + + +/* read a lump of data, allocating the space for it */ +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) +{ + unsigned char *buf; + + /* some systems don't like zero length malloc */ + if (len == 0) { + len = 1; + } + + if (!(buf = (unsigned char *)malloc(len))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_OOM, buf); + } + if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* Give a piece of tdb data to a parser */ + +int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + TDB_DATA data; + int result; + + data.dsize = len; + + if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { + /* + * Optimize by avoiding the malloc/memcpy/free, point the + * parser directly at the mmap area. + */ + if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) { + return -1; + } + data.dptr = offset + (unsigned char *)tdb->map_ptr; + return parser(key, data, private_data); + } + + if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) { + return -1; + } + + result = parser(key, data, private_data); + free(data.dptr); + return result; +} + +/* read/write a record */ +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} + +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + struct list_struct r = *rec; + return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +static const struct tdb_methods io_methods = { + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_oob, + tdb_expand_file, + tdb_brlock +}; + +/* + initialise the default methods table +*/ +void tdb_io_init(struct tdb_context *tdb) +{ + tdb->methods = &io_methods; +} + +/* file: transaction.c */ + +/* + transaction design: + + - only allow a single transaction at a time per database. This makes + using the transaction API simpler, as otherwise the caller would + have to cope with temporary failures in transactions that conflict + with other current transactions + + - keep the transaction recovery information in the same file as the + database, using a special 'transaction recovery' record pointed at + by the header. This removes the need for extra journal files as + used by some other databases + + - dynamically allocated the transaction recover record, re-using it + for subsequent transactions. If a larger record is needed then + tdb_free() the old record to place it on the normal tdb freelist + before allocating the new record + + - during transactions, keep a linked list of writes all that have + been performed by intercepting all tdb_write() calls. The hooked + transaction versions of tdb_read() and tdb_write() check this + linked list and try to use the elements of the list in preference + to the real database. + + - don't allow any locks to be held when a transaction starts, + otherwise we can end up with deadlock (plus lack of lock nesting + in posix locks would mean the lock is lost) + + - if the caller gains a lock during the transaction but doesn't + release it then fail the commit + + - allow for nested calls to tdb_transaction_start(), re-using the + existing transaction record. If the inner transaction is cancelled + then a subsequent commit will fail + + - keep a mirrored copy of the tdb hash chain heads to allow for the + fast hash heads scan on traverse, updating the mirrored copy in + the transaction version of tdb_write + + - allow callers to mix transaction and non-transaction use of tdb, + although once a transaction is started then an exclusive lock is + gained until the transaction is committed or cancelled + + - the commit strategy involves first saving away all modified data + into a linearised buffer in the transaction recovery area, then + marking the transaction recovery area with a magic value to + indicate a valid recovery record. In total 4 fsync/msync calls are + needed per commit to prevent race conditions. It might be possible + to reduce this to 3 or even 2 with some more work. + + - check for a valid recovery record on open of the tdb, while the + global lock is held. Automatically recover from the transaction + recovery area if needed, then continue with the open as + usual. This allows for smooth crash recovery with no administrator + intervention. + + - if TDB_NOSYNC is passed to flags in tdb_open then transactions are + still available, but no transaction recovery area is used and no + fsync/msync calls are made. + +*/ + +struct tdb_transaction_el { + struct tdb_transaction_el *next, *prev; + tdb_off_t offset; + tdb_len_t length; + unsigned char *data; +}; + +/* + hold the context of any current transaction +*/ +struct tdb_transaction { + /* we keep a mirrored copy of the tdb hash heads here so + tdb_next_hash_chain() can operate efficiently */ + u32 *hash_heads; + + /* the original io methods - used to do IOs to the real db */ + const struct tdb_methods *io_methods; + + /* the list of transaction elements. We use a doubly linked + list with a last pointer to allow us to keep the list + ordered, with first element at the front of the list. It + needs to be doubly linked as the read/write traversals need + to be backwards, while the commit needs to be forwards */ + struct tdb_transaction_el *elements, *elements_last; + + /* non-zero when an internal transaction error has + occurred. All write operations will then fail until the + transaction is ended */ + int transaction_error; + + /* when inside a transaction we need to keep track of any + nested tdb_transaction_start() calls, as these are allowed, + but don't create a new transaction */ + int nesting; + + /* old file size before transaction */ + tdb_len_t old_map_size; +}; + + +/* + read while in a transaction. We need to check first if the data is in our list + of transaction elements, then if not do a real read +*/ +static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + struct tdb_transaction_el *el; + + /* we need to walk the list backwards to get the most recent data */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping read - needs to be split into up to + 2 reads and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_read(tdb, off, buf, partial, cv) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(buf, el->data + (off - el->offset), partial); + if (cv) { + tdb_convert(buf, len); + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + + if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) { + goto fail; + } + + return 0; + } + + /* its not in the transaction elements - do a real read */ + return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction +*/ +static int transaction_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + struct tdb_transaction_el *el, *best_el=NULL; + + if (len == 0) { + return 0; + } + + /* if the write is to a hash head, then update the transaction + hash heads */ + if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && + off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { + u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); + memcpy(&tdb->transaction->hash_heads[chain], buf, len); + } + + /* first see if we can replace an existing entry */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (best_el == NULL && off == el->offset+el->length) { + best_el = el; + } + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping write - needs to be split into up to + 2 writes and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_write(tdb, off, buf, partial) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(el->data + (off - el->offset), buf, partial); + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + + if (len != 0 && transaction_write(tdb, off, buf, len) != 0) { + goto fail; + } + + return 0; + } + + /* see if we can append the new entry to an existing entry */ + if (best_el && best_el->offset + best_el->length == off && + (off+len < tdb->transaction->old_map_size || + off > tdb->transaction->old_map_size)) { + unsigned char *data = best_el->data; + el = best_el; + el->data = (unsigned char *)realloc(el->data, + el->length + len); + if (el->data == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + el->data = data; + return -1; + } + if (buf) { + memcpy(el->data + el->length, buf, len); + } else { + memset(el->data + el->length, TDB_PAD_BYTE, len); + } + el->length += len; + return 0; + } + + /* add a new entry at the end of the list */ + el = (struct tdb_transaction_el *)malloc(sizeof(*el)); + if (el == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + el->next = NULL; + el->prev = tdb->transaction->elements_last; + el->offset = off; + el->length = len; + el->data = (unsigned char *)malloc(len); + if (el->data == NULL) { + free(el); + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + if (buf) { + memcpy(el->data, buf, len); + } else { + memset(el->data, TDB_PAD_BYTE, len); + } + if (el->prev) { + el->prev->next = el; + } else { + tdb->transaction->elements = el; + } + tdb->transaction->elements_last = el; + return 0; + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + +/* + accelerated hash chain head search, using the cached hash heads +*/ +static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + for (;h < tdb->header.hash_size;h++) { + /* the +1 takes account of the freelist */ + if (0 != tdb->transaction->hash_heads[h+1]) { + break; + } + } + (*chain) = h; +} + +/* + out of bounds check during a transaction +*/ +static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, + int probe EXT2FS_ATTR((unused))) +{ + if (len <= tdb->map_size) { + return 0; + } + return TDB_ERRCODE(TDB_ERR_IO, -1); +} + +/* + transaction version of tdb_expand(). +*/ +static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, + tdb_off_t addition) +{ + /* add a write to the transaction elements, so subsequent + reads see the zero data */ + if (transaction_write(tdb, size, NULL, addition) != 0) { + return -1; + } + + return 0; +} + +/* + brlock during a transaction - ignore them +*/ +static int transaction_brlock(struct tdb_context *tdb EXT2FS_ATTR((unused)), + tdb_off_t offset EXT2FS_ATTR((unused)), + int rw_type EXT2FS_ATTR((unused)), + int lck_type EXT2FS_ATTR((unused)), + int probe EXT2FS_ATTR((unused)), + size_t len EXT2FS_ATTR((unused))) +{ + return 0; +} + +static const struct tdb_methods transaction_methods = { + transaction_read, + transaction_write, + transaction_next_hash_chain, + transaction_oob, + transaction_expand_file, + transaction_brlock +}; + + +/* + start a tdb transaction. No token is returned, as only a single + transaction is allowed to be pending per tdb_context +*/ +int tdb_transaction_start(struct tdb_context *tdb) +{ + /* some sanity checks */ + if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + /* cope with nested tdb_transaction_start() calls */ + if (tdb->transaction != NULL) { + tdb->transaction->nesting++; + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", + tdb->transaction->nesting)); + return 0; + } + + if (tdb->num_locks != 0 || tdb->global_lock.count) { + /* the caller must not have any locks when starting a + transaction as otherwise we'll be screwed by lack + of nested locks in posix */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->travlocks.next != NULL) { + /* you cannot use transactions inside a traverse (although you can use + traverse inside a transaction) as otherwise you can end up with + deadlock */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->transaction = (struct tdb_transaction *) + calloc(sizeof(struct tdb_transaction), 1); + if (tdb->transaction == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* get the transaction write lock. This is a blocking lock. As + discussed with Volker, there are a number of ways we could + make this async, which we will probably do in the future */ + if (tdb_transaction_lock(tdb, F_WRLCK) == -1) { + SAFE_FREE(tdb->transaction); + return -1; + } + + /* get a read lock from the freelist to the end of file. This + is upgraded to a write lock during the commit */ + if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + goto fail; + } + + /* setup a copy of the hash table heads so the hash scan in + traverse can be fast */ + tdb->transaction->hash_heads = (u32 *) + calloc(tdb->header.hash_size+1, sizeof(u32)); + if (tdb->transaction->hash_heads == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb), 0) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + /* make sure we know about any file expansions already done by + anyone else */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + tdb->transaction->old_map_size = tdb->map_size; + + /* finally hook the io methods, replacing them with + transaction specific methods */ + tdb->transaction->io_methods = tdb->methods; + tdb->methods = &transaction_methods; + + /* by calling this transaction write here, we ensure that we don't grow the + transaction linked list due to hash table updates */ + if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb)) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n")); + tdb->ecode = TDB_ERR_IO; + tdb->methods = tdb->transaction->io_methods; + goto fail; + } + + return 0; + +fail: + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_transaction_unlock(tdb); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + return -1; +} + + +/* + cancel the current transaction +*/ +int tdb_transaction_cancel(struct tdb_context *tdb) +{ + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->transaction_error = 1; + tdb->transaction->nesting--; + return 0; + } + + tdb->map_size = tdb->transaction->old_map_size; + + /* free all the transaction elements */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + /* remove any global lock created during the transaction */ + if (tdb->global_lock.count != 0) { + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); + tdb->global_lock.count = 0; + } + + /* remove any locks created during the transaction */ + if (tdb->num_locks != 0) { + int i; + for (i=0;inum_lockrecs;i++) { + tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, + F_UNLCK,F_SETLKW, 0, 1); + } + tdb->num_locks = 0; + tdb->num_lockrecs = 0; + SAFE_FREE(tdb->lockrecs); + } + + /* restore the normal io methods */ + tdb->methods = tdb->transaction->io_methods; + + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_transaction_unlock(tdb); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + + return 0; +} + +/* + sync to disk +*/ +static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) +{ + if (fsync(tdb->fd) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); + return -1; + } +#if defined(HAVE_MSYNC) && defined(MS_SYNC) + if (tdb->map_ptr) { + tdb_off_t moffset = offset & ~(tdb->page_size-1); + if (msync(moffset + (char *)tdb->map_ptr, + length + (offset - moffset), MS_SYNC) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", + strerror(errno))); + return -1; + } + } +#endif + return 0; +} + + +/* + work out how much space the linearised recovery data will consume +*/ +static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size = 0; + + recovery_size = sizeof(u32); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= tdb->transaction->old_map_size) { + continue; + } + recovery_size += 2*sizeof(tdb_off_t) + el->length; + } + + return recovery_size; +} + +/* + allocate the recovery area, or use an existing recovery area if it is + large enough +*/ +static int tdb_recovery_allocate(struct tdb_context *tdb, + tdb_len_t *recovery_size, + tdb_off_t *recovery_offset, + tdb_len_t *recovery_max_size) +{ + struct list_struct rec; + const struct tdb_methods *methods = tdb->transaction->io_methods; + tdb_off_t recovery_head; + + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); + return -1; + } + + rec.rec_len = 0; + + if (recovery_head != 0 && + methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); + return -1; + } + + *recovery_size = tdb_recovery_size(tdb); + + if (recovery_head != 0 && *recovery_size <= rec.rec_len) { + /* it fits in the existing area */ + *recovery_max_size = rec.rec_len; + *recovery_offset = recovery_head; + return 0; + } + + /* we need to free up the old recovery area, then allocate a + new one at the end of the file. Note that we cannot use + tdb_allocate() to allocate the new one as that might return + us an area that is being currently used (as of the start of + the transaction) */ + if (recovery_head != 0) { + if (tdb_free(tdb, recovery_head, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n")); + return -1; + } + } + + /* the tdb_free() call might have increased the recovery size */ + *recovery_size = tdb_recovery_size(tdb); + + /* round up to a multiple of page size */ + *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); + *recovery_offset = tdb->map_size; + recovery_head = *recovery_offset; + + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + (tdb->map_size - tdb->transaction->old_map_size) + + sizeof(rec) + *recovery_max_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); + return -1; + } + + /* remap the file (if using mmap) */ + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* we have to reset the old map size so that we don't try to expand the file + again in the transaction commit, which would destroy the recovery area */ + tdb->transaction->old_map_size = tdb->map_size; + + /* write the recovery header offset and sync - we can sync without a race here + as the magic ptr in the recovery record has not been set */ + CONVERT(recovery_head); + if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, + &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + + return 0; +} + + +/* + setup the recovery data that will be used on a crash during commit +*/ +static int transaction_setup_recovery(struct tdb_context *tdb, + tdb_off_t *magic_offset) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size; + unsigned char *data, *p; + const struct tdb_methods *methods = tdb->transaction->io_methods; + struct list_struct *rec; + tdb_off_t recovery_offset, recovery_max_size; + tdb_off_t old_map_size = tdb->transaction->old_map_size; + u32 magic, tailer; + + /* + check that the recovery area has enough space + */ + if (tdb_recovery_allocate(tdb, &recovery_size, + &recovery_offset, &recovery_max_size) == -1) { + return -1; + } + + data = (unsigned char *)malloc(recovery_size + sizeof(*rec)); + if (data == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + rec = (struct list_struct *)data; + memset(rec, 0, sizeof(*rec)); + + rec->magic = 0; + rec->data_len = recovery_size; + rec->rec_len = recovery_max_size; + rec->key_len = old_map_size; + CONVERT(rec); + + /* build the recovery data into a single blob to allow us to do a single + large write, which should be more efficient */ + p = data + sizeof(*rec); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= old_map_size) { + continue; + } + if (el->offset + el->length > tdb->transaction->old_map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); + free(data); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + memcpy(p, &el->offset, 4); + memcpy(p+4, &el->length, 4); + if (DOCONV()) { + tdb_convert(p, 8); + } + /* the recovery area contains the old data, not the + new data, so we have to call the original tdb_read + method to get it */ + if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) { + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + el->length; + } + + /* and the tailer */ + tailer = sizeof(*rec) + recovery_max_size; + memcpy(p, &tailer, 4); + CONVERT(p); + + /* write the recovery data to the recovery area */ + if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* as we don't have ordered writes, we have to sync the recovery + data before we update the magic to indicate that the recovery + data is present */ + if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { + free(data); + return -1; + } + + free(data); + + magic = TDB_RECOVERY_MAGIC; + CONVERT(magic); + + *magic_offset = recovery_offset + offsetof(struct list_struct, magic); + + if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* ensure the recovery magic marker is on disk */ + if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { + return -1; + } + + return 0; +} + +/* + commit the current transaction +*/ +int tdb_transaction_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + tdb_off_t magic_offset = 0; + u32 zero = 0; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); + return -1; + } + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->nesting--; + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->elements == NULL) { + tdb_transaction_cancel(tdb); + return 0; + } + + methods = tdb->transaction->io_methods; + + /* if there are any locks pending then the caller has not + nested their locks properly, so fail the transaction */ + if (tdb->num_locks || tdb->global_lock.count) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + /* upgrade the main transaction lock region to a write lock */ + if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + + /* get the global lock - this prevents new users attaching to the database + during the commit */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &magic_offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n")); + tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + } + + /* expand the file to the new size if needed */ + if (tdb->map_size != tdb->transaction->old_map_size) { + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + tdb->map_size - + tdb->transaction->old_map_size) == -1) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n")); + tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + tdb->map_size = tdb->transaction->old_map_size; + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + } + + /* perform all the writes */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + + if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); + + /* we've overwritten part of the data and + possibly expanded the file, so we need to + run the crash recovery code */ + tdb->methods = methods; + tdb_transaction_recover(tdb); + + tdb_transaction_cancel(tdb); + tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); + return -1; + } + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* ensure the new data is on disk */ + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + return -1; + } + + /* remove the recovery marker */ + if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n")); + return -1; + } + + /* ensure the recovery marker has been removed on disk */ + if (transaction_sync(tdb, magic_offset, 4) == -1) { + return -1; + } + } + + tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + /* + TODO: maybe write to some dummy hdr field, or write to magic + offset without mmap, before the last sync, instead of the + utime() call + */ + + /* on some systems (like Linux 2.6.x) changes via mmap/msync + don't change the mtime of the file, this means the file may + not be backed up (as tdb rounding to block sizes means that + file size changes are quite rare too). The following forces + mtime changes when a transaction completes */ +#ifdef HAVE_UTIME + utime(tdb->name, NULL); +#endif + + /* use a transaction cancel to free memory and remove the + transaction locks */ + tdb_transaction_cancel(tdb); + return 0; +} + + +/* + recover from an aborted transaction. Must be called with exclusive + database write access already established (including the global + lock to prevent new processes attaching) +*/ +int tdb_transaction_recover(struct tdb_context *tdb) +{ + tdb_off_t recovery_head, recovery_eof; + unsigned char *data, *p; + u32 zero = 0; + struct list_struct rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return 0; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (rec.magic != TDB_RECOVERY_MAGIC) { + /* there is no valid recovery data */ + return 0; + } + + if (tdb->read_only) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + + recovery_eof = rec.key_len; + + data = (unsigned char *)malloc(rec.data_len); + if (data == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* read the full recovery data */ + if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, + rec.data_len, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); + tdb->ecode = TDB_ERR_IO; + free(data); + return -1; + } + + /* recover the file data */ + p = data; + while (p+8 < data + rec.data_len) { + u32 ofs, len; + if (DOCONV()) { + tdb_convert(p, 8); + } + memcpy(&ofs, p, 4); + memcpy(&len, p+4, 4); + + if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { + free(data); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + len; + } + + free(data); + + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* if the recovery area is after the recovered eof then remove it */ + if (recovery_eof <= recovery_head) { + if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + } + + /* remove the recovery magic */ + if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), + &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* reduce the file size to the old size */ + tdb_munmap(tdb); + if (ftruncate(tdb->fd, recovery_eof) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = recovery_eof; + tdb_mmap(tdb); + + if (transaction_sync(tdb, 0, recovery_eof) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", + recovery_eof)); + + /* all done */ + return 0; +} + +/* file: freelist.c */ + +/* read a freelist record and check for simple errors */ +static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) +{ + if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + + + +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) +{ + tdb_off_t last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return tdb_ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); +} + + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, + const struct list_struct *rec) +{ + tdb_off_t totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), + &totalsize); +} + +/* Add an element into the freelist. Merge adjacent records if + necessary. */ +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + tdb_off_t right, left; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); + goto fail; + } + + /* Look right first (I'm an Australian, dammit) */ + right = offset + sizeof(*rec) + rec->rec_len; + if (right + sizeof(*rec) <= tdb->map_size) { + struct list_struct r; + + if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + } + } + +left: + /* Look left */ + left = offset - sizeof(tdb_off_t); + if (left > TDB_DATA_START(tdb->header.hash_size)) { + struct list_struct l; + tdb_off_t leftsize; + + /* Read in tailer and jump back to header */ + if (tdb_ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + + /* it could be uninitialised data */ + if (leftsize == 0 || leftsize == TDB_PAD_U32) { + goto update; + } + + left = offset - leftsize; + + /* Now read in record */ + if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, left, l.next) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left)); + goto update; + } else { + offset = left; + rec->rec_len += leftsize; + } + } + } + +update: + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + tdb_rec_write(tdb, offset, rec) == -1 || + tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + */ +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, + struct list_struct *rec, tdb_off_t last_ptr) +{ + struct list_struct newrec; + tdb_off_t newrec_ptr; + + memset(&newrec, '\0', sizeof(newrec)); + + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else { + newrec_ptr = 0; + } + + /* Remove allocated record from the free list */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { + return 0; + } + } + + /* all done - return the new record offset */ + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected list_struct within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec) +{ + tdb_off_t rec_ptr, last_ptr, newrec_ptr; + struct { + tdb_off_t rec_ptr, last_ptr; + tdb_len_t rec_len; + } bestfit; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off_t); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + bestfit.rec_ptr = 0; + bestfit.last_ptr = 0; + bestfit.rec_len = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) { + goto fail; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + /* consider a fit to be good enough if + we aren't wasting more than half + the space */ + if (bestfit.rec_len < 2*length) { + break; + } + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + } + + if (bestfit.rec_ptr != 0) { + if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + +/* file: freelistcheck.c */ + +/* Check the freelist is good and contains no loops. + Very memory intensive - only do this as a consistency + checker. Heh heh - uses an in memory tdb as the storage + for the "seen" record list. For some reason this strikes + me as extremely clever as I don't have to write another tree + data structure implementation :-). + */ + +static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr) +{ + TDB_DATA key, data; + + memset(&data, '\0', sizeof(data)); + key.dptr = (unsigned char *)&rec_ptr; + key.dsize = sizeof(rec_ptr); + return tdb_store(mem_tdb, key, data, TDB_INSERT); +} + +int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) +{ + struct tdb_context *mem_tdb = NULL; + struct list_struct rec; + tdb_off_t rec_ptr, last_ptr; + int ret = -1; + + *pnum_entries = 0; + + mem_tdb = tdb_open("flval", tdb->header.hash_size, + TDB_INTERNAL, O_RDWR, 0600); + if (!mem_tdb) { + return -1; + } + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + tdb_close(mem_tdb); + return 0; + } + + last_ptr = FREELIST_TOP; + + /* Store the FREELIST_TOP record. */ + if (seen_insert(mem_tdb, last_ptr) == -1) { + ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + goto fail; + } + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { + goto fail; + } + + while (rec_ptr) { + + /* If we can't store this record (we've seen it + before) then the free list has a loop and must + be corrupt. */ + + if (seen_insert(mem_tdb, rec_ptr)) { + ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + goto fail; + } + + if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec.next; + *pnum_entries += 1; + } + + ret = 0; + + fail: + + tdb_close(mem_tdb); + tdb_unlock(tdb, -1, F_WRLCK); + return ret; +} + +/* file: traverse.c */ + +/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ +static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, + struct list_struct *rec) +{ + int want_next = (tlock->off != 0); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (!tlock->off && tlock->hash != 0) { + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then that's OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). + */ + tdb->methods->next_hash_chain(tdb, &tlock->hash); + if (tlock->hash == tdb->header.hash_size) { + continue; + } + } + + if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) + return -1; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (tdb_unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off_t current; + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + + /* Detect infinite loops. From "Shlomi Yaakobovich" . */ + if (tlock->off == rec->next) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); + goto fail; + } + + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (tdb_lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (!(tdb->read_only || tdb->traverse_read) && + tdb_do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, tlock->lock_rw); + want_next = 0; + } + /* We finished iteration without finding anything */ + return TDB_ERRCODE(TDB_SUCCESS, 0); + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); + return -1; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +static int tdb_traverse_internal(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data, + struct tdb_traverse_lock *tl) +{ + TDB_DATA key, dbuf; + struct list_struct rec; + int ret, count = 0; + + /* This was in the initialization, above, but the IRIX compiler + * did not like it. crh + */ + tl->next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) { + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) + goto out; + if (tdb_unlock_record(tdb, tl->off) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { + ret = -1; + SAFE_FREE(key.dptr); + goto out; + } + if (fn && fn(tdb, key, dbuf, private_data)) { + /* They want us to terminate traversal */ + ret = count; + if (tdb_unlock_record(tdb, tl->off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + SAFE_FREE(key.dptr); + goto out; + } + SAFE_FREE(key.dptr); + } +out: + tdb->travlocks.next = tl->next; + if (ret < 0) + return -1; + else + return count; +} + + +/* + a write style traverse - temporarily marks the db read only +*/ +int tdb_traverse_read(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; + int ret; + + /* we need to get a read lock on the transaction lock here to + cope with the lock ordering semantics of solaris10 */ + if (tdb_transaction_lock(tdb, F_RDLCK)) { + return -1; + } + + tdb->traverse_read++; + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_read--; + + tdb_transaction_unlock(tdb); + + return ret; +} + +/* + a write style traverse - needs to get the transaction lock to + prevent deadlocks +*/ +int tdb_traverse(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + return tdb_traverse_read(tdb, fn, private_data); + } + + if (tdb_transaction_lock(tdb, F_WRLCK)) { + return -1; + } + + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + + tdb_transaction_unlock(tdb); + + return ret; +} + + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(struct tdb_context *tdb) +{ + TDB_DATA key; + struct list_struct rec; + + /* release any old lock */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + tdb->travlocks.lock_rw = F_RDLCK; + + /* Grab first record: locks chain and returned record. */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) + return tdb_null; + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + + /* Unlock the hash chain of the record we just read. */ + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) +{ + u32 oldhash; + TDB_DATA key = tdb_null; + struct list_struct rec; + unsigned char *k = NULL; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw)) + return tdb_null; + if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { + SAFE_FREE(k); + return tdb_null; + } + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) { + SAFE_FREE(k); + return tdb_null; + } + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); + if (!tdb->travlocks.off) + return tdb_null; + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + return key; +} + +/* file: dump.c */ + +static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash, + tdb_off_t offset) +{ + struct list_struct rec; + tdb_off_t tailer_ofs, tailer; + + if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d " + "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, + rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(struct tdb_context *tdb, int i) +{ + tdb_off_t rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, i, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(struct tdb_context *tdb) +{ + int i; + for (i = 0; i < (int)tdb->header.hash_size; i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(struct tdb_context *tdb) +{ + int ret; + long total_free = 0; + tdb_off_t offset, rec_ptr; + struct list_struct rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + +/* file: tdb.c */ + +/* + non-blocking increment of the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + if (!(tdb->flags & TDB_SEQNUM)) { + return; + } + + /* we ignore errors from this, as we have no sane way of + dealing with them. + */ + if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) + return; + seqnum++; + (void) tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); +} + +/* + increment the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +static void tdb_increment_seqnum(struct tdb_context *tdb) +{ + if (!(tdb->flags & TDB_SEQNUM)) { + return; + } + + if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) { + return; + } + + tdb_increment_seqnum_nonblock(tdb); + + tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); +} + +static int tdb_key_compare(TDB_DATA key, TDB_DATA data, + void *private_data EXT2FS_ATTR((unused))) +{ + return memcmp(data.dptr, key.dptr, data.dsize); +} + +/* Returns 0 on fail. On success, return offset of record, and fills + in rec */ +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, + struct list_struct *r) +{ + tdb_off_t rec_ptr; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (!TDB_DEAD(r) && hash==r->full_hash + && key.dsize==r->key_len + && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), + r->key_len, tdb_key_compare, + NULL) == 0) { + return rec_ptr; + } + rec_ptr = r->next; + } + return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); +} + +/* As tdb_find, but if you succeed, keep the lock */ +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec) +{ + u32 rec_ptr; + + if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) + return 0; + if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) + tdb_unlock(tdb, BUCKET(hash), locktype); + return rec_ptr; +} + + +/* update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. +*/ +static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) +{ + struct list_struct rec; + tdb_off_t rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) + return -1; + + /* must be long enough key, data and tailer */ + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + dbuf.dptr, dbuf.dsize) == -1) + return -1; + + if (dbuf.dsize != rec.data_len) { + /* update size */ + rec.data_len = dbuf.dsize; + return tdb_rec_write(tdb, rec_ptr, &rec); + } + + return 0; +} + +/* find an entry in the database given a key */ +/* If an entry doesn't exist tdb_err will be set to + * TDB_ERR_NOEXIST. If a key has no data attached + * then the TDB_DATA will have zero length but + * a non-zero pointer + */ +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_off_t rec_ptr; + struct list_struct rec; + TDB_DATA ret; + u32 hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) + return tdb_null; + + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; +} + +/* + * Find an entry in the database and hand the record's data to a parsing + * function. The parsing function is executed under the chain read lock, so it + * should be fast and should not block on other syscalls. + * + * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. + * + * For mmapped tdb's that do not have a transaction open it points the parsing + * function directly at the mmap area, it avoids the malloc/memcpy in this + * case. If a transaction is open or no mmap is available, it has to do + * malloc/read/parse/free. + * + * This is interesting for all readers of potentially large data structures in + * the tdb records, ldb indexes being one example. + */ + +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + tdb_off_t rec_ptr; + struct list_struct rec; + int ret; + u32 hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { + return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); + } + + ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len, parser, private_data); + + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + + return ret; +} + +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) +{ + struct list_struct rec; + + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; +} + +int tdb_exists(struct tdb_context *tdb, TDB_DATA key) +{ + u32 hash = tdb->hash_fn(&key); + return tdb_exists_hash(tdb, key, hash); +} + +/* actually delete an entry in the database given the offset */ +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) +{ + tdb_off_t last_ptr, i; + struct list_struct lastrec; + + if (tdb->read_only || tdb->traverse_read) return -1; + + if (tdb_write_lock_record(tdb, rec_ptr) == -1) { + /* Someone traversing here: mark it as dead */ + rec->magic = TDB_DEAD_MAGIC; + return tdb_rec_write(tdb, rec_ptr, rec); + } + if (tdb_write_unlock_record(tdb, rec_ptr) != 0) + return -1; + + /* find previous record in hash chain */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + return -1; + for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) + if (tdb_rec_read(tdb, i, &lastrec) == -1) + return -1; + + /* unlink it: next ptr is at start of record. */ + if (last_ptr == 0) + last_ptr = TDB_HASH_TOP(rec->full_hash); + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) + return -1; + + /* recover the space */ + if (tdb_free(tdb, rec_ptr, rec) == -1) + return -1; + return 0; +} + +static int tdb_count_dead(struct tdb_context *tdb, u32 hash) +{ + int res = 0; + tdb_off_t rec_ptr; + struct list_struct rec; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) + return 0; + + if (rec.magic == TDB_DEAD_MAGIC) { + res += 1; + } + rec_ptr = rec.next; + } + return res; +} + +/* + * Purge all DEAD records from a hash chain + */ +static int tdb_purge_dead(struct tdb_context *tdb, u32 hash) +{ + int res = -1; + struct list_struct rec; + tdb_off_t rec_ptr; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + return -1; + } + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + goto fail; + + while (rec_ptr) { + tdb_off_t next; + + if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + + next = rec.next; + + if (rec.magic == TDB_DEAD_MAGIC + && tdb_do_delete(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + rec_ptr = next; + } + res = 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return res; +} + +/* delete an entry in the database given a key */ +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) +{ + tdb_off_t rec_ptr; + struct list_struct rec; + int ret; + + if (tdb->max_dead_records != 0) { + + /* + * Allow for some dead records per hash chain, mainly for + * tdb's with a very high create/delete rate like locking.tdb. + */ + + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) { + /* + * Don't let the per-chain freelist grow too large, + * delete all existing dead records + */ + tdb_purge_dead(tdb, hash); + } + + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return -1; + } + + /* + * Just mark the record as dead. + */ + rec.magic = TDB_DEAD_MAGIC; + ret = tdb_rec_write(tdb, rec_ptr, &rec); + } + else { + if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, + &rec))) + return -1; + + ret = tdb_do_delete(tdb, rec_ptr, &rec); + } + + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); + return ret; +} + +int tdb_delete(struct tdb_context *tdb, TDB_DATA key) +{ + u32 hash = tdb->hash_fn(&key); + return tdb_delete_hash(tdb, key, hash); +} + +/* + * See if we have a dead record around with enough space + */ +static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash, + struct list_struct *r, tdb_len_t length) +{ + tdb_off_t rec_ptr; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (TDB_DEAD(r) && r->rec_len >= length) { + /* + * First fit for simple coding, TODO: change to best + * fit + */ + return rec_ptr; + } + rec_ptr = r->next; + } + return 0; +} + +/* store an element in the database, replacing any existing element + with the same key + + return 0 on success, -1 on failure +*/ +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +{ + struct list_struct rec; + u32 hash; + tdb_off_t rec_ptr; + char *p = NULL; + int ret = -1; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + /* check for it existing, on insert. */ + if (flag == TDB_INSERT) { + if (tdb_exists_hash(tdb, key, hash)) { + tdb->ecode = TDB_ERR_EXISTS; + goto fail; + } + } else { + /* first try in-place update, on modify or replace. */ + if (tdb_update_hash(tdb, key, hash, dbuf) == 0) { + goto done; + } + if (tdb->ecode == TDB_ERR_NOEXIST && + flag == TDB_MODIFY) { + /* if the record doesn't exist and we are in TDB_MODIFY mode then + we should fail the store */ + goto fail; + } + } + /* reset the error code potentially set by the tdb_update() */ + tdb->ecode = TDB_SUCCESS; + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + if (flag != TDB_INSERT) + tdb_delete_hash(tdb, key, hash); + + /* Copy key+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + memcpy(p, key.dptr, key.dsize); + if (dbuf.dsize) + memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); + + if (tdb->max_dead_records != 0) { + /* + * Allow for some dead records per hash chain, look if we can + * find one that can hold the new record. We need enough space + * for key, data and tailer. If we find one, we don't have to + * consult the central freelist. + */ + rec_ptr = tdb_find_dead( + tdb, hash, &rec, + key.dsize + dbuf.dsize + sizeof(tdb_off_t)); + + if (rec_ptr != 0) { + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write( + tdb, rec_ptr + sizeof(rec), + p, key.dsize + dbuf.dsize) == -1) { + goto fail; + } + goto done; + } + } + + /* + * We have to allocate some space from the freelist, so this means we + * have to lock it. Use the chance to purge all the DEAD records from + * the hash chain under the freelist lock. + */ + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + goto fail; + } + + if ((tdb->max_dead_records != 0) + && (tdb_purge_dead(tdb, hash) == -1)) { + tdb_unlock(tdb, -1, F_WRLCK); + goto fail; + } + + /* we have to allocate some space */ + rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec); + + tdb_unlock(tdb, -1, F_WRLCK); + + if (rec_ptr == 0) { + goto fail; + } + + /* Read hash top into next ptr */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + + done: + ret = 0; + fail: + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + + SAFE_FREE(p); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; +} + + +/* Append to an entry. Create if not exist. */ +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) +{ + u32 hash; + TDB_DATA dbuf; + int ret = -1; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + dbuf = tdb_fetch(tdb, key); + + if (dbuf.dptr == NULL) { + dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize); + } else { + unsigned char *new_dptr = (unsigned char *)realloc(dbuf.dptr, + dbuf.dsize + new_dbuf.dsize); + if (new_dptr == NULL) { + free(dbuf.dptr); + } + dbuf.dptr = new_dptr; + } + + if (dbuf.dptr == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto failed; + } + + memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); + dbuf.dsize += new_dbuf.dsize; + + ret = tdb_store(tdb, key, dbuf, 0); + +failed: + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbuf.dptr); + return ret; +} + + +/* + return the name of the current tdb file + useful for external logging functions +*/ +const char *tdb_name(struct tdb_context *tdb) +{ + return tdb->name; +} + +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +int tdb_fd(struct tdb_context *tdb) +{ + return tdb->fd; +} + +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +tdb_log_func tdb_log_fn(struct tdb_context *tdb) +{ + return tdb->log.log_fn; +} + + +/* + get the tdb sequence number. Only makes sense if the writers opened + with TDB_SEQNUM set. Note that this sequence number will wrap quite + quickly, so it should only be used for a 'has something changed' + test, not for code that relies on the count of the number of changes + made. If you want a counter then use a tdb record. + + The aim of this sequence number is to allow for a very lightweight + test of a possible tdb change. +*/ +int tdb_get_seqnum(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) + return 0; + return seqnum; +} + +int tdb_hash_size(struct tdb_context *tdb) +{ + return tdb->header.hash_size; +} + +size_t tdb_map_size(struct tdb_context *tdb) +{ + return tdb->map_size; +} + +int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + + +/* + enable sequence number handling on an open tdb +*/ +void tdb_enable_seqnum(struct tdb_context *tdb) +{ + tdb->flags |= TDB_SEQNUM; +} + +/* file: open.c */ + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static struct tdb_context *tdbs = NULL; + + +/* This is from a hash algorithm suggested by Rogier Wolff */ +static unsigned int default_tdb_hash(TDB_DATA *key) +{ + u32 value; /* Used to compute the hash value. */ + u32 i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0, i=0; i < key->dsize; i++) + value = value * 256 + key->dptr[i] + (value >> 24) * 241; + + return value; +} + + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(struct tdb_context *tdb, int hash_size) +{ + struct tdb_header *newdb; + int size, ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); + if (!(newdb = (struct tdb_header *)calloc(size, 1))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + if (write(tdb->fd, newdb, size) != size) { + ret = -1; + } else { + ret = 0; + } + + fail: + SAFE_FREE(newdb); + return ret; +} + + + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + struct tdb_context *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); +} + +/* a default logging function */ +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void null_log_fn(struct tdb_context *tdb EXT2FS_ATTR((unused)), + enum tdb_debug_level level EXT2FS_ATTR((unused)), + const char *fmt EXT2FS_ATTR((unused)), ...) +{ +} + + +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn) +{ + struct tdb_context *tdb; + struct stat st; + int rev = 0, locked = 0; + unsigned char *vp; + u32 vertest; + + if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb_io_init(tdb); + tdb->fd = -1; + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + if (log_ctx) { + tdb->log = *log_ctx; + } else { + tdb->log.log_fn = null_log_fn; + tdb->log.log_private = NULL; + } + tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + + /* cache the page size */ + tdb->page_size = sysconf(_SC_PAGESIZE); + if (tdb->page_size <= 0) { + tdb->page_size = 0x2000; + } + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* ensure there is only one process initialising at once */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || memcmp(tdb->header.magic_food, TDB_MAGIC_FOOD, + sizeof(TDB_MAGIC_FOOD)) != 0 + || (tdb->header.version != TDB_VERSION + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { + /* its not a valid database - possibly initialise it */ + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } + vp = (unsigned char *)&tdb->header.version; + vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | + (((u32)vp[2]) << 8) | (u32)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + tdb_convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + if (tdb->header.rwlocks != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); + goto fail; + } + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, (int)st.st_dev, (int)st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb->max_dead_records = 0; + tdb_mmap(tdb); + if (locked) { + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + /* leave this lock in place to indicate it's in use */ + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) + goto fail; + } + + /* if needed, run recovery */ + if (tdb_transaction_recover(tdb) == -1) { + goto fail; + } + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/* + * Set the maximum number of dead records per hash chain + */ + +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) +{ + tdb->max_dead_records = max_dead; +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(struct tdb_context *tdb) +{ + struct tdb_context **i; + int ret = 0; + + if (tdb->transaction) { + tdb_transaction_cancel(tdb); + } + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + ret = close(tdb->fd); + SAFE_FREE(tdb->lockrecs); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* register a logging function */ +void tdb_set_logging_function(struct tdb_context *tdb, + const struct tdb_logging_context *log_ctx) +{ + tdb->log = *log_ctx; +} + +void *tdb_get_logging_private(struct tdb_context *tdb) +{ + return tdb->log.log_private; +} + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(struct tdb_context *tdb) +{ + struct stat st; + + if (tdb->flags & TDB_INTERNAL) { + return 0; /* Nothing to do. */ + } + + if (tdb->num_locks != 0 || tdb->global_lock.count) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); + goto fail; + } + + if (tdb->transaction != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); + goto fail; + } + + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if ((tdb->flags & TDB_CLEAR_IF_FIRST) && + (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(int parent_longlived) +{ + struct tdb_context *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + /* + * If the parent is longlived (ie. a + * parent daemon architecture), we know + * it will keep it's active lock on a + * tdb opened with CLEAR_IF_FIRST. Thus + * for child processes we don't have to + * add an active lock. This is essential + * to improve performance on systems that + * keep POSIX locks as a non-scalable data + * structure in the kernel. + */ + if (parent_longlived) { + /* Ensure no clear-if-first. */ + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + if (tdb_reopen(tdb) != 0) + return -1; + } + + return 0; +} + +/** + * Flush a database file from the page cache. + **/ +int tdb_flush(struct tdb_context *tdb) +{ + if (tdb->fd != -1) + return fsync(tdb->fd); + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/tdb.h b/jni/e2fsprogs/lib/ext2fs/tdb.h new file mode 100755 index 0000000..de7aa33 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tdb.h @@ -0,0 +1,215 @@ +#ifndef __TDB_H__ +#define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* flags to tdb_store() */ +#define TDB_REPLACE 1 +#define TDB_INSERT 2 +#define TDB_MODIFY 3 + +/* flags for tdb_open() */ +#define TDB_DEFAULT 0 /* just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 +#define TDB_INTERNAL 2 /* don't store on disk */ +#define TDB_NOLOCK 4 /* don't do any locking */ +#define TDB_NOMMAP 8 /* don't use mmap */ +#define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /* don't use synchronous transactions */ +#define TDB_SEQNUM 128 /* maintain a sequence number */ + +#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) + +/* error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY}; + +/* debugging uses one of the following levels */ +enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, + TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; + +typedef struct TDB_DATA { + unsigned char *dptr; + size_t dsize; +} TDB_DATA; + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* ext2fs tdb renames */ +#define tdb_open ext2fs_tdb_open +#define tdb_open_ex ext2fs_tdb_open_ex +#define tdb_set_max_dead ext2fs_tdb_set_max_dead +#define tdb_reopen ext2fs_tdb_reopen +#define tdb_reopen_all ext2fs_tdb_reopen_all +#define tdb_set_logging_function ext2fs_tdb_set_logging_function +#define tdb_error ext2fs_tdb_error +#define tdb_errorstr ext2fs_tdb_errorstr +#define tdb_fetch ext2fs_tdb_fetch +#define tdb_parse_record ext2fs_tdb_parse_record +#define tdb_delete ext2fs_tdb_delete +#define tdb_store ext2fs_tdb_store +#define tdb_append ext2fs_tdb_append +#define tdb_close ext2fs_tdb_close +#define tdb_firstkey ext2fs_tdb_firstkey +#define tdb_nextkey ext2fs_tdb_nextkey +#define tdb_traverse ext2fs_tdb_traverse +#define tdb_traverse_read ext2fs_tdb_traverse_read +#define tdb_exists ext2fs_tdb_exists +#define tdb_lockall ext2fs_tdb_lockall +#define tdb_unlockall ext2fs_tdb_unlockall +#define tdb_lockall_read ext2fs_tdb_lockall_read +#define tdb_unlockall_read ext2fs_tdb_unlockall_read +#define tdb_name ext2fs_tdb_name +#define tdb_fd ext2fs_tdb_fd +#define tdb_log_fn ext2fs_tdb_log_fn +#define tdb_get_logging_private ext2fs_tdb_get_logging_private +#define tdb_transaction_start ext2fs_tdb_transaction_start +#define tdb_transaction_commit ext2fs_tdb_transaction_commit +#define tdb_transaction_cancel ext2fs_tdb_transaction_cancel +#define tdb_transaction_recover ext2fs_tdb_transaction_recover +#define tdb_get_seqnum ext2fs_tdb_get_seqnum +#define tdb_hash_size ext2fs_tdb_hash_size +#define tdb_map_size ext2fs_tdb_map_size +#define tdb_get_flags ext2fs_tdb_get_flags +#define tdb_chainlock ext2fs_tdb_chainlock +#define tdb_chainunlock ext2fs_tdb_chainunlock +#define tdb_chainlock_read ext2fs_tdb_chainlock_read +#define tdb_chainunlock_read ext2fs_tdb_chainunlock_read +#define tdb_dump_all ext2fs_tdb_dump_all +#define tdb_printfreelist ext2fs_tdb_printfreelist +#define tdb_validate_freelist ext2fs_tdb_validate_freelist +#define tdb_chainlock_mark ext2fs_tdb_chainlock_mark +#define tdb_chainlock_nonblock ext2fs_tdb_chainlock_nonblock +#define tdb_chainlock_unmark ext2fs_tdb_chainlock_unmark +#define tdb_enable_seqnum ext2fs_tdb_enable_seqnum +#define tdb_increment_seqnum_nonblock ext2fs_tdb_increment_seqnum_nonblock +#define tdb_lock_nonblock ext2fs_tdb_lock_nonblock +#define tdb_lockall_mark ext2fs_tdb_lockall_mark +#define tdb_lockall_nonblock ext2fs_tdb_lockall_nonblock +#define tdb_lockall_read_nonblock ext2fs_tdb_lockall_read_nonblock +#define tdb_lockall_unmark ext2fs_tdb_lockall_unmark +#define tdb_flush ext2fs_tdb_flush + +/* this is the context structure that is returned from a db open */ +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_logging_context { + tdb_log_func log_fn; + void *log_private; +}; + +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn); +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead); + +int tdb_reopen(struct tdb_context *tdb); +int tdb_reopen_all(int parent_longlived); +void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx); +enum TDB_ERROR tdb_error(struct tdb_context *tdb); +const char *tdb_errorstr(struct tdb_context *tdb); +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(struct tdb_context *tdb); +TDB_DATA tdb_firstkey(struct tdb_context *tdb); +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key); +int tdb_lockall(struct tdb_context *tdb); +int tdb_lockall_nonblock(struct tdb_context *tdb); +int tdb_unlockall(struct tdb_context *tdb); +int tdb_lockall_read(struct tdb_context *tdb); +int tdb_lockall_read_nonblock(struct tdb_context *tdb); +int tdb_unlockall_read(struct tdb_context *tdb); +int tdb_lockall_mark(struct tdb_context *tdb); +int tdb_lockall_unmark(struct tdb_context *tdb); +const char *tdb_name(struct tdb_context *tdb); +int tdb_fd(struct tdb_context *tdb); +tdb_log_func tdb_log_fn(struct tdb_context *tdb); +void *tdb_get_logging_private(struct tdb_context *tdb); +int tdb_transaction_start(struct tdb_context *tdb); +int tdb_transaction_commit(struct tdb_context *tdb); +int tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_transaction_recover(struct tdb_context *tdb); +int tdb_get_seqnum(struct tdb_context *tdb); +int tdb_hash_size(struct tdb_context *tdb); +size_t tdb_map_size(struct tdb_context *tdb); +int tdb_get_flags(struct tdb_context *tdb); +void tdb_enable_seqnum(struct tdb_context *tdb); +void tdb_increment_seqnum_nonblock(struct tdb_context *tdb); +int tdb_flush(struct tdb_context *tdb); + +/* Low level locking functions: use with care */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(struct tdb_context *tdb); +int tdb_printfreelist(struct tdb_context *tdb); +int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries); + +#ifdef __cplusplus +} +#endif + +#endif /* tdb.h */ diff --git a/jni/e2fsprogs/lib/ext2fs/tdbtool.c b/jni/e2fsprogs/lib/ext2fs/tdbtool.c new file mode 100755 index 0000000..eeac0c8 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tdbtool.c @@ -0,0 +1,621 @@ +/* + Unix SMB/CIFS implementation. + Samba database functions + Copyright (C) Andrew Tridgell 1999-2000 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000 + Copyright (C) Andrew Esh 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tdb.h" + +static int do_command(void); +const char *cmdname; +char *arg1, *arg2; +size_t arg1len, arg2len; +int bIterate = 0; +char *line; +TDB_DATA iterate_kbuf; +char cmdline[1024]; + +enum commands { + CMD_CREATE_TDB, + CMD_OPEN_TDB, + CMD_ERASE, + CMD_DUMP, + CMD_INSERT, + CMD_MOVE, + CMD_STORE, + CMD_SHOW, + CMD_KEYS, + CMD_HEXKEYS, + CMD_DELETE, + CMD_LIST_HASH_FREE, + CMD_LIST_FREE, + CMD_INFO, + CMD_FIRST, + CMD_NEXT, + CMD_SYSTEM, + CMD_QUIT, + CMD_HELP +}; + +typedef struct { + const char *name; + enum commands cmd; +} COMMAND_TABLE; + +COMMAND_TABLE cmd_table[] = { + {"create", CMD_CREATE_TDB}, + {"open", CMD_OPEN_TDB}, + {"erase", CMD_ERASE}, + {"dump", CMD_DUMP}, + {"insert", CMD_INSERT}, + {"move", CMD_MOVE}, + {"store", CMD_STORE}, + {"show", CMD_SHOW}, + {"keys", CMD_KEYS}, + {"hexkeys", CMD_HEXKEYS}, + {"delete", CMD_DELETE}, + {"list", CMD_LIST_HASH_FREE}, + {"free", CMD_LIST_FREE}, + {"info", CMD_INFO}, + {"first", CMD_FIRST}, + {"1", CMD_FIRST}, + {"next", CMD_NEXT}, + {"n", CMD_NEXT}, + {"quit", CMD_QUIT}, + {"q", CMD_QUIT}, + {"!", CMD_SYSTEM}, + {NULL, CMD_HELP} +}; + +/* a tdb tool for manipulating a tdb database */ + +static TDB_CONTEXT *tdb; + +static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); +static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); +static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); + +static void print_asc(const char *buf,int len) +{ + int i; + + /* We're probably printing ASCII strings so don't try to display + the trailing NULL character. */ + + if (buf[len - 1] == 0) + len--; + + for (i=0;i8) printf(" "); + while (n--) printf(" "); + + n = i%16; + if (n > 8) n = 8; + print_asc(&buf[i-(i%16)],n); printf(" "); + n = (i%16) - n; + if (n>0) print_asc(&buf[i-n],n); + printf("\n"); + } +} + +static void help(void) +{ + printf("\n" +"tdbtool: \n" +" create dbname : create a database\n" +" open dbname : open an existing database\n" +" erase : erase the database\n" +" dump : dump the database as strings\n" +" keys : dump the database keys as strings\n" +" hexkeys : dump the database keys as hex values\n" +" info : print summary info about the database\n" +" insert key data : insert a record\n" +" move key file : move a record to a destination tdb\n" +" store key data : store a record (replace)\n" +" show key : show a record by key\n" +" delete key : delete a record by key\n" +" list : print the database hash table and freelist\n" +" free : print the database freelist\n" +" ! command : execute system command\n" +" 1 | first : print the first record\n" +" n | next : print the next record\n" +" q | quit : terminate\n" +" \\n : repeat 'next' command\n" +"\n"); +} + +static void terror(const char *why) +{ + printf("%s\n", why); +} + +static void create_tdb(const char *tdbname) +{ + if (tdb) tdb_close(tdb); + tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT | O_TRUNC, 0600); + if (!tdb) { + printf("Could not create %s: %s\n", tdbname, strerror(errno)); + } +} + +static void open_tdb(const char *tdbname) +{ + if (tdb) tdb_close(tdb); + tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600); + if (!tdb) { + printf("Could not open %s: %s\n", tdbname, strerror(errno)); + } +} + +static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen) +{ + TDB_DATA key, dbuf; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + dbuf.dptr = (unsigned char *)data; + dbuf.dsize = datalen; + + if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) { + terror("insert failed"); + } +} + +static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen) +{ + TDB_DATA key, dbuf; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + if ((data == NULL) || (datalen == 0)) { + terror("need data"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + dbuf.dptr = (unsigned char *)data; + dbuf.dsize = datalen; + + printf("Storing key:\n"); + print_rec(tdb, key, dbuf, NULL); + + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { + terror("store failed"); + } +} + +static void show_tdb(char *keyname, size_t keylen) +{ + TDB_DATA key, dbuf; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + terror("fetch failed"); + return; + } + + print_rec(tdb, key, dbuf, NULL); + + free( dbuf.dptr ); + + return; +} + +static void delete_tdb(char *keyname, size_t keylen) +{ + TDB_DATA key; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + + if (tdb_delete(tdb, key) != 0) { + terror("delete failed"); + } +} + +static void move_rec(char *keyname, size_t keylen, char* tdbname) +{ + TDB_DATA key, dbuf; + TDB_CONTEXT *dst_tdb; + + if ((keyname == NULL) || (keylen == 0)) { + terror("need key"); + return; + } + + if ( !tdbname ) { + terror("need destination tdb name"); + return; + } + + key.dptr = (unsigned char *)keyname; + key.dsize = keylen; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + terror("fetch failed"); + return; + } + + print_rec(tdb, key, dbuf, NULL); + + dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600); + if ( !dst_tdb ) { + terror("unable to open destination tdb"); + return; + } + + if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) { + terror("failed to move record"); + } + else + printf("record moved\n"); + + tdb_close( dst_tdb ); + + return; +} + +static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + printf("\nkey %d bytes\n", (int)key.dsize); + print_asc((const char *)key.dptr, key.dsize); + printf("\ndata %d bytes\n", (int)dbuf.dsize); + print_data((const char *)dbuf.dptr, dbuf.dsize); + return 0; +} + +static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + printf("key %d bytes: ", (int)key.dsize); + print_asc((const char *)key.dptr, key.dsize); + printf("\n"); + return 0; +} + +static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + printf("key %d bytes\n", (int)key.dsize); + print_data((const char *)key.dptr, key.dsize); + printf("\n"); + return 0; +} + +static int total_bytes; + +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + total_bytes += dbuf.dsize; + return 0; +} + +static void info_tdb(void) +{ + int count; + total_bytes = 0; + if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1) + printf("Error = %s\n", tdb_errorstr(tdb)); + else + printf("%d records totalling %d bytes\n", count, total_bytes); +} + +static char *tdb_getline(const char *prompt) +{ + static char thisline[1024]; + char *p; + fputs(prompt, stdout); + thisline[0] = 0; + p = fgets(thisline, sizeof(thisline)-1, stdin); + if (p) p = strchr(p, '\n'); + if (p) *p = 0; + return p?thisline:NULL; +} + +static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + +static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +{ + TDB_DATA dbuf; + *pkey = tdb_firstkey(the_tdb); + + dbuf = tdb_fetch(the_tdb, *pkey); + if (!dbuf.dptr) terror("fetch failed"); + else { + print_rec(the_tdb, *pkey, dbuf, NULL); + } +} + +static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +{ + TDB_DATA dbuf; + *pkey = tdb_nextkey(the_tdb, *pkey); + + dbuf = tdb_fetch(the_tdb, *pkey); + if (!dbuf.dptr) + terror("fetch failed"); + else + print_rec(the_tdb, *pkey, dbuf, NULL); +} + +static int do_command(void) +{ + COMMAND_TABLE *ctp = cmd_table; + enum commands mycmd = CMD_HELP; + int cmd_len; + + if (cmdname && strlen(cmdname) == 0) { + mycmd = CMD_NEXT; + } else { + while (ctp->name) { + cmd_len = strlen(ctp->name); + if (strncmp(ctp->name,cmdname,cmd_len) == 0) { + mycmd = ctp->cmd; + break; + } + ctp++; + } + } + + switch (mycmd) { + case CMD_CREATE_TDB: + bIterate = 0; + create_tdb(arg1); + return 0; + case CMD_OPEN_TDB: + bIterate = 0; + open_tdb(arg1); + return 0; + case CMD_SYSTEM: + /* Shell command */ + system(arg1); + return 0; + case CMD_QUIT: + return 1; + default: + /* all the rest require a open database */ + if (!tdb) { + bIterate = 0; + terror("database not open"); + help(); + return 0; + } + switch (mycmd) { + case CMD_ERASE: + bIterate = 0; + tdb_traverse(tdb, do_delete_fn, NULL); + return 0; + case CMD_DUMP: + bIterate = 0; + tdb_traverse(tdb, print_rec, NULL); + return 0; + case CMD_INSERT: + bIterate = 0; + insert_tdb(arg1, arg1len,arg2,arg2len); + return 0; + case CMD_MOVE: + bIterate = 0; + move_rec(arg1,arg1len,arg2); + return 0; + case CMD_STORE: + bIterate = 0; + store_tdb(arg1,arg1len,arg2,arg2len); + return 0; + case CMD_SHOW: + bIterate = 0; + show_tdb(arg1, arg1len); + return 0; + case CMD_KEYS: + tdb_traverse(tdb, print_key, NULL); + return 0; + case CMD_HEXKEYS: + tdb_traverse(tdb, print_hexkey, NULL); + return 0; + case CMD_DELETE: + bIterate = 0; + delete_tdb(arg1,arg1len); + return 0; + case CMD_LIST_HASH_FREE: + tdb_dump_all(tdb); + return 0; + case CMD_LIST_FREE: + tdb_printfreelist(tdb); + return 0; + case CMD_INFO: + info_tdb(); + return 0; + case CMD_FIRST: + bIterate = 1; + first_record(tdb, &iterate_kbuf); + return 0; + case CMD_NEXT: + if (bIterate) + next_record(tdb, &iterate_kbuf); + return 0; + case CMD_HELP: + help(); + return 0; + case CMD_CREATE_TDB: + case CMD_OPEN_TDB: + case CMD_SYSTEM: + case CMD_QUIT: + /* + * unhandled commands. cases included here to avoid compiler + * warnings. + */ + return 0; + } + } + + return 0; +} + +static char *convert_string(char *instring, size_t *sizep) +{ + size_t length = 0; + char *outp, *inp; + char temp[3]; + + + outp = inp = instring; + + while (*inp) { + if (*inp == '\\') { + inp++; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[0] = *inp++; + temp[1] = '\0'; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[1] = *inp++; + temp[2] = '\0'; + } + *outp++ = (char)strtol((const char *)temp,NULL,16); + } else { + *outp++ = *inp++; + } + } else { + *outp++ = *inp++; + } + length++; + } + *sizep = length; + return instring; +} + +int main(int argc, char *argv[]) +{ + cmdname = ""; + arg1 = NULL; + arg1len = 0; + arg2 = NULL; + arg2len = 0; + + if (argv[1]) { + cmdname = "open"; + arg1 = argv[1]; + do_command(); + cmdname = ""; + arg1 = NULL; + } + + switch (argc) { + case 1: + case 2: + /* Interactive mode */ + while ((cmdname = tdb_getline("tdb> "))) { + arg2 = arg1 = NULL; + if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) { + arg1++; + arg2 = arg1; + while (*arg2) { + if (*arg2 == ' ') { + *arg2++ = '\0'; + break; + } + if ((*arg2++ == '\\') && (*arg2 == ' ')) { + arg2++; + } + } + } + if (arg1) arg1 = convert_string(arg1,&arg1len); + if (arg2) arg2 = convert_string(arg2,&arg2len); + if (do_command()) break; + } + break; + case 5: + arg2 = convert_string(argv[4],&arg2len); + case 4: + arg1 = convert_string(argv[3],&arg1len); + case 3: + cmdname = argv[2]; + default: + do_command(); + break; + } + + if (tdb) tdb_close(tdb); + + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/test_io.c b/jni/e2fsprogs/lib/ext2fs/test_io.c new file mode 100755 index 0000000..6843edb --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/test_io.c @@ -0,0 +1,557 @@ +/* + * test_io.c --- This is the Test I/O interface. + * + * Copyright (C) 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PRCTL_H +#include +#else +#define PR_GET_DUMPABLE 3 +#endif +#if (!defined(HAVE_PRCTL) && defined(linux)) +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct test_private_data { + int magic; + io_channel real; + int flags; + FILE *outfile; + unsigned long block; + int read_abort_count, write_abort_count; + void (*read_blk)(unsigned long block, int count, errcode_t err); + void (*write_blk)(unsigned long block, int count, errcode_t err); + void (*set_blksize)(int blksize, errcode_t err); + void (*write_byte)(unsigned long block, int count, errcode_t err); + void (*read_blk64)(unsigned long long block, int count, errcode_t err); + void (*write_blk64)(unsigned long long block, int count, errcode_t err); +}; + +/* + * These global variable can be set by the test program as + * necessary *before* calling test_open + */ +io_manager test_io_backing_manager = 0; +void (*test_io_cb_read_blk) + (unsigned long block, int count, errcode_t err) = 0; +void (*test_io_cb_write_blk) + (unsigned long block, int count, errcode_t err) = 0; +void (*test_io_cb_read_blk64) + (unsigned long long block, int count, errcode_t err) = 0; +void (*test_io_cb_write_blk64) + (unsigned long long block, int count, errcode_t err) = 0; +void (*test_io_cb_set_blksize) + (int blksize, errcode_t err) = 0; +void (*test_io_cb_write_byte) + (unsigned long block, int count, errcode_t err) = 0; + +/* + * Test flags + */ +#define TEST_FLAG_READ 0x01 +#define TEST_FLAG_WRITE 0x02 +#define TEST_FLAG_SET_BLKSIZE 0x04 +#define TEST_FLAG_FLUSH 0x08 +#define TEST_FLAG_DUMP 0x10 +#define TEST_FLAG_SET_OPTION 0x20 +#define TEST_FLAG_DISCARD 0x40 +#define TEST_FLAG_READAHEAD 0x80 +#define TEST_FLAG_ZEROOUT 0x100 + +static void test_dump_block(io_channel channel, + struct test_private_data *data, + unsigned long block, const void *buf) +{ + const unsigned char *cp; + FILE *f = data->outfile; + int i; + unsigned long cksum = 0; + + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { + cksum += *cp; + } + fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum); + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { + if ((i % 16) == 0) + fprintf(f, "%04x: ", i); + fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' '); + } +} + +/* + * Flush data buffers to disk. + */ +static errcode_t test_flush(io_channel channel) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *)channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_flush(data->real); + + if (data->flags & TEST_FLAG_FLUSH) + fprintf(data->outfile, "Test_io: flush() returned %s\n", + retval ? error_message(retval) : "OK"); + + return retval; +} + +static void test_abort(io_channel channel, unsigned long block) +{ + struct test_private_data *data; + FILE *f; + + data = (struct test_private_data *) channel->private_data; + f = data->outfile; + test_flush(channel); + + fprintf(f, "Aborting due to I/O to block %lu\n", block); + fflush(f); + abort(); +} + +static char *safe_getenv(const char *arg) +{ +#if !defined(_WIN32) + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#endif +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if defined(HAVE_SECURE_GETENV) + return secure_getenv(arg); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +static errcode_t test_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct test_private_data *data = NULL; + errcode_t retval; + char *value; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + goto cleanup; + memset(io, 0, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + retval = ext2fs_get_mem(sizeof(struct test_private_data), &data); + if (retval) + goto cleanup; + io->manager = test_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + io->flags = 0; + + memset(data, 0, sizeof(struct test_private_data)); + data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; + if (test_io_backing_manager) { + retval = test_io_backing_manager->open(name, flags, + &data->real); + if (retval) + goto cleanup; + } else { + data->real = 0; + } + data->read_blk = test_io_cb_read_blk; + data->write_blk = test_io_cb_write_blk; + data->set_blksize = test_io_cb_set_blksize; + data->write_byte = test_io_cb_write_byte; + data->read_blk64 = test_io_cb_read_blk64; + data->write_blk64 = test_io_cb_write_blk64; + + data->outfile = NULL; + if ((value = safe_getenv("TEST_IO_LOGFILE")) != NULL) + data->outfile = fopen(value, "w"); + if (!data->outfile) + data->outfile = stderr; + + data->flags = 0; + if ((value = safe_getenv("TEST_IO_FLAGS")) != NULL) + data->flags = strtoul(value, NULL, 0); + + data->block = 0; + if ((value = safe_getenv("TEST_IO_BLOCK")) != NULL) + data->block = strtoul(value, NULL, 0); + + data->read_abort_count = 0; + if ((value = safe_getenv("TEST_IO_READ_ABORT")) != NULL) + data->read_abort_count = strtoul(value, NULL, 0); + + data->write_abort_count = 0; + if ((value = safe_getenv("TEST_IO_WRITE_ABORT")) != NULL) + data->write_abort_count = strtoul(value, NULL, 0); + + if (data->real) { + io->align = data->real->align; + if (data->real->flags & CHANNEL_FLAGS_THREADS) + io->flags |= CHANNEL_FLAGS_THREADS; + } + + *channel = io; + return 0; + +cleanup: + if (io && io->name) + ext2fs_free_mem(&io->name); + if (io) + ext2fs_free_mem(&io); + if (data) + ext2fs_free_mem(&data); + return retval; +} + +static errcode_t test_close(io_channel channel) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + + if (data->real) + retval = io_channel_close(data->real); + + if (data->outfile && data->outfile != stderr) + fclose(data->outfile); + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t test_set_blksize(io_channel channel, int blksize) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) { + retval = io_channel_set_blksize(data->real, blksize); + channel->align = data->real->align; + } + if (data->set_blksize) + data->set_blksize(blksize, retval); + if (data->flags & TEST_FLAG_SET_BLKSIZE) + fprintf(data->outfile, + "Test_io: set_blksize(%d) returned %s\n", + blksize, retval ? error_message(retval) : "OK"); + channel->block_size = blksize; + return retval; +} + + +static errcode_t test_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_read_blk(data->real, block, count, buf); + if (data->read_blk) + data->read_blk(block, count, retval); + if (data->flags & TEST_FLAG_READ) + fprintf(data->outfile, + "Test_io: read_blk(%lu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->read_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_write_blk(data->real, block, count, buf); + if (data->write_blk) + data->write_blk(block, count, retval); + if (data->flags & TEST_FLAG_WRITE) + fprintf(data->outfile, + "Test_io: write_blk(%lu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->write_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_read_blk64(io_channel channel, unsigned long long block, + int count, void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_read_blk64(data->real, block, count, buf); + if (data->read_blk64) + data->read_blk64(block, count, retval); + if (data->flags & TEST_FLAG_READ) + fprintf(data->outfile, + "Test_io: read_blk64(%llu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->read_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_write_blk64(io_channel channel, unsigned long long block, + int count, const void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_write_blk64(data->real, block, count, buf); + if (data->write_blk64) + data->write_blk64(block, count, retval); + if (data->flags & TEST_FLAG_WRITE) + fprintf(data->outfile, + "Test_io: write_blk64(%llu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->write_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_write_byte(io_channel channel, unsigned long offset, + int count, const void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real && data->real->manager->write_byte) + retval = io_channel_write_byte(data->real, offset, count, buf); + if (data->write_byte) + data->write_byte(offset, count, retval); + if (data->flags & TEST_FLAG_WRITE) + fprintf(data->outfile, + "Test_io: write_byte(%lu, %d) returned %s\n", + offset, count, retval ? error_message(retval) : "OK"); + return retval; +} + +static errcode_t test_set_option(io_channel channel, const char *option, + const char *arg) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "Test_io: set_option(%s, %s) ", + option, arg); + if (data->real && data->real->manager->set_option) { + retval = (data->real->manager->set_option)(data->real, + option, arg); + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "returned %s\n", + retval ? error_message(retval) : "OK"); + } else { + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "not implemented\n"); + } + return retval; +} + +static errcode_t test_get_stats(io_channel channel, io_stats *stats) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real && data->real->manager->get_stats) { + retval = (data->real->manager->get_stats)(data->real, stats); + } + return retval; +} + +static errcode_t test_discard(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_discard(data->real, block, count); + if (data->flags & TEST_FLAG_DISCARD) + fprintf(data->outfile, + "Test_io: discard(%llu, %llu) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + return retval; +} + +static errcode_t test_cache_readahead(io_channel channel, + unsigned long long block, + unsigned long long count) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_cache_readahead(data->real, block, count); + if (data->flags & TEST_FLAG_READAHEAD) + fprintf(data->outfile, + "Test_io: readahead(%llu, %llu) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + return retval; +} + +static errcode_t test_zeroout(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_zeroout(data->real, block, count); + if (data->flags & TEST_FLAG_ZEROOUT) + fprintf(data->outfile, + "Test_io: zeroout(%llu, %llu) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + return retval; +} + +static struct struct_io_manager struct_test_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Test I/O Manager", + .open = test_open, + .close = test_close, + .set_blksize = test_set_blksize, + .read_blk = test_read_blk, + .write_blk = test_write_blk, + .flush = test_flush, + .write_byte = test_write_byte, + .set_option = test_set_option, + .get_stats = test_get_stats, + .read_blk64 = test_read_blk64, + .write_blk64 = test_write_blk64, + .discard = test_discard, + .cache_readahead = test_cache_readahead, + .zeroout = test_zeroout, +}; + +io_manager test_io_manager = &struct_test_manager; diff --git a/jni/e2fsprogs/lib/ext2fs/test_io.o b/jni/e2fsprogs/lib/ext2fs/test_io.o new file mode 100755 index 0000000000000000000000000000000000000000..bc93bb1f08585be878723f0792aa934059293aa7 GIT binary patch literal 16064 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 P!mE6)MPle2-mU*{MdD8{ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c b/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c new file mode 100755 index 0000000..b6e766a --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c @@ -0,0 +1,369 @@ +/* + * This testing program makes sure the badblocks implementation works. + * + * Copyright (C) 1996 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#define ADD_BLK 0x0001 +#define DEL_BLK 0x0002 + +blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }; +blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 0 }; +blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 }; +blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 }; +blk_t test4a[] = { + 20, 1, + 50, 1, + 3, 0, + 17, 1, + 18, 0, + 16, 0, + 11, 0, + 12, 1, + 13, 1, + 14, 0, + 80, 0, + 45, 0, + 66, 1, + 0 }; +blk_t test5[] = { 31, 20, 17, 51, 23, 1, 56, 57, 0 }; +blk_t test5a[] = { + 50, ADD_BLK, + 51, DEL_BLK, + 57, DEL_BLK, + 66, ADD_BLK, + 31, DEL_BLK, + 12, ADD_BLK, + 2, ADD_BLK, + 13, ADD_BLK, + 1, DEL_BLK, + 0 + }; + + +static int test_fail = 0; +static int test_expected_fail = 0; + +static errcode_t create_test_list(blk_t *vec, badblocks_list *ret) +{ + errcode_t retval; + badblocks_list bb; + int i; + + retval = ext2fs_badblocks_list_create(&bb, 5); + if (retval) { + com_err("create_test_list", retval, "while creating list"); + return retval; + } + for (i=0; vec[i]; i++) { + retval = ext2fs_badblocks_list_add(bb, vec[i]); + if (retval) { + com_err("create_test_list", retval, + "while adding test vector %d", i); + ext2fs_badblocks_list_free(bb); + return retval; + } + } + *ret = bb; + return 0; +} + +static void print_list(badblocks_list bb, int verify) +{ + errcode_t retval; + badblocks_iterate iter; + blk_t blk; + int i, ok; + + retval = ext2fs_badblocks_list_iterate_begin(bb, &iter); + if (retval) { + com_err("print_list", retval, "while setting up iterator"); + return; + } + ok = i = 1; + while (ext2fs_badblocks_list_iterate(iter, &blk)) { + printf("%u ", blk); + if (i++ != blk) + ok = 0; + } + ext2fs_badblocks_list_iterate_end(iter); + if (verify) { + if (ok) + printf("--- OK"); + else { + printf("--- NOT OK"); + test_fail++; + } + } +} + +static void validate_test_seq(badblocks_list bb, blk_t *vec) +{ + int i, match, ok; + + for (i = 0; vec[i]; i += 2) { + match = ext2fs_badblocks_list_test(bb, vec[i]); + if (match == vec[i+1]) + ok = 1; + else { + ok = 0; + test_fail++; + } + printf("\tblock %u is %s --- %s\n", vec[i], + match ? "present" : "absent", + ok ? "OK" : "NOT OK"); + } +} + +static void do_test_seq(badblocks_list bb, blk_t *vec) +{ + int i, match; + + for (i = 0; vec[i]; i += 2) { + switch (vec[i+1]) { + case ADD_BLK: + ext2fs_badblocks_list_add(bb, vec[i]); + match = ext2fs_badblocks_list_test(bb, vec[i]); + printf("Adding block %u --- now %s\n", vec[i], + match ? "present" : "absent"); + if (!match) { + printf("FAILURE!\n"); + test_fail++; + } + break; + case DEL_BLK: + ext2fs_badblocks_list_del(bb, vec[i]); + match = ext2fs_badblocks_list_test(bb, vec[i]); + printf("Removing block %u --- now %s\n", vec[i], + ext2fs_badblocks_list_test(bb, vec[i]) ? + "present" : "absent"); + if (match) { + printf("FAILURE!\n"); + test_fail++; + } + break; + } + } +} + + +int file_test(badblocks_list bb) +{ + badblocks_list new_bb = 0; + errcode_t retval; + FILE *f; + + f = tmpfile(); + if (!f) { + fprintf(stderr, "Error opening temp file: %s\n", + error_message(errno)); + return 1; + } + retval = ext2fs_write_bb_FILE(bb, 0, f); + if (retval) { + com_err("file_test", retval, "while writing bad blocks"); + return 1; + } + + rewind(f); + retval = ext2fs_read_bb_FILE2(0, f, &new_bb, 0, 0); + if (retval) { + com_err("file_test", retval, "while reading bad blocks"); + return 1; + } + fclose(f); + + if (ext2fs_badblocks_equal(bb, new_bb)) { + printf("Block bitmap matched after reading and writing.\n"); + } else { + printf("Block bitmap NOT matched.\n"); + test_fail++; + } + ext2fs_badblocks_list_free(new_bb); + return 0; +} + +static void invalid_proc(ext2_filsys fs, blk_t blk) +{ + if (blk == 34500) { + printf("Expected invalid block\n"); + test_expected_fail++; + } else { + printf("Invalid block #: %u\n", blk); + test_fail++; + } +} + +void file_test_invalid(badblocks_list bb) +{ + badblocks_list new_bb = 0; + errcode_t retval; + ext2_filsys fs; + FILE *f; + + fs = malloc(sizeof(struct struct_ext2_filsys)); + memset(fs, 0, sizeof(struct struct_ext2_filsys)); + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; + fs->super = malloc(SUPERBLOCK_SIZE); + memset(fs->super, 0, SUPERBLOCK_SIZE); + fs->super->s_first_data_block = 1; + ext2fs_blocks_count_set(fs->super, 100); + + f = tmpfile(); + if (!f) { + fprintf(stderr, "Error opening temp file: %s\n", + error_message(errno)); + test_fail++; + goto out; + } + retval = ext2fs_write_bb_FILE(bb, 0, f); + if (retval) { + com_err("file_test", retval, "while writing bad blocks"); + test_fail++; + goto out; + } + fprintf(f, "34500\n"); + + rewind(f); + test_expected_fail = 0; + retval = ext2fs_read_bb_FILE(fs, f, &new_bb, invalid_proc); + if (retval) { + com_err("file_test", retval, "while reading bad blocks"); + test_fail++; + goto out; + } + fclose(f); + if (!test_expected_fail) { + printf("Expected test failure didn't happen!\n"); + test_fail++; + } + + + if (ext2fs_badblocks_equal(bb, new_bb)) { + printf("Block bitmap matched after reading and writing.\n"); + } else { + printf("Block bitmap NOT matched.\n"); + test_fail++; + } + ext2fs_badblocks_list_free(new_bb); +out: + free(fs->super); + free(fs); +} + +int main(int argc, char **argv) +{ + badblocks_list bb1, bb2, bb3, bb4, bb5; + int equal; + errcode_t retval; + + add_error_table(&et_ext2_error_table); + + bb1 = bb2 = bb3 = bb4 = bb5 = 0; + + printf("test1: "); + retval = create_test_list(test1, &bb1); + if (retval == 0) + print_list(bb1, 1); + printf("\n"); + + printf("test2: "); + retval = create_test_list(test2, &bb2); + if (retval == 0) + print_list(bb2, 1); + printf("\n"); + + printf("test3: "); + retval = create_test_list(test3, &bb3); + if (retval == 0) + print_list(bb3, 1); + printf("\n"); + + printf("test4: "); + retval = create_test_list(test4, &bb4); + if (retval == 0) { + print_list(bb4, 0); + printf("\n"); + validate_test_seq(bb4, test4a); + } + printf("\n"); + + printf("test5: "); + retval = create_test_list(test5, &bb5); + if (retval == 0) { + print_list(bb5, 0); + printf("\n"); + do_test_seq(bb5, test5a); + printf("After test5 sequence: "); + print_list(bb5, 0); + printf("\n"); + } + printf("\n"); + + if (bb1 && bb2 && bb3 && bb4 && bb5) { + printf("Comparison tests:\n"); + equal = ext2fs_badblocks_equal(bb1, bb2); + printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT "); + if (equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb1, bb3); + printf("bb1 and bb3 are %sequal.\n", equal ? "" : "NOT "); + if (!equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb1, bb4); + printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT "); + if (equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb4, bb5); + printf("bb4 and bb5 are %sequal.\n", equal ? "" : "NOT "); + if (!equal) + test_fail++; + printf("\n"); + } + + file_test(bb4); + + file_test_invalid(bb4); + + if (test_fail == 0) + printf("ext2fs library badblocks tests checks out OK!\n"); + + if (bb1) + ext2fs_badblocks_list_free(bb1); + if (bb2) + ext2fs_badblocks_list_free(bb2); + if (bb3) + ext2fs_badblocks_list_free(bb3); + if (bb4) + ext2fs_badblocks_list_free(bb4); + if (bb5) + ext2fs_badblocks_list_free(bb5); + + return test_fail; + +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c new file mode 100755 index 0000000..cb3c70d --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c @@ -0,0 +1,732 @@ +/* + * tst_bitmaps.c + * + * Copyright (C) 2011 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include +#include +#include +#include +#include "ss/ss.h" + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +extern ss_request_table tst_bitmaps_cmds; + +static char subsystem_name[] = "tst_bitmaps"; +static char version[] = "1.0"; + +ext2_filsys test_fs; +int exit_status = 0; + +static int source_file(const char *cmd_file, int sci_idx) +{ + FILE *f; + char buf[256]; + char *cp; + int retval; + int noecho; + + if (strcmp(cmd_file, "-") == 0) + f = stdin; + else { + f = fopen(cmd_file, "r"); + if (!f) { + perror(cmd_file); + exit(1); + } + } + fflush(stdout); + fflush(stderr); + setbuf(stdout, NULL); + setbuf(stderr, NULL); + while (!feof(f)) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + if (buf[0] == '#') + continue; + noecho = 0; + if (buf[0] == '-') { + noecho = 1; + buf[0] = ' '; + } + cp = strchr(buf, '\n'); + if (cp) + *cp = 0; + cp = strchr(buf, '\r'); + if (cp) + *cp = 0; + if (!noecho) + printf("%s: %s\n", subsystem_name, buf); + retval = ss_execute_line(sci_idx, buf); + if (retval) { + ss_perror(sci_idx, retval, buf); + exit_status++; + } + } + return exit_status; +} + + +/* + * This function resets the libc getopt() function, which keeps + * internal state. Bad design! Stupid libc API designers! No + * biscuit! + * + * BSD-derived getopt() functions require that optind be reset to 1 in + * order to reset getopt() state. This used to be generally accepted + * way of resetting getopt(). However, glibc's getopt() + * has additional getopt() state beyond optind, and requires that + * optind be set zero to reset its state. So the unfortunate state of + * affairs is that BSD-derived versions of getopt() misbehave if + * optind is set to 0 in order to reset getopt(), and glibc's getopt() + * will core dump if optind is set 1 in order to reset getopt(). + * + * More modern versions of BSD require that optreset be set to 1 in + * order to reset getopt(). Sigh. Standards, anyone? + * + * We hide the hair here. + */ +void reset_getopt(void) +{ +#if defined(__GLIBC__) || defined(__linux__) + optind = 0; +#else + optind = 1; +#endif +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif +} + +/* + * This function will convert a string to an unsigned long, printing + * an error message if it fails, and returning success or failure in err. + */ +unsigned long parse_ulong(const char *str, const char *cmd, + const char *descr, int *err) +{ + char *tmp; + unsigned long ret; + + ret = strtoul(str, &tmp, 0); + if (*tmp == 0) { + if (err) + *err = 0; + return ret; + } + com_err(cmd, 0, "Bad %s - %s", descr, str); + if (err) + *err = 1; + else + exit(1); + return 0; +} + + +int check_fs_open(char *name) +{ + if (!test_fs) { + com_err(name, 0, "Filesystem not open"); + return 1; + } + return 0; +} + +static void setup_filesystem(const char *name, + unsigned int blocks, unsigned int inodes, + unsigned int type, int flags) +{ + struct ext2_super_block param; + errcode_t retval; + + memset(¶m, 0, sizeof(param)); + ext2fs_blocks_count_set(¶m, blocks); + param.s_inodes_count = inodes; + + retval = ext2fs_initialize("test fs", flags, ¶m, + test_io_manager, &test_fs); + + if (retval) { + com_err(name, retval, "while initializing filesystem"); + return; + } + test_fs->default_bitmap_type = type; + ext2fs_free_block_bitmap(test_fs->block_map); + test_fs->block_map = 0; + ext2fs_free_inode_bitmap(test_fs->inode_map); + test_fs->inode_map = 0; + retval = ext2fs_allocate_block_bitmap(test_fs, "block bitmap", + &test_fs->block_map); + if (retval) { + com_err(name, retval, "while allocating block bitmap"); + goto errout; + } + retval = ext2fs_allocate_inode_bitmap(test_fs, "inode bitmap", + &test_fs->inode_map); + if (retval) { + com_err(name, retval, "while allocating inode bitmap"); + goto errout; + } + return; + +errout: + ext2fs_close_free(&test_fs); +} + +void setup_cmd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + int c, err; + unsigned int blocks = 128; + unsigned int inodes = 0; + unsigned int type = EXT2FS_BMAP64_BITARRAY; + int flags = EXT2_FLAG_64BITS; + + if (test_fs) + ext2fs_close_free(&test_fs); + + reset_getopt(); + while ((c = getopt(argc, argv, "b:i:lt:")) != EOF) { + switch (c) { + case 'b': + blocks = parse_ulong(optarg, argv[0], + "number of blocks", &err); + if (err) + return; + break; + case 'i': + inodes = parse_ulong(optarg, argv[0], + "number of blocks", &err); + if (err) + return; + break; + case 'l': /* Legacy bitmaps */ + flags = 0; + break; + case 't': + type = parse_ulong(optarg, argv[0], + "bitmap backend type", &err); + if (err) + return; + break; + default: + fprintf(stderr, "%s: usage: setup [-b blocks] " + "[-i inodes] [-t type]\n", argv[0]); + return; + } + } + setup_filesystem(argv[0], blocks, inodes, type, flags); +} + +void close_cmd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + + ext2fs_close_free(&test_fs); +} + + +void dump_bitmap(ext2fs_generic_bitmap bmap, unsigned int start, unsigned num) +{ + unsigned char *buf; + errcode_t retval; + int i, len = (num - start + 7) / 8; + + buf = malloc(len); + if (!buf) { + com_err("dump_bitmap", 0, "couldn't allocate buffer"); + return; + } + memset(buf, 0, len); + retval = ext2fs_get_generic_bmap_range(bmap, (__u64) start, num, buf); + if (retval) { + com_err("dump_bitmap", retval, + "while calling ext2fs_generic_bmap_range"); + free(buf); + return; + } + for (i=0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); + printf("bits set: %u\n", ext2fs_bitcount(buf, len)); + free(buf); +} + +void dump_inode_bitmap_cmd(int argc, char **argv, + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + + printf("inode bitmap: "); + dump_bitmap(test_fs->inode_map, 1, test_fs->super->s_inodes_count); +} + +void dump_block_bitmap_cmd(int argc, char **argv, + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + + printf("block bitmap: "); + dump_bitmap(test_fs->block_map, test_fs->super->s_first_data_block, + test_fs->super->s_blocks_count); +} + +void do_setb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int block, num; + int err; + int test_result, op_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2 && argc != 3) { + com_err(argv[0], 0, "Usage: setb [num]"); + return; + } + + block = parse_ulong(argv[1], argv[0], "block", &err); + if (err) + return; + + if (argc == 3) { + num = parse_ulong(argv[2], argv[0], "num", &err); + if (err) + return; + + ext2fs_mark_block_bitmap_range2(test_fs->block_map, + block, num); + printf("Marking blocks %u to %u\n", block, block + num - 1); + return; + } + + test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); + op_result = ext2fs_mark_block_bitmap2(test_fs->block_map, block); + printf("Setting block %u, was %s before\n", block, op_result ? + "set" : "clear"); + if (!test_result != !op_result) + com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", + test_result, op_result); +} + +void do_clearb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int block, num; + int err; + int test_result, op_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2 && argc != 3) { + com_err(argv[0], 0, "Usage: clearb [num]"); + return; + } + + block = parse_ulong(argv[1], argv[0], "block", &err); + if (err) + return; + + if (argc == 3) { + num = parse_ulong(argv[2], argv[0], "num", &err); + if (err) + return; + + ext2fs_unmark_block_bitmap_range2(test_fs->block_map, + block, num); + printf("Clearing blocks %u to %u\n", block, block + num - 1); + return; + } + + test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); + op_result = ext2fs_unmark_block_bitmap2(test_fs->block_map, block); + printf("Clearing block %u, was %s before\n", block, op_result ? + "set" : "clear"); + if (!test_result != !op_result) + com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", + test_result, op_result); +} + +void do_testb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int block, num; + int err; + int test_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2 && argc != 3) { + com_err(argv[0], 0, "Usage: testb [num]"); + return; + } + + block = parse_ulong(argv[1], argv[0], "block", &err); + if (err) + return; + + if (argc == 3) { + num = parse_ulong(argv[2], argv[0], "num", &err); + if (err) + return; + + test_result = + ext2fs_test_block_bitmap_range2(test_fs->block_map, + block, num); + printf("Blocks %u to %u are %sall clear.\n", + block, block + num - 1, test_result ? "" : "NOT "); + return; + } + + test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); + printf("Block %u is %s\n", block, test_result ? "set" : "clear"); +} + +void do_ffzb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int start, end; + int err; + errcode_t retval; + blk64_t out; + + if (check_fs_open(argv[0])) + return; + + if (argc != 3 && argc != 3) { + com_err(argv[0], 0, "Usage: ffzb "); + return; + } + + start = parse_ulong(argv[1], argv[0], "start", &err); + if (err) + return; + + end = parse_ulong(argv[2], argv[0], "end", &err); + if (err) + return; + + retval = ext2fs_find_first_zero_block_bitmap2(test_fs->block_map, + start, end, &out); + if (retval) { + printf("ext2fs_find_first_zero_block_bitmap2() returned %s\n", + error_message(retval)); + return; + } + printf("First unmarked block is %llu\n", (unsigned long long) out); +} + +void do_ffsb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int start, end; + int err; + errcode_t retval; + blk64_t out; + + if (check_fs_open(argv[0])) + return; + + if (argc != 3 && argc != 3) { + com_err(argv[0], 0, "Usage: ffsb "); + return; + } + + start = parse_ulong(argv[1], argv[0], "start", &err); + if (err) + return; + + end = parse_ulong(argv[2], argv[0], "end", &err); + if (err) + return; + + retval = ext2fs_find_first_set_block_bitmap2(test_fs->block_map, + start, end, &out); + if (retval) { + printf("ext2fs_find_first_set_block_bitmap2() returned %s\n", + error_message(retval)); + return; + } + printf("First marked block is %llu\n", (unsigned long long) out); +} + + +void do_zerob(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + + printf("Clearing block bitmap.\n"); + ext2fs_clear_block_bitmap(test_fs->block_map); +} + +void do_seti(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int inode; + int err; + int test_result, op_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2) { + com_err(argv[0], 0, "Usage: seti "); + return; + } + + inode = parse_ulong(argv[1], argv[0], "inode", &err); + if (err) + return; + + test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); + op_result = ext2fs_mark_inode_bitmap2(test_fs->inode_map, inode); + printf("Setting inode %u, was %s before\n", inode, op_result ? + "set" : "clear"); + if (!test_result != !op_result) { + com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", + test_result, op_result); + exit_status++; + } +} + +void do_cleari(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int inode; + int err; + int test_result, op_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2) { + com_err(argv[0], 0, "Usage: clearb "); + return; + } + + inode = parse_ulong(argv[1], argv[0], "inode", &err); + if (err) + return; + + test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); + op_result = ext2fs_unmark_inode_bitmap2(test_fs->inode_map, inode); + printf("Clearing inode %u, was %s before\n", inode, op_result ? + "set" : "clear"); + if (!test_result != !op_result) { + com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", + test_result, op_result); + exit_status++; + } +} + +void do_testi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int inode; + int err; + int test_result; + + if (check_fs_open(argv[0])) + return; + + if (argc != 2) { + com_err(argv[0], 0, "Usage: testb "); + return; + } + + inode = parse_ulong(argv[1], argv[0], "inode", &err); + if (err) + return; + + test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); + printf("Inode %u is %s\n", inode, test_result ? "set" : "clear"); +} + +void do_ffzi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int start, end; + int err; + errcode_t retval; + ext2_ino_t out; + + if (check_fs_open(argv[0])) + return; + + if (argc != 3 && argc != 3) { + com_err(argv[0], 0, "Usage: ffzi "); + return; + } + + start = parse_ulong(argv[1], argv[0], "start", &err); + if (err) + return; + + end = parse_ulong(argv[2], argv[0], "end", &err); + if (err) + return; + + retval = ext2fs_find_first_zero_inode_bitmap2(test_fs->inode_map, + start, end, &out); + if (retval) { + printf("ext2fs_find_first_zero_inode_bitmap2() returned %s\n", + error_message(retval)); + return; + } + printf("First unmarked inode is %u\n", out); +} + +void do_ffsi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + unsigned int start, end; + int err; + errcode_t retval; + ext2_ino_t out; + + if (check_fs_open(argv[0])) + return; + + if (argc != 3 && argc != 3) { + com_err(argv[0], 0, "Usage: ffsi "); + return; + } + + start = parse_ulong(argv[1], argv[0], "start", &err); + if (err) + return; + + end = parse_ulong(argv[2], argv[0], "end", &err); + if (err) + return; + + retval = ext2fs_find_first_set_inode_bitmap2(test_fs->inode_map, + start, end, &out); + if (retval) { + printf("ext2fs_find_first_set_inode_bitmap2() returned %s\n", + error_message(retval)); + return; + } + printf("First marked inode is %u\n", out); +} + +void do_zeroi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + + printf("Clearing inode bitmap.\n"); + ext2fs_clear_inode_bitmap(test_fs->inode_map); +} + +int main(int argc, char **argv) +{ + unsigned int blocks = 128; + unsigned int inodes = 0; + unsigned int type = EXT2FS_BMAP64_BITARRAY; + int c, err, code; + char *request = (char *)NULL; + char *cmd_file = 0; + int sci_idx; + int flags = EXT2_FLAG_64BITS; + + add_error_table(&et_ss_error_table); + add_error_table(&et_ext2_error_table); + while ((c = getopt (argc, argv, "b:i:lt:R:f:")) != EOF) { + switch (c) { + case 'b': + blocks = parse_ulong(optarg, argv[0], + "number of blocks", &err); + if (err) + exit(1); + break; + case 'i': + inodes = parse_ulong(optarg, argv[0], + "number of blocks", &err); + if (err) + exit(1); + break; + case 'l': /* Legacy bitmaps */ + flags = 0; + break; + case 't': + type = parse_ulong(optarg, argv[0], + "bitmap backend type", &err); + if (err) + exit(1); + break; + case 'R': + request = optarg; + break; + case 'f': + cmd_file = optarg; + break; + default: + com_err(argv[0], 0, "Usage: %s [-R request] " + "[-f cmd_file]", subsystem_name); + exit(1); + } + } + + sci_idx = ss_create_invocation(subsystem_name, version, + (char *)NULL, &tst_bitmaps_cmds, &code); + if (code) { + ss_perror(sci_idx, code, "creating invocation"); + exit(1); + } + + (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &code); + if (code) { + ss_perror(sci_idx, code, "adding standard requests"); + exit (1); + } + + printf("%s %s. Type '?' for a list of commands.\n\n", + subsystem_name, version); + + setup_filesystem(argv[0], blocks, inodes, type, flags); + + if (request) { + code = ss_execute_line(sci_idx, request); + if (code) { + ss_perror(sci_idx, code, request); + exit_status++; + } + } else if (cmd_file) { + exit_status = source_file(cmd_file, sci_idx); + } else { + ss_listen(sci_idx); + } + + exit(exit_status); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct new file mode 100755 index 0000000..13b7fa7 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct @@ -0,0 +1,51 @@ +command_table tst_bitmaps_cmds; + +request setup_cmd, "Setup file system", + setup; + +request close_cmd, "Close file system", + close; + +request dump_inode_bitmap_cmd, "Dump the inode bitmap", + dump_inode_bitmap, dump_ib; + +request dump_block_bitmap_cmd, "Dump the block bitmap", + dump_block_bitmap, dump_bb; + +request do_setb, "Set block", + set_block, setb; + +request do_clearb, "Clear block", + clear_block, clearb; + +request do_testb, "Test block", + test_block, testb; + +request do_ffzb, "Find first zero block", + find_first_zero_block, ffzb; + +request do_ffsb, "Find first set block", + find_first_set_block, ffsb; + +request do_zerob, "Clear block bitmap", + clear_block_bitmap, zerob; + +request do_seti, "Set inode", + set_inode, seti; + +request do_cleari, "Clear inode", + clear_inode, cleari; + +request do_testi, "Test inode", + test_inode, testi; + +request do_ffzi, "Find first zero inode", + find_first_zero_inode, ffzi; + +request do_ffsi, "Find first set inode", + find_first_set_inode, ffsi; + +request do_zeroi, "Clear inode bitmap", + clear_inode_bitmap, zeroi; + +end; diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds new file mode 100755 index 0000000..dc116b1 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds @@ -0,0 +1,150 @@ +setb 12 0 +setb 12 +setb 12 +clearb 12 +clearb 12 +setb 12 +setb 14 +setb 16 +testb 13 +testb 15 +testb 12 +testb 14 +setb 13 +setb 15 +testb 12 +testb 11 +testb 15 +testb 16 +dump_bb +ffzb 11 16 +ffzb 12 16 +ffzb 12 20 +ffsb 0 127 +ffsb 1 128 +ffsb 1 127 +ffsb 1 10 +ffsb 1 11 +ffsb 12 12 +ffsb 13 12 +ffsb 12 15 +clearb 13 +ffzb 12 20 +ffsb 13 18 +setb 13 +clearb 12 7 +testb 12 7 +setb 15 +testb 12 7 +clearb 15 +testb 12 7 +setb 12 0 +setb 12 7 +dump_bb +seti 2 +seti 5 +seti 4 +seti 3 +seti 4 +seti 5 +testi 6 +testi 1 +dump_ib +ffzi 1 6 +ffzi 2 5 +ffzi 2 6 +ffsi 0 31 +ffsi 1 33 +ffsi 1 32 +ffsi 2 32 +ffsi 6 32 +cleari 4 +ffzi 2 6 +ffsi 4 32 +ffsi 5 32 +zeroi +testi 5 +seti 5 +seti 5 +cleari 5 +cleari 5 +testi 17 +testi 6 +testi 4 +clearb 7 12 +dump_bb +setb 1 +dump_bb +setb 2 +dump_bb +setb 3 +dump_bb +setb 4 +dump_bb +setb 5 +dump_bb +setb 6 +dump_bb +setb 7 +dump_bb +setb 8 +dump_bb +setb 10 +setb 12 +setb 14 +setb 17 +setb 19 +setb 24 +setb 26 +setb 27 +setb 30 +setb 31 +setb 32 +setb 35 +setb 39 +setb 40 +setb 44 +setb 46 +setb 47 +setb 49 +setb 51 +setb 52 +clearb 2 +clearb 3 +clearb 7 +dump_bb +ffsb 14 127 +ffsb 15 127 +ffsb 36 127 +ffsb 32 127 +ffsb 52 127 +ffsb 53 127 +ffsb 46 127 +ffsb 45 127 +ffsb 41 127 +ffsb 20 127 +ffsb 1 127 +ffsb 2 127 +ffsb 3 127 +ffsb 4 127 +ffsb 5 127 +ffsb 6 127 +ffsb 7 127 +ffsb 8 127 +ffzb 1 127 +ffzb 2 127 +ffzb 3 127 +ffzb 4 127 +ffzb 5 127 +ffzb 6 127 +ffzb 7 127 +ffzb 8 127 +ffzb 45 127 +ffzb 46 127 +ffzb 47 127 +ffzb 48 127 +ffzb 49 127 +ffzb 50 127 +ffzb 51 127 +quit + diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp new file mode 100755 index 0000000..9cfea13 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp @@ -0,0 +1,313 @@ +tst_bitmaps 1.0. Type '?' for a list of commands. + +tst_bitmaps: setb 12 0 +Marking blocks 12 to 11 +tst_bitmaps: setb 12 +Setting block 12, was clear before +tst_bitmaps: setb 12 +Setting block 12, was set before +tst_bitmaps: clearb 12 +Clearing block 12, was set before +tst_bitmaps: clearb 12 +Clearing block 12, was clear before +tst_bitmaps: setb 12 +Setting block 12, was clear before +tst_bitmaps: setb 14 +Setting block 14, was clear before +tst_bitmaps: setb 16 +Setting block 16, was clear before +tst_bitmaps: testb 13 +Block 13 is clear +tst_bitmaps: testb 15 +Block 15 is clear +tst_bitmaps: testb 12 +Block 12 is set +tst_bitmaps: testb 14 +Block 14 is set +tst_bitmaps: setb 13 +Setting block 13, was clear before +tst_bitmaps: setb 15 +Setting block 15, was clear before +tst_bitmaps: testb 12 +Block 12 is set +tst_bitmaps: testb 11 +Block 11 is clear +tst_bitmaps: testb 15 +Block 15 is set +tst_bitmaps: testb 16 +Block 16 is set +tst_bitmaps: dump_bb +block bitmap: 00f80000000000000000000000000000 +bits set: 5 +tst_bitmaps: ffzb 11 16 +First unmarked block is 11 +tst_bitmaps: ffzb 12 16 +ext2fs_find_first_zero_block_bitmap2() returned No such file or directory +tst_bitmaps: ffzb 12 20 +First unmarked block is 17 +tst_bitmaps: ffsb 0 127 +ext2fs_find_first_set_block_bitmap2() returned Invalid argument +tst_bitmaps: ffsb 1 128 +ext2fs_find_first_set_block_bitmap2() returned Invalid argument +tst_bitmaps: ffsb 1 127 +First marked block is 12 +tst_bitmaps: ffsb 1 10 +ext2fs_find_first_set_block_bitmap2() returned No such file or directory +tst_bitmaps: ffsb 1 11 +ext2fs_find_first_set_block_bitmap2() returned No such file or directory +tst_bitmaps: ffsb 12 12 +First marked block is 12 +tst_bitmaps: ffsb 13 12 +ext2fs_find_first_set_block_bitmap2() returned Invalid argument +tst_bitmaps: ffsb 12 15 +First marked block is 12 +tst_bitmaps: clearb 13 +Clearing block 13, was set before +tst_bitmaps: ffzb 12 20 +First unmarked block is 13 +tst_bitmaps: ffsb 13 18 +First marked block is 14 +tst_bitmaps: setb 13 +Setting block 13, was clear before +tst_bitmaps: clearb 12 7 +Clearing blocks 12 to 18 +tst_bitmaps: testb 12 7 +Blocks 12 to 18 are all clear. +tst_bitmaps: setb 15 +Setting block 15, was clear before +tst_bitmaps: testb 12 7 +Blocks 12 to 18 are NOT all clear. +tst_bitmaps: clearb 15 +Clearing block 15, was set before +tst_bitmaps: testb 12 7 +Blocks 12 to 18 are all clear. +tst_bitmaps: setb 12 0 +Marking blocks 12 to 11 +tst_bitmaps: setb 12 7 +Marking blocks 12 to 18 +tst_bitmaps: dump_bb +block bitmap: 00f80300000000000000000000000000 +bits set: 7 +tst_bitmaps: seti 2 +Setting inode 2, was clear before +tst_bitmaps: seti 5 +Setting inode 5, was clear before +tst_bitmaps: seti 4 +Setting inode 4, was clear before +tst_bitmaps: seti 3 +Setting inode 3, was clear before +tst_bitmaps: seti 4 +Setting inode 4, was set before +tst_bitmaps: seti 5 +Setting inode 5, was set before +tst_bitmaps: testi 6 +Inode 6 is clear +tst_bitmaps: testi 1 +Inode 1 is clear +tst_bitmaps: dump_ib +inode bitmap: 1e000000 +bits set: 4 +tst_bitmaps: ffzi 1 6 +First unmarked inode is 1 +tst_bitmaps: ffzi 2 5 +ext2fs_find_first_zero_inode_bitmap2() returned No such file or directory +tst_bitmaps: ffzi 2 6 +First unmarked inode is 6 +tst_bitmaps: ffsi 0 31 +ext2fs_find_first_set_inode_bitmap2() returned Invalid argument +tst_bitmaps: ffsi 1 33 +ext2fs_find_first_set_inode_bitmap2() returned Invalid argument +tst_bitmaps: ffsi 1 32 +First marked inode is 2 +tst_bitmaps: ffsi 2 32 +First marked inode is 2 +tst_bitmaps: ffsi 6 32 +ext2fs_find_first_set_inode_bitmap2() returned No such file or directory +tst_bitmaps: cleari 4 +Clearing inode 4, was set before +tst_bitmaps: ffzi 2 6 +First unmarked inode is 4 +tst_bitmaps: ffsi 4 32 +First marked inode is 5 +tst_bitmaps: ffsi 5 32 +First marked inode is 5 +tst_bitmaps: zeroi +Clearing inode bitmap. +tst_bitmaps: testi 5 +Inode 5 is clear +tst_bitmaps: seti 5 +Setting inode 5, was clear before +tst_bitmaps: seti 5 +Setting inode 5, was set before +tst_bitmaps: cleari 5 +Clearing inode 5, was set before +tst_bitmaps: cleari 5 +Clearing inode 5, was clear before +tst_bitmaps: testi 17 +Inode 17 is clear +tst_bitmaps: testi 6 +Inode 6 is clear +tst_bitmaps: testi 4 +Inode 4 is clear +tst_bitmaps: clearb 7 12 +Clearing blocks 7 to 18 +tst_bitmaps: dump_bb +block bitmap: 00000000000000000000000000000000 +bits set: 0 +tst_bitmaps: setb 1 +Setting block 1, was clear before +tst_bitmaps: dump_bb +block bitmap: 01000000000000000000000000000000 +bits set: 1 +tst_bitmaps: setb 2 +Setting block 2, was clear before +tst_bitmaps: dump_bb +block bitmap: 03000000000000000000000000000000 +bits set: 2 +tst_bitmaps: setb 3 +Setting block 3, was clear before +tst_bitmaps: dump_bb +block bitmap: 07000000000000000000000000000000 +bits set: 3 +tst_bitmaps: setb 4 +Setting block 4, was clear before +tst_bitmaps: dump_bb +block bitmap: 0f000000000000000000000000000000 +bits set: 4 +tst_bitmaps: setb 5 +Setting block 5, was clear before +tst_bitmaps: dump_bb +block bitmap: 1f000000000000000000000000000000 +bits set: 5 +tst_bitmaps: setb 6 +Setting block 6, was clear before +tst_bitmaps: dump_bb +block bitmap: 3f000000000000000000000000000000 +bits set: 6 +tst_bitmaps: setb 7 +Setting block 7, was clear before +tst_bitmaps: dump_bb +block bitmap: 7f000000000000000000000000000000 +bits set: 7 +tst_bitmaps: setb 8 +Setting block 8, was clear before +tst_bitmaps: dump_bb +block bitmap: ff000000000000000000000000000000 +bits set: 8 +tst_bitmaps: setb 10 +Setting block 10, was clear before +tst_bitmaps: setb 12 +Setting block 12, was clear before +tst_bitmaps: setb 14 +Setting block 14, was clear before +tst_bitmaps: setb 17 +Setting block 17, was clear before +tst_bitmaps: setb 19 +Setting block 19, was clear before +tst_bitmaps: setb 24 +Setting block 24, was clear before +tst_bitmaps: setb 26 +Setting block 26, was clear before +tst_bitmaps: setb 27 +Setting block 27, was clear before +tst_bitmaps: setb 30 +Setting block 30, was clear before +tst_bitmaps: setb 31 +Setting block 31, was clear before +tst_bitmaps: setb 32 +Setting block 32, was clear before +tst_bitmaps: setb 35 +Setting block 35, was clear before +tst_bitmaps: setb 39 +Setting block 39, was clear before +tst_bitmaps: setb 40 +Setting block 40, was clear before +tst_bitmaps: setb 44 +Setting block 44, was clear before +tst_bitmaps: setb 46 +Setting block 46, was clear before +tst_bitmaps: setb 47 +Setting block 47, was clear before +tst_bitmaps: setb 49 +Setting block 49, was clear before +tst_bitmaps: setb 51 +Setting block 51, was clear before +tst_bitmaps: setb 52 +Setting block 52, was clear before +tst_bitmaps: clearb 2 +Clearing block 2, was set before +tst_bitmaps: clearb 3 +Clearing block 3, was set before +tst_bitmaps: clearb 7 +Clearing block 7, was set before +tst_bitmaps: dump_bb +block bitmap: b92a85e6c4680d000000000000000000 +bits set: 25 +tst_bitmaps: ffsb 14 127 +First marked block is 14 +tst_bitmaps: ffsb 15 127 +First marked block is 17 +tst_bitmaps: ffsb 36 127 +First marked block is 39 +tst_bitmaps: ffsb 32 127 +First marked block is 32 +tst_bitmaps: ffsb 52 127 +First marked block is 52 +tst_bitmaps: ffsb 53 127 +ext2fs_find_first_set_block_bitmap2() returned No such file or directory +tst_bitmaps: ffsb 46 127 +First marked block is 46 +tst_bitmaps: ffsb 45 127 +First marked block is 46 +tst_bitmaps: ffsb 41 127 +First marked block is 44 +tst_bitmaps: ffsb 20 127 +First marked block is 24 +tst_bitmaps: ffsb 1 127 +First marked block is 1 +tst_bitmaps: ffsb 2 127 +First marked block is 4 +tst_bitmaps: ffsb 3 127 +First marked block is 4 +tst_bitmaps: ffsb 4 127 +First marked block is 4 +tst_bitmaps: ffsb 5 127 +First marked block is 5 +tst_bitmaps: ffsb 6 127 +First marked block is 6 +tst_bitmaps: ffsb 7 127 +First marked block is 8 +tst_bitmaps: ffsb 8 127 +First marked block is 8 +tst_bitmaps: ffzb 1 127 +First unmarked block is 2 +tst_bitmaps: ffzb 2 127 +First unmarked block is 2 +tst_bitmaps: ffzb 3 127 +First unmarked block is 3 +tst_bitmaps: ffzb 4 127 +First unmarked block is 7 +tst_bitmaps: ffzb 5 127 +First unmarked block is 7 +tst_bitmaps: ffzb 6 127 +First unmarked block is 7 +tst_bitmaps: ffzb 7 127 +First unmarked block is 7 +tst_bitmaps: ffzb 8 127 +First unmarked block is 9 +tst_bitmaps: ffzb 45 127 +First unmarked block is 45 +tst_bitmaps: ffzb 46 127 +First unmarked block is 48 +tst_bitmaps: ffzb 47 127 +First unmarked block is 48 +tst_bitmaps: ffzb 48 127 +First unmarked block is 48 +tst_bitmaps: ffzb 49 127 +First unmarked block is 50 +tst_bitmaps: ffzb 50 127 +First unmarked block is 50 +tst_bitmaps: ffzb 51 127 +First unmarked block is 53 +tst_bitmaps: quit +tst_bitmaps: diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitops.c b/jni/e2fsprogs/lib/ext2fs/tst_bitops.c new file mode 100755 index 0000000..adef12d --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_bitops.c @@ -0,0 +1,288 @@ +/* + * This testing program makes sure the bitops functions work + * + * Copyright (C) 2001 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +unsigned char bitarray[] = { + 0x80, 0xF0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x10, 0x20, 0x00, 0x00 + }; + +int bits_list[] = { + 7, 12, 13, 14,15, 22, 30, 68, 77, -1, +}; + +#define BIG_TEST_BIT (((unsigned) 1 << 31) + 42) + + +int main(int argc, char **argv) +{ + int i, j, size; + unsigned char testarray[12]; + unsigned char *bigarray; + + size = sizeof(bitarray)*8; +#if 0 + i = ext2fs_find_first_bit_set(bitarray, size); + while (i < size) { + printf("Bit set: %d\n", i); + i = ext2fs_find_next_bit_set(bitarray, size, i+1); + } +#endif + + /* Test test_bit */ + for (i=0,j=0; i < size; i++) { + if (ext2fs_test_bit(i, bitarray)) { + if (bits_list[j] == i) { + j++; + } else { + printf("Bit %d set, not expected\n", i); + exit(1); + } + } else { + if (bits_list[j] == i) { + printf("Expected bit %d to be clear.\n", i); + exit(1); + } + } + } + printf("ext2fs_test_bit appears to be correct\n"); + + /* Test ext2fs_set_bit */ + memset(testarray, 0, sizeof(testarray)); + for (i=0; bits_list[i] > 0; i++) { + ext2fs_set_bit(bits_list[i], testarray); + } + if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { + printf("ext2fs_set_bit test succeeded.\n"); + } else { + printf("ext2fs_set_bit test failed.\n"); + for (i=0; i < sizeof(testarray); i++) { + printf("%02x ", testarray[i]); + } + printf("\n"); + exit(1); + } + for (i=0; bits_list[i] > 0; i++) { + ext2fs_clear_bit(bits_list[i], testarray); + } + for (i=0; i < sizeof(testarray); i++) { + if (testarray[i]) { + printf("ext2fs_clear_bit failed, " + "testarray[%d] is %d\n", i, testarray[i]); + exit(1); + } + } + printf("ext2fs_clear_bit test succeed.\n"); + + + /* Do bigarray test */ + bigarray = malloc(1 << 29); + if (!bigarray) { + fprintf(stderr, "Failed to allocate scratch memory!\n"); + exit(0); + } + + bigarray[BIG_TEST_BIT >> 3] = 0; + + ext2fs_set_bit(BIG_TEST_BIT, bigarray); + printf("big bit number (%u) test: %d, expected %d\n", BIG_TEST_BIT, + bigarray[BIG_TEST_BIT >> 3], (1 << (BIG_TEST_BIT & 7))); + if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) + exit(1); + + ext2fs_clear_bit(BIG_TEST_BIT, bigarray); + + printf("big bit number (%u) test: %d, expected 0\n", BIG_TEST_BIT, + bigarray[BIG_TEST_BIT >> 3]); + if (bigarray[BIG_TEST_BIT >> 3] != 0) + exit(1); + + printf("ext2fs_set_bit big_test successful\n"); + + + /* Now test ext2fs_fast_set_bit */ + memset(testarray, 0, sizeof(testarray)); + for (i=0; bits_list[i] > 0; i++) { + ext2fs_fast_set_bit(bits_list[i], testarray); + } + if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { + printf("ext2fs_fast_set_bit test succeeded.\n"); + } else { + printf("ext2fs_fast_set_bit test failed.\n"); + for (i=0; i < sizeof(testarray); i++) { + printf("%02x ", testarray[i]); + } + printf("\n"); + exit(1); + } + for (i=0; bits_list[i] > 0; i++) { + ext2fs_clear_bit(bits_list[i], testarray); + } + for (i=0; i < sizeof(testarray); i++) { + if (testarray[i]) { + printf("ext2fs_clear_bit failed, " + "testarray[%d] is %d\n", i, testarray[i]); + exit(1); + } + } + printf("ext2fs_clear_bit test succeed.\n"); + + + bigarray[BIG_TEST_BIT >> 3] = 0; + + ext2fs_fast_set_bit(BIG_TEST_BIT, bigarray); + printf("big bit number (%u) test: %d, expected %d\n", BIG_TEST_BIT, + bigarray[BIG_TEST_BIT >> 3], (1 << (BIG_TEST_BIT & 7))); + if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) + exit(1); + + ext2fs_fast_clear_bit(BIG_TEST_BIT, bigarray); + + printf("big bit number (%u) test: %d, expected 0\n", BIG_TEST_BIT, + bigarray[BIG_TEST_BIT >> 3]); + if (bigarray[BIG_TEST_BIT >> 3] != 0) + exit(1); + + printf("ext2fs_fast_set_bit big_test successful\n"); + + /* Repeat foregoing tests for 64-bit bitops */ + + /* Test test_bit */ + for (i=0,j=0; i < size; i++) { + if (ext2fs_test_bit64(i, bitarray)) { + if (bits_list[j] == i) { + j++; + } else { + printf("64-bit: Bit %d set, not expected\n", + i); + exit(1); + } + } else { + if (bits_list[j] == i) { + printf("64-bit: " + "Expected bit %d to be clear.\n", i); + exit(1); + } + } + } + printf("64-bit: ext2fs_test_bit appears to be correct\n"); + + /* Test ext2fs_set_bit */ + memset(testarray, 0, sizeof(testarray)); + for (i=0; bits_list[i] > 0; i++) { + ext2fs_set_bit64(bits_list[i], testarray); + } + if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { + printf("64-bit: ext2fs_set_bit test succeeded.\n"); + } else { + printf("64-bit: ext2fs_set_bit test failed.\n"); + for (i=0; i < sizeof(testarray); i++) { + printf("%02x ", testarray[i]); + } + printf("\n"); + exit(1); + } + for (i=0; bits_list[i] > 0; i++) { + ext2fs_clear_bit64(bits_list[i], testarray); + } + for (i=0; i < sizeof(testarray); i++) { + if (testarray[i]) { + printf("64-bit: ext2fs_clear_bit failed, " + "testarray[%d] is %d\n", i, testarray[i]); + exit(1); + } + } + printf("64-bit: ext2fs_clear_bit test succeed.\n"); + + /* Do bigarray test */ + bigarray[BIG_TEST_BIT >> 3] = 0; + + ext2fs_set_bit64(BIG_TEST_BIT, bigarray); + printf("64-bit: big bit number (%u) test: %d, expected %d\n", + BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3], + (1 << (BIG_TEST_BIT & 7))); + if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) + exit(1); + + ext2fs_clear_bit64(BIG_TEST_BIT, bigarray); + + printf("64-bit: big bit number (%u) test: %d, expected 0\n", + BIG_TEST_BIT, + bigarray[BIG_TEST_BIT >> 3]); + if (bigarray[BIG_TEST_BIT >> 3] != 0) + exit(1); + + printf("64-bit: ext2fs_set_bit big_test successful\n"); + + /* Now test ext2fs_fast_set_bit */ + memset(testarray, 0, sizeof(testarray)); + for (i=0; bits_list[i] > 0; i++) { + ext2fs_fast_set_bit64(bits_list[i], testarray); + } + if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { + printf("64-bit: ext2fs_fast_set_bit test succeeded.\n"); + } else { + printf("64-bit: ext2fs_fast_set_bit test failed.\n"); + for (i=0; i < sizeof(testarray); i++) { + printf("%02x ", testarray[i]); + } + printf("\n"); + exit(1); + } + for (i=0; bits_list[i] > 0; i++) { + ext2fs_clear_bit64(bits_list[i], testarray); + } + for (i=0; i < sizeof(testarray); i++) { + if (testarray[i]) { + printf("64-bit: ext2fs_clear_bit failed, " + "testarray[%d] is %d\n", i, testarray[i]); + exit(1); + } + } + printf("64-bit: ext2fs_clear_bit test succeed.\n"); + + bigarray[BIG_TEST_BIT >> 3] = 0; + + ext2fs_fast_set_bit64(BIG_TEST_BIT, bigarray); + printf("64-bit: big bit number (%u) test: %d, expected %d\n", + BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3], + (1 << (BIG_TEST_BIT & 7))); + if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) + exit(1); + + ext2fs_fast_clear_bit64(BIG_TEST_BIT, bigarray); + + printf("64-bit: big bit number (%u) test: %d, expected 0\n", + BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3]); + if (bigarray[BIG_TEST_BIT >> 3] != 0) + exit(1); + + printf("64-bit: ext2fs_fast_set_bit big_test successful\n"); + free(bigarray); + exit(0); +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c b/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c new file mode 100755 index 0000000..c500cae --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c @@ -0,0 +1,93 @@ +/* + * This testing program makes sure the byteswap functions work + * + * Copyright (C) 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +__u16 test1[] = { + 0x0001, 0x0100, + 0x1234, 0x3412, + 0xff00, 0x00ff, + 0x4000, 0x0040, + 0xfeff, 0xfffe, + 0x0000, 0x0000 + }; + +__u32 test2[] = { + 0x00000001, 0x01000000, + 0x80000000, 0x00000080, + 0x12345678, 0x78563412, + 0xffff0000, 0x0000ffff, + 0x00ff0000, 0x0000ff00, + 0xff000000, 0x000000ff, + 0x00000000, 0x00000000 + }; + +int main(int argc, char **argv) +{ + int i; + int errors = 0; + + printf("Testing ext2fs_swab16\n"); + i=0; + do { + printf("swab16(0x%04x) = 0x%04x\n", test1[i], + ext2fs_swab16(test1[i])); + if (ext2fs_swab16(test1[i]) != test1[i+1]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab16(test1[i]), test1[i+1]); + errors++; + } + if (ext2fs_swab16(test1[i+1]) != test1[i]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab16(test1[i+1]), test1[i]); + errors++; + } + i += 2; + } while (test1[i] != 0); + + printf("Testing ext2fs_swab32\n"); + i = 0; + do { + printf("swab32(0x%08x) = 0x%08x\n", test2[i], + ext2fs_swab32(test2[i])); + if (ext2fs_swab32(test2[i]) != test2[i+1]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab32(test2[i]), test2[i+1]); + errors++; + } + if (ext2fs_swab32(test2[i+1]) != test2[i]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab32(test2[i+1]), test2[i]); + errors++; + } + i += 2; + } while (test2[i] != 0); + + if (!errors) + printf("No errors found in the byteswap implementation!\n"); + + return errors; +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct b/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct new file mode 100755 index 0000000..45a8594 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct @@ -0,0 +1,6 @@ +command_table libext2fs_cmds; + +request do_block_iterate, "block_iterate", + block_iterate; + +end; diff --git a/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c b/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c new file mode 100755 index 0000000..6f44df1 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c @@ -0,0 +1,81 @@ +/* + * This testing program checks the offset of the ext2_filsys structure + * + * Copyright (C) 2007 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include +#include +#include + +#include "ext2fs.h" + +struct struct_ext2_filsys fs; + +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof (type, member) +#endif +#define check_field(x) cur_offset = do_field(#x, sizeof(fs.x), \ + offsetof(struct struct_ext2_filsys, x), \ + cur_offset) + +static int do_field(const char *field, size_t size, int offset, int cur_offset) +{ + if (offset != cur_offset) { + printf("\t(padding %d bytes?)\n", offset - cur_offset); + } + printf("%8d %-30s %3u\n", offset, field, (unsigned) size); + return offset + size; +} + +int main(int argc, char **argv) +{ +#if (__GNUC__ >= 4) + int cur_offset = 0; + + printf("%8s %-30s %3s\n", "offset", "field", "size"); + check_field(magic); + check_field(io); + check_field(flags); + check_field(device_name); + check_field(super); + check_field(blocksize); + check_field(fragsize); + check_field(group_desc_count); + check_field(desc_blocks); + check_field(group_desc); + check_field(inode_blocks_per_group); + check_field(inode_map); + check_field(block_map); + check_field(get_blocks); + check_field(check_directory); + check_field(write_bitmaps); + check_field(read_inode); + check_field(write_inode); + check_field(badblocks); + check_field(dblist); + check_field(stride); + check_field(orig_super); + check_field(image_header); + check_field(umask); + check_field(now); + check_field(cluster_ratio_bits); + check_field(reserved); + check_field(priv_data); + check_field(icache); + check_field(image_io); + check_field(get_alloc_block); + check_field(block_alloc_stats); + check_field(mmp_buf); + check_field(mmp_cmp); + check_field(mmp_fd); + check_field(mmp_last_written); + printf("Ending offset is %d\n\n", cur_offset); +#endif + exit(0); +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c b/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c new file mode 100755 index 0000000..d616965 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c @@ -0,0 +1,63 @@ +/* + * tst_getsize.c --- this function tests the getsize function + * + * Copyright (C) 1997 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int main(int argc, char **argv) +{ + int lsectsize, psectsize; + int retval; + int fd; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + retval = ext2fs_get_device_sectsize(argv[1], &lsectsize); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_get_device_sectsize"); + exit(1); + } + retval = ext2fs_get_device_phys_sectsize(argv[1], &psectsize); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_get_device_phys_sectsize"); + exit(1); + } + printf("Device %s has logical/physical sector size of %d/%d.\n", + argv[1], lsectsize, psectsize); + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror("open"); + exit(1); + } + printf("The device's DIO alignment is %d\n", + ext2fs_get_dio_alignment(fd)); + close(fd); + exit(0); +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_getsize.c b/jni/e2fsprogs/lib/ext2fs/tst_getsize.c new file mode 100755 index 0000000..ba869dc --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_getsize.c @@ -0,0 +1,47 @@ +/* + * tst_getsize.c --- this function tests the getsize function + * + * Copyright (C) 1997 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int main(int argc, const char *argv[]) +{ + errcode_t retval; + blk64_t blocks; + + if (argc < 2) { + fprintf(stderr, "%s device\n", argv[0]); + exit(1); + } + add_error_table(&et_ext2_error_table); + retval = ext2fs_get_device_size2(argv[1], 1024, &blocks); + if (retval) { + com_err(argv[0], retval, "while getting device size"); + exit(1); + } + printf("%s is device has %llu blocks.\n", argv[1], + (unsigned long long) blocks); + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c b/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c new file mode 100755 index 0000000..cc5d165 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c @@ -0,0 +1,89 @@ +/* + * This testing program makes sure the ext2_inode structure is 1024 bytes long + * + * Copyright (C) 2007 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "ext2_fs.h" + +struct ext2_inode_large inode; + +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof(type, member) +#endif + +#define check_field(x, s) cur_offset = do_field(#x, s, sizeof(inode.x), \ + offsetof(struct ext2_inode_large, x), \ + cur_offset) + +static int do_field(const char *field, unsigned size, unsigned cur_size, + unsigned offset, unsigned cur_offset) +{ + if (size != cur_size) { + printf("error: %s size %u should be %u\n", + field, cur_size, size); + exit(1); + } + if (offset != cur_offset) { + printf("error: %s offset %u should be %u\n", + field, cur_offset, offset); + exit(1); + } + printf("%8d %-30s %3u\n", offset, field, (unsigned) size); + return offset + size; +} + +int main(int argc, char **argv) +{ +#if (__GNUC__ >= 4) + int cur_offset = 0; + + printf("%8s %-30s %3s\n", "offset", "field", "size"); + check_field(i_mode, 2); + check_field(i_uid, 2); + check_field(i_size, 4); + check_field(i_atime, 4); + check_field(i_ctime, 4); + check_field(i_mtime, 4); + check_field(i_dtime, 4); + check_field(i_gid, 2); + check_field(i_links_count, 2); + check_field(i_blocks, 4); + check_field(i_flags, 4); + check_field(osd1.linux1.l_i_version, 4); + check_field(i_block, 15 * 4); + check_field(i_generation, 4); + check_field(i_file_acl, 4); + check_field(i_size_high, 4); + check_field(i_faddr, 4); + check_field(osd2.linux2.l_i_blocks_hi, 2); + check_field(osd2.linux2.l_i_file_acl_high, 2); + check_field(osd2.linux2.l_i_uid_high, 2); + check_field(osd2.linux2.l_i_gid_high, 2); + check_field(osd2.linux2.l_i_checksum_lo, 2); + check_field(osd2.linux2.l_i_reserved, 2); + do_field("Small inode end", 0, 0, cur_offset, 128); + check_field(i_extra_isize, 2); + check_field(i_checksum_hi, 2); + check_field(i_ctime_extra, 4); + check_field(i_mtime_extra, 4); + check_field(i_atime_extra, 4); + check_field(i_crtime, 4); + check_field(i_crtime_extra, 4); + check_field(i_version_hi, 4); + check_field(i_projid, 4); + /* This size will change as new fields are added */ + do_field("Large inode end", 0, 0, cur_offset, sizeof(inode)); +#endif + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_iscan.c b/jni/e2fsprogs/lib/ext2fs/tst_iscan.c new file mode 100755 index 0000000..76aaa9a --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_iscan.c @@ -0,0 +1,227 @@ +/* + * tst_inode.c --- this function tests the inode scan function + * + * Copyright (C) 1996 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +blk64_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 }; + +ext2_filsys test_fs; +ext2fs_block_bitmap bad_block_map, touched_map; +ext2fs_inode_bitmap bad_inode_map; +badblocks_list test_badblocks; + +int first_no_comma = 1; +int failed = 0; + +static void iscan_test_read_blk64(unsigned long long block, int count, errcode_t err) +{ + int i; + + if (first_no_comma) + first_no_comma = 0; + else + printf(", "); + + if (count > 1) + printf("%llu-%llu", block, block+count-1); + else + printf("%llu", block); + + for (i=0; i < count; i++, block++) { + if (ext2fs_test_block_bitmap2(touched_map, block)) { + printf("\nDuplicate block?!? --- %llu\n", block); + failed++; + first_no_comma = 1; + } + ext2fs_mark_block_bitmap2(touched_map, block); + } +} + +static void iscan_test_read_blk(unsigned long block, int count, errcode_t err) +{ + iscan_test_read_blk64(block, count, err); +} + +/* + * Setup the variables for doing the inode scan test. + */ +static void setup(void) +{ + errcode_t retval; + int i; + struct ext2_super_block param; + + initialize_ext2_error_table(); + + memset(¶m, 0, sizeof(param)); + ext2fs_blocks_count_set(¶m, 12000); + + + test_io_cb_read_blk = iscan_test_read_blk; + test_io_cb_read_blk64 = iscan_test_read_blk64; + + retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, + test_io_manager, &test_fs); + if (retval) { + com_err("setup", retval, + "While initializing filesystem"); + exit(1); + } + retval = ext2fs_allocate_tables(test_fs); + if (retval) { + com_err("setup", retval, + "While allocating tables for test filesystem"); + exit(1); + } + retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map", + &bad_block_map); + if (retval) { + com_err("setup", retval, + "While allocating bad_block bitmap"); + exit(1); + } + retval = ext2fs_allocate_block_bitmap(test_fs, "touched map", + &touched_map); + if (retval) { + com_err("setup", retval, + "While allocating touched block bitmap"); + exit(1); + } + retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map", + &bad_inode_map); + if (retval) { + com_err("setup", retval, + "While allocating bad inode bitmap"); + exit(1); + } + + retval = ext2fs_badblocks_list_create(&test_badblocks, 5); + if (retval) { + com_err("setup", retval, "while creating badblocks list"); + exit(1); + } + for (i=0; test_vec[i]; i++) { + retval = ext2fs_badblocks_list_add(test_badblocks, test_vec[i]); + if (retval) { + com_err("setup", retval, + "while adding test vector %d", i); + exit(1); + } + ext2fs_mark_block_bitmap2(bad_block_map, test_vec[i]); + } + test_fs->badblocks = test_badblocks; +} + +/* + * Iterate using inode_scan + */ +static void iterate(void) +{ + struct ext2_inode inode; + ext2_inode_scan scan; + errcode_t retval; + ext2_ino_t ino; + + retval = ext2fs_open_inode_scan(test_fs, 8, &scan); + if (retval) { + com_err("iterate", retval, "While opening inode scan"); + exit(1); + } + printf("Reading blocks: "); + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) { + com_err("iterate", retval, "while reading first inode"); + exit(1); + } + while (ino) { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { + ext2fs_mark_inode_bitmap2(bad_inode_map, ino); + continue; + } + if (retval) { + com_err("iterate", retval, + "while getting next inode"); + exit(1); + } + } + printf("\n"); + ext2fs_close_inode_scan(scan); +} + +/* + * Verify the touched map + */ +static void check_map(void) +{ + int i, j, first=1; + blk64_t blk; + + for (i=0; test_vec[i]; i++) { + if (ext2fs_test_block_bitmap2(touched_map, test_vec[i])) { + printf("Bad block was touched --- %llu\n", + (unsigned long long) test_vec[i]); + failed++; + first_no_comma = 1; + } + ext2fs_mark_block_bitmap2(touched_map, test_vec[i]); + } + for (i = 0; i < test_fs->group_desc_count; i++) { + for (j=0, blk = ext2fs_inode_table_loc(test_fs, i); + j < test_fs->inode_blocks_per_group; + j++, blk++) { + if (!ext2fs_test_block_bitmap2(touched_map, blk) && + !ext2fs_test_block_bitmap2(bad_block_map, blk)) { + printf("Missing block --- %llu\n", + (unsigned long long) blk); + failed++; + } + } + } + printf("Bad inodes: "); + for (i=1; i <= test_fs->super->s_inodes_count; i++) { + if (ext2fs_test_inode_bitmap2(bad_inode_map, i)) { + if (first) + first = 0; + else + printf(", "); + printf("%u", i); + } + } + printf("\n"); +} + + +int main(int argc, char **argv) +{ + setup(); + iterate(); + check_map(); + if (!failed) + printf("Inode scan tested OK!\n"); + return failed; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c b/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c new file mode 100755 index 0000000..4c86464 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c @@ -0,0 +1,72 @@ +/* + * tst_libext2fs.c + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +#include "ss/ss.h" +#include "debugfs.h" + +/* + * Hook in new commands into debugfs + * Override debugfs's prompt + */ +const char *debug_prog_name = "tst_libext2fs"; +extern ss_request_table libext2fs_cmds; +ss_request_table *extra_cmds = &libext2fs_cmds; + +static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *blocknr, e2_blkcnt_t blockcnt, + blk64_t ref_block, int ref_offset, + void *private EXT2FS_ATTR((unused))) +{ + printf("%6lld %8llu (%d %llu)\n", (long long) blockcnt, + (unsigned long long) *blocknr, ref_offset, + (unsigned long long) ref_block); + return 0; +} + + +void do_block_iterate(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + const char *usage = "block_iterate 2) { + flags = parse_ulong(argv[2], argv[0], "flags", &err); + if (err) + return; + } + flags |= BLOCK_FLAG_READ_ONLY; + + ext2fs_block_iterate3(current_fs, ino, flags, NULL, + print_blocks_proc, NULL); + putc('\n', stdout); +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_super_size.c b/jni/e2fsprogs/lib/ext2fs/tst_super_size.c new file mode 100755 index 0000000..80a5269 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_super_size.c @@ -0,0 +1,160 @@ +/* + * This testing program makes sure superblock size is 1024 bytes long + * + * Copyright (C) 2007 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "ext2_fs.h" + +#define sb_struct ext2_super_block +#define sb_struct_name "ext2_super_block" + +struct sb_struct sb; + +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof (type, member) +#endif + +#define check_field(x, s) cur_offset = do_field(#x, s, sizeof(sb.x), \ + offsetof(struct sb_struct, x), \ + cur_offset) + +static int do_field(const char *field, unsigned size, unsigned cur_size, + unsigned offset, unsigned cur_offset) +{ + if (size != cur_size) { + printf("error: %s size %u should be %u\n", + field, cur_size, size); + exit(1); + } + if (offset != cur_offset) { + printf("error: %s offset %u should be %u\n", + field, cur_offset, offset); + exit(1); + } + printf("%8d %-30s %3u\n", offset, field, size); + return offset + size; +} + +int main(int argc, char **argv) +{ +#if (__GNUC__ >= 4) + int cur_offset = 0; + + printf("%8s %-30s %3s\n", "offset", "field", "size"); + check_field(s_inodes_count, 4); + check_field(s_blocks_count, 4); + check_field(s_r_blocks_count, 4); + check_field(s_free_blocks_count, 4); + check_field(s_free_inodes_count, 4); + check_field(s_first_data_block, 4); + check_field(s_log_block_size, 4); + check_field(s_log_cluster_size, 4); + check_field(s_blocks_per_group, 4); + check_field(s_clusters_per_group, 4); + check_field(s_inodes_per_group, 4); + check_field(s_mtime, 4); + check_field(s_wtime, 4); + check_field(s_mnt_count, 2); + check_field(s_max_mnt_count, 2); + check_field(s_magic, 2); + check_field(s_state, 2); + check_field(s_errors, 2); + check_field(s_minor_rev_level, 2); + check_field(s_lastcheck, 4); + check_field(s_checkinterval, 4); + check_field(s_creator_os, 4); + check_field(s_rev_level, 4); + check_field(s_def_resuid, 2); + check_field(s_def_resgid, 2); + check_field(s_first_ino, 4); + check_field(s_inode_size, 2); + check_field(s_block_group_nr, 2); + check_field(s_feature_compat, 4); + check_field(s_feature_incompat, 4); + check_field(s_feature_ro_compat, 4); + check_field(s_uuid, 16); + check_field(s_volume_name, 16); + check_field(s_last_mounted, 64); + check_field(s_algorithm_usage_bitmap, 4); + check_field(s_prealloc_blocks, 1); + check_field(s_prealloc_dir_blocks, 1); + check_field(s_reserved_gdt_blocks, 2); + check_field(s_journal_uuid, 16); + check_field(s_journal_inum, 4); + check_field(s_journal_dev, 4); + check_field(s_last_orphan, 4); + check_field(s_hash_seed, 4 * 4); + check_field(s_def_hash_version, 1); + check_field(s_jnl_backup_type, 1); + check_field(s_desc_size, 2); + check_field(s_default_mount_opts, 4); + check_field(s_first_meta_bg, 4); + check_field(s_mkfs_time, 4); + check_field(s_jnl_blocks, 17 * 4); + check_field(s_blocks_count_hi, 4); + check_field(s_r_blocks_count_hi, 4); + check_field(s_free_blocks_hi, 4); + check_field(s_min_extra_isize, 2); + check_field(s_want_extra_isize, 2); + check_field(s_flags, 4); + check_field(s_raid_stride, 2); + check_field(s_mmp_update_interval, 2); + check_field(s_mmp_block, 8); + check_field(s_raid_stripe_width, 4); + check_field(s_log_groups_per_flex, 1); + check_field(s_checksum_type, 1); + check_field(s_encryption_level, 1); + check_field(s_reserved_pad, 1); + check_field(s_kbytes_written, 8); + check_field(s_snapshot_inum, 4); + check_field(s_snapshot_id, 4); + check_field(s_snapshot_r_blocks_count, 8); + check_field(s_snapshot_list, 4); + check_field(s_error_count, 4); + check_field(s_first_error_time, 4); + check_field(s_first_error_ino, 4); + check_field(s_first_error_block, 8); + check_field(s_first_error_func, 32); + check_field(s_first_error_line, 4); + check_field(s_last_error_time, 4); + check_field(s_last_error_ino, 4); + check_field(s_last_error_line, 4); + check_field(s_last_error_block, 8); + check_field(s_last_error_func, 32); + check_field(s_mount_opts, 64); + check_field(s_usr_quota_inum, 4); + check_field(s_grp_quota_inum, 4); + check_field(s_overhead_clusters, 4); + check_field(s_backup_bgs, 8); + check_field(s_encrypt_algos, 4); + check_field(s_encrypt_pw_salt, 16); + check_field(s_lpf_ino, 4); + check_field(s_prj_quota_inum, 4); + check_field(s_checksum_seed, 4); + check_field(s_wtime_hi, 1); + check_field(s_mtime_hi, 1); + check_field(s_mkfs_time_hi, 1); + check_field(s_lastcheck_hi, 1); + check_field(s_first_error_time_hi, 1); + check_field(s_last_error_time_hi, 1); + check_field(s_first_error_errcode, 1); + check_field(s_last_error_errcode, 1); + check_field(s_encoding, 2); + check_field(s_encoding_flags, 2); + check_field(s_reserved, 95 * 4); + check_field(s_checksum, 4); + do_field("Superblock end", 0, 0, cur_offset, 1024); +#endif + return 0; +} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_types.c b/jni/e2fsprogs/lib/ext2fs/tst_types.c new file mode 100755 index 0000000..3e41128 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/tst_types.c @@ -0,0 +1,64 @@ +/* + * This testing program makes sure the ext2_types header file + * + * Copyright (C) 2006 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include + +#include "ext2fs/ext2_types.h" + +int main(int argc, char **argv) +{ + if (sizeof(__u8) != 1) { + printf("Sizeof(__u8) is %d should be 1\n", + (int)sizeof(__u8)); + exit(1); + } + if (sizeof(__s8) != 1) { + printf("Sizeof(_s8) is %d should be 1\n", + (int)sizeof(__s8)); + exit(1); + } + if (sizeof(__u16) != 2) { + printf("Sizeof(__u16) is %d should be 2\n", + (int)sizeof(__u16)); + exit(1); + } + if (sizeof(__s16) != 2) { + printf("Sizeof(__s16) is %d should be 2\n", + (int)sizeof(__s16)); + exit(1); + } + if (sizeof(__u32) != 4) { + printf("Sizeof(__u32) is %d should be 4\n", + (int)sizeof(__u32)); + exit(1); + } + if (sizeof(__s32) != 4) { + printf("Sizeof(__s32) is %d should be 4\n", + (int)sizeof(__s32)); + exit(1); + } + if (sizeof(__u64) != 8) { + printf("Sizeof(__u64) is %d should be 8\n", + (int)sizeof(__u64)); + exit(1); + } + if (sizeof(__s64) != 8) { + printf("Sizeof(__s64) is %d should be 8\n", + (int)sizeof(__s64)); + exit(1); + } + printf("The ext2_types.h types are correct.\n"); + exit(0); +} + diff --git a/jni/e2fsprogs/lib/ext2fs/undo_io.c b/jni/e2fsprogs/lib/ext2fs/undo_io.c new file mode 100755 index 0000000..f4a6d52 --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/undo_io.c @@ -0,0 +1,1108 @@ +/* + * undo_io.c --- This is the undo io manager that copies the old data that + * copies the old data being overwritten into a tdb database + * + * Copyright IBM Corporation, 2007 + * Author Aneesh Kumar K.V + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef __linux__ +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +#ifdef __GNUC__ +#define ATTR(x) __attribute__(x) +#else +#define ATTR(x) +#endif + +#undef DEBUG + +#ifdef DEBUG +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) +#else +# define dbg_printf(f, a...) +#endif + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) +/* + * Undo file format: The file is cut up into undo_header.block_size blocks. + * The first block contains the header. + * The second block contains the superblock. + * There is then a repeating series of blocks as follows: + * A key block, which contains undo_keys to map the following data blocks. + * Data blocks + * (Note that there are pointers to the first key block and the sb, so this + * order isn't strictly necessary.) + */ +#define E2UNDO_MAGIC "E2UNDO02" +#define KEYBLOCK_MAGIC 0xCADECADE + +#define E2UNDO_STATE_FINISHED 0x1 /* undo file is complete */ + +#define E2UNDO_MIN_BLOCK_SIZE 1024 /* undo blocks are no less than 1KB */ +#define E2UNDO_MAX_BLOCK_SIZE 1048576 /* undo blocks are no more than 1MB */ + +struct undo_header { + char magic[8]; /* "E2UNDO02" */ + __le64 num_keys; /* how many keys? */ + __le64 super_offset; /* where in the file is the superblock copy? */ + __le64 key_offset; /* where do the key/data block chunks start? */ + __le32 block_size; /* block size of the undo file */ + __le32 fs_block_size; /* block size of the target device */ + __le32 sb_crc; /* crc32c of the superblock */ + __le32 state; /* e2undo state flags */ + __le32 f_compat; /* compatible features */ + __le32 f_incompat; /* incompatible features (none so far) */ + __le32 f_rocompat; /* ro compatible features (none so far) */ + __le32 pad32; /* padding for fs_offset */ + __le64 fs_offset; /* filesystem offset */ + __u8 padding[436]; /* padding */ + __le32 header_crc; /* crc32c of this header (but not this field) */ +}; + +#define E2UNDO_MAX_EXTENT_BLOCKS 512 /* max extent size, in blocks */ + +struct undo_key { + __le64 fsblk; /* where in the fs does the block go */ + __le32 blk_crc; /* crc32c of the block */ + __le32 size; /* how many bytes in this block? */ +}; + +struct undo_key_block { + __le32 magic; /* KEYBLOCK_MAGIC number */ + __le32 crc; /* block checksum */ + __le64 reserved; /* zero */ + +#if __STDC_VERSION__ >= 199901L + struct undo_key keys[]; /* keys, which come immediately after */ +#else + struct undo_key keys[0]; /* keys, which come immediately after */ +#endif +}; + +struct undo_private_data { + int magic; + + /* the undo file io channel */ + io_channel undo_file; + blk64_t undo_blk_num; /* next free block */ + blk64_t key_blk_num; /* current key block location */ + blk64_t super_blk_num; /* superblock location */ + blk64_t first_key_blk; /* first key block location */ + struct undo_key_block *keyb; + size_t num_keys, keys_in_block; + + /* The backing io channel */ + io_channel real; + + unsigned long long tdb_data_size; + int tdb_written; + + /* to support offset in unix I/O manager */ + ext2_loff_t offset; + + ext2fs_block_bitmap written_block_map; + struct struct_ext2_filsys fake_fs; + char *tdb_file; + struct undo_header hdr; +}; +#define KEYS_PER_BLOCK(d) (((d)->tdb_data_size / sizeof(struct undo_key)) - 1) + +#define E2UNDO_FEATURE_COMPAT_FS_OFFSET 0x1 /* the filesystem offset */ + +static inline void e2undo_set_feature_fs_offset(struct undo_header *header) { + header->f_compat |= ext2fs_le32_to_cpu(E2UNDO_FEATURE_COMPAT_FS_OFFSET); +} + +static inline void e2undo_clear_feature_fs_offset(struct undo_header *header) { + header->f_compat &= ~ext2fs_le32_to_cpu(E2UNDO_FEATURE_COMPAT_FS_OFFSET); +} + +static io_manager undo_io_backing_manager; +static char *tdb_file; +static int actual_size; + +errcode_t set_undo_io_backing_manager(io_manager manager) +{ + /* + * We may want to do some validation later + */ + undo_io_backing_manager = manager; + return 0; +} + +errcode_t set_undo_io_backup_file(char *file_name) +{ + tdb_file = strdup(file_name); + + if (tdb_file == NULL) { + return EXT2_ET_NO_MEMORY; + } + + return 0; +} + +static errcode_t write_undo_indexes(struct undo_private_data *data, int flush) +{ + errcode_t retval; + struct ext2_super_block super; + io_channel channel; + int block_size; + __u32 sb_crc, hdr_crc; + + /* Spit out a key block, if there's any data */ + if (data->keys_in_block) { + data->keyb->magic = ext2fs_cpu_to_le32(KEYBLOCK_MAGIC); + data->keyb->crc = 0; + data->keyb->crc = ext2fs_cpu_to_le32( + ext2fs_crc32c_le(~0, + (unsigned char *)data->keyb, + data->tdb_data_size)); + dbg_printf("Writing keyblock to blk %llu\n", data->key_blk_num); + retval = io_channel_write_blk64(data->undo_file, + data->key_blk_num, + 1, data->keyb); + if (retval) + return retval; + /* Move on to the next key block if it's full. */ + if (data->keys_in_block == KEYS_PER_BLOCK(data)) { + memset(data->keyb, 0, data->tdb_data_size); + data->keys_in_block = 0; + data->key_blk_num = data->undo_blk_num; + data->undo_blk_num++; + } + } + + /* Prepare superblock for write */ + channel = data->real; + block_size = channel->block_size; + + io_channel_set_blksize(channel, SUPERBLOCK_OFFSET); + retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super); + if (retval) + goto err_out; + sb_crc = ext2fs_crc32c_le(~0, (unsigned char *)&super, SUPERBLOCK_SIZE); + super.s_magic = ~super.s_magic; + + /* Write the undo header to disk. */ + memcpy(data->hdr.magic, E2UNDO_MAGIC, sizeof(data->hdr.magic)); + data->hdr.num_keys = ext2fs_cpu_to_le64(data->num_keys); + data->hdr.super_offset = ext2fs_cpu_to_le64(data->super_blk_num); + data->hdr.key_offset = ext2fs_cpu_to_le64(data->first_key_blk); + data->hdr.fs_block_size = ext2fs_cpu_to_le32(block_size); + data->hdr.sb_crc = ext2fs_cpu_to_le32(sb_crc); + data->hdr.fs_offset = ext2fs_cpu_to_le64(data->offset); + if (data->offset) + e2undo_set_feature_fs_offset(&data->hdr); + else + e2undo_clear_feature_fs_offset(&data->hdr); + hdr_crc = ext2fs_crc32c_le(~0, (unsigned char *)&data->hdr, + sizeof(data->hdr) - + sizeof(data->hdr.header_crc)); + data->hdr.header_crc = ext2fs_cpu_to_le32(hdr_crc); + retval = io_channel_write_blk64(data->undo_file, 0, + -(int)sizeof(data->hdr), + &data->hdr); + if (retval) + goto err_out; + + /* + * Record the entire superblock (in FS byte order) so that we can't + * apply e2undo files to the wrong FS or out of order. + */ + dbg_printf("Writing superblock to block %llu\n", data->super_blk_num); + retval = io_channel_write_blk64(data->undo_file, data->super_blk_num, + -SUPERBLOCK_SIZE, &super); + if (retval) + goto err_out; + + if (flush) + retval = io_channel_flush(data->undo_file); +err_out: + io_channel_set_blksize(channel, block_size); + return retval; +} + +static errcode_t undo_setup_tdb(struct undo_private_data *data) +{ + int i; + errcode_t retval; + + if (data->tdb_written == 1) + return 0; + + data->tdb_written = 1; + + /* Make a bitmap to track what we've written */ + memset(&data->fake_fs, 0, sizeof(data->fake_fs)); + data->fake_fs.blocksize = data->tdb_data_size; + retval = ext2fs_alloc_generic_bmap(&data->fake_fs, + EXT2_ET_MAGIC_BLOCK_BITMAP64, + EXT2FS_BMAP64_RBTREE, + 0, ~1ULL, ~1ULL, + "undo block map", &data->written_block_map); + if (retval) + return retval; + + /* Allocate key block */ + retval = ext2fs_get_mem(data->tdb_data_size, &data->keyb); + if (retval) + return retval; + data->key_blk_num = data->first_key_blk; + + /* Record block size */ + dbg_printf("Undo block size %llu\n", data->tdb_data_size); + dbg_printf("Keys per block %llu\n", KEYS_PER_BLOCK(data)); + data->hdr.block_size = ext2fs_cpu_to_le32(data->tdb_data_size); + io_channel_set_blksize(data->undo_file, data->tdb_data_size); + + /* Ensure that we have space for header blocks */ + for (i = 0; i <= 2; i++) { + retval = io_channel_read_blk64(data->undo_file, i, 1, + data->keyb); + if (retval) + memset(data->keyb, 0, data->tdb_data_size); + retval = io_channel_write_blk64(data->undo_file, i, 1, + data->keyb); + if (retval) + return retval; + retval = io_channel_flush(data->undo_file); + if (retval) + return retval; + } + memset(data->keyb, 0, data->tdb_data_size); + return 0; +} + +static errcode_t undo_write_tdb(io_channel channel, + unsigned long long block, int count) + +{ + int size, sz; + unsigned long long block_num, backing_blk_num; + errcode_t retval = 0; + ext2_loff_t offset; + struct undo_private_data *data; + unsigned char *read_ptr; + unsigned long long end_block; + unsigned long long data_size; + struct undo_key *key; + __u32 blk_crc; + + data = (struct undo_private_data *) channel->private_data; + + if (data->undo_file == NULL) { + /* + * Transaction database not initialized + */ + return 0; + } + + if (count == 1) + size = channel->block_size; + else { + if (count < 0) + size = -count; + else + size = count * channel->block_size; + } + + retval = undo_setup_tdb(data); + if (retval) + return retval; + /* + * Data is stored in tdb database as blocks of tdb_data_size size + * This helps in efficient lookup further. + * + * We divide the disk to blocks of tdb_data_size. + */ + offset = (block * channel->block_size) + data->offset ; + block_num = offset / data->tdb_data_size; + end_block = (offset + size - 1) / data->tdb_data_size; + + while (block_num <= end_block) { + __u32 keysz; + + /* + * Check if we have the record already + */ + if (ext2fs_test_block_bitmap2(data->written_block_map, + block_num)) { + /* Try the next block */ + block_num++; + continue; + } + ext2fs_mark_block_bitmap2(data->written_block_map, block_num); + + /* + * Read one block using the backing I/O manager + * The backing I/O manager block size may be + * different from the tdb_data_size. + * Also we need to recalculate the block number with respect + * to the backing I/O manager. + */ + offset = block_num * data->tdb_data_size + + (data->offset % data->tdb_data_size); + backing_blk_num = (offset - data->offset) / channel->block_size; + + retval = ext2fs_get_mem(data->tdb_data_size, &read_ptr); + if (retval) { + return retval; + } + + memset(read_ptr, 0, data->tdb_data_size); + actual_size = 0; + if ((data->tdb_data_size % channel->block_size) == 0) + sz = data->tdb_data_size / channel->block_size; + else + sz = -data->tdb_data_size; + retval = io_channel_read_blk64(data->real, backing_blk_num, + sz, read_ptr); + if (retval) { + if (retval != EXT2_ET_SHORT_READ) { + free(read_ptr); + return retval; + } + /* + * short read so update the record size + * accordingly + */ + data_size = actual_size; + } else { + data_size = data->tdb_data_size; + } + if (data_size == 0) { + free(read_ptr); + block_num++; + continue; + } + dbg_printf("Read %llu bytes from FS block %llu (blk=%llu cnt=%llu)\n", + data_size, backing_blk_num, block, data->tdb_data_size); + if ((data_size % data->undo_file->block_size) == 0) + sz = data_size / data->undo_file->block_size; + else + sz = -data_size;; + /* extend this key? */ + if (data->keys_in_block) { + key = data->keyb->keys + data->keys_in_block - 1; + keysz = ext2fs_le32_to_cpu(key->size); + } else { + key = NULL; + keysz = 0; + } + if (key != NULL && + (ext2fs_le64_to_cpu(key->fsblk) * channel->block_size + + channel->block_size - 1 + + keysz) / channel->block_size == backing_blk_num && + E2UNDO_MAX_EXTENT_BLOCKS * data->tdb_data_size > + keysz + data_size) { + blk_crc = ext2fs_le32_to_cpu(key->blk_crc); + blk_crc = ext2fs_crc32c_le(blk_crc, read_ptr, data_size); + key->blk_crc = ext2fs_cpu_to_le32(blk_crc); + key->size = ext2fs_cpu_to_le32(keysz + data_size); + } else { + data->num_keys++; + key = data->keyb->keys + data->keys_in_block; + data->keys_in_block++; + key->fsblk = ext2fs_cpu_to_le64(backing_blk_num); + blk_crc = ext2fs_crc32c_le(~0, read_ptr, data_size); + key->blk_crc = ext2fs_cpu_to_le32(blk_crc); + key->size = ext2fs_cpu_to_le32(data_size); + } + dbg_printf("Writing block %llu to offset %llu size %d key %zu\n", + block_num, + data->undo_blk_num, + sz, data->num_keys - 1); + retval = io_channel_write_blk64(data->undo_file, + data->undo_blk_num, sz, read_ptr); + if (retval) { + free(read_ptr); + return retval; + } + data->undo_blk_num++; + free(read_ptr); + + /* Write out the key block */ + retval = write_undo_indexes(data, 0); + if (retval) + return retval; + + /* Next block */ + block_num++; + } + + return retval; +} + +static errcode_t undo_io_read_error(io_channel channel ATTR((unused)), + unsigned long block ATTR((unused)), + int count ATTR((unused)), + void *data ATTR((unused)), + size_t size ATTR((unused)), + int actual, + errcode_t error ATTR((unused))) +{ + actual_size = actual; + return error; +} + +static void undo_err_handler_init(io_channel channel) +{ + channel->read_error = undo_io_read_error; +} + +static int check_filesystem(struct undo_header *hdr, io_channel undo_file, + unsigned int blocksize, blk64_t super_block, + io_channel channel) +{ + struct ext2_super_block super, *sb; + char *buf; + __u32 sb_crc; + errcode_t retval; + + io_channel_set_blksize(channel, SUPERBLOCK_OFFSET); + retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super); + if (retval) + return retval; + + /* + * Compare the FS and the undo file superblock so that we don't + * append to something that doesn't match this FS. + */ + retval = ext2fs_get_mem(blocksize, &buf); + if (retval) + return retval; + retval = io_channel_read_blk64(undo_file, super_block, + -SUPERBLOCK_SIZE, buf); + if (retval) + goto out; + sb = (struct ext2_super_block *)buf; + sb->s_magic = ~sb->s_magic; + if (memcmp(&super, buf, sizeof(super))) { + retval = -1; + goto out; + } + sb_crc = ext2fs_crc32c_le(~0, (unsigned char *)buf, SUPERBLOCK_SIZE); + if (ext2fs_le32_to_cpu(hdr->sb_crc) != sb_crc) { + retval = -1; + goto out; + } + +out: + ext2fs_free_mem(&buf); + return retval; +} + +/* + * Try to re-open the undo file, so that we can resume where we left off. + * That way, the user can pass the same undo file to various programs as + * part of an FS upgrade instead of having to create multiple files and + * then apply them in correct order. + */ +static errcode_t try_reopen_undo_file(int undo_fd, + struct undo_private_data *data) +{ + struct undo_header hdr; + struct undo_key *dkey; + ext2fs_struct_stat statbuf; + unsigned int blocksize, fs_blocksize; + blk64_t super_block, lblk; + size_t num_keys, keys_per_block, i; + __u32 hdr_crc, key_crc; + errcode_t retval; + + /* Zero size already? */ + retval = ext2fs_fstat(undo_fd, &statbuf); + if (retval) + goto bad_file; + if (statbuf.st_size == 0) + goto out; + + /* check the file header */ + retval = io_channel_read_blk64(data->undo_file, 0, -(int)sizeof(hdr), + &hdr); + if (retval) + goto bad_file; + + if (memcmp(hdr.magic, E2UNDO_MAGIC, + sizeof(hdr.magic))) + goto bad_file; + hdr_crc = ext2fs_crc32c_le(~0, (unsigned char *)&hdr, + sizeof(struct undo_header) - + sizeof(__u32)); + if (ext2fs_le32_to_cpu(hdr.header_crc) != hdr_crc) + goto bad_file; + blocksize = ext2fs_le32_to_cpu(hdr.block_size); + fs_blocksize = ext2fs_le32_to_cpu(hdr.fs_block_size); + if (blocksize > E2UNDO_MAX_BLOCK_SIZE || + blocksize < E2UNDO_MIN_BLOCK_SIZE || + !blocksize || !fs_blocksize) + goto bad_file; + super_block = ext2fs_le64_to_cpu(hdr.super_offset); + num_keys = ext2fs_le64_to_cpu(hdr.num_keys); + io_channel_set_blksize(data->undo_file, blocksize); + /* + * Do not compare hdr.f_compat with the available compatible + * features set, because a "missing" compatible feature should + * not cause any problems. + */ + if (hdr.f_incompat || hdr.f_rocompat) + goto bad_file; + + /* Superblock matches this FS? */ + if (check_filesystem(&hdr, data->undo_file, blocksize, super_block, + data->real) != 0) { + retval = EXT2_ET_UNDO_FILE_WRONG; + goto out; + } + + /* Try to set ourselves up */ + data->tdb_data_size = blocksize; + retval = undo_setup_tdb(data); + if (retval) + goto bad_file; + data->num_keys = num_keys; + data->super_blk_num = super_block; + data->first_key_blk = ext2fs_le64_to_cpu(hdr.key_offset); + + /* load the written block map */ + keys_per_block = KEYS_PER_BLOCK(data); + lblk = data->first_key_blk; + dbg_printf("nr_keys=%lu, kpb=%zu, blksz=%u\n", + num_keys, keys_per_block, blocksize); + for (i = 0; i < num_keys; i += keys_per_block) { + size_t j, max_j; + __le32 crc; + + data->key_blk_num = lblk; + retval = io_channel_read_blk64(data->undo_file, + lblk, 1, data->keyb); + if (retval) + goto bad_key_replay; + + /* check keys */ + if (ext2fs_le32_to_cpu(data->keyb->magic) != KEYBLOCK_MAGIC) { + retval = EXT2_ET_UNDO_FILE_CORRUPT; + goto bad_key_replay; + } + crc = data->keyb->crc; + data->keyb->crc = 0; + key_crc = ext2fs_crc32c_le(~0, (unsigned char *)data->keyb, + blocksize); + if (ext2fs_le32_to_cpu(crc) != key_crc) { + retval = EXT2_ET_UNDO_FILE_CORRUPT; + goto bad_key_replay; + } + + /* load keys from key block */ + lblk++; + max_j = data->num_keys - i; + if (max_j > keys_per_block) + max_j = keys_per_block; + for (j = 0, dkey = data->keyb->keys; + j < max_j; + j++, dkey++) { + blk64_t fsblk = ext2fs_le64_to_cpu(dkey->fsblk); + blk64_t undo_blk = fsblk * fs_blocksize / blocksize; + size_t size = ext2fs_le32_to_cpu(dkey->size); + + ext2fs_mark_block_bitmap_range2(data->written_block_map, + undo_blk, + (size + blocksize - 1) / blocksize); + lblk += (size + blocksize - 1) / blocksize; + data->undo_blk_num = lblk; + data->keys_in_block = j + 1; + } + } + dbg_printf("Reopen undo, keyblk=%llu undoblk=%llu nrkeys=%zu kib=%zu\n", + data->key_blk_num, data->undo_blk_num, data->num_keys, + data->keys_in_block); + + data->hdr.state = hdr.state & ~E2UNDO_STATE_FINISHED; + data->hdr.f_compat = hdr.f_compat; + data->hdr.f_incompat = hdr.f_incompat; + data->hdr.f_rocompat = hdr.f_rocompat; + return retval; + +bad_key_replay: + data->key_blk_num = data->undo_blk_num = 0; + data->keys_in_block = 0; + ext2fs_free_mem(&data->keyb); + ext2fs_free_generic_bitmap(data->written_block_map); + data->tdb_written = 0; + goto out; +bad_file: + retval = EXT2_ET_UNDO_FILE_CORRUPT; +out: + return retval; +} + +static void undo_atexit(void *p) +{ + struct undo_private_data *data = p; + errcode_t err; + + err = write_undo_indexes(data, 1); + io_channel_close(data->undo_file); + + com_err(data->tdb_file, err, "while force-closing undo file"); +} + +static errcode_t undo_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct undo_private_data *data = NULL; + int undo_fd = -1; + errcode_t retval; + + /* We don't support multi-threading, at least for now */ + flags &= ~IO_FLAG_THREADS; + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + goto cleanup; + memset(io, 0, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + retval = ext2fs_get_mem(sizeof(struct undo_private_data), &data); + if (retval) + goto cleanup; + + io->manager = undo_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + memset(data, 0, sizeof(struct undo_private_data)); + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; + data->super_blk_num = 1; + data->first_key_blk = 2; + data->undo_blk_num = 3; + + if (undo_io_backing_manager) { + retval = undo_io_backing_manager->open(name, flags, + &data->real); + if (retval) + goto cleanup; + + data->tdb_file = strdup(tdb_file); + if (data->tdb_file == NULL) + goto cleanup; + undo_fd = ext2fs_open_file(data->tdb_file, O_RDWR | O_CREAT, + 0600); + if (undo_fd < 0) + goto cleanup; + + retval = undo_io_backing_manager->open(data->tdb_file, + IO_FLAG_RW, + &data->undo_file); + if (retval) + goto cleanup; + } else { + data->real = NULL; + data->undo_file = NULL; + } + + if (data->real) + io->flags = (io->flags & ~CHANNEL_FLAGS_DISCARD_ZEROES) | + (data->real->flags & CHANNEL_FLAGS_DISCARD_ZEROES); + + /* + * setup err handler for read so that we know + * when the backing manager fails do short read + */ + if (data->real) + undo_err_handler_init(data->real); + + if (data->undo_file) { + retval = try_reopen_undo_file(undo_fd, data); + if (retval) + goto cleanup; + } + retval = ext2fs_add_exit_fn(undo_atexit, data); + if (retval) + goto cleanup; + + *channel = io; + if (undo_fd >= 0) + close(undo_fd); + return retval; + +cleanup: + ext2fs_remove_exit_fn(undo_atexit, data); + if (undo_fd >= 0) + close(undo_fd); + if (data && data->undo_file) + io_channel_close(data->undo_file); + if (data && data->tdb_file) + free(data->tdb_file); + if (data && data->real) + io_channel_close(data->real); + if (data) + ext2fs_free_mem(&data); + if (io && io->name) + ext2fs_free_mem(&io->name); + if (io) + ext2fs_free_mem(&io); + return retval; +} + +static errcode_t undo_close(io_channel channel) +{ + struct undo_private_data *data; + errcode_t err, retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + /* Before closing write the file system identity */ + if (!getenv("UNDO_IO_SIMULATE_UNFINISHED")) + data->hdr.state = ext2fs_cpu_to_le32(E2UNDO_STATE_FINISHED); + err = write_undo_indexes(data, 1); + ext2fs_remove_exit_fn(undo_atexit, data); + if (data->real) + retval = io_channel_close(data->real); + if (data->tdb_file) + free(data->tdb_file); + if (data->undo_file) + io_channel_close(data->undo_file); + ext2fs_free_mem(&data->keyb); + if (data->written_block_map) + ext2fs_free_generic_bitmap(data->written_block_map); + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + + if (err) + return err; + return retval; +} + +static errcode_t undo_set_blksize(io_channel channel, int blksize) +{ + struct undo_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (blksize > E2UNDO_MAX_BLOCK_SIZE || blksize < E2UNDO_MIN_BLOCK_SIZE) + return EXT2_ET_INVALID_ARGUMENT; + + if (data->real) + retval = io_channel_set_blksize(data->real, blksize); + /* + * Set the block size used for tdb + */ + if (!data->tdb_data_size || !data->tdb_written) + data->tdb_data_size = blksize; + channel->block_size = blksize; + return retval; +} + +static errcode_t undo_read_blk64(io_channel channel, unsigned long long block, + int count, void *buf) +{ + errcode_t retval = 0; + struct undo_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (data->real) + retval = io_channel_read_blk64(data->real, block, count, buf); + + return retval; +} + +static errcode_t undo_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + return undo_read_blk64(channel, block, count, buf); +} + +static errcode_t undo_write_blk64(io_channel channel, unsigned long long block, + int count, const void *buf) +{ + struct undo_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + /* + * First write the existing content into database + */ + retval = undo_write_tdb(channel, block, count); + if (retval) + return retval; + if (data->real) + retval = io_channel_write_blk64(data->real, block, count, buf); + + return retval; +} + +static errcode_t undo_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + return undo_write_blk64(channel, block, count, buf); +} + +static errcode_t undo_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + struct undo_private_data *data; + errcode_t retval = 0; + ext2_loff_t location; + unsigned long blk_num, count;; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + location = offset + data->offset; + blk_num = location/channel->block_size; + /* + * the size specified may spread across multiple blocks + * also make sure we account for the fact that block start + * offset for tdb is different from the backing I/O manager + * due to possible different block size + */ + count = (size + (location % channel->block_size) + + channel->block_size -1)/channel->block_size; + retval = undo_write_tdb(channel, blk_num, count); + if (retval) + return retval; + if (data->real && data->real->manager->write_byte) + retval = io_channel_write_byte(data->real, offset, size, buf); + + return retval; +} + +static errcode_t undo_discard(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct undo_private_data *data; + errcode_t retval = 0; + int icount; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (count > INT_MAX) + return EXT2_ET_UNIMPLEMENTED; + icount = count; + + /* + * First write the existing content into database + */ + retval = undo_write_tdb(channel, block, icount); + if (retval) + return retval; + if (data->real) + retval = io_channel_discard(data->real, block, count); + + return retval; +} + +static errcode_t undo_zeroout(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct undo_private_data *data; + errcode_t retval = 0; + int icount; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (count > INT_MAX) + return EXT2_ET_UNIMPLEMENTED; + icount = count; + + /* + * First write the existing content into database + */ + retval = undo_write_tdb(channel, block, icount); + if (retval) + return retval; + if (data->real) + retval = io_channel_zeroout(data->real, block, count); + + return retval; +} + +static errcode_t undo_cache_readahead(io_channel channel, + unsigned long long block, + unsigned long long count) +{ + struct undo_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (data->real) + retval = io_channel_cache_readahead(data->real, block, count); + + return retval; +} + +/* + * Flush data buffers to disk. + */ +static errcode_t undo_flush(io_channel channel) +{ + errcode_t retval = 0; + struct undo_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (data->real) + retval = io_channel_flush(data->real); + + return retval; +} + +static errcode_t undo_set_option(io_channel channel, const char *option, + const char *arg) +{ + errcode_t retval = 0; + struct undo_private_data *data; + unsigned long tmp; + char *end; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (!strcmp(option, "tdb_data_size")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + + tmp = strtoul(arg, &end, 0); + if (*end) + return EXT2_ET_INVALID_ARGUMENT; + if (tmp > E2UNDO_MAX_BLOCK_SIZE || tmp < E2UNDO_MIN_BLOCK_SIZE) + return EXT2_ET_INVALID_ARGUMENT; + if (!data->tdb_data_size || !data->tdb_written) { + data->tdb_written = -1; + data->tdb_data_size = tmp; + } + return 0; + } + /* + * Need to support offset option to work with + * Unix I/O manager + */ + if (data->real && data->real->manager->set_option) { + retval = data->real->manager->set_option(data->real, + option, arg); + } + if (!retval && !strcmp(option, "offset")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + + tmp = strtoul(arg, &end, 0); + if (*end) + return EXT2_ET_INVALID_ARGUMENT; + data->offset = tmp; + } + return retval; +} + +static errcode_t undo_get_stats(io_channel channel, io_stats *stats) +{ + errcode_t retval = 0; + struct undo_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct undo_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (data->real) + retval = (data->real->manager->get_stats)(data->real, stats); + + return retval; +} + +static struct struct_io_manager struct_undo_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Undo I/O Manager", + .open = undo_open, + .close = undo_close, + .set_blksize = undo_set_blksize, + .read_blk = undo_read_blk, + .write_blk = undo_write_blk, + .flush = undo_flush, + .write_byte = undo_write_byte, + .set_option = undo_set_option, + .get_stats = undo_get_stats, + .read_blk64 = undo_read_blk64, + .write_blk64 = undo_write_blk64, + .discard = undo_discard, + .zeroout = undo_zeroout, + .cache_readahead = undo_cache_readahead, +}; + +io_manager undo_io_manager = &struct_undo_manager; diff --git a/jni/e2fsprogs/lib/ext2fs/undo_io.o b/jni/e2fsprogs/lib/ext2fs/undo_io.o new file mode 100755 index 0000000000000000000000000000000000000000..251031eaf6ac46d195f14bdc972d4096ce642c1a GIT binary patch literal 18592 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 +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef __linux__ +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_PRCTL_H +#include +#else +#define PR_GET_DUMPABLE 3 +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include +#endif +#if HAVE_LINUX_FALLOC_H +#include +#endif +#ifdef HAVE_PTHREAD +#include +#endif + +#if defined(__linux__) && defined(_IO) && !defined(BLKROGET) +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ +#endif + +#undef ALIGN_DEBUG + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct unix_cache { + char *buf; + unsigned long long block; + int access_time; + unsigned dirty:1; + unsigned in_use:1; + unsigned write_err:1; +}; + +#define CACHE_SIZE 8 +#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */ +#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */ + +struct unix_private_data { + int magic; + int dev; + int flags; + int align; + int access_time; + ext2_loff_t offset; + struct unix_cache cache[CACHE_SIZE]; + void *bounce; + struct struct_io_stats io_stats; +#ifdef HAVE_PTHREAD + pthread_mutex_t cache_mutex; + pthread_mutex_t bounce_mutex; + pthread_mutex_t stats_mutex; +#endif +}; + +#define IS_ALIGNED(n, align) ((((uintptr_t) n) & \ + ((uintptr_t) ((align)-1))) == 0) + +typedef enum lock_kind { + CACHE_MTX, BOUNCE_MTX, STATS_MTX +} kind_t; + +#ifdef HAVE_PTHREAD +static inline pthread_mutex_t *get_mutex(struct unix_private_data *data, + kind_t kind) +{ + if (data->flags & IO_FLAG_THREADS) { + switch (kind) { + case CACHE_MTX: + return &data->cache_mutex; + case BOUNCE_MTX: + return &data->bounce_mutex; + case STATS_MTX: + return &data->stats_mutex; + } + } + return NULL; +} +#endif + +static inline void mutex_lock(struct unix_private_data *data, kind_t kind) +{ +#ifdef HAVE_PTHREAD + pthread_mutex_t *mtx = get_mutex(data,kind); + + if (mtx) + pthread_mutex_lock(mtx); +#endif +} + +static inline void mutex_unlock(struct unix_private_data *data, kind_t kind) +{ +#ifdef HAVE_PTHREAD + pthread_mutex_t *mtx = get_mutex(data,kind); + + if (mtx) + pthread_mutex_unlock(mtx); +#endif +} + +static errcode_t unix_get_stats(io_channel channel, io_stats *stats) +{ + errcode_t retval = 0; + + struct unix_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (stats) { + mutex_lock(data, STATS_MTX); + *stats = &data->io_stats; + mutex_unlock(data, STATS_MTX); + } + + return retval; +} + +static char *safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#ifdef HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if defined(HAVE_SECURE_GETENV) + return secure_getenv(arg); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +/* + * Here are the raw I/O functions + */ +static errcode_t raw_read_blk(io_channel channel, + struct unix_private_data *data, + unsigned long long block, + int count, void *bufv) +{ + errcode_t retval; + ssize_t size; + ext2_loff_t location; + int actual = 0; + unsigned char *buf = bufv; + ssize_t really_read = 0; + unsigned long long aligned_blk; + int align_size, offset; + + size = (count < 0) ? -count : (ext2_loff_t) count * channel->block_size; + mutex_lock(data, STATS_MTX); + data->io_stats.bytes_read += size; + mutex_unlock(data, STATS_MTX); + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + + if (data->flags & IO_FLAG_FORCE_BOUNCE) + goto bounce_read; + +#ifdef HAVE_PREAD64 + /* Try an aligned pread */ + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align))) { + actual = pread64(data->dev, buf, size, location); + if (actual == size) + return 0; + actual = 0; + } +#elif HAVE_PREAD + /* Try an aligned pread */ + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) && + ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align)))) { + actual = pread(data->dev, buf, size, location); + if (actual == size) + return 0; + actual = 0; + } +#endif /* HAVE_PREAD */ + + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align))) { + mutex_lock(data, BOUNCE_MTX); + if (ext2fs_llseek(data->dev, location, SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_unlock; + } + actual = read(data->dev, buf, size); + if (actual != size) { + short_read: + if (actual < 0) { + retval = errno; + actual = 0; + } else + retval = EXT2_ET_SHORT_READ; + goto error_unlock; + } + goto success_unlock; + } + +#ifdef ALIGN_DEBUG + printf("raw_read_blk: O_DIRECT fallback: %p %lu\n", buf, + (unsigned long) size); +#endif + + /* + * The buffer or size which we're trying to read isn't aligned + * to the O_DIRECT rules, so we need to do this the hard way... + */ +bounce_read: + if (channel->align == 0) + channel->align = 1; + if ((channel->block_size > channel->align) && + (channel->block_size % channel->align) == 0) + align_size = channel->block_size; + else + align_size = channel->align; + aligned_blk = location / align_size; + offset = location % align_size; + + mutex_lock(data, BOUNCE_MTX); + if (ext2fs_llseek(data->dev, aligned_blk * align_size, SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_unlock; + } + while (size > 0) { + actual = read(data->dev, data->bounce, align_size); + if (actual != align_size) { + mutex_unlock(data, BOUNCE_MTX); + actual = really_read; + buf -= really_read; + size += really_read; + goto short_read; + } + if ((actual + offset) > align_size) + actual = align_size - offset; + if (actual > size) + actual = size; + memcpy(buf, (char *)data->bounce + offset, actual); + + really_read += actual; + size -= actual; + buf += actual; + offset = 0; + aligned_blk++; + } +success_unlock: + mutex_unlock(data, BOUNCE_MTX); + return 0; + +error_unlock: + mutex_unlock(data, BOUNCE_MTX); + if (actual >= 0 && actual < size) + memset((char *) buf+actual, 0, size-actual); + if (channel->read_error) + retval = (channel->read_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} + +#define RAW_WRITE_NO_HANDLER 1 + +static errcode_t raw_write_blk(io_channel channel, + struct unix_private_data *data, + unsigned long long block, + int count, const void *bufv, + int flags) +{ + ssize_t size; + ext2_loff_t location; + int actual = 0; + errcode_t retval; + const unsigned char *buf = bufv; + unsigned long long aligned_blk; + int align_size, offset; + + if (count == 1) + size = channel->block_size; + else { + if (count < 0) + size = -count; + else + size = (ext2_loff_t) count * channel->block_size; + } + mutex_lock(data, STATS_MTX); + data->io_stats.bytes_written += size; + mutex_unlock(data, STATS_MTX); + + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + + if (data->flags & IO_FLAG_FORCE_BOUNCE) + goto bounce_write; + +#ifdef HAVE_PWRITE64 + /* Try an aligned pwrite */ + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align))) { + actual = pwrite64(data->dev, buf, size, location); + if (actual == size) + return 0; + } +#elif HAVE_PWRITE + /* Try an aligned pwrite */ + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) && + ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align)))) { + actual = pwrite(data->dev, buf, size, location); + if (actual == size) + return 0; + } +#endif /* HAVE_PWRITE */ + + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(location, channel->align) && + IS_ALIGNED(size, channel->align))) { + mutex_lock(data, BOUNCE_MTX); + if (ext2fs_llseek(data->dev, location, SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_unlock; + } + actual = write(data->dev, buf, size); + mutex_unlock(data, BOUNCE_MTX); + if (actual < 0) { + retval = errno; + goto error_out; + } + if (actual != size) { + short_write: + retval = EXT2_ET_SHORT_WRITE; + goto error_out; + } + return 0; + } + +#ifdef ALIGN_DEBUG + printf("raw_write_blk: O_DIRECT fallback: %p %lu\n", buf, + (unsigned long) size); +#endif + /* + * The buffer or size which we're trying to write isn't aligned + * to the O_DIRECT rules, so we need to do this the hard way... + */ +bounce_write: + if (channel->align == 0) + channel->align = 1; + if ((channel->block_size > channel->align) && + (channel->block_size % channel->align) == 0) + align_size = channel->block_size; + else + align_size = channel->align; + aligned_blk = location / align_size; + offset = location % align_size; + + while (size > 0) { + int actual_w; + + mutex_lock(data, BOUNCE_MTX); + if (size < align_size || offset) { + if (ext2fs_llseek(data->dev, aligned_blk * align_size, + SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_unlock; + } + actual = read(data->dev, data->bounce, + align_size); + if (actual != align_size) { + if (actual < 0) { + retval = errno; + goto error_unlock; + } + memset((char *) data->bounce + actual, 0, + align_size - actual); + } + } + actual = size; + if ((actual + offset) > align_size) + actual = align_size - offset; + if (actual > size) + actual = size; + memcpy(((char *)data->bounce) + offset, buf, actual); + if (ext2fs_llseek(data->dev, aligned_blk * align_size, SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_unlock; + } + actual_w = write(data->dev, data->bounce, align_size); + mutex_unlock(data, BOUNCE_MTX); + if (actual_w < 0) { + retval = errno; + goto error_out; + } + if (actual_w != align_size) + goto short_write; + size -= actual; + buf += actual; + location += actual; + aligned_blk++; + offset = 0; + } + return 0; + +error_unlock: + mutex_unlock(data, BOUNCE_MTX); +error_out: + if (((flags & RAW_WRITE_NO_HANDLER) == 0) && channel->write_error) + retval = (channel->write_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} + + +/* + * Here we implement the cache functions + */ + +/* Allocate the cache buffers */ +static errcode_t alloc_cache(io_channel channel, + struct unix_private_data *data) +{ + errcode_t retval; + struct unix_cache *cache; + int i; + + data->access_time = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + cache->block = 0; + cache->access_time = 0; + cache->dirty = 0; + cache->in_use = 0; + if (cache->buf) + ext2fs_free_mem(&cache->buf); + retval = io_channel_alloc_buf(channel, 0, &cache->buf); + if (retval) + return retval; + } + if (channel->align || data->flags & IO_FLAG_FORCE_BOUNCE) { + if (data->bounce) + ext2fs_free_mem(&data->bounce); + retval = io_channel_alloc_buf(channel, 0, &data->bounce); + } + return retval; +} + +/* Free the cache buffers */ +static void free_cache(struct unix_private_data *data) +{ + struct unix_cache *cache; + int i; + + data->access_time = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + cache->block = 0; + cache->access_time = 0; + cache->dirty = 0; + cache->in_use = 0; + if (cache->buf) + ext2fs_free_mem(&cache->buf); + } + if (data->bounce) + ext2fs_free_mem(&data->bounce); +} + +#ifndef NO_IO_CACHE +/* + * Try to find a block in the cache. If the block is not found, and + * eldest is a non-zero pointer, then fill in eldest with the cache + * entry to that should be reused. + */ +static struct unix_cache *find_cached_block(struct unix_private_data *data, + unsigned long long block, + struct unix_cache **eldest) +{ + struct unix_cache *cache, *unused_cache, *oldest_cache; + int i; + + unused_cache = oldest_cache = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use) { + if (!unused_cache) + unused_cache = cache; + continue; + } + if (cache->block == block) { + cache->access_time = ++data->access_time; + return cache; + } + if (!oldest_cache || + (cache->access_time < oldest_cache->access_time)) + oldest_cache = cache; + } + if (eldest) + *eldest = (unused_cache) ? unused_cache : oldest_cache; + return 0; +} + +/* + * Reuse a particular cache entry for another block. + */ +static errcode_t reuse_cache(io_channel channel, + struct unix_private_data *data, struct unix_cache *cache, + unsigned long long block) +{ + if (cache->dirty && cache->in_use) { + errcode_t retval; + + retval = raw_write_blk(channel, data, cache->block, 1, + cache->buf, RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + return retval; + } + } + + cache->in_use = 1; + cache->dirty = 0; + cache->write_err = 0; + cache->block = block; + cache->access_time = ++data->access_time; + return 0; +} + +#define FLUSH_INVALIDATE 0x01 +#define FLUSH_NOLOCK 0x02 + +/* + * Flush all of the blocks in the cache + */ +static errcode_t flush_cached_blocks(io_channel channel, + struct unix_private_data *data, + int flags) +{ + struct unix_cache *cache; + errcode_t retval, retval2 = 0; + int i; + int errors_found = 0; + + if ((flags & FLUSH_NOLOCK) == 0) + mutex_lock(data, CACHE_MTX); + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use || !cache->dirty) + continue; + retval = raw_write_blk(channel, data, + cache->block, 1, cache->buf, + RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + errors_found = 1; + retval2 = retval; + } else { + cache->dirty = 0; + cache->write_err = 0; + if (flags & FLUSH_INVALIDATE) + cache->in_use = 0; + } + } + if ((flags & FLUSH_NOLOCK) == 0) + mutex_unlock(data, CACHE_MTX); +retry: + while (errors_found) { + if ((flags & FLUSH_NOLOCK) == 0) + mutex_lock(data, CACHE_MTX); + errors_found = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use || !cache->write_err) + continue; + errors_found = 1; + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, + &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, + channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, + 1, err_buf, channel->block_size, -1, + retval2); + if (err_buf) + ext2fs_free_mem(&err_buf); + goto retry; + } else + cache->write_err = 0; + } + if ((flags & FLUSH_NOLOCK) == 0) + mutex_unlock(data, CACHE_MTX); + } + return retval2; +} +#endif /* NO_IO_CACHE */ + +#ifdef __linux__ +#ifndef BLKDISCARDZEROES +#define BLKDISCARDZEROES _IO(0x12,124) +#endif +#endif + +int ext2fs_open_file(const char *pathname, int flags, mode_t mode) +{ + if (mode) +#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return open64(pathname, flags, mode); + else + return open64(pathname, flags); +#else + return open(pathname, flags, mode); + else + return open(pathname, flags); +#endif +} + +int ext2fs_stat(const char *path, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return stat64(path, buf); +#else + return stat(path, buf); +#endif +} + +int ext2fs_fstat(int fd, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return fstat64(fd, buf); +#else + return fstat(fd, buf); +#endif +} + + +static errcode_t unix_open_channel(const char *name, int fd, + int flags, io_channel *channel, + io_manager io_mgr) +{ + io_channel io = NULL; + struct unix_private_data *data = NULL; + errcode_t retval; + ext2fs_struct_stat st; +#ifdef __linux__ + struct utsname ut; +#endif + + if (safe_getenv("UNIX_IO_FORCE_BOUNCE")) + flags |= IO_FLAG_FORCE_BOUNCE; + +#ifdef __linux__ + /* + * We need to make sure any previous errors in the block + * device are thrown away, sigh. + */ + (void) fsync(fd); +#endif + + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + goto cleanup; + memset(io, 0, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); + if (retval) + goto cleanup; + + io->manager = io_mgr; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + io->flags = 0; + + memset(data, 0, sizeof(struct unix_private_data)); + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; + data->io_stats.num_fields = 2; + data->flags = flags; + data->dev = fd; + +#if defined(O_DIRECT) + if (flags & IO_FLAG_DIRECT_IO) + io->align = ext2fs_get_dio_alignment(data->dev); +#elif defined(F_NOCACHE) + if (flags & IO_FLAG_DIRECT_IO) + io->align = 4096; +#endif + + /* + * If the device is really a block device, then set the + * appropriate flag, otherwise we can set DISCARD_ZEROES flag + * because we are going to use punch hole instead of discard + * and if it succeed, subsequent read from sparse area returns + * zero. + */ + if (ext2fs_fstat(data->dev, &st) == 0) { + if (ext2fsP_is_disk_device(st.st_mode)) + io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE; + else + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } + +#ifdef BLKDISCARDZEROES + { + int zeroes = 0; + if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && + zeroes) + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } +#endif + +#if defined(__CYGWIN__) + /* + * Some operating systems require that the buffers be aligned, + * regardless of O_DIRECT + */ + if (!io->align) + io->align = 512; +#endif + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if (io->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { + int dio_align = ext2fs_get_dio_alignment(fd); + + if (io->align < dio_align) + io->align = dio_align; + } +#endif + + if ((retval = alloc_cache(io, data))) + goto cleanup; + +#ifdef BLKROGET + if (flags & IO_FLAG_RW) { + int error; + int readonly = 0; + + /* Is the block device actually writable? */ + error = ioctl(data->dev, BLKROGET, &readonly); + if (!error && readonly) { + retval = EPERM; + goto cleanup; + } + } +#endif + +#ifdef __linux__ +#undef RLIM_INFINITY +#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) +#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) +#else +#define RLIM_INFINITY (~0UL) +#endif + /* + * Work around a bug in 2.4.10-2.4.18 kernels where writes to + * block devices are wrongly getting hit by the filesize + * limit. This workaround isn't perfect, since it won't work + * if glibc wasn't built against 2.2 header files. (Sigh.) + * + */ + if ((flags & IO_FLAG_RW) && + (uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] == '4') && (ut.release[3] == '.') && + (ut.release[4] == '1') && (ut.release[5] >= '0') && + (ut.release[5] < '8')) && + (ext2fs_fstat(data->dev, &st) == 0) && + (ext2fsP_is_disk_device(st.st_mode))) { + struct rlimit rlim; + + rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; + setrlimit(RLIMIT_FSIZE, &rlim); + getrlimit(RLIMIT_FSIZE, &rlim); + if (((unsigned long) rlim.rlim_cur) < + ((unsigned long) rlim.rlim_max)) { + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_FSIZE, &rlim); + } + } +#endif +#ifdef HAVE_PTHREAD + if (flags & IO_FLAG_THREADS) { + io->flags |= CHANNEL_FLAGS_THREADS; + retval = pthread_mutex_init(&data->cache_mutex, NULL); + if (retval) + goto cleanup; + retval = pthread_mutex_init(&data->bounce_mutex, NULL); + if (retval) { + pthread_mutex_destroy(&data->cache_mutex); + goto cleanup; + } + retval = pthread_mutex_init(&data->stats_mutex, NULL); + if (retval) { + pthread_mutex_destroy(&data->cache_mutex); + pthread_mutex_destroy(&data->bounce_mutex); + goto cleanup; + } + } +#endif + *channel = io; + return 0; + +cleanup: + if (data) { + if (data->dev >= 0) + close(data->dev); + free_cache(data); + ext2fs_free_mem(&data); + } + if (io) { + if (io->name) { + ext2fs_free_mem(&io->name); + } + ext2fs_free_mem(&io); + } + return retval; +} + +static errcode_t unixfd_open(const char *str_fd, int flags, + io_channel *channel) +{ + int fd; + int fd_flags; + + fd = atoi(str_fd); +#if defined(HAVE_FCNTL) + fd_flags = fcntl(fd, F_GETFD); + if (fd_flags == -1) + return EBADF; + + flags = 0; + if (fd_flags & O_RDWR) + flags |= IO_FLAG_RW; + if (fd_flags & O_EXCL) + flags |= IO_FLAG_EXCLUSIVE; +#if defined(O_DIRECT) + if (fd_flags & O_DIRECT) + flags |= IO_FLAG_DIRECT_IO; +#endif +#endif /* HAVE_FCNTL */ + + return unix_open_channel(str_fd, fd, flags, channel, unixfd_io_manager); +} + +static errcode_t unix_open(const char *name, int flags, + io_channel *channel) +{ + int fd = -1; + int open_flags; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; + if (flags & IO_FLAG_EXCLUSIVE) + open_flags |= O_EXCL; +#if defined(O_DIRECT) + if (flags & IO_FLAG_DIRECT_IO) + open_flags |= O_DIRECT; +#endif + fd = ext2fs_open_file(name, open_flags, 0); + if (fd < 0) + return errno; +#if defined(F_NOCACHE) && !defined(IO_DIRECT) + if (flags & IO_FLAG_DIRECT_IO) { + if (fcntl(fd, F_NOCACHE, 1) < 0) + return errno; + } +#endif + return unix_open_channel(name, fd, flags, channel, unix_io_manager); +} + +static errcode_t unix_close(io_channel channel) +{ + struct unix_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif + + if (close(data->dev) < 0) + retval = errno; + free_cache(data); +#ifdef HAVE_PTHREAD + if (data->flags & IO_FLAG_THREADS) { + pthread_mutex_destroy(&data->cache_mutex); + pthread_mutex_destroy(&data->bounce_mutex); + pthread_mutex_destroy(&data->stats_mutex); + } +#endif + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t unix_set_blksize(io_channel channel, int blksize) +{ + struct unix_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (channel->block_size != blksize) { + mutex_lock(data, CACHE_MTX); + mutex_lock(data, BOUNCE_MTX); +#ifndef NO_IO_CACHE + if ((retval = flush_cached_blocks(channel, data, FLUSH_NOLOCK))){ + mutex_unlock(data, BOUNCE_MTX); + mutex_unlock(data, CACHE_MTX); + return retval; + } +#endif + + channel->block_size = blksize; + free_cache(data); + retval = alloc_cache(channel, data); + mutex_unlock(data, BOUNCE_MTX); + mutex_unlock(data, CACHE_MTX); + } + return retval; +} + +static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, + int count, void *buf) +{ + struct unix_private_data *data; + struct unix_cache *cache; + errcode_t retval; + char *cp; + int i, j; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifdef NO_IO_CACHE + return raw_read_blk(channel, data, block, count, buf); +#else + if (data->flags & IO_FLAG_NOCACHE) + return raw_read_blk(channel, data, block, count, buf); + /* + * If we're doing an odd-sized read or a very large read, + * flush out the cache and then do a direct read. + */ + if (count < 0 || count > WRITE_DIRECT_SIZE) { + if ((retval = flush_cached_blocks(channel, data, 0))) + return retval; + return raw_read_blk(channel, data, block, count, buf); + } + + cp = buf; + mutex_lock(data, CACHE_MTX); + while (count > 0) { + /* If it's in the cache, use it! */ + if ((cache = find_cached_block(data, block, NULL))) { +#ifdef DEBUG + printf("Using cached block %lu\n", block); +#endif + memcpy(cp, cache->buf, channel->block_size); + count--; + block++; + cp += channel->block_size; + continue; + } + + /* + * Find the number of uncached blocks so we can do a + * single read request + */ + for (i=1; i < count; i++) + if (find_cached_block(data, block+i, NULL)) + break; +#ifdef DEBUG + printf("Reading %d blocks starting at %lu\n", i, block); +#endif + mutex_unlock(data, CACHE_MTX); + if ((retval = raw_read_blk(channel, data, block, i, cp))) + return retval; + mutex_lock(data, CACHE_MTX); + + /* Save the results in the cache */ + for (j=0; j < i; j++) { + if (!find_cached_block(data, block, &cache)) { + retval = reuse_cache(channel, data, + cache, block); + if (retval) + goto call_write_handler; + memcpy(cache->buf, cp, channel->block_size); + } + count--; + block++; + cp += channel->block_size; + } + } + mutex_unlock(data, CACHE_MTX); + return 0; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); + return retval; +#endif /* NO_IO_CACHE */ +} + +static errcode_t unix_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + return unix_read_blk64(channel, block, count, buf); +} + +static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, + int count, const void *buf) +{ + struct unix_private_data *data; + struct unix_cache *cache, *reuse; + errcode_t retval = 0; + const char *cp; + int writethrough; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifdef NO_IO_CACHE + return raw_write_blk(channel, data, block, count, buf, 0); +#else + if (data->flags & IO_FLAG_NOCACHE) + return raw_write_blk(channel, data, block, count, buf, 0); + /* + * If we're doing an odd-sized write or a very large write, + * flush out the cache completely and then do a direct write. + */ + if (count < 0 || count > WRITE_DIRECT_SIZE) { + if ((retval = flush_cached_blocks(channel, data, + FLUSH_INVALIDATE))) + return retval; + return raw_write_blk(channel, data, block, count, buf, 0); + } + + /* + * For a moderate-sized multi-block write, first force a write + * if we're in write-through cache mode, and then fill the + * cache with the blocks. + */ + writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; + if (writethrough) + retval = raw_write_blk(channel, data, block, count, buf, 0); + + cp = buf; + mutex_lock(data, CACHE_MTX); + while (count > 0) { + cache = find_cached_block(data, block, &reuse); + if (!cache) { + errcode_t err; + + cache = reuse; + err = reuse_cache(channel, data, cache, block); + if (err) + goto call_write_handler; + } + if (cache->buf != cp) + memcpy(cache->buf, cp, channel->block_size); + cache->dirty = !writethrough; + count--; + block++; + cp += channel->block_size; + } + mutex_unlock(data, CACHE_MTX); + return retval; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); + return retval; +#endif /* NO_IO_CACHE */ +} + +static errcode_t unix_cache_readahead(io_channel channel, + unsigned long long block, + unsigned long long count) +{ +#ifdef POSIX_FADV_WILLNEED + struct unix_private_data *data; + + data = (struct unix_private_data *)channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + return posix_fadvise(data->dev, + (ext2_loff_t)block * channel->block_size + data->offset, + (ext2_loff_t)count * channel->block_size, + POSIX_FADV_WILLNEED); +#else + return EXT2_ET_OP_NOT_SUPPORTED; +#endif +} + +static errcode_t unix_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + return unix_write_blk64(channel, block, count, buf); +} + +static errcode_t unix_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + struct unix_private_data *data; + errcode_t retval = 0; + ssize_t actual; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (channel->align != 0) { +#ifdef ALIGN_DEBUG + printf("unix_write_byte: O_DIRECT fallback\n"); +#endif + return EXT2_ET_UNIMPLEMENTED; + } + +#ifndef NO_IO_CACHE + /* + * Flush out the cache completely + */ + if ((retval = flush_cached_blocks(channel, data, FLUSH_INVALIDATE))) + return retval; +#endif + + if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0) + return errno; + + actual = write(data->dev, buf, size); + if (actual < 0) + return errno; + if (actual != size) + return EXT2_ET_SHORT_WRITE; + + return 0; +} + +/* + * Flush data buffers to disk. + */ +static errcode_t unix_flush(io_channel channel) +{ + struct unix_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif +#ifdef HAVE_FSYNC + if (!retval && fsync(data->dev) != 0) + return errno; +#endif + return retval; +} + +static errcode_t unix_set_option(io_channel channel, const char *option, + const char *arg) +{ + struct unix_private_data *data; + unsigned long long tmp; + errcode_t retval; + char *end; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (!strcmp(option, "offset")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + + tmp = strtoull(arg, &end, 0); + if (*end) + return EXT2_ET_INVALID_ARGUMENT; + data->offset = tmp; + if (data->offset < 0) + return EXT2_ET_INVALID_ARGUMENT; + return 0; + } + if (!strcmp(option, "cache")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + if (!strcmp(arg, "on")) { + data->flags &= ~IO_FLAG_NOCACHE; + return 0; + } + if (!strcmp(arg, "off")) { + retval = flush_cached_blocks(channel, data, 0); + data->flags |= IO_FLAG_NOCACHE; + return retval; + } + return EXT2_ET_INVALID_ARGUMENT; + } + return EXT2_ET_INVALID_ARGUMENT; +} + +#if defined(__linux__) && !defined(BLKDISCARD) +#define BLKDISCARD _IO(0x12,119) +#endif + +static errcode_t unix_discard(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct unix_private_data *data; + int ret; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { +#ifdef BLKDISCARD + __u64 range[2]; + + range[0] = (__u64)(block) * channel->block_size + data->offset; + range[1] = (__u64)(count) * channel->block_size; + + ret = ioctl(data->dev, BLKDISCARD, &range); +#else + goto unimplemented; +#endif + } else { +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE) + /* + * If we are not on block device, try to use punch hole + * to reclaim free space. + */ + ret = fallocate(data->dev, + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + (off_t)(block) * channel->block_size + data->offset, + (off_t)(count) * channel->block_size); +#else + goto unimplemented; +#endif + } + if (ret < 0) { + if (errno == EOPNOTSUPP) + goto unimplemented; + return errno; + } + return 0; +unimplemented: + return EXT2_ET_UNIMPLEMENTED; +} + +/* + * If we know about ZERO_RANGE, try that before we try PUNCH_HOLE because + * ZERO_RANGE doesn't unmap preallocated blocks. We prefer fallocate because + * it always invalidates page cache, and libext2fs requires that reads after + * ZERO_RANGE return zeroes. + */ +static int __unix_zeroout(int fd, off_t offset, off_t len) +{ + int ret = -1; + +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_ZERO_RANGE) + ret = fallocate(fd, FALLOC_FL_ZERO_RANGE, offset, len); + if (ret == 0) + return 0; +#endif +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) + ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + offset, len); + if (ret == 0) + return 0; +#endif + errno = EOPNOTSUPP; + return ret; +} + +/* parameters might not be used if OS doesn't support zeroout */ +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +static errcode_t unix_zeroout(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct unix_private_data *data; + int ret; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (safe_getenv("UNIX_IO_NOZEROOUT")) + goto unimplemented; + + if (!(channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE)) { + /* Regular file, try to use truncate/punch/zero. */ + struct stat statbuf; + + if (count == 0) + return 0; + /* + * If we're trying to zero a range past the end of the file, + * extend the file size, then truncate everything. + */ + ret = fstat(data->dev, &statbuf); + if (ret) + goto err; + if ((unsigned long long) statbuf.st_size < + (block + count) * channel->block_size + data->offset) { + ret = ftruncate(data->dev, + (block + count) * channel->block_size + data->offset); + if (ret) + goto err; + } + } + + ret = __unix_zeroout(data->dev, + (off_t)(block) * channel->block_size + data->offset, + (off_t)(count) * channel->block_size); +err: + if (ret < 0) { + if (errno == EOPNOTSUPP) + goto unimplemented; + return errno; + } + return 0; +unimplemented: + return EXT2_ET_UNIMPLEMENTED; +} +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +static struct struct_io_manager struct_unix_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Unix I/O Manager", + .open = unix_open, + .close = unix_close, + .set_blksize = unix_set_blksize, + .read_blk = unix_read_blk, + .write_blk = unix_write_blk, + .flush = unix_flush, + .write_byte = unix_write_byte, + .set_option = unix_set_option, + .get_stats = unix_get_stats, + .read_blk64 = unix_read_blk64, + .write_blk64 = unix_write_blk64, + .discard = unix_discard, + .cache_readahead = unix_cache_readahead, + .zeroout = unix_zeroout, +}; + +io_manager unix_io_manager = &struct_unix_manager; + +static struct struct_io_manager struct_unixfd_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Unix fd I/O Manager", + .open = unixfd_open, + .close = unix_close, + .set_blksize = unix_set_blksize, + .read_blk = unix_read_blk, + .write_blk = unix_write_blk, + .flush = unix_flush, + .write_byte = unix_write_byte, + .set_option = unix_set_option, + .get_stats = unix_get_stats, + .read_blk64 = unix_read_blk64, + .write_blk64 = unix_write_blk64, + .discard = unix_discard, + .cache_readahead = unix_cache_readahead, + .zeroout = unix_zeroout, +}; + +io_manager unixfd_io_manager = &struct_unixfd_manager; diff --git a/jni/e2fsprogs/lib/ext2fs/unix_io.o b/jni/e2fsprogs/lib/ext2fs/unix_io.o new file mode 100755 index 0000000000000000000000000000000000000000..c2c4433747ec9fe6fdd05b941a71df1f2e211535 GIT binary patch literal 23800 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/unlink.c b/jni/e2fsprogs/lib/ext2fs/unlink.c new file mode 100755 index 0000000..3ec04cf --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/unlink.c @@ -0,0 +1,100 @@ +/* + * unlink.c --- delete links in a ext2fs directory + * + * Copyright (C) 1993, 1994, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct link_struct { + const char *name; + int namelen; + ext2_ino_t inode; + int flags; + struct ext2_dir_entry *prev; + int done; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int unlink_proc(struct ext2_dir_entry *dirent, + int offset, + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct link_struct *ls = (struct link_struct *) priv_data; + struct ext2_dir_entry *prev; + + prev = ls->prev; + ls->prev = dirent; + + if (ls->name) { + if (ext2fs_dirent_name_len(dirent) != ls->namelen) + return 0; + if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent))) + return 0; + } + if (!(ls->flags & EXT2FS_UNLINK_FORCE) && ls->inode) { + if (dirent->inode != ls->inode) + return 0; + } else { + if (!dirent->inode) + return 0; + } + + if (offset) + prev->rec_len += dirent->rec_len; + else + dirent->inode = 0; + ls->done++; + return DIRENT_ABORT|DIRENT_CHANGED; +} + +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, + const char *name, ext2_ino_t ino, + int flags) +{ + errcode_t retval; + struct link_struct ls; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!name && !ino) + return EXT2_ET_INVALID_ARGUMENT; + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + ls.name = name; + ls.namelen = name ? strlen(name) : 0; + ls.inode = ino; + ls.flags = flags; + ls.done = 0; + ls.prev = 0; + + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, + 0, unlink_proc, &ls); + if (retval) + return retval; + + return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE; +} + diff --git a/jni/e2fsprogs/lib/ext2fs/unlink.o b/jni/e2fsprogs/lib/ext2fs/unlink.o new file mode 100755 index 0000000000000000000000000000000000000000..c373219afd82878fd64701a18ec93e4a2f2a626a GIT binary patch literal 2176 zcmbVMU1%It6h5<)G_(0>8`BzLO*YXyY*QVZQZXRNh;6MRB1Ip3u#1LG1 zC>FM0eM?ZJ2+G!0*c72J6?dL2>`Q%A#5W~s3!C;ypLW1y{mz|xH`D3n#k$#}k@HYH9R6ZNDj$$l4Y0g=;D*9^4?9N*HL3%2G~5XYB}9}4)0a{R5PQ|cO0wM z->TgrdYb)4W1DwG@Q`!Z@)3VVaR1znKOyrp`Y7Oh;M`zN1wPvTY*VM8hjZ%bYYq4! zzitJ09;fxj2>D#MF$!CTO_AR|Nd8~ownr$aV3y1EQ?o;}#*LIop?A>U+5Ye+d zUb_NKZ;ztRs1=}3JXT-~!QaDk+RZJzXNDvWy>IDiZd=SP_({t*$XGZp_5Y!su079M za4zg=41~FiNoWE6cwV0Gk3K8d(rJ2g031Czo%qoDlyT%a!ZUE5r(lJaoC{}TB*L?i zefk%*kSp(l&;1@40#8fc*UuR87UOQQdTayQi!-2HA?v;~@t#v!&M&$X zGqdK5Ig5dL?F|iS@1G>?gK;f2n5HRUk4XGAB&4Iemre|h?fok8Wsg3q4W^e)?55v; zqYOfpb!SA)RuHu~+_B(W+%zGIw9-8J=l z9|XoZ;!^CBL*YN`zNPwC_9aA>A0R-VHINj!-llrT< dcpq!5_N)0X0gKlLM3-d!2{{~_K0NXL{{cmTbY%bl literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/ext2fs/valid_blk.c b/jni/e2fsprogs/lib/ext2fs/valid_blk.c new file mode 100755 index 0000000..db5d90a --- /dev/null +++ b/jni/e2fsprogs/lib/ext2fs/valid_blk.c @@ -0,0 +1,68 @@ +/* + * valid_blk.c --- does the inode have valid blocks? + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * This function returns 1 if the inode's block entries actually + * contain block entries. + */ +int ext2fs_inode_has_valid_blocks2(ext2_filsys fs, struct ext2_inode *inode) +{ + /* + * Only directories, regular files, and some symbolic links + * have valid block entries. + */ + if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) && + !LINUX_S_ISLNK(inode->i_mode)) + return 0; + + /* + * If the symbolic link is a "fast symlink", then the symlink + * target is stored in the block entries. + */ + if (LINUX_S_ISLNK (inode->i_mode)) { + if (ext2fs_file_acl_block(fs, inode) == 0) { + /* With no EA block, we can rely on i_blocks */ + 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[] */ + if (inode->i_size > 4 && inode->i_block[1] == 0) + return 1; /* definitely using i_block[] */ + return 0; /* Probably a fast symlink */ + } + } + + /* + * If this inode has inline data, it shouldn't have valid block + * entries. + */ + if (inode->i_flags & EXT4_INLINE_DATA_FL) + return 0; + return 1; +} + +int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode) +{ + return ext2fs_inode_has_valid_blocks2(NULL, inode); +} diff --git a/jni/e2fsprogs/lib/ext2fs/valid_blk.o b/jni/e2fsprogs/lib/ext2fs/valid_blk.o new file mode 100755 index 0000000000000000000000000000000000000000..3f47ca78a21b7bbaed59ac88c09db049e5397919 GIT binary patch literal 1624 zcmbtTL2DCH5S~p^6G>Xy617rmQpq7bbV({o4<4RcwStHgJ$P}u-E2(ACL!6Sw5DL8 z9=sO3DvBN&!HXa^UM%Dnco8p3ym{?0hY)9W-%GaZ>cxS5GxN>&X5P$u`}o?e>j6mu zArgFqp(jv)snF17w#nc)GW%`#(rW~oy&c%?M4|gL4BcO0){RJPGcp>Vj7+c^1mG^_ zj32>gS&d0P_#CTkgM)u=C-%>K_hI~1$ccBN4C}Ej9_Lw7f)9flGpzL#-~#!S;~eT! zBF_kGMGm3%n%79f_R1b|PP^k1P@8j~ZJxFEcs{`&<+-D%2X$wuZs($?izAB*K4CB0 z%6_kLrHM1!JqRja`#Ur{soA@Vv%|SjFP&iGE%noDTyA3A=7DCYm50f7y>1q(m1K5N z&dQ7S9RQ4TEj?NRY3r;s9ZNt8u_=yU!osjLmRXL?jK2sx4+T?FERk6rgCE}^jUmQ) zWFs#rcz0rnq{HHbzo-J@Avo;&g@btUUU_E&f8sb_6xSoOeE_^Clw;f*swZepy7Jq7 zB8Kl}Fq0u0-~{Ijp4~5El!s&*=M;8Kd!+|ULb$v783%?D#NAyid2mq&q%Otz?R5zG&!*su>Opa;0kN@{QZ~=1oi0 zN<6P#Q1W%Ptb@oXS_vKKSFoxd|;q^tI5e(8jk|q)VO$=?yA$SxcdBf|Tblkxz zjwAF +#endif +#include +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +#include "version.h" + +static const char *lib_version = E2FSPROGS_VERSION; +static const char *lib_date = E2FSPROGS_DATE; + +int ext2fs_parse_version_string(const char *ver_string) +{ + const char *cp; + int version = 0, dot_count = 0; + + for (cp = ver_string; *cp; cp++) { + if (*cp == '.') { + if (dot_count++) + break; + else + continue; + } + if (!isdigit(*cp)) + break; + version = (version * 10) + (*cp - '0'); + } + return version; +} + + +int ext2fs_get_library_version(const char **ver_string, + const char **date_string) +{ + if (ver_string) + *ver_string = lib_version; + if (date_string) + *date_string = lib_date; + + return ext2fs_parse_version_string(lib_version); +} diff --git a/jni/e2fsprogs/lib/ext2fs/version.o b/jni/e2fsprogs/lib/ext2fs/version.o new file mode 100755 index 0000000000000000000000000000000000000000..33c4ed3693ee5750819f200cc225f425628f2741 GIT binary patch literal 2264 zcmbtVO-vI}5T0#8N?Hs48xdL)4tQWgD;m93t%!;7KrkT@Qda%NY+mchN&4o^H{bW>z1g?hyJyb# zc?<)@3|NM(NKk+;ja&1Wn#Lf2%*uOMEzf$E%JZ=BY(BJ6X@Pvj5BbIU#75B%C0uKF z(H|@MjM#~;2IzIizC2t%WWXR}`Q}F0v5wkt*yQa&Z7b^m^%y_A0&tZ0LBd;N`E$nH zfbVv5+d9@bjGV(OaNTD#`-`}bYOO|CpuK#nRQ9c*raXIU3HQBF@FqT2PQ&UNa@P^} z!Q24pk(>Voyf4CkBKG0w0m5akc=Vm9-CSdydSEP-FIH$uKSV0W?tZWKL!X*|@Nw15q$T+-HldW|G zC+~%A?oiE_)mV$aR(Mkl|D{5jYw$rtcDnjdU`9LR4S3nMubs z&tAAlZ(#D8$fm4p&K6Q4=VVivF{K-|9GmOfYbL=&relqupGhmPHi#Mv zI!Dc38jjEqr6GdrOj3?i5ez%0%^p7Lf4K*!_SRd0{|7#4Iex5Flx{j<`i+km6F$pejW@N(fFC_Qf4L{}{d$2It)ZXc71x#TA5xTwUgGCCsaO9VZ&aF0^$8Na z)L%i2N=5PKwgT4=xj~#WT=fCQq>j+PGjXo~>~(#d^%@QS2vJMu@Ez8>-z}1CFma9o qm&y4Bn!!oE{=Mb?^)r$BNAJ7nrGJkQ(`%Dtn!$122RZtV==#6yuL6Gn literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/misc/create_inode.c b/jni/e2fsprogs/lib/misc/create_inode.c new file mode 100755 index 0000000..a3a34cd --- /dev/null +++ b/jni/e2fsprogs/lib/misc/create_inode.c @@ -0,0 +1,1092 @@ +/* + * create_inode.c --- create an inode + * + * Copyright (C) 2014 Robert Yang + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU library + * General Public License, version 2. + * %End-Header% + */ + +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE64_SOURCE 1 +#define _GNU_SOURCE 1 + +#include "config.h" +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include /* for scandir() and alphasort() */ +#if defined HAVE_SYS_XATTR_H +#include +#elif defined HAVE_ATTR_XATTR_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include +#include +#include + +#include "create_inode.h" +#include "support/nls-enable.h" + +/* 64KiB is the minimum blksize to best minimize system call overhead. */ +#define COPY_FILE_BUFLEN 65536 + +static int ext2_file_type(unsigned int mode) +{ + if (LINUX_S_ISREG(mode)) + return EXT2_FT_REG_FILE; + + if (LINUX_S_ISDIR(mode)) + return EXT2_FT_DIR; + + if (LINUX_S_ISCHR(mode)) + return EXT2_FT_CHRDEV; + + if (LINUX_S_ISBLK(mode)) + return EXT2_FT_BLKDEV; + + if (LINUX_S_ISLNK(mode)) + return EXT2_FT_SYMLINK; + + if (LINUX_S_ISFIFO(mode)) + return EXT2_FT_FIFO; + + if (LINUX_S_ISSOCK(mode)) + return EXT2_FT_SOCK; + + return 0; +} + +/* Link an inode number to a directory */ +static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino, + ext2_ino_t ino, const char *name) +{ + struct ext2_inode inode; + errcode_t retval; + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) { + com_err(__func__, retval, _("while reading inode %u"), ino); + return retval; + } + + retval = ext2fs_link(fs, parent_ino, name, ino, + ext2_file_type(inode.i_mode)); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, parent_ino); + if (retval) { + com_err(__func__, retval, + _("while expanding directory")); + return retval; + } + retval = ext2fs_link(fs, parent_ino, name, ino, + ext2_file_type(inode.i_mode)); + } + if (retval) { + com_err(__func__, retval, _("while linking \"%s\""), name); + return retval; + } + + inode.i_links_count++; + + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) + com_err(__func__, retval, _("while writing inode %u"), ino); + + return retval; +} + +/* Set the uid, gid, mode and time for the inode */ +static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino, + struct stat *st) +{ + errcode_t retval; + struct ext2_inode inode; + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) { + com_err(__func__, retval, _("while reading inode %u"), ino); + return retval; + } + + inode.i_uid = st->st_uid; + ext2fs_set_i_uid_high(inode, st->st_uid >> 16); + inode.i_gid = st->st_gid; + ext2fs_set_i_gid_high(inode, st->st_gid >> 16); + inode.i_mode = (LINUX_S_IFMT & inode.i_mode) | (~S_IFMT & st->st_mode); + inode.i_atime = st->st_atime; + inode.i_mtime = st->st_mtime; + inode.i_ctime = st->st_ctime; + + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) + com_err(__func__, retval, _("while writing inode %u"), ino); + return retval; +} + +#ifdef HAVE_LLISTXATTR +static errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino, + const char *filename) +{ + errcode_t retval, close_retval; + struct ext2_xattr_handle *handle; + ssize_t size, value_size; + char *list = NULL; + int i; + + if (no_copy_xattrs) + return 0; + + size = llistxattr(filename, NULL, 0); + if (size == -1) { + if (errno == ENOTSUP) + return 0; + retval = errno; + com_err(__func__, retval, _("while listing attributes of \"%s\""), + filename); + return retval; + } else if (size == 0) { + return 0; + } + + retval = ext2fs_xattrs_open(fs, ino, &handle); + if (retval) { + if (retval == EXT2_ET_MISSING_EA_FEATURE) + return 0; + com_err(__func__, retval, _("while opening inode %u"), ino); + return retval; + } + + retval = ext2fs_xattrs_read(handle); + if (retval) { + com_err(__func__, retval, + _("while reading xattrs for inode %u"), ino); + goto out; + } + + retval = ext2fs_get_mem(size, &list); + if (retval) { + com_err(__func__, retval, _("while allocating memory")); + goto out; + } + + size = llistxattr(filename, list, size); + if (size == -1) { + retval = errno; + com_err(__func__, retval, _("while listing attributes of \"%s\""), + filename); + goto out; + } + + for (i = 0; i < size; i += strlen(&list[i]) + 1) { + const char *name = &list[i]; + char *value; + + value_size = lgetxattr(filename, name, NULL, 0); + if (value_size == -1) { + retval = errno; + com_err(__func__, retval, + _("while reading attribute \"%s\" of \"%s\""), + name, filename); + break; + } + + retval = ext2fs_get_mem(value_size, &value); + if (retval) { + com_err(__func__, retval, _("while allocating memory")); + break; + } + + value_size = lgetxattr(filename, name, value, value_size); + if (value_size == -1) { + ext2fs_free_mem(&value); + retval = errno; + com_err(__func__, retval, + _("while reading attribute \"%s\" of \"%s\""), + name, filename); + break; + } + + retval = ext2fs_xattr_set(handle, name, value, value_size); + ext2fs_free_mem(&value); + if (retval) { + com_err(__func__, retval, + _("while writing attribute \"%s\" to inode %u"), + name, ino); + break; + } + + } + out: + ext2fs_free_mem(&list); + close_retval = ext2fs_xattrs_close(&handle); + if (close_retval) { + com_err(__func__, retval, _("while closing inode %u"), ino); + retval = retval ? retval : close_retval; + } + return retval; +} +#else /* HAVE_LLISTXATTR */ +static errcode_t set_inode_xattr(ext2_filsys fs EXT2FS_ATTR((unused)), + ext2_ino_t ino EXT2FS_ATTR((unused)), + const char *filename EXT2FS_ATTR((unused))) +{ + return 0; +} +#endif /* HAVE_LLISTXATTR */ + +#ifndef _WIN32 +/* Make a special files (block and character devices), fifo's, and sockets */ +errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, + unsigned int st_mode, unsigned int st_rdev) +{ + ext2_ino_t ino; + errcode_t retval; + struct ext2_inode inode; + unsigned long devmajor, devminor, mode; + int filetype; + + switch(st_mode & S_IFMT) { + case S_IFCHR: + mode = LINUX_S_IFCHR; + filetype = EXT2_FT_CHRDEV; + break; + case S_IFBLK: + mode = LINUX_S_IFBLK; + filetype = EXT2_FT_BLKDEV; + break; + case S_IFIFO: + mode = LINUX_S_IFIFO; + filetype = EXT2_FT_FIFO; + break; +#ifndef _WIN32 + case S_IFSOCK: + mode = LINUX_S_IFSOCK; + filetype = EXT2_FT_SOCK; + break; +#endif + default: + return EXT2_ET_INVALID_ARGUMENT; + } + + retval = ext2fs_new_inode(fs, cwd, 010755, 0, &ino); + if (retval) { + com_err(__func__, retval, _("while allocating inode \"%s\""), + name); + return retval; + } + +#ifdef DEBUGFS + printf("Allocated inode: %u\n", ino); +#endif + retval = ext2fs_link(fs, cwd, name, ino, filetype); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, cwd); + if (retval) { + com_err(__func__, retval, + _("while expanding directory")); + return retval; + } + retval = ext2fs_link(fs, cwd, name, ino, filetype); + } + if (retval) { + com_err(name, retval, _("while creating inode \"%s\""), name); + return retval; + } + if (ext2fs_test_inode_bitmap2(fs->inode_map, ino)) + com_err(__func__, 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(fs, ino, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = mode; + inode.i_atime = inode.i_ctime = inode.i_mtime = + fs->now ? fs->now : time(0); + + if (filetype != S_IFIFO) { + devmajor = major(st_rdev); + devminor = minor(st_rdev); + + if ((devmajor < 256) && (devminor < 256)) { + inode.i_block[0] = devmajor * 256 + devminor; + inode.i_block[1] = 0; + } else { + inode.i_block[0] = 0; + inode.i_block[1] = (devminor & 0xff) | (devmajor << 8) | + ((devminor & ~0xff) << 12); + } + } + inode.i_links_count = 1; + + retval = ext2fs_write_new_inode(fs, ino, &inode); + if (retval) + com_err(__func__, retval, _("while writing inode %u"), ino); + + return retval; +} +#endif + +/* Make a symlink name -> target */ +errcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, + char *target, ext2_ino_t root) +{ + char *cp; + ext2_ino_t parent_ino; + errcode_t retval; + + cp = strrchr(name, '/'); + if (cp) { + *cp = 0; + retval = ext2fs_namei(fs, root, cwd, name, &parent_ino); + if (retval) { + com_err(name, retval, 0); + return retval; + } + name = cp+1; + } else + parent_ino = cwd; + + retval = ext2fs_symlink(fs, parent_ino, 0, name, target); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, parent_ino); + if (retval) { + com_err("do_symlink_internal", retval, + _("while expanding directory")); + return retval; + } + retval = ext2fs_symlink(fs, parent_ino, 0, name, target); + } + if (retval) + com_err("ext2fs_symlink", retval, + _("while creating symlink \"%s\""), name); + return retval; +} + +/* Make a directory in the fs */ +errcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, + ext2_ino_t root) +{ + char *cp; + ext2_ino_t parent_ino; + errcode_t retval; + + + cp = strrchr(name, '/'); + if (cp) { + *cp = 0; + retval = ext2fs_namei(fs, root, cwd, name, &parent_ino); + if (retval) { + com_err(name, retval, _("while looking up \"%s\""), + name); + return retval; + } + name = cp+1; + } else + parent_ino = cwd; + + retval = ext2fs_mkdir(fs, parent_ino, 0, name); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, parent_ino); + if (retval) { + com_err(__func__, retval, + _("while expanding directory")); + return retval; + } + retval = ext2fs_mkdir(fs, parent_ino, 0, name); + } + if (retval) + com_err("ext2fs_mkdir", retval, + _("while creating directory \"%s\""), name); + return retval; +} + +#if !defined HAVE_PREAD64 && !defined HAVE_PREAD +static ssize_t my_pread(int fd, void *buf, size_t count, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) < 0) + return 0; + + return read(fd, buf, count); +} +#endif /* !defined HAVE_PREAD64 && !defined HAVE_PREAD */ + +static errcode_t copy_file_chunk(ext2_filsys fs, int fd, ext2_file_t e2_file, + off_t start, off_t end, char *buf, + char *zerobuf) +{ + off_t off, bpos; + ssize_t got, blen; + unsigned int written; + char *ptr; + errcode_t err = 0; + + for (off = start; off < end; off += COPY_FILE_BUFLEN) { +#ifdef HAVE_PREAD64 + got = pread64(fd, buf, COPY_FILE_BUFLEN, off); +#elif HAVE_PREAD + got = pread(fd, buf, COPY_FILE_BUFLEN, off); +#else + got = my_pread(fd, buf, COPY_FILE_BUFLEN, off); +#endif + if (got < 0) { + err = errno; + goto fail; + } + for (bpos = 0, ptr = buf; bpos < got; bpos += fs->blocksize) { + blen = fs->blocksize; + if (blen > got - bpos) + blen = got - bpos; + if (memcmp(ptr, zerobuf, blen) == 0) { + ptr += blen; + continue; + } + err = ext2fs_file_llseek(e2_file, off + bpos, + EXT2_SEEK_SET, NULL); + if (err) + goto fail; + while (blen > 0) { + err = ext2fs_file_write(e2_file, ptr, blen, + &written); + if (err) + goto fail; + if (written == 0) { + err = EIO; + goto fail; + } + blen -= written; + ptr += written; + } + } + } +fail: + return err; +} + +#if defined(SEEK_DATA) && defined(SEEK_HOLE) +static errcode_t try_lseek_copy(ext2_filsys fs, int fd, struct stat *statbuf, + ext2_file_t e2_file, char *buf, char *zerobuf) +{ + off_t data = 0, hole; + off_t data_blk, hole_blk; + errcode_t err = 0; + + /* Try to use SEEK_DATA and SEEK_HOLE */ + while (data < statbuf->st_size) { + data = lseek(fd, data, SEEK_DATA); + if (data < 0) { + if (errno == ENXIO) + break; + return EXT2_ET_UNIMPLEMENTED; + } + hole = lseek(fd, data, SEEK_HOLE); + if (hole < 0) + return EXT2_ET_UNIMPLEMENTED; + + data_blk = data & ~(off_t)(fs->blocksize - 1); + hole_blk = ((hole + (off_t)(fs->blocksize - 1)) & + ~(off_t)(fs->blocksize - 1)); + err = copy_file_chunk(fs, fd, e2_file, data_blk, hole_blk, buf, + zerobuf); + if (err) + return err; + + data = hole; + } + + return err; +} +#endif /* SEEK_DATA and SEEK_HOLE */ + +#if defined(FS_IOC_FIEMAP) +static errcode_t try_fiemap_copy(ext2_filsys fs, int fd, ext2_file_t e2_file, + char *buf, char *zerobuf) +{ +#define EXTENT_MAX_COUNT 512 + struct fiemap *fiemap_buf; + struct fiemap_extent *ext_buf, *ext; + int ext_buf_size, fie_buf_size; + off_t pos = 0; + unsigned int i; + errcode_t err; + + ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent); + fie_buf_size = sizeof(struct fiemap) + ext_buf_size; + + err = ext2fs_get_memzero(fie_buf_size, &fiemap_buf); + if (err) + return err; + + ext_buf = fiemap_buf->fm_extents; + memset(fiemap_buf, 0, fie_buf_size); + fiemap_buf->fm_length = FIEMAP_MAX_OFFSET; + fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC; + fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT; + + do { + fiemap_buf->fm_start = pos; + memset(ext_buf, 0, ext_buf_size); + err = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf); + if (err < 0 && (errno == EOPNOTSUPP || errno == ENOTTY)) { + err = EXT2_ET_UNIMPLEMENTED; + goto out; + } else if (err < 0) { + err = errno; + goto out; + } else if (fiemap_buf->fm_mapped_extents == 0) + goto out; + for (i = 0, ext = ext_buf; i < fiemap_buf->fm_mapped_extents; + i++, ext++) { + err = copy_file_chunk(fs, fd, e2_file, ext->fe_logical, + ext->fe_logical + ext->fe_length, + buf, zerobuf); + if (err) + goto out; + } + + ext--; + /* Record file's logical offset this time */ + pos = ext->fe_logical + ext->fe_length; + /* + * If fm_extents array has been filled and + * there are extents left, continue to cycle. + */ + } while (fiemap_buf->fm_mapped_extents == EXTENT_MAX_COUNT && + !(ext->fe_flags & FIEMAP_EXTENT_LAST)); +out: + ext2fs_free_mem(&fiemap_buf); + return err; +} +#endif /* FS_IOC_FIEMAP */ + +static errcode_t copy_file(ext2_filsys fs, int fd, struct stat *statbuf, + ext2_ino_t ino) +{ + ext2_file_t e2_file; + char *buf = NULL, *zerobuf = NULL; + errcode_t err, close_err; + + err = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file); + if (err) + return err; + + err = ext2fs_get_mem(COPY_FILE_BUFLEN, &buf); + if (err) + goto out; + + err = ext2fs_get_memzero(fs->blocksize, &zerobuf); + if (err) + goto out; + +#if defined(SEEK_DATA) && defined(SEEK_HOLE) + err = try_lseek_copy(fs, fd, statbuf, e2_file, buf, zerobuf); + if (err != EXT2_ET_UNIMPLEMENTED) + goto out; +#endif + +#if defined(FS_IOC_FIEMAP) + err = try_fiemap_copy(fs, fd, e2_file, buf, zerobuf); + if (err != EXT2_ET_UNIMPLEMENTED) + goto out; +#endif + + err = copy_file_chunk(fs, fd, e2_file, 0, statbuf->st_size, buf, + zerobuf); +out: + ext2fs_free_mem(&zerobuf); + ext2fs_free_mem(&buf); + close_err = ext2fs_file_close(e2_file); + if (err == 0) + err = close_err; + return err; +} + +static int is_hardlink(struct hdlinks_s *hdlinks, dev_t dev, ino_t ino) +{ + int i; + + for (i = 0; i < hdlinks->count; i++) { + if (hdlinks->hdl[i].src_dev == dev && + hdlinks->hdl[i].src_ino == ino) + return i; + } + return -1; +} + +/* Copy the native file to the fs */ +errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src, + const char *dest, ext2_ino_t root) +{ + int fd; + struct stat statbuf; + ext2_ino_t newfile, parent_ino; + errcode_t retval; + struct ext2_inode inode; + char *cp; + + fd = ext2fs_open_file(src, O_RDONLY, 0); + if (fd < 0) { + retval = errno; + com_err(__func__, retval, _("while opening \"%s\" to copy"), + src); + return retval; + } + if (fstat(fd, &statbuf) < 0) { + retval = errno; + goto out; + } + + cp = strrchr(dest, '/'); + if (cp) { + *cp = 0; + retval = ext2fs_namei(fs, root, cwd, dest, &parent_ino); + if (retval) { + com_err(dest, retval, _("while looking up \"%s\""), + dest); + goto out; + } + dest = cp+1; + } else + parent_ino = cwd; + + retval = ext2fs_namei(fs, root, parent_ino, dest, &newfile); + if (retval == 0) { + retval = EXT2_ET_FILE_EXISTS; + goto out; + } + + retval = ext2fs_new_inode(fs, parent_ino, 010755, 0, &newfile); + if (retval) + goto out; +#ifdef DEBUGFS + printf("Allocated inode: %u\n", newfile); +#endif + retval = ext2fs_link(fs, parent_ino, dest, newfile, EXT2_FT_REG_FILE); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, parent_ino); + if (retval) + goto out; + retval = ext2fs_link(fs, parent_ino, dest, newfile, + EXT2_FT_REG_FILE); + } + if (retval) + goto out; + if (ext2fs_test_inode_bitmap2(fs->inode_map, newfile)) + com_err(__func__, 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(fs, newfile, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = (statbuf.st_mode & ~S_IFMT) | LINUX_S_IFREG; + inode.i_atime = inode.i_ctime = inode.i_mtime = + fs->now ? fs->now : time(0); + inode.i_links_count = 1; + retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size); + if (retval) + goto out; + if (ext2fs_has_feature_inline_data(fs->super)) { + inode.i_flags |= EXT4_INLINE_DATA_FL; + } else if (ext2fs_has_feature_extents(fs->super)) { + ext2_extent_handle_t handle; + + inode.i_flags &= ~EXT4_EXTENTS_FL; + retval = ext2fs_extent_open2(fs, newfile, &inode, &handle); + if (retval) + goto out; + ext2fs_extent_free(handle); + } + + retval = ext2fs_write_new_inode(fs, newfile, &inode); + if (retval) + goto out; + if (inode.i_flags & EXT4_INLINE_DATA_FL) { + retval = ext2fs_inline_data_init(fs, newfile); + if (retval) + goto out; + } + if (LINUX_S_ISREG(inode.i_mode)) { + retval = copy_file(fs, fd, &statbuf, newfile); + if (retval) + goto out; + } +out: + close(fd); + return retval; +} + +struct file_info { + char *path; + size_t path_len; + size_t path_max_len; +}; + +static errcode_t path_append(struct file_info *target, const char *file) +{ + if (strlen(file) + target->path_len + 1 > target->path_max_len) { + void *p; + target->path_max_len *= 2; + p = realloc(target->path, target->path_max_len); + if (p == NULL) + return EXT2_ET_NO_MEMORY; + target->path = p; + } + target->path_len += sprintf(target->path + target->path_len, "/%s", + file); + return 0; +} + +#ifdef _WIN32 +static int scandir(const char *dir_name, struct dirent ***name_list, + int (*filter)(const struct dirent*), + int (*compar)(const struct dirent**, const struct dirent**)) { + DIR *dir; + struct dirent *dent; + struct dirent **temp_list = NULL; + size_t temp_list_size = 0; // unit: num of dirent + size_t num_dent = 0; + + dir = opendir(dir_name); + if (dir == NULL) { + return -1; + } + + while ((dent = readdir(dir))) { + if (filter != NULL && !(*filter)(dent)) + continue; + + // re-allocate the list + if (num_dent == temp_list_size) { + size_t new_list_size = temp_list_size + 32; + struct dirent **new_list = (struct dirent**)realloc( + temp_list, new_list_size * sizeof(struct dirent*)); + if (new_list == NULL) + goto out_err; + temp_list_size = new_list_size; + temp_list = new_list; + } + // add the copy of dirent to the list + temp_list[num_dent] = (struct dirent*)malloc((dent->d_reclen + 3) & ~3); + if (!temp_list[num_dent]) + goto out_err; + memcpy(temp_list[num_dent], dent, dent->d_reclen); + num_dent++; + } + closedir(dir); + + if (compar != NULL) { + qsort(temp_list, num_dent, sizeof(struct dirent*), + (int (*)(const void*, const void*))compar); + } + *name_list = temp_list; + return num_dent; + +out_err: + closedir(dir); + while (num_dent > 0) + free(temp_list[--num_dent]); + free(temp_list); + return -1; +} + +static int alphasort(const struct dirent **a, const struct dirent **b) { + return strcoll((*a)->d_name, (*b)->d_name); +} +#endif + +/* Copy files from source_dir to fs in alphabetical order */ +static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, + const char *source_dir, ext2_ino_t root, + struct hdlinks_s *hdlinks, + struct file_info *target, + struct fs_ops_callbacks *fs_callbacks) +{ + const char *name; + struct dirent **dent; + struct stat st; + unsigned int save_inode; + ext2_ino_t ino; + errcode_t retval = 0; + int hdlink; + size_t cur_dir_path_len; + int i, num_dents; + + if (chdir(source_dir) < 0) { + retval = errno; + com_err(__func__, retval, + _("while changing working directory to \"%s\""), + source_dir); + return retval; + } + + num_dents = scandir(".", &dent, NULL, alphasort); + + if (num_dents < 0) { + retval = errno; + com_err(__func__, retval, + _("while scanning directory \"%s\""), source_dir); + return retval; + } + + for (i = 0; i < num_dents; free(dent[i]), i++) { + name = dent[i]->d_name; + if ((!strcmp(name, ".")) || (!strcmp(name, ".."))) + continue; + if (lstat(name, &st)) { + retval = errno; + com_err(__func__, retval, _("while lstat \"%s\""), + name); + goto out; + } + + /* Check for hardlinks */ + save_inode = 0; + if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && + st.st_nlink > 1) { + hdlink = is_hardlink(hdlinks, st.st_dev, st.st_ino); + if (hdlink >= 0) { + retval = add_link(fs, parent_ino, + hdlinks->hdl[hdlink].dst_ino, + name); + if (retval) { + com_err(__func__, retval, + "while linking %s", name); + goto out; + } + continue; + } else + save_inode = 1; + } + + cur_dir_path_len = target->path_len; + retval = path_append(target, name); + if (retval) { + com_err(__func__, retval, + "while appending %s", name); + goto out; + } + + if (fs_callbacks && fs_callbacks->create_new_inode) { + retval = fs_callbacks->create_new_inode(fs, + target->path, name, parent_ino, root, + st.st_mode & S_IFMT); + if (retval) + goto out; + } + + switch(st.st_mode & S_IFMT) { + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: +#ifndef _WIN32 + case S_IFSOCK: + retval = do_mknod_internal(fs, parent_ino, name, + st.st_mode, st.st_rdev); + if (retval) { + com_err(__func__, retval, + _("while creating special file " + "\"%s\""), name); + goto out; + } + break; + case S_IFLNK: { + char *ln_target; + int read_cnt; + + ln_target = malloc(st.st_size + 1); + if (ln_target == NULL) { + com_err(__func__, retval, + _("malloc failed")); + goto out; + } + read_cnt = readlink(name, ln_target, + st.st_size + 1); + if (read_cnt == -1) { + retval = errno; + com_err(__func__, retval, + _("while trying to read link \"%s\""), + name); + free(ln_target); + goto out; + } + if (read_cnt > st.st_size) { + com_err(__func__, retval, + _("symlink increased in size " + "between lstat() and readlink()")); + free(ln_target); + goto out; + } + ln_target[read_cnt] = '\0'; + retval = do_symlink_internal(fs, parent_ino, name, + ln_target, root); + free(ln_target); + if (retval) { + com_err(__func__, retval, + _("while writing symlink\"%s\""), + name); + goto out; + } + break; + } +#endif /* !_WIN32 */ + case S_IFREG: + retval = do_write_internal(fs, parent_ino, name, name, + root); + if (retval) { + com_err(__func__, retval, + _("while writing file \"%s\""), name); + goto out; + } + break; + case S_IFDIR: + /* Don't choke on /lost+found */ + if (parent_ino == EXT2_ROOT_INO && + strcmp(name, "lost+found") == 0) + goto find_lnf; + retval = do_mkdir_internal(fs, parent_ino, name, + root); + if (retval) { + com_err(__func__, retval, + _("while making dir \"%s\""), name); + goto out; + } +find_lnf: + retval = ext2fs_namei(fs, root, parent_ino, + name, &ino); + if (retval) { + com_err(name, retval, 0); + goto out; + } + /* Populate the dir recursively*/ + retval = __populate_fs(fs, ino, name, root, hdlinks, + target, fs_callbacks); + if (retval) + goto out; + if (chdir("..")) { + retval = errno; + com_err(__func__, retval, + _("while changing directory")); + goto out; + } + break; + default: + com_err(__func__, 0, + _("ignoring entry \"%s\""), name); + } + + retval = ext2fs_namei(fs, root, parent_ino, name, &ino); + if (retval) { + com_err(name, retval, _("while looking up \"%s\""), + name); + goto out; + } + + retval = set_inode_extra(fs, ino, &st); + if (retval) { + com_err(__func__, retval, + _("while setting inode for \"%s\""), name); + goto out; + } + + retval = set_inode_xattr(fs, ino, name); + if (retval) { + com_err(__func__, retval, + _("while setting xattrs for \"%s\""), name); + goto out; + } + + if (fs_callbacks && fs_callbacks->end_create_new_inode) { + retval = fs_callbacks->end_create_new_inode(fs, + target->path, name, parent_ino, root, + st.st_mode & S_IFMT); + if (retval) + goto out; + } + + /* Save the hardlink ino */ + if (save_inode) { + /* + * Check whether need more memory, and we don't need + * free() since the lifespan will be over after the fs + * populated. + */ + if (hdlinks->count == hdlinks->size) { + void *p = realloc(hdlinks->hdl, + (hdlinks->size + HDLINK_CNT) * + sizeof(struct hdlink_s)); + if (p == NULL) { + retval = EXT2_ET_NO_MEMORY; + com_err(name, retval, + _("while saving inode data")); + goto out; + } + hdlinks->hdl = p; + hdlinks->size += HDLINK_CNT; + } + hdlinks->hdl[hdlinks->count].src_dev = st.st_dev; + hdlinks->hdl[hdlinks->count].src_ino = st.st_ino; + hdlinks->hdl[hdlinks->count].dst_ino = ino; + hdlinks->count++; + } + target->path_len = cur_dir_path_len; + target->path[target->path_len] = 0; + } + +out: + for (; i < num_dents; free(dent[i]), i++); + free(dent); + return retval; +} + +errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino, + const char *source_dir, ext2_ino_t root, + struct fs_ops_callbacks *fs_callbacks) +{ + struct file_info file_info; + struct hdlinks_s hdlinks; + errcode_t retval; + + if (!(fs->flags & EXT2_FLAG_RW)) { + com_err(__func__, 0, "Filesystem opened readonly"); + return EROFS; + } + + hdlinks.count = 0; + hdlinks.size = HDLINK_CNT; + hdlinks.hdl = realloc(NULL, hdlinks.size * sizeof(struct hdlink_s)); + if (hdlinks.hdl == NULL) { + retval = errno; + com_err(__func__, retval, _("while allocating memory")); + return retval; + } + + file_info.path_len = 0; + file_info.path_max_len = 255; + file_info.path = calloc(file_info.path_max_len, 1); + + retval = set_inode_xattr(fs, root, source_dir); + if (retval) { + com_err(__func__, retval, + _("while copying xattrs on root directory")); + goto out; + } + + retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks, + &file_info, fs_callbacks); + +out: + free(file_info.path); + free(hdlinks.hdl); + return retval; +} + +errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, + const char *source_dir, ext2_ino_t root) +{ + return populate_fs2(fs, parent_ino, source_dir, root, NULL); +} diff --git a/jni/e2fsprogs/lib/misc/create_inode.o b/jni/e2fsprogs/lib/misc/create_inode.o new file mode 100755 index 0000000000000000000000000000000000000000..8352cd685b51f867213d49b92ba54d52815c8892 GIT binary patch literal 25504 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 G>;FI4aHLHD literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/devname.c b/jni/e2fsprogs/lib/support/devname.c new file mode 100755 index 0000000..e0306dd --- /dev/null +++ b/jni/e2fsprogs/lib/support/devname.c @@ -0,0 +1,65 @@ +/* + * devname.c --- Support function to translate a user provided string + * identifying a device to an actual device path + * + * Copyright (C) 2022 Red Hat, Inc., Lukas Czerner + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#include + +#include "config.h" +#include "devname.h" +#include "nls-enable.h" + +/* + * blkid_get_devname() is primarily intended for parsing "NAME=value" + * tokens. It will return the device matching the specified token, NULL if + * nothing is found, or copy of the string if it's not in "NAME=value" + * format. + * get_devname() takes the same parameters and works the same way as + * blkid_get_devname() except it can handle '=' in the file name. + */ +char *get_devname(blkid_cache cache, const char *token, const char *value) +{ + int is_file = 0; + char *ret = NULL; + + if (!token) + goto out; + + if (value) { + ret = blkid_get_devname(cache, token, value); + goto out; + } + + if (access(token, F_OK) == 0) + is_file = 1; + + ret = blkid_get_devname(cache, token, NULL); + if (ret) { + /* + * In case of collision prefer the result from + * blkid_get_devname() to avoid a file masking file system with + * existing tag. + */ + if (is_file && (strcmp(ret, token) != 0)) { + fprintf(stderr, + _("Collision found: '%s' refers to both '%s' " + "and a file '%s'. Using '%s'!\n"), + token, ret, token, ret); + } + goto out; + } + + if (is_file) + ret = strdup(token); +out: + return ret; +} diff --git a/jni/e2fsprogs/lib/support/devname.o b/jni/e2fsprogs/lib/support/devname.o new file mode 100755 index 0000000000000000000000000000000000000000..defc34d3ad3b9e773fa5ca418b77490de7bae980 GIT binary patch literal 1936 zcmbu9O=uHQ5P)a1t&KIdMXeR8X2nX2(8bih;%TM+M35rIf(J2fcQ;LJvRihyrP_jp zdhsGHdQ_=Ju=OYv+neB}M+FftN>zj$6+9$hi8Gt`n$0#jIq-I7zBe=PW!{jx=PzFf z2?B5t;0=^LP61l#%eLZ~3N&J5Q4~IGOo~ez?_h3zCYpaHM)TjBp-^mt)nWq_7R5w9 z1@Ibc?m2}k*Q^x60xXk1Ka;@t1jZ``Ecs|1D2269scx=KS&fI_1jVi+r!%}-LWzX|X2SxWiE9D(eqhXV)IU*U&g>z8If|$J z?YOAk8kBPBZv0Hzr$uLMO!h5dFXrBgiBEl2CX;s3mMJBzF;hPybslj#CEG|Ewj;Tg zG-SD{5>riGQl(@%V|czS4LWIa*s~8c0%#c(y>U#VVzFL1CimjuBrPQc!kqySrVa}2 zktlQ_+s8Ov49+zv@yLOer=cfxp}&!+5^sX9Usym5bqjeN{4Q4879q3+FL-1tCoE#6 zpgi!vR({{(z9D0Y_dMOeyt2B1<}TlTyx)uL8ZO?Oax_3|4NgN=Eq;FuezpcbT!Y7v zleFV|;4E#*b!HLAm)?|VW(DIHeSF7eG{7>mPh*{kkFPMhH^ARBz8ks!6+SZF8sMK9 zr~B+=HmN^8-sI!dHU0}p-&7eS-R?~6ct0aV?sVwy8HipT}&3M6iBgVzXOmOu^-so9t4*7^GRG_X#tf|8G1*pKA0l&ec_RQ9jR{GwkIMqZuR?Y~^DX zxR-)_63ma`9%sHVcvTHniS1{sV)l@&uzUq=zwqDB*(Efp_3sL6H18AjkN%Z-KIc=& Sf@dRwJUc(dG%3mr=Kli>_t6Ca literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/dict.c b/jni/e2fsprogs/lib/support/dict.c new file mode 100755 index 0000000..06dda7e --- /dev/null +++ b/jni/e2fsprogs/lib/support/dict.c @@ -0,0 +1,1542 @@ +/* + * Dictionary Abstract Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $ + * $Name: kazlib_1_20 $ + * The work has been modified. + */ + +#define DICT_NODEBUG + +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + +#include "config.h" +#include +#include +#ifdef DICT_NODEBUG +#define dict_assert(x) +#else +#include +#define dict_assert(x) assert(x) +#endif +#define DICT_IMPLEMENTATION +#include "dict.h" + +#ifdef KAZLIB_RCSID +static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $"; +#endif + +/* + * These macros provide short convenient names for structure members, + * which are embellished with dict_ prefixes so that they are + * properly confined to the documented namespace. It's legal for a + * program which uses dict to define, for instance, a macro called ``parent''. + * Such a macro would interfere with the dnode_t struct definition. + * In general, highly portable and reusable C modules which expose their + * structures need to confine structure member names to well-defined spaces. + * The resulting identifiers aren't necessarily convenient to use, nor + * readable, in the implementation, however! + */ + +#define left dict_left +#define right dict_right +#define parent dict_parent +#define color dict_color +#define key dict_key +#define data dict_data + +#define nilnode dict_nilnode +#define nodecount dict_nodecount +#define maxcount dict_maxcount +#define compare dict_compare +#define allocnode dict_allocnode +#define freenode dict_freenode +#define context dict_context +#define dupes dict_dupes + +#define dictptr dict_dictptr + +#define dict_root(D) ((D)->nilnode.left) +#define dict_nil(D) (&(D)->nilnode) +#define DICT_DEPTH_MAX 64 + +static dnode_t *dnode_alloc(void *context); +static void dnode_free(dnode_t *node, void *context); + +/* + * Perform a ``left rotation'' adjustment on the tree. The given node P and + * its right child C are rearranged so that the P instead becomes the left + * child of C. The left subtree of C is inherited as the new right subtree + * for P. The ordering of the keys within the tree is thus preserved. + */ + +static void rotate_left(dnode_t *upper) +{ + dnode_t *lower, *lowleft, *upparent; + + lower = upper->right; + upper->right = lowleft = lower->left; + lowleft->parent = upper; + + lower->parent = upparent = upper->parent; + + /* don't need to check for root node here because root->parent is + the sentinel nil node, and root->parent->left points back to root */ + + if (upper == upparent->left) { + upparent->left = lower; + } else { + dict_assert (upper == upparent->right); + upparent->right = lower; + } + + lower->left = upper; + upper->parent = lower; +} + +/* + * This operation is the ``mirror'' image of rotate_left. It is + * the same procedure, but with left and right interchanged. + */ + +static void rotate_right(dnode_t *upper) +{ + dnode_t *lower, *lowright, *upparent; + + lower = upper->left; + upper->left = lowright = lower->right; + lowright->parent = upper; + + lower->parent = upparent = upper->parent; + + if (upper == upparent->right) { + upparent->right = lower; + } else { + dict_assert (upper == upparent->left); + upparent->left = lower; + } + + lower->right = upper; + upper->parent = lower; +} + +/* + * Do a postorder traversal of the tree rooted at the specified + * node and free everything under it. Used by dict_free(). + */ + +static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) +{ + if (node == nil) + return; + free_nodes(dict, node->left, nil); + free_nodes(dict, node->right, nil); + dict->freenode(node, dict->context); +} + +/* + * This procedure performs a verification that the given subtree is a binary + * search tree. It performs an inorder traversal of the tree using the + * dict_next() successor function, verifying that the key of each node is + * strictly lower than that of its successor, if duplicates are not allowed, + * or lower or equal if duplicates are allowed. This function is used for + * debugging purposes. + */ +#ifndef DICT_NODEBUG +static int verify_bintree(dict_t *dict) +{ + dnode_t *first, *next; + + first = dict_first(dict); + + if (dict->dupes) { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) > 0) + return 0; + first = next; + } + } else { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) >= 0) + return 0; + first = next; + } + } + return 1; +} + +/* + * This function recursively verifies that the given binary subtree satisfies + * three of the red black properties. It checks that every red node has only + * black children. It makes sure that each node is either red or black. And it + * checks that every path has the same count of black nodes from root to leaf. + * It returns the blackheight of the given subtree; this allows blackheights to + * be computed recursively and compared for left and right siblings for + * mismatches. It does not check for every nil node being black, because there + * is only one sentinel nil node. The return value of this function is the + * black height of the subtree rooted at the node ``root'', or zero if the + * subtree is not red-black. + */ + +static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) +{ + unsigned height_left, height_right; + + if (root != nil) { + height_left = verify_redblack(nil, root->left); + height_right = verify_redblack(nil, root->right); + if (height_left == 0 || height_right == 0) + return 0; + if (height_left != height_right) + return 0; + if (root->color == dnode_red) { + if (root->left->color != dnode_black) + return 0; + if (root->right->color != dnode_black) + return 0; + return height_left; + } + if (root->color != dnode_black) + return 0; + return height_left + 1; + } + return 1; +} + +/* + * Compute the actual count of nodes by traversing the tree and + * return it. This could be compared against the stored count to + * detect a mismatch. + */ + +static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) +{ + if (root == nil) + return 0; + else + return 1 + verify_node_count(nil, root->left) + + verify_node_count(nil, root->right); +} +#endif + +/* + * Verify that the tree contains the given node. This is done by + * traversing all of the nodes and comparing their pointers to the + * given pointer. Returns 1 if the node is found, otherwise + * returns zero. It is intended for debugging purposes. + */ + +static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) +{ + if (root != nil) { + return root == node + || verify_dict_has_node(nil, root->left, node) + || verify_dict_has_node(nil, root->right, node); + } + return 0; +} + + +#ifdef E2FSCK_NOTUSED +/* + * Dynamically allocate and initialize a dictionary object. + */ + +dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp) +{ + dict_t *new = malloc(sizeof *new); + + if (new) { + new->compare = comp; + new->allocnode = dnode_alloc; + new->freenode = dnode_free; + new->context = NULL; + new->cmp_ctx = NULL; + new->nodecount = 0; + new->maxcount = maxcount; + new->nilnode.left = &new->nilnode; + new->nilnode.right = &new->nilnode; + new->nilnode.parent = &new->nilnode; + new->nilnode.color = dnode_black; + new->dupes = 0; + } + return new; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Select a different set of node allocator routines. + */ + +void dict_set_allocator(dict_t *dict, dnode_alloc_t al, + dnode_free_t fr, void *context) +{ + dict_assert (dict_count(dict) == 0); + dict_assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); + + dict->allocnode = al ? al : dnode_alloc; + dict->freenode = fr ? fr : dnode_free; + dict->context = context; +} + +void dict_set_cmp_context(dict_t *dict, const void *cmp_ctx) +{ + dict_assert (!dict->cmp_ctx); + dict_assert (dict_count(dict) == 0); + + dict->cmp_ctx = (void *)cmp_ctx; +} + +#ifdef E2FSCK_NOTUSED +/* + * Free a dynamically allocated dictionary object. Removing the nodes + * from the tree before deleting it is required. + */ + +void dict_destroy(dict_t *dict) +{ + dict_assert (dict_isempty(dict)); + free(dict); +} +#endif + +/* + * Free all the nodes in the dictionary by using the dictionary's + * installed free routine. The dictionary is emptied. + */ + +void dict_free_nodes(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + free_nodes(dict, root, nil); + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; +} + +#ifdef E2FSCK_NOTUSED +/* + * Obsolescent function, equivalent to dict_free_nodes + */ +void dict_free(dict_t *dict) +{ +#ifdef KAZLIB_OBSOLESCENT_DEBUG + dict_assert ("call to obsolescent function dict_free()" && 0); +#endif + dict_free_nodes(dict); +} +#endif + +/* + * Initialize a user-supplied dictionary object. + */ + +dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) +{ + dict->compare = comp; + dict->allocnode = dnode_alloc; + dict->freenode = dnode_free; + dict->context = NULL; + dict->nodecount = 0; + dict->maxcount = maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = 0; + return dict; +} + +#ifdef E2FSCK_NOTUSED +/* + * Initialize a dictionary in the likeness of another dictionary + */ + +void dict_init_like(dict_t *dict, const dict_t *template) +{ + dict->compare = template->compare; + dict->allocnode = template->allocnode; + dict->freenode = template->freenode; + dict->context = template->context; + dict->nodecount = 0; + dict->maxcount = template->maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = template->dupes; + + dict_assert (dict_similar(dict, template)); +} + +/* + * Remove all nodes from the dictionary (without freeing them in any way). + */ + +static void dict_clear(dict_t *dict) +{ + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict_assert (dict->nilnode.color == dnode_black); +} +#endif /* E2FSCK_NOTUSED */ + + +/* + * Verify the integrity of the dictionary structure. This is provided for + * debugging purposes, and should be placed in assert statements. Just because + * this function succeeds doesn't mean that the tree is not corrupt. Certain + * corruptions in the tree may simply cause undefined behavior. + */ +#ifndef DICT_NODEBUG +int dict_verify(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + + /* check that the sentinel node and root node are black */ + if (root->color != dnode_black) + return 0; + if (nil->color != dnode_black) + return 0; + if (nil->right != nil) + return 0; + /* nil->left is the root node; check that its parent pointer is nil */ + if (nil->left->parent != nil) + return 0; + /* perform a weak test that the tree is a binary search tree */ + if (!verify_bintree(dict)) + return 0; + /* verify that the tree is a red-black tree */ + if (!verify_redblack(nil, root)) + return 0; + if (verify_node_count(nil, root) != dict_count(dict)) + return 0; + return 1; +} +#endif /* DICT_NODEBUG */ + +#ifdef E2FSCK_NOTUSED +/* + * Determine whether two dictionaries are similar: have the same comparison and + * allocator functions, and same status as to whether duplicates are allowed. + */ +int dict_similar(const dict_t *left, const dict_t *right) +{ + if (left->compare != right->compare) + return 0; + + if (left->allocnode != right->allocnode) + return 0; + + if (left->freenode != right->freenode) + return 0; + + if (left->context != right->context) + return 0; + + if (left->dupes != right->dupes) + return 0; + + return 1; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Locate a node in the dictionary having the given key. + * If the node is not found, a null a pointer is returned (rather than + * a pointer that dictionary's nil sentinel node), otherwise a pointer to the + * located node is returned. + */ + +dnode_t *dict_lookup(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *saved; + int result; + + /* simple binary search adapted for trees that contain duplicate keys */ + + while (root != nil) { + result = dict->compare(dict->cmp_ctx, key, root->key); + if (result < 0) + root = root->left; + else if (result > 0) + root = root->right; + else { + if (!dict->dupes) { /* no duplicates, return match */ + return root; + } else { /* could be dupes, find leftmost one */ + do { + saved = root; + root = root->left; + while (root != nil + && dict->compare(dict->cmp_ctx, key, root->key)) + root = root->right; + } while (root != nil); + return saved; + } + } + } + + return NULL; +} + +#ifdef E2FSCK_NOTUSED +/* + * Look for the node corresponding to the lowest key that is equal to or + * greater than the given key. If there is no such node, return null. + */ + +dnode_t *dict_lower_bound(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(dict->cmp_ctx, key, root->key); + + if (result > 0) { + root = root->right; + } else if (result < 0) { + tentative = root; + root = root->left; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->left; + } + } + } + + return tentative; +} + +/* + * Look for the node corresponding to the greatest key that is equal to or + * lower than the given key. If there is no such node, return null. + */ + +dnode_t *dict_upper_bound(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(dict->cmp_ctx, key, root->key); + + if (result < 0) { + root = root->left; + } else if (result > 0) { + tentative = root; + root = root->right; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->right; + } + } + } + + return tentative; +} +#endif + +/* + * Insert a node into the dictionary. The node should have been + * initialized with a data field. All other fields are ignored. + * The behavior is undefined if the user attempts to insert into + * a dictionary that is already full (for which the dict_isfull() + * function returns true). + */ + +void dict_insert(dict_t *dict, dnode_t *node, const void *key) +{ + dnode_t *where = dict_root(dict), *nil = dict_nil(dict); + dnode_t *parent = nil, *uncle, *grandpa; + int result = -1; + + node->key = key; + + dict_assert (!dict_isfull(dict)); + dict_assert (!dict_contains(dict, node)); + dict_assert (!dnode_is_in_a_dict(node)); + + /* basic binary tree insert */ + + while (where != nil) { + parent = where; + result = dict->compare(dict->cmp_ctx, key, where->key); + /* trap attempts at duplicate key insertion unless it's explicitly allowed */ + dict_assert (dict->dupes || result != 0); + if (result < 0) + where = where->left; + else + where = where->right; + } + + dict_assert (where == nil); + + if (result < 0) + parent->left = node; + else + parent->right = node; + + node->parent = parent; + node->left = nil; + node->right = nil; + + dict->nodecount++; + + /* red black adjustments */ + + node->color = dnode_red; + + while (parent->color == dnode_red) { + grandpa = parent->parent; + if (parent == grandpa->left) { + uncle = grandpa->right; + if (uncle->color == dnode_red) { /* red parent, red uncle */ + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { /* red parent, black uncle */ + if (node == parent->right) { + rotate_left(parent); + parent = node; + dict_assert (grandpa == parent->parent); + /* rotation between parent and child preserves grandpa */ + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_right(grandpa); + break; + } + } else { /* symmetric cases: parent == parent->parent->right */ + uncle = grandpa->left; + if (uncle->color == dnode_red) { + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { + if (node == parent->left) { + rotate_right(parent); + parent = node; + dict_assert (grandpa == parent->parent); + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_left(grandpa); + break; + } + } + } + + dict_root(dict)->color = dnode_black; + + dict_assert (dict_verify(dict)); +} + +#ifdef E2FSCK_NOTUSED +/* + * Delete the given node from the dictionary. If the given node does not belong + * to the given dictionary, undefined behavior results. A pointer to the + * deleted node is returned. + */ + +dnode_t *dict_delete(dict_t *dict, dnode_t *delete) +{ + dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; + + /* basic deletion */ + + dict_assert (!dict_isempty(dict)); + dict_assert (dict_contains(dict, delete)); + + /* + * If the node being deleted has two children, then we replace it with its + * successor (i.e. the leftmost node in the right subtree.) By doing this, + * we avoid the traditional algorithm under which the successor's key and + * value *only* move to the deleted node and the successor is spliced out + * from the tree. We cannot use this approach because the user may hold + * pointers to the successor, or nodes may be inextricably tied to some + * other structures by way of embedding, etc. So we must splice out the + * node we are given, not some other node, and must not move contents from + * one node to another behind the user's back. + */ + + if (delete->left != nil && delete->right != nil) { + dnode_t *next = dict_next(dict, delete); + dnode_t *nextparent = next->parent; + dnode_color_t nextcolor = next->color; + + dict_assert (next != nil); + dict_assert (next->parent != nil); + dict_assert (next->left == nil); + + /* + * First, splice out the successor from the tree completely, by + * moving up its right child into its place. + */ + + child = next->right; + child->parent = nextparent; + + if (nextparent->left == next) { + nextparent->left = child; + } else { + dict_assert (nextparent->right == next); + nextparent->right = child; + } + + /* + * Now that the successor has been extricated from the tree, install it + * in place of the node that we want deleted. + */ + + next->parent = delparent; + next->left = delete->left; + next->right = delete->right; + next->left->parent = next; + next->right->parent = next; + next->color = delete->color; + delete->color = nextcolor; + + if (delparent->left == delete) { + delparent->left = next; + } else { + dict_assert (delparent->right == delete); + delparent->right = next; + } + + } else { + dict_assert (delete != nil); + dict_assert (delete->left == nil || delete->right == nil); + + child = (delete->left != nil) ? delete->left : delete->right; + + child->parent = delparent = delete->parent; + + if (delete == delparent->left) { + delparent->left = child; + } else { + dict_assert (delete == delparent->right); + delparent->right = child; + } + } + + delete->parent = NULL; + delete->right = NULL; + delete->left = NULL; + + dict->nodecount--; + + dict_assert (verify_bintree(dict)); + + /* red-black adjustments */ + + if (delete->color == dnode_black) { + dnode_t *parent, *sister; + + dict_root(dict)->color = dnode_red; + + while (child->color == dnode_black) { + parent = child->parent; + if (child == parent->left) { + sister = parent->right; + dict_assert (sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_left(parent); + sister = parent->right; + dict_assert (sister != nil); + } + if (sister->left->color == dnode_black + && sister->right->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->right->color == dnode_black) { + dict_assert (sister->left->color == dnode_red); + sister->left->color = dnode_black; + sister->color = dnode_red; + rotate_right(sister); + sister = parent->right; + dict_assert (sister != nil); + } + sister->color = parent->color; + sister->right->color = dnode_black; + parent->color = dnode_black; + rotate_left(parent); + break; + } + } else { /* symmetric case: child == child->parent->right */ + dict_assert (child == parent->right); + sister = parent->left; + dict_assert (sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_right(parent); + sister = parent->left; + dict_assert (sister != nil); + } + if (sister->right->color == dnode_black + && sister->left->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->left->color == dnode_black) { + dict_assert (sister->right->color == dnode_red); + sister->right->color = dnode_black; + sister->color = dnode_red; + rotate_left(sister); + sister = parent->left; + dict_assert (sister != nil); + } + sister->color = parent->color; + sister->left->color = dnode_black; + parent->color = dnode_black; + rotate_right(parent); + break; + } + } + } + + child->color = dnode_black; + dict_root(dict)->color = dnode_black; + } + + dict_assert (dict_verify(dict)); + + return delete; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Allocate a node using the dictionary's allocator routine, give it + * the data item. + */ + +int dict_alloc_insert(dict_t *dict, const void *key, void *data) +{ + dnode_t *node = dict->allocnode(dict->context); + + if (node) { + dnode_init(node, data); + dict_insert(dict, node, key); + return 1; + } + return 0; +} + +#ifdef E2FSCK_NOTUSED +void dict_delete_free(dict_t *dict, dnode_t *node) +{ + dict_delete(dict, node); + dict->freenode(node, dict->context); +} +#endif + +/* + * Return the node with the lowest (leftmost) key. If the dictionary is empty + * (that is, dict_isempty(dict) returns 1) a null pointer is returned. + */ + +dnode_t *dict_first(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; + + if (root != nil) + while ((left = root->left) != nil) + root = left; + + return (root == nil) ? NULL : root; +} + +/* + * Return the node with the highest (rightmost) key. If the dictionary is empty + * (that is, dict_isempty(dict) returns 1) a null pointer is returned. + */ + +dnode_t *dict_last(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; + + if (root != nil) + while ((right = root->right) != nil) + root = right; + + return (root == nil) ? NULL : root; +} + +/* + * Return the given node's successor node---the node which has the + * next key in the the left to right ordering. If the node has + * no successor, a null pointer is returned rather than a pointer to + * the nil node. + */ + +dnode_t *dict_next(dict_t *dict, dnode_t *curr) +{ + dnode_t *nil = dict_nil(dict), *parent, *left; + + if (curr->right != nil) { + curr = curr->right; + while ((left = curr->left) != nil) + curr = left; + return curr; + } + + parent = curr->parent; + + while (parent != nil && curr == parent->right) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; +} + +/* + * Return the given node's predecessor, in the key order. + * The nil sentinel node is returned if there is no predecessor. + */ + +dnode_t *dict_prev(dict_t *dict, dnode_t *curr) +{ + dnode_t *nil = dict_nil(dict), *parent, *right; + + if (curr->left != nil) { + curr = curr->left; + while ((right = curr->right) != nil) + curr = right; + return curr; + } + + parent = curr->parent; + + while (parent != nil && curr == parent->left) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; +} + +void dict_allow_dupes(dict_t *dict) +{ + dict->dupes = 1; +} + +#undef dict_count +#undef dict_isempty +#undef dict_isfull +#undef dnode_get +#undef dnode_put +#undef dnode_getkey + +dictcount_t dict_count(dict_t *dict) +{ + return dict->nodecount; +} + +int dict_isempty(dict_t *dict) +{ + return dict->nodecount == 0; +} + +int dict_isfull(dict_t *dict) +{ + return dict->nodecount == dict->maxcount; +} + +int dict_contains(dict_t *dict, dnode_t *node) +{ + return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); +} + +static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused))) +{ + return malloc(sizeof *dnode_alloc(NULL)); +} + +static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused))) +{ + free(node); +} + +dnode_t *dnode_create(void *data) +{ + dnode_t *new = malloc(sizeof *new); + if (new) { + new->data = data; + new->parent = NULL; + new->left = NULL; + new->right = NULL; + } + return new; +} + +dnode_t *dnode_init(dnode_t *dnode, void *data) +{ + dnode->data = data; + dnode->parent = NULL; + dnode->left = NULL; + dnode->right = NULL; + return dnode; +} + +void dnode_destroy(dnode_t *dnode) +{ + dict_assert (!dnode_is_in_a_dict(dnode)); + free(dnode); +} + +void *dnode_get(dnode_t *dnode) +{ + return dnode->data; +} + +const void *dnode_getkey(dnode_t *dnode) +{ + return dnode->key; +} + +#ifdef E2FSCK_NOTUSED +void dnode_put(dnode_t *dnode, void *data) +{ + dnode->data = data; +} +#endif + +#ifndef DICT_NODEBUG +int dnode_is_in_a_dict(dnode_t *dnode) +{ + return (dnode->parent && dnode->left && dnode->right); +} +#endif + +#ifdef E2FSCK_NOTUSED +void dict_process(dict_t *dict, void *context, dnode_process_t function) +{ + dnode_t *node = dict_first(dict), *next; + + while (node != NULL) { + /* check for callback function deleting */ + /* the next node from under us */ + dict_assert (dict_contains(dict, node)); + next = dict_next(dict, node); + function(dict, node, context); + node = next; + } +} + +static void load_begin_internal(dict_load_t *load, dict_t *dict) +{ + load->dictptr = dict; + load->nilnode.left = &load->nilnode; + load->nilnode.right = &load->nilnode; +} + +void dict_load_begin(dict_load_t *load, dict_t *dict) +{ + dict_assert (dict_isempty(dict)); + load_begin_internal(load, dict); +} + +void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key) +{ + dict_t *dict = load->dictptr; + dnode_t *nil = &load->nilnode; + + dict_assert (!dnode_is_in_a_dict(newnode)); + dict_assert (dict->nodecount < dict->maxcount); + +#ifndef DICT_NODEBUG + if (dict->nodecount > 0) { + if (dict->dupes) + dict_assert (dict->compare(nil->left->key, key) <= 0); + else + dict_assert (dict->compare(nil->left->key, key) < 0); + } +#endif + + newnode->key = key; + nil->right->left = newnode; + nil->right = newnode; + newnode->left = nil; + dict->nodecount++; +} + +void dict_load_end(dict_load_t *load) +{ + dict_t *dict = load->dictptr; + dnode_t *tree[DICT_DEPTH_MAX] = { 0 }; + dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next; + dnode_t *complete = 0; + dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; + dictcount_t botrowcount; + unsigned baselevel = 0, level = 0, i; + + dict_assert (dnode_red == 0 && dnode_black == 1); + + while (fullcount >= nodecount && fullcount) + fullcount >>= 1; + + botrowcount = nodecount - fullcount; + + for (curr = loadnil->left; curr != loadnil; curr = next) { + next = curr->left; + + if (complete == NULL && botrowcount-- == 0) { + dict_assert (baselevel == 0); + dict_assert (level == 0); + baselevel = level = 1; + complete = tree[0]; + + if (complete != 0) { + tree[0] = 0; + complete->right = dictnil; + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } + } + + if (complete == NULL) { + curr->left = dictnil; + curr->right = dictnil; + curr->color = level % 2; + complete = curr; + + dict_assert (level == baselevel); + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } else { + curr->left = complete; + curr->color = (level + 1) % 2; + complete->parent = curr; + tree[level] = curr; + complete = 0; + level = baselevel; + } + } + + if (complete == NULL) + complete = dictnil; + + for (i = 0; i < DICT_DEPTH_MAX; i++) { + if (tree[i] != 0) { + tree[i]->right = complete; + complete->parent = tree[i]; + complete = tree[i]; + } + } + + dictnil->color = dnode_black; + dictnil->right = dictnil; + complete->parent = dictnil; + complete->color = dnode_black; + dict_root(dict) = complete; + + dict_assert (dict_verify(dict)); +} + +void dict_merge(dict_t *dest, dict_t *source) +{ + dict_load_t load; + dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); + + dict_assert (dict_similar(dest, source)); + + if (source == dest) + return; + + dest->nodecount = 0; + load_begin_internal(&load, dest); + + for (;;) { + if (leftnode != NULL && rightnode != NULL) { + if (dest->compare(leftnode->key, rightnode->key) < 0) + goto copyleft; + else + goto copyright; + } else if (leftnode != NULL) { + goto copyleft; + } else if (rightnode != NULL) { + goto copyright; + } else { + dict_assert (leftnode == NULL && rightnode == NULL); + break; + } + + copyleft: + { + dnode_t *next = dict_next(dest, leftnode); +#ifndef DICT_NODEBUG + leftnode->left = NULL; /* suppress assertion in dict_load_next */ +#endif + dict_load_next(&load, leftnode, leftnode->key); + leftnode = next; + continue; + } + + copyright: + { + dnode_t *next = dict_next(source, rightnode); +#ifndef DICT_NODEBUG + rightnode->left = NULL; +#endif + dict_load_next(&load, rightnode, rightnode->key); + rightnode = next; + continue; + } + } + + dict_clear(source); + dict_load_end(&load); +} +#endif /* E2FSCK_NOTUSED */ + +#ifdef KAZLIB_TEST_MAIN + +#include +#include +#include +#include + +typedef char input_t[256]; + +static int tokenize(char *string, ...) +{ + char **tokptr; + va_list arglist; + int tokcount = 0; + + va_start(arglist, string); + tokptr = va_arg(arglist, char **); + while (tokptr) { + while (*string && isspace((unsigned char) *string)) + string++; + if (!*string) + break; + *tokptr = string; + while (*string && !isspace((unsigned char) *string)) + string++; + tokptr = va_arg(arglist, char **); + tokcount++; + if (!*string) + break; + *string++ = 0; + } + va_end(arglist); + + return tokcount; +} + +static int comparef(const void *cmp_ctx, const void *key1, const void *key2) +{ + return strcmp(key1, key2); +} + +static char *dupstring(char *str) +{ + int sz = strlen(str) + 1; + char *new = malloc(sz); + if (new) + memcpy(new, str, sz); + return new; +} + +static dnode_t *new_node(void *c) +{ + static dnode_t few[5]; + static int count; + + if (count < 5) + return few + count++; + + return NULL; +} + +static void del_node(dnode_t *n, void *c) +{ +} + +static int prompt = 0; + +static void construct(dict_t *d) +{ + input_t in; + int done = 0; + dict_load_t dl; + dnode_t *dn; + char *tok1, *tok2, *val; + const char *key; + char *help = + "p turn prompt on\n" + "q finish construction\n" + "a add new entry\n"; + + if (!dict_isempty(d)) + puts("warning: dictionary not empty!"); + + dict_load_begin(&dl, d); + + while (!done) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch (in[0]) { + case '?': + puts(help); + break; + case 'p': + prompt = 1; + break; + case 'q': + done = 1; + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + dn = dnode_create(val); + + if (!key || !val || !dn) { + puts("out of memory"); + free((void *) key); + free(val); + if (dn) + dnode_destroy(dn); + } + + dict_load_next(&dl, dn, key); + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + dict_load_end(&dl); +} + +int main(void) +{ + input_t in; + dict_t darray[10]; + dict_t *d = &darray[0]; + dnode_t *dn; + int i; + char *tok1, *tok2, *val; + const char *key; + + char *help = + "a add value to dictionary\n" + "d delete value from dictionary\n" + "l lookup value in dictionary\n" + "( lookup lower bound\n" + ") lookup upper bound\n" + "# switch to alternate dictionary (0-9)\n" + "j merge two dictionaries\n" + "f free the whole dictionary\n" + "k allow duplicate keys\n" + "c show number of entries\n" + "t dump whole dictionary in sort order\n" + "m make dictionary out of sorted items\n" + "p turn prompt on\n" + "s switch to non-functioning allocator\n" + "q quit"; + + for (i = 0; i < sizeof darray / sizeof *darray; i++) + dict_init(&darray[i], DICTCOUNT_T_MAX, comparef); + + for (;;) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch(in[0]) { + case '?': + puts(help); + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + + if (!key || !val) { + puts("out of memory"); + free((void *) key); + free(val); + } + + if (!dict_alloc_insert(d, key, val)) { + puts("dict_alloc_insert failed"); + free((void *) key); + free(val); + break; + } + break; + case 'd': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + dn = dict_lookup(d, tok1); + if (!dn) { + puts("dict_lookup failed"); + break; + } + val = dnode_get(dn); + key = dnode_getkey(dn); + dict_delete_free(d, dn); + + free(val); + free((void *) key); + break; + case 'f': + dict_free(d); + break; + case 'l': + case '(': + case ')': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + dn = 0; + switch (in[0]) { + case 'l': + dn = dict_lookup(d, tok1); + break; + case '(': + dn = dict_lower_bound(d, tok1); + break; + case ')': + dn = dict_upper_bound(d, tok1); + break; + } + if (!dn) { + puts("lookup failed"); + break; + } + val = dnode_get(dn); + puts(val); + break; + case 'm': + construct(d); + break; + case 'k': + dict_allow_dupes(d); + break; + case 'c': + printf("%lu\n", (unsigned long) dict_count(d)); + break; + case 't': + for (dn = dict_first(d); dn; dn = dict_next(d, dn)) { + printf("%s\t%s\n", (char *) dnode_getkey(dn), + (char *) dnode_get(dn)); + } + break; + case 'q': + exit(0); + break; + case '\0': + break; + case 'p': + prompt = 1; + break; + case 's': + dict_set_allocator(d, new_node, del_node, NULL); + break; + case '#': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } else { + int dictnum = atoi(tok1); + if (dictnum < 0 || dictnum > 9) { + puts("invalid number"); + break; + } + d = &darray[dictnum]; + } + break; + case 'j': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } else { + int dict1 = atoi(tok1), dict2 = atoi(tok2); + if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) { + puts("invalid number"); + break; + } + dict_merge(&darray[dict1], &darray[dict2]); + } + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + return 0; +} + +#endif diff --git a/jni/e2fsprogs/lib/support/dict.o b/jni/e2fsprogs/lib/support/dict.o new file mode 100755 index 0000000000000000000000000000000000000000..cb1888c355f3bf94c0890c7d21d6d17e793533ab GIT binary patch literal 7440 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 K%~yu#{{I48OCJUR literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/mkquota.c b/jni/e2fsprogs/lib/support/mkquota.c new file mode 100755 index 0000000..c89f895 --- /dev/null +++ b/jni/e2fsprogs/lib/support/mkquota.c @@ -0,0 +1,706 @@ +/* + * mkquota.c --- create quota files for a filesystem + * + * Aditya Kali + */ +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "e2p/e2p.h" + +#include "quotaio.h" +#include "quotaio_v2.h" +#include "quotaio_tree.h" +#include "common.h" +#include "dict.h" + +/* Needed for architectures where sizeof(int) != sizeof(void *) */ +#define UINT_TO_VOIDPTR(val) ((void *)(intptr_t)(val)) +#define VOIDPTR_TO_UINT(ptr) ((unsigned int)(intptr_t)(ptr)) + +#if DEBUG_QUOTA +static void print_inode(struct ext2_inode *inode) +{ + if (!inode) + return; + + fprintf(stderr, " i_mode = %d\n", inode->i_mode); + fprintf(stderr, " i_uid = %d\n", inode->i_uid); + fprintf(stderr, " i_size = %d\n", inode->i_size); + fprintf(stderr, " i_atime = %d\n", inode->i_atime); + fprintf(stderr, " i_ctime = %d\n", inode->i_ctime); + fprintf(stderr, " i_mtime = %d\n", inode->i_mtime); + fprintf(stderr, " i_dtime = %d\n", inode->i_dtime); + fprintf(stderr, " i_gid = %d\n", inode->i_gid); + fprintf(stderr, " i_links_count = %d\n", inode->i_links_count); + fprintf(stderr, " i_blocks = %d\n", inode->i_blocks); + fprintf(stderr, " i_flags = %d\n", inode->i_flags); + + return; +} + +static void print_dquot(const char *desc, struct dquot *dq) +{ + if (desc) + fprintf(stderr, "%s: ", desc); + fprintf(stderr, "%u %lld:%lld:%lld %lld:%lld:%lld\n", + dq->dq_id, (long long) dq->dq_dqb.dqb_curspace, + (long long) dq->dq_dqb.dqb_bsoftlimit, + (long long) dq->dq_dqb.dqb_bhardlimit, + (long long) dq->dq_dqb.dqb_curinodes, + (long long) dq->dq_dqb.dqb_isoftlimit, + (long long) dq->dq_dqb.dqb_ihardlimit); +} +#else +static void print_dquot(const char *desc EXT2FS_ATTR((unused)), + struct dquot *dq EXT2FS_ATTR((unused))) +{ +} +#endif + +/* + * Returns 0 if not able to find the quota file, otherwise returns its + * inode number. + */ +int quota_file_exists(ext2_filsys fs, enum quota_type qtype) +{ + char qf_name[256]; + errcode_t ret; + ext2_ino_t ino; + + if (qtype >= MAXQUOTAS) + return -EINVAL; + + quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name); + + ret = ext2fs_lookup(fs, EXT2_ROOT_INO, qf_name, strlen(qf_name), 0, + &ino); + if (ret) + return 0; + + return ino; +} + +/* + * Set the value for reserved quota inode number field in superblock. + */ +void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype) +{ + ext2_ino_t *inump; + + inump = quota_sb_inump(fs->super, qtype); + + log_debug("setting quota ino in superblock: ino=%u, type=%d", ino, + qtype); + if (inump == NULL) + return; + *inump = ino; + ext2fs_mark_super_dirty(fs); +} + +errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype) +{ + ext2_ino_t qf_ino; + errcode_t retval; + + retval = ext2fs_read_bitmaps(fs); + if (retval) { + log_debug("Couldn't read bitmaps: %s", error_message(retval)); + return retval; + } + + qf_ino = *quota_sb_inump(fs->super, qtype); + if (qf_ino == 0) + return 0; + retval = quota_inode_truncate(fs, qf_ino); + if (retval) + return retval; + if (qf_ino >= EXT2_FIRST_INODE(fs->super)) { + struct ext2_inode inode; + + retval = ext2fs_read_inode(fs, qf_ino, &inode); + if (!retval) { + memset(&inode, 0, sizeof(struct ext2_inode)); + ext2fs_write_inode(fs, qf_ino, &inode); + } + ext2fs_inode_alloc_stats2(fs, qf_ino, -1, 0); + ext2fs_mark_ib_dirty(fs); + + } + quota_set_sb_inum(fs, 0, qtype); + + ext2fs_mark_super_dirty(fs); + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + retval = ext2fs_write_bitmaps(fs); + if (retval) { + log_debug("Couldn't write bitmaps: %s", error_message(retval)); + return retval; + } + return 0; +} + +static void write_dquots(dict_t *dict, struct quota_handle *qh) +{ + dnode_t *n; + struct dquot *dq; + + for (n = dict_first(dict); n; n = dict_next(dict, n)) { + dq = dnode_get(n); + if (dq) { + print_dquot("write", dq); + dq->dq_h = qh; + update_grace_times(dq); + qh->qh_ops->commit_dquot(dq); + } + } +} + +errcode_t quota_write_inode(quota_ctx_t qctx, unsigned int qtype_bits) +{ + int retval = 0; + enum quota_type qtype; + dict_t *dict; + ext2_filsys fs; + struct quota_handle *h = NULL; + int fmt = QFMT_VFS_V1; + + if (!qctx) + return 0; + + fs = qctx->fs; + retval = ext2fs_get_mem(sizeof(struct quota_handle), &h); + if (retval) { + log_debug("Unable to allocate quota handle: %s", + error_message(retval)); + goto out; + } + + retval = ext2fs_read_bitmaps(fs); + if (retval) { + log_debug("Couldn't read bitmaps: %s", error_message(retval)); + goto out; + } + + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (((1 << qtype) & qtype_bits) == 0) + continue; + + dict = qctx->quota_dict[qtype]; + if (!dict) + continue; + + retval = quota_file_create(h, fs, qtype, fmt); + if (retval) { + log_debug("Cannot initialize io on quotafile: %s", + error_message(retval)); + goto out; + } + + write_dquots(dict, h); + retval = quota_file_close(qctx, h); + if (retval) { + log_debug("Cannot finish IO on new quotafile: %s", + strerror(errno)); + if (h->qh_qf.e2_file) + ext2fs_file_close(h->qh_qf.e2_file); + (void) quota_inode_truncate(fs, h->qh_qf.ino); + goto out; + } + + /* Set quota inode numbers in superblock. */ + quota_set_sb_inum(fs, h->qh_qf.ino, qtype); + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + } + + retval = ext2fs_write_bitmaps(fs); + if (retval) { + log_debug("Couldn't write bitmaps: %s", error_message(retval)); + goto out; + } +out: + if (h) + ext2fs_free_mem(&h); + return retval; +} + +/******************************************************************/ +/* Helper functions for computing quota in memory. */ +/******************************************************************/ + +static int dict_uint_cmp(const void *cmp_ctx EXT2FS_ATTR((unused)), + const void *a, const void *b) +{ + unsigned int c, d; + + c = VOIDPTR_TO_UINT(a); + d = VOIDPTR_TO_UINT(b); + + if (c == d) + return 0; + else if (c > d) + return 1; + else + return -1; +} + +static inline int project_quota_valid(quota_ctx_t qctx) +{ + return (EXT2_INODE_SIZE(qctx->fs->super) > EXT2_GOOD_OLD_INODE_SIZE); +} + +static inline qid_t get_qid(struct ext2_inode_large *inode, enum quota_type qtype) +{ + unsigned int inode_size; + + switch (qtype) { + case USRQUOTA: + return inode_uid(*inode); + case GRPQUOTA: + return inode_gid(*inode); + case PRJQUOTA: + inode_size = EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize; + if (inode_includes(inode_size, i_projid)) + return inode_projid(*inode); + return 0; + default: + return 0; + } + + return 0; +} + +static void quota_dnode_free(dnode_t *node, + void *context EXT2FS_ATTR((unused))) +{ + void *ptr = node ? dnode_get(node) : 0; + + ext2fs_free_mem(&ptr); + free(node); +} + +/* + * Set up the quota tracking data structures. + */ +errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, + unsigned int qtype_bits) +{ + errcode_t err; + dict_t *dict; + quota_ctx_t ctx; + enum quota_type qtype; + + err = ext2fs_get_mem(sizeof(struct quota_ctx), &ctx); + if (err) { + log_debug("Failed to allocate quota context"); + return err; + } + + memset(ctx, 0, sizeof(struct quota_ctx)); + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + ctx->quota_file[qtype] = NULL; + if (qtype_bits) { + if (((1 << qtype) & qtype_bits) == 0) + continue; + } else { + if (*quota_sb_inump(fs->super, qtype) == 0) + continue; + } + err = ext2fs_get_mem(sizeof(dict_t), &dict); + if (err) { + log_debug("Failed to allocate dictionary"); + quota_release_context(&ctx); + return err; + } + ctx->quota_dict[qtype] = dict; + dict_init(dict, DICTCOUNT_T_MAX, dict_uint_cmp); + dict_set_allocator(dict, NULL, quota_dnode_free, NULL); + } + + ctx->fs = fs; + *qctx = ctx; + return 0; +} + +void quota_release_context(quota_ctx_t *qctx) +{ + errcode_t err; + dict_t *dict; + enum quota_type qtype; + quota_ctx_t ctx; + + if (!qctx) + return; + + ctx = *qctx; + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + dict = ctx->quota_dict[qtype]; + ctx->quota_dict[qtype] = 0; + if (dict) { + dict_free_nodes(dict); + free(dict); + } + if (ctx->quota_file[qtype]) { + err = quota_file_close(ctx, ctx->quota_file[qtype]); + if (err) { + log_err("Cannot close quotafile: %s", + strerror(errno)); + ext2fs_free_mem(&ctx->quota_file[qtype]); + } + } + } + *qctx = NULL; + free(ctx); +} + +static struct dquot *get_dq(dict_t *dict, __u32 key) +{ + struct dquot *dq; + dnode_t *n; + + n = dict_lookup(dict, UINT_TO_VOIDPTR(key)); + if (n) + dq = dnode_get(n); + else { + if (ext2fs_get_mem(sizeof(struct dquot), &dq)) { + log_err("Unable to allocate dquot"); + return NULL; + } + memset(dq, 0, sizeof(struct dquot)); + dict_alloc_insert(dict, UINT_TO_VOIDPTR(key), dq); + dq->dq_id = key; + } + return dq; +} + + +/* + * Called to update the blocks used by a particular inode + */ +void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino EXT2FS_ATTR((unused)), + qsize_t space) +{ + struct dquot *dq; + dict_t *dict; + enum quota_type qtype; + + if (!qctx) + return; + + log_debug("ADD_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino, + inode_uid(*inode), + inode_gid(*inode), space); + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (qtype == PRJQUOTA && !project_quota_valid(qctx)) + continue; + dict = qctx->quota_dict[qtype]; + if (dict) { + dq = get_dq(dict, get_qid(inode, qtype)); + if (dq) + dq->dq_dqb.dqb_curspace += space; + } + } +} + +/* + * Called to remove some blocks used by a particular inode + */ +void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino EXT2FS_ATTR((unused)), + qsize_t space) +{ + struct dquot *dq; + dict_t *dict; + enum quota_type qtype; + + if (!qctx) + return; + + log_debug("SUB_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino, + inode_uid(*inode), + inode_gid(*inode), space); + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (qtype == PRJQUOTA && !project_quota_valid(qctx)) + continue; + dict = qctx->quota_dict[qtype]; + if (dict) { + dq = get_dq(dict, get_qid(inode, qtype)); + if (dq) + dq->dq_dqb.dqb_curspace -= space; + } + } +} + +/* + * Called to count the files used by an inode's user/group + */ +void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode, + ext2_ino_t ino EXT2FS_ATTR((unused)), int adjust) +{ + struct dquot *dq; + dict_t *dict; + enum quota_type qtype; + + if (!qctx) + return; + + log_debug("ADJ_INODE: Inode: %u, UID/GID: %u/%u, adjust: %d", ino, + inode_uid(*inode), + inode_gid(*inode), adjust); + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (qtype == PRJQUOTA && !project_quota_valid(qctx)) + continue; + dict = qctx->quota_dict[qtype]; + if (dict) { + dq = get_dq(dict, get_qid(inode, qtype)); + if (dq) + dq->dq_dqb.dqb_curinodes += adjust; + } + } +} + +errcode_t quota_compute_usage(quota_ctx_t qctx) +{ + ext2_filsys fs; + ext2_ino_t ino; + errcode_t ret; + struct ext2_inode_large *inode; + int inode_size; + qsize_t space; + ext2_inode_scan scan; + + if (!qctx) + return 0; + + fs = qctx->fs; + ret = ext2fs_open_inode_scan(fs, 0, &scan); + if (ret) { + log_err("while opening inode scan. ret=%ld", ret); + return ret; + } + inode_size = fs->super->s_inode_size; + inode = malloc(inode_size); + if (!inode) { + ext2fs_close_inode_scan(scan); + return ENOMEM; + } + while (1) { + ret = ext2fs_get_next_inode_full(scan, &ino, + EXT2_INODE(inode), inode_size); + if (ret) { + log_err("while getting next inode. ret=%ld", ret); + ext2fs_close_inode_scan(scan); + free(inode); + return ret; + } + if (ino == 0) + break; + if (!inode->i_links_count) + continue; + if (ino == EXT2_ROOT_INO || + (ino >= EXT2_FIRST_INODE(fs->super) && + ino != quota_type2inum(PRJQUOTA, fs->super))) { + space = ext2fs_get_stat_i_blocks(fs, + EXT2_INODE(inode)) << 9; + quota_data_add(qctx, inode, ino, space); + quota_data_inodes(qctx, inode, ino, +1); + } + } + + ext2fs_close_inode_scan(scan); + free(inode); + return 0; +} + +struct scan_dquots_data { + dict_t *quota_dict; + int update_limits; /* update limits from disk */ + int update_usage; + int check_consistency; + int usage_is_inconsistent; +}; + +static int scan_dquots_callback(struct dquot *dquot, void *cb_data) +{ + struct scan_dquots_data *scan_data = cb_data; + dict_t *quota_dict = scan_data->quota_dict; + struct dquot *dq; + + dq = get_dq(quota_dict, dquot->dq_id); + if (!dq) + return -1; + dq->dq_id = dquot->dq_id; + dq->dq_flags |= DQF_SEEN; + + print_dquot("mem", dq); + print_dquot("dsk", dquot); + + /* Check if there is inconsistency */ + if (scan_data->check_consistency && + (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace || + dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes)) { + scan_data->usage_is_inconsistent = 1; + fprintf(stderr, "[QUOTA WARNING] Usage inconsistent for ID %u:" + "actual (%lld, %lld) != expected (%lld, %lld)\n", + dq->dq_id, (long long) dq->dq_dqb.dqb_curspace, + (long long) dq->dq_dqb.dqb_curinodes, + (long long) dquot->dq_dqb.dqb_curspace, + (long long) dquot->dq_dqb.dqb_curinodes); + } + + if (scan_data->update_limits) { + dq->dq_dqb.dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit; + dq->dq_dqb.dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit; + dq->dq_dqb.dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit; + dq->dq_dqb.dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit; + } + + if (scan_data->update_usage) { + dq->dq_dqb.dqb_curspace = dquot->dq_dqb.dqb_curspace; + dq->dq_dqb.dqb_curinodes = dquot->dq_dqb.dqb_curinodes; + } + + return 0; +} + +/* + * Read quotas from disk and updates the in-memory information determined by + * 'flags' from the on-disk data. + */ +errcode_t quota_read_all_dquots(quota_ctx_t qctx, ext2_ino_t qf_ino, + enum quota_type qtype, unsigned int flags) +{ + struct scan_dquots_data scan_data; + struct quota_handle *qh; + errcode_t err; + + if (!qctx) + return 0; + + err = ext2fs_get_mem(sizeof(struct quota_handle), &qh); + if (err) { + log_debug("Unable to allocate quota handle"); + return err; + } + + err = quota_file_open(qctx, qh, qf_ino, qtype, -1, 0); + if (err) { + log_debug("Open quota file failed"); + goto out; + } + + scan_data.quota_dict = qctx->quota_dict[qh->qh_type]; + scan_data.check_consistency = 0; + scan_data.update_limits = !!(flags & QREAD_LIMITS); + scan_data.update_usage = !!(flags & QREAD_USAGE); + qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data); + + err = quota_file_close(qctx, qh); + if (err) { + log_debug("Cannot finish IO on new quotafile: %s", + strerror(errno)); + if (qh->qh_qf.e2_file) + ext2fs_file_close(qh->qh_qf.e2_file); + } +out: + ext2fs_free_mem(&qh); + return err; +} + +/* + * Compares the measured quota in qctx->quota_dict with that in the quota inode + * on disk and updates the limits in qctx->quota_dict. 'usage_inconsistent' is + * set to 1 if the supplied and on-disk quota usage values are not identical. + */ +errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype, + int *usage_inconsistent) +{ + struct quota_handle qh; + struct scan_dquots_data scan_data; + struct dquot *dq; + dnode_t *n; + dict_t *dict = qctx->quota_dict[qtype]; + errcode_t err = 0; + + if (!dict) + goto out; + + err = quota_file_open(qctx, &qh, 0, qtype, -1, 0); + if (err) { + log_debug("Open quota file failed"); + goto out; + } + + scan_data.quota_dict = qctx->quota_dict[qtype]; + scan_data.update_limits = 1; + scan_data.update_usage = 0; + scan_data.check_consistency = 1; + scan_data.usage_is_inconsistent = 0; + err = qh.qh_ops->scan_dquots(&qh, scan_dquots_callback, &scan_data); + if (err) { + log_debug("Error scanning dquots"); + *usage_inconsistent = 1; + goto out_close_qh; + } + + for (n = dict_first(dict); n; n = dict_next(dict, n)) { + dq = dnode_get(n); + if (!dq) + continue; + if ((dq->dq_flags & DQF_SEEN) == 0) { + fprintf(stderr, "[QUOTA WARNING] " + "Missing quota entry ID %d\n", dq->dq_id); + scan_data.usage_is_inconsistent = 1; + } + } + *usage_inconsistent = scan_data.usage_is_inconsistent; + +out_close_qh: + err = quota_file_close(qctx, &qh); + if (err) { + log_debug("Cannot close quotafile: %s", error_message(errno)); + if (qh.qh_qf.e2_file) + ext2fs_file_close(qh.qh_qf.e2_file); + } +out: + return err; +} + +int parse_quota_opts(const char *opts, int (*func)(char *)) +{ + char *buf, *token, *next, *p; + int len; + int ret = 0; + + len = strlen(opts); + buf = malloc(len + 1); + if (!buf) { + fprintf(stderr, + "Couldn't allocate memory to parse quota options!\n"); + return -ENOMEM; + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p + 1; + } + ret = func(token); + if (ret) + break; + } + free(buf); + return ret; +} diff --git a/jni/e2fsprogs/lib/support/mkquota.o b/jni/e2fsprogs/lib/support/mkquota.o new file mode 100755 index 0000000000000000000000000000000000000000..c1d086ec3e3005b65cabb450caeec5565d9ea8cf GIT binary patch literal 14792 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/parse_qtype.c b/jni/e2fsprogs/lib/support/parse_qtype.c new file mode 100755 index 0000000..d8df07d --- /dev/null +++ b/jni/e2fsprogs/lib/support/parse_qtype.c @@ -0,0 +1,90 @@ +/* + * parse_qtype.c + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "quotaio.h" + +#define PARSE_DELIM ":," + +int parse_quota_types(const char *in_str, unsigned int *qtype_bits, + char **err_token) +{ + char *buf, *token, *next, *tmp; + unsigned int qtype = *qtype_bits; + int len, ret = 0; + + if (!in_str) + return 0; + + len = strlen(in_str); + buf = malloc(len + 1); + if (!buf) + return ENOMEM; + strcpy(buf, in_str); + + for (token = buf, next = strtok_r(buf, PARSE_DELIM, &tmp); + token && *token; token = next) { + int not = 0; + char *p = token; + + if (*p == '^') { + not = 1; + p++; + } + if (!strcmp(p, "usr") || !strcmp(p, "usrquota")) { + if (not) + qtype &= ~QUOTA_USR_BIT; + else + qtype |= QUOTA_USR_BIT; + } else if (!strcmp(p, "grp") || !strcmp(p, "grpquota")) { + if (not) + qtype &= ~QUOTA_GRP_BIT; + else + qtype |= QUOTA_GRP_BIT; + } else if (!strcmp(p, "prj") || !strcmp(p, "prjquota")) { + if (not) + qtype &= ~QUOTA_PRJ_BIT; + else + qtype |= QUOTA_PRJ_BIT; + } else { + if (err_token) { + *err_token = malloc(strlen(token) + 1); + if (*err_token) + strcpy(*err_token, token); + } + ret = EINVAL; + goto errout; + } +#ifdef DEBUG_PROGRAM + printf("word: %s\n", token); +#endif + next = strtok_r(NULL, PARSE_DELIM, &tmp); + } + *qtype_bits = qtype; +errout: + free(buf); + return ret; +} + +#ifdef DEBUG_PROGRAM +int main(int argc, char **argv) +{ + unsigned int qtype_bits = 0; + int ret; + char *err_token = 0; + + ret = parse_quota_types(argv[1], &qtype_bits, &err_token); + printf("parse_quota_types returns %d, %d\n", ret, qtype_bits); + if (err_token) + printf("err_token is %s\n", err_token); + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/support/parse_qtype.o b/jni/e2fsprogs/lib/support/parse_qtype.o new file mode 100755 index 0000000000000000000000000000000000000000..32923f28bd4571155e8ce85d42bb11eeec06ac00 GIT binary patch literal 2904 zcmb`IO>7%Q6vy9slg23_v`xW?5ZjeKvfiSY z6o}*s<%F>4p@$Y+#KA$mAc4r9S}B)axu9M^260%9+-!-+{NL`3JDu9%K%X?8dB1t{ zpV>EW*Pk9caXeudB+a0o=)NZ@(Y@sTu^kO<+KKjg>S}1xd^k-(IBf^xqjWGd$LHx| z`%9i{)@Pvgey1hYZW)^^Ev&!J>%ngd4UU0Eml^i>;s{aWk2*D2qn)BI?+g9zIBl-{ zHAX?wpdTc|IbVgp7LI-WOo+LNkJ-WU6ZA5VdsETbx|l<=yHR}2SVP)Q^86e$LyqCO zQEG4;^EQ0+(OLK$NY{&l_#J~@VjfP}!Ci`D!i*gxYnelwzfqoJ-=IbIIri;GqMz3E zGkyJ|k3@e)(@*#HQ_ydjr#s7u_#WE0njF|1jM5eMlNx%InA_jLA;1T+}H)z%* z7Jbn09>N~xOid{1b}a%AbADNgP^p@I9{FP$C3+U*kg{*|ykKvj$=s-mE)3zgn}PAx z5dO*#zB+{4;B3>_XgnT9zwe1L^Zg3HqVUHQepQU85U*x0&L`268gD8(6N*k2acok@ zj9r=)T%KxIB+I z4t*=Qym!fODLQKX+*A0Z3`WoIBiksRPlUvv>U;T0jV#YCIF|3O`()+I#iCpCsp5E5 zHy3^7a(=DiRtdp=`C`uFLB3ewuHcr)DwTcLdh4B2&sTjXe^H3J=W}O0r|8mI&vmKj z6bj|M)MPm;PZkS0XVBM*+|RCBFYwPI|13bKyz2N4M=ijeUAKm~mTOy3)bcEtJ5i$rn9YxVX20#pxTH~;_u literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/plausible.c b/jni/e2fsprogs/lib/support/plausible.c new file mode 100755 index 0000000..65a6b2e --- /dev/null +++ b/jni/e2fsprogs/lib/support/plausible.c @@ -0,0 +1,287 @@ +/* + * plausible.c --- Figure out if a pathname is ext* or something else. + * + * Copyright 2014, Oracle, Inc. + * + * Some parts are: + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_MAGIC_H +#include +#endif +#include "plausible.h" +#include "ext2fs/ext2fs.h" +#include "nls-enable.h" +#include "blkid/blkid.h" + +#ifdef HAVE_MAGIC_H +static magic_t (*dl_magic_open)(int); +static const char *(*dl_magic_file)(magic_t, const char *); +static int (*dl_magic_load)(magic_t, const char *); +static void (*dl_magic_close)(magic_t); + +/* + * NO_CHECK functionality was only added in file 4.20. + * Older systems like RHEL 5.x still have file 4.17 + */ +#ifndef MAGIC_NO_CHECK_COMPRESS +#define MAGIC_NO_CHECK_COMPRESS 0x0001000 +#endif +#ifndef MAGIC_NO_CHECK_ELF +#define MAGIC_NO_CHECK_ELF 0x0010000 +#endif + +#ifdef HAVE_DLOPEN +#include + +static void *magic_handle; + +static int magic_library_available(void) +{ + if (!magic_handle) { + magic_handle = dlopen("libmagic.so.1", RTLD_NOW); + if (!magic_handle) + return 0; + + dl_magic_open = (magic_t (*)(int)) + dlsym(magic_handle, "magic_open"); + dl_magic_file = (const char *(*)(magic_t, const char *)) + dlsym(magic_handle, "magic_file"); + dl_magic_load = (int (*)(magic_t, const char *)) + dlsym(magic_handle, "magic_load"); + dl_magic_close = (void (*)(magic_t)) + dlsym(magic_handle, "magic_close"); + } + + if (!dl_magic_open || !dl_magic_file || + !dl_magic_load || !dl_magic_close) + return 0; + return 1; +} +#else +static int magic_library_available(void) +{ + dl_magic_open = magic_open; + dl_magic_file = magic_file; + dl_magic_load = magic_load; + dl_magic_close = magic_close; + + return 1; +} +#endif +#endif + +static void print_ext2_info(const char *device) + +{ + struct ext2_super_block *sb; + ext2_filsys fs; + errcode_t retval; + time_t tm; + + retval = ext2fs_open2(device, 0, EXT2_FLAG_64BITS, 0, 0, + default_io_manager, &fs); + if (retval) + return; + sb = fs->super; + + if (sb->s_mtime) { + tm = sb->s_mtime; + if (sb->s_last_mounted[0]) + printf(_("\tlast mounted on %.*s on %s"), + EXT2_LEN_STR(sb->s_last_mounted), ctime(&tm)); + else + printf(_("\tlast mounted on %s"), ctime(&tm)); + } else if (sb->s_mkfs_time) { + tm = sb->s_mkfs_time; + printf(_("\tcreated on %s"), ctime(&tm)); + } else if (sb->s_wtime) { + tm = sb->s_wtime; + printf(_("\tlast modified on %s"), ctime(&tm)); + } + ext2fs_close_free(&fs); +} + +/* + * return 1 if there is no partition table, 0 if a partition table is + * detected, and -1 on an error. + */ +#ifdef HAVE_BLKID_PROBE_ENABLE_PARTITIONS +static int check_partition_table(const char *device) +{ + blkid_probe pr; + const char *value; + int ret; + + pr = blkid_new_probe_from_filename(device); + if (!pr) + return -1; + + ret = blkid_probe_enable_partitions(pr, 1); + if (ret < 0) + goto errout; + + ret = blkid_probe_enable_superblocks(pr, 0); + if (ret < 0) + goto errout; + + ret = blkid_do_fullprobe(pr); + if (ret < 0) + goto errout; + + ret = blkid_probe_lookup_value(pr, "PTTYPE", &value, NULL); + if (ret == 0) + fprintf(stderr, _("Found a %s partition table in %s\n"), + value, device); + else + ret = 1; + +errout: + blkid_free_probe(pr); + return ret; +} +#else +static int check_partition_table(const char *device EXT2FS_ATTR((unused))) +{ + return -1; +} +#endif + +/* + * return 1 if the device looks plausible, creating the file if necessary + */ +int check_plausibility(const char *device, int flags, int *ret_is_dev) +{ + int fd, ret, is_dev = 0; + ext2fs_struct_stat s; + int fl = O_RDONLY; + blkid_cache cache = NULL; + char *fs_type = NULL; + char *fs_label = NULL; + + fd = ext2fs_open_file(device, fl, 0666); + if ((fd < 0) && (errno == ENOENT) && (flags & NO_SIZE)) { + fprintf(stderr, _("The file %s does not exist and no " + "size was specified.\n"), device); + exit(1); + } + if ((fd < 0) && (errno == ENOENT) && (flags & CREATE_FILE)) { + fl |= O_CREAT; + fd = ext2fs_open_file(device, fl, 0666); + if (fd >= 0 && (flags & VERBOSE_CREATE)) + printf(_("Creating regular file %s\n"), device); + } + if (fd < 0) { + fprintf(stderr, _("Could not open %s: %s\n"), + device, error_message(errno)); + if (errno == ENOENT) + fputs(_("\nThe device apparently does not exist; " + "did you specify it correctly?\n"), stderr); + exit(1); + } + + if (ext2fs_fstat(fd, &s) < 0) { + perror("stat"); + exit(1); + } + close(fd); + + if (S_ISBLK(s.st_mode)) + is_dev = 1; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + /* On FreeBSD, all disk devices are character specials */ + if (S_ISCHR(s.st_mode)) + is_dev = 1; +#endif + if (ret_is_dev) + *ret_is_dev = is_dev; + + if ((flags & CHECK_BLOCK_DEV) && !is_dev) { + printf(_("%s is not a block special device.\n"), device); + return 0; + } + + /* + * Note: we use the older-style blkid API's here because we + * want as much functionality to be available when using the + * internal blkid library, when e2fsprogs is compiled for + * non-Linux systems that will probably not have the libraries + * from util-linux available. We only use the newer + * blkid-probe interfaces to access functionality not + * available in the original blkid library. + */ + if ((flags & CHECK_FS_EXIST) && blkid_get_cache(&cache, NULL) >= 0) { + fs_type = blkid_get_tag_value(cache, "TYPE", device); + if (fs_type) + fs_label = blkid_get_tag_value(cache, "LABEL", device); + blkid_put_cache(cache); + } + + if (fs_type) { + if (fs_label) + printf(_("%s contains a %s file system labelled '%s'\n"), + device, fs_type, fs_label); + else + printf(_("%s contains a %s file system\n"), device, + fs_type); + if (strncmp(fs_type, "ext", 3) == 0) + print_ext2_info(device); + free(fs_type); + free(fs_label); + return 0; + } + +#ifdef HAVE_MAGIC_H + if ((flags & CHECK_FS_EXIST) && + !getenv("E2FSPROGS_LIBMAGIC_SUPPRESS") && + magic_library_available()) { + const char *msg; + magic_t mag; + int has_magic = 0; + + mag = dl_magic_open(MAGIC_RAW | MAGIC_SYMLINK | MAGIC_DEVICES | + MAGIC_ERROR | MAGIC_NO_CHECK_ELF | + MAGIC_NO_CHECK_COMPRESS); + dl_magic_load(mag, NULL); + + msg = dl_magic_file(mag, device); + if (msg && strcmp(msg, "data") && strcmp(msg, "empty")) { + printf(_("%s contains `%s' data\n"), device, msg); + has_magic = 1; + } + + dl_magic_close(mag); + return !has_magic; + } +#endif + if (flags & CHECK_FS_EXIST) { + ret = check_partition_table(device); + if (ret >= 0) + return ret; + } + return 1; +} + diff --git a/jni/e2fsprogs/lib/support/plausible.o b/jni/e2fsprogs/lib/support/plausible.o new file mode 100755 index 0000000000000000000000000000000000000000..89f67eec3a3e5a26ee101f4fc968c3289800360a GIT binary patch literal 8232 zcmb_hU2Igx6`s4h;Kex91yTrqz7!J-RW>no6WT`28k^v#ZgFi=wN>bHy?gDw$qO#ZkpRL#)t;`*X zPXF%tk#3+nH!-_?syKUWYBVtaJow*;SXe}-!)wIJIYS&ptT_AqsZqm}?d7%6${HcY z_8QTO37-J)fz8-XA;z(v#-nPh+M$nf9Af{(#`WQ+q9@-LUaXoRrbU=b z921TMeU^o|hV}bUFSZ?`av-nN1O192>bG?{2kQJ7+V29c z#uj2OW5Dfdo8*T+kjwShD@Oi=zGlSI_;GC=BmX6^#rBft;~d7~TNI0%HC`-KezQjW z3Vr+>IaiAoEW^H<=5-LYe$s7x1LwqWqi8HZz*0T!MF2?7enCQM2Y}j`<7~1#uxVM)}YauS6BT4JM z9r(+iff#-k)=sctz8D0aXQI=^pceVa|G^QB!LKks*rnGyER zFVF^S)w7v{^MKoNE^v$u@R59LTBk=YvsRee$P7vBCPn zskX}yTQA1&9k6i9xV+FN#yPghRo^6}$g^Zrcs98HTYwYWFh&CA1$zZ2c(CRm7EwKHlqCW&Y`dVB#)e7rScrj`dw@Pwu zM%FJvoN#R(P1~%Bo6P~r@5v>tw?E!OjDS6BC;o*t2~3YM@_*~0KLqT@hqVq2|P<602cRAwMu0G}C%PGnzR z=J^%c0E=Uo$#lsiA!mX5xlV7&>UZLid?wN?WHE-3ry|ZR72S-Lpkmz3w&WCgb&PVVvG!Y^`e$O@M4B{3@?~cq8;nRM;{8bbIGpJvoou9bzobqzB$TSH#-^$AtS}gIAQ#?@$?W-YW>5CLDiIJxOKEMyPy1 z!_N}F0q{C1V>U+RCpG*W;pq2sRL1Orf^SmrD+;daEGxJ=u6p3b#Cl%vs`4cXi>!z7 z&18>y_)I~&7Q*#7;P^4=ap+WdRGmi^{3)-ieDZn8I^p+)Oi8k5os7E*j~chEf~$UU z{b17dj}oryA0wRgB)#tPr51~^PYmMe&1Jc<;q07NMCh4Uid8|Q+2+;;5!sOr#1fD)Hb5=GyaCc z1HU1vX;S0)E436g9>%Zu@LX4Lv&t^S1C4)<+8%2BjDMo=sQV=x^g41p@%tN79pM~L z#_I{!)qu^bH^SDybj_D}jJTAsxQ+QY-+QaX1nRNcF#{VYq7c_px zhZG)_e^S9!{Z};pi^P9b<7fPu!lUxvQE-+2p2mNL_{$nU;|~-bm0!>+HO8mO3zdAD zgk$`1J($$iNI0(t#-CH{abNtF^t2Gp^Tqg!grncR#En^0;Zgmz6R!L1@WEg6;Ys+| zCl!0t|3}jA63+S=&k~OM_bK{^6dv_lI!!q1=Pn}}Zc@V=3J>b}3+Wjpob@n%mT+Cq zIfV!H@Huv#aMr{41r29C6ABON`5Wn(B%JjyUL;)Cb5-F%J$w#dBb@axKBeKT=eoj! zdLELV8Nyi)<2MM`_1si=P!I2o_XuY_jK8nhLl>Do(Cit%r`dCy%bGpopJ?_Rhk4DO z@lcKDiT5e%3=^*F=XbnS5HEW5kOUnhm~sBSoYnA+q~pAX^F4uxC++x&Sk|=$@=mYg zI&eePZx`(Jporvb*NPPIYAX`Yq*8Dz2lreKJ_`H$^07X7JOC*7A330K}wC0ytT zS6AMBRl>~=r$hv94(-U{Z@&5rc#fYCeX?(#=ygvxi5RGk6|DZ)pydwOKtuh#>#TUe zN!c_aI~nWCSx}{Mpud>B3#)cgZpM;u)d|;R6ecTIa0+lC2A+DCF3+6aoRu4nS%a1X zw}yawiXbwvxCK2GgbkV-+Ct*Dpxax^)v9f^ww#1DK!KAgh5F%fCO z#}}CeN3$Oh`DlhQXYhg%`!&NQVB=8aIa&(;Q+5^BBfSzWe5OlUxi zmM5EuD3v;CKX3!Rj&N0=8^oej#4B{sAwGkL45V84;J)Gg$NOy#oTLB!@KMuQ^7{xI zmBdxf4?`Pr>MGDDm-8zMhV7g#k$;GSCbwGyz literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/prof_err.c b/jni/e2fsprogs/lib/support/prof_err.c new file mode 100755 index 0000000..2c8d43b --- /dev/null +++ b/jni/e2fsprogs/lib/support/prof_err.c @@ -0,0 +1,85 @@ +/* + * prof_err.c: + * This file is automatically generated; please do not edit it. + */ + +#include + +#define N_(a) a + +static const char * const text[] = { + N_("Profile version 0.0"), + N_("Bad magic value in profile_node"), + N_("Profile section not found"), + N_("Profile relation not found"), + N_( "Attempt to add a relation to node which is not a section"), + N_( "A profile section header has a non-zero value"), + N_("Bad linked list in profile structures"), + N_("Bad group level in profile structures"), + N_( "Bad parent pointer in profile structures"), + N_("Bad magic value in profile iterator"), + N_("Can't set value on section node"), + N_("Invalid argument passed to profile library"), + N_("Attempt to modify read-only profile"), + N_("Profile section header not at top level"), + N_("Syntax error in profile section header"), + N_("Syntax error in profile relation"), + N_("Extra closing brace in profile"), + N_("Missing open brace in profile"), + N_("Bad magic value in profile_t"), + N_("Bad magic value in profile_section_t"), + N_( "Iteration through all top level section not supported"), + N_("Invalid profile_section object"), + N_("No more sections"), + N_("Bad nameset passed to query routine"), + N_("No profile file open"), + N_("Bad magic value in profile_file_t"), + N_("Couldn't open profile file"), + N_("Section already exists"), + N_("Invalid boolean value"), + N_("Invalid integer value"), + N_("Bad magic value in profile_file_data_t"), + 0 +}; + +struct error_table { + char const * const * msgs; + long base; + int n_msgs; +}; +struct et_list { + struct et_list *next; + const struct error_table * table; +}; +extern struct et_list *_et_list; + +const struct error_table et_prof_error_table = { text, -1429577728L, 31 }; + +static struct et_list link = { 0, 0 }; + +void initialize_prof_error_table_r(struct et_list **list); +void initialize_prof_error_table(void); + +void initialize_prof_error_table(void) { + initialize_prof_error_table_r(&_et_list); +} + +/* For Heimdal compatibility */ +void initialize_prof_error_table_r(struct et_list **list) +{ + struct et_list *et, **end; + + for (end = list, et = *list; et; end = &et->next, et = et->next) + if (et->table->msgs == text) + return; + et = malloc(sizeof(struct et_list)); + if (et == 0) { + if (!link.table) + et = &link; + else + return; + } + et->table = &et_prof_error_table; + et->next = 0; + *end = et; +} diff --git a/jni/e2fsprogs/lib/support/prof_err.o b/jni/e2fsprogs/lib/support/prof_err.o new file mode 100755 index 0000000000000000000000000000000000000000..e965fca02c02433381b4a330740ad951dd6897a2 GIT binary patch literal 4416 zcmeI0Pi$007{I^nf-F*MK~NHqP9h0-=%z)CJuXnNBuG#+;b5|T-JR|}ef!?}-Ym4# zM3Tk?EXEiQ8qt^t@gRCI_$Q_ZHN=A{(HOWGdT8qR&HKLX>(JJNS0~vw zGr#%1Z|3{Hd2gnD_0ZA79l0Dx$-yVE*b|C%*J8V5n8B`ot`Y;om~fWR2Ookx!DachjVS2-B6kv>VS`= zU07S1qw)1<^RXOE6>{tU@Bp5p@kj9|a%78i#nxX73lBrb+3#r$H_V7Hm!VVZqM4(PERhaZ>>XyZL&E(ao{rgI7PnNko^Au82;wH z1uQ)ri{o)L>IYh#(sANPq3SF4!2z$T8eYw>s8e3h(#j82GZia`QB{NJB)VcqCyb05 zjap%~Jre7{bB6XCqZ>`5Or*SORe7o{gM`eg({;a6SAJscd5W#Wewkc|s%x*RV^#MO zG!sT)?-?CO>00gD13!F8S5@FACbM>xn7CCjtym{ksuoABrV8{a9jqeN^kN+v)r|bm z;GB!0aLp|rFy*6`XQCJmdf{$^E*K6f#%(cv7}O&n2HVHL#I;t#PU$5HdV$g5;G;t$ zu@{d+CX|h+>W_|NEWK)P6b9oW+s=f{!7-y$d6We998Qdf#v4;Qj-#dCac)z+6~!cp zaA?fLo~i^<;)gYb>#St=4Lt29b|7l%@ZQl?Hk?^)H?nhO14nF_X)~HS=CxK=UJxw0 znF%%Kpw(K3s1;Ochu8>ZEx-v*g%?no$CVz#jh(a?KN3ZO_CntOvW;lF)^Nkx zH~3%YuX@JAML;F+FnjVX=pQKd7YEW0MK^yha%Y}}+$%eC+dF$;7qV^4cThdp)jinx zNcY>4n+0#AP1;74+cn|(c_@nYCJqEk_hFGrS$IhOu70L(5*T9{H<%aWs zr-M`O*#5nI9r7GnY8N~xsGPuG4(_vUdWgT&&S&KbU?IO~Maz|Z#*U27*v6uL;Z)~= zR<*SJV7vG7Z!O2u&naKq{{0RGcmv7iOnhvfkl|Un#79xY^V`acoXr=qcUO=|Lx3-*fc#Zjahrh=BO^07%e$nAyF`st$Jo677z9XN4D-Q2v ze%0a6Fu(5bQRX)sevbK!!{1?k)8U^npLO^R=C>XGJ9GIi(0<6izw&)qi=0DXEex_9 z;UWh`x@r`S9y3tZrc9SRC|05d-Ibs?k|f}VzVY!6bw-!z{4Co$P1$%Oc)-T2PX`@Y zD#j7eH4%zO-7_WkTJB_ZFM`Jwb0cUb;tu_xd@Y)eoKy-=~DB`sf*MRkS zgX&$?;uG}PM~}zpv6mkGICErIhw}Z{-8F_c@&8^vMH7;WthK_%v?uSgjPdIvU7Isv z+1$}!i5^(+Z?+}HJrQY`SZRqAz?DJ@6zkKuK>L7k`(AMv8Hu<)46)ueu2IAm(U<;y zY%Dkb4F2(I3mc~SNlx^)rK7NunLGb5Z`y8_lS=fZ{~I=FiF*ZbE&3asfQdU&Z)JUV zFEltI4>@*4PwJDb?})*qn@|=IJ&|v)KD#Rz&ar;IP11(zKaDRNf4&HaU(}^@Q1m7K W*O0k$BZAvJ|8-t4RrD_qSN|VL5r;(p literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/profile.c b/jni/e2fsprogs/lib/support/profile.c new file mode 100755 index 0000000..bdb14b1 --- /dev/null +++ b/jni/e2fsprogs/lib/support/profile.c @@ -0,0 +1,1910 @@ +/* + * profile.c -- A simple configuration file parsing "library in a file" + * + * The profile library was originally written by Theodore Ts'o in 1995 + * for use in the MIT Kerberos v5 library. It has been + * modified/enhanced/bug-fixed over time by other members of the MIT + * Kerberos team. This version was originally taken from the Kerberos + * v5 distribution, version 1.4.2, and radically simplified for use in + * e2fsprogs. (Support for locking for multi-threaded operations, + * being able to modify and update the configuration file + * programmatically, and Mac/Windows portability have been removed. + * It has been folded into a single C source file to make it easier to + * fold into an application program.) + * + * Copyright (C) 2005, 2006 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original MIT software. + * M.I.T. makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include "config.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_PWD_H +#include +#endif + +#include +#include "profile.h" +#include "prof_err.h" + +#undef STAT_ONCE_PER_SECOND +#undef HAVE_STAT + +/* + * prof_int.h + */ + +typedef long prf_magic_t; + +/* + * This is the structure which stores the profile information for a + * particular configuration file. + */ +struct _prf_file_t { + prf_magic_t magic; + char *filespec; +#ifdef STAT_ONCE_PER_SECOND + time_t last_stat; +#endif + time_t timestamp; /* time tree was last updated from file */ + int flags; /* r/w, dirty */ + int upd_serial; /* incremented when data changes */ + struct profile_node *root; + struct _prf_file_t *next; +}; + +typedef struct _prf_file_t *prf_file_t; + +/* + * The profile flags + */ +#define PROFILE_FILE_RW 0x0001 +#define PROFILE_FILE_DIRTY 0x0002 +#define PROFILE_FILE_NO_RELOAD 0x0004 + +/* + * This structure defines the high-level, user visible profile_t + * object, which is used as a handle by users who need to query some + * configuration file(s) + */ +struct _profile_t { + prf_magic_t magic; + prf_file_t first_file; +}; + +/* + * Used by the profile iterator in prof_get.c + */ +#define PROFILE_ITER_LIST_SECTION 0x0001 +#define PROFILE_ITER_SECTIONS_ONLY 0x0002 +#define PROFILE_ITER_RELATIONS_ONLY 0x0004 + +#define PROFILE_ITER_FINAL_SEEN 0x0100 + +/* + * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS + */ + +#define PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0')) + +struct profile_node { + errcode_t magic; + char *name; + char *value; + int group_level; + unsigned int final:1; /* Indicate don't search next file */ + unsigned int deleted:1; + struct profile_node *first_child; + struct profile_node *parent; + struct profile_node *next, *prev; +}; + +#define CHECK_MAGIC(node) \ + if ((node)->magic != PROF_MAGIC_NODE) \ + return PROF_MAGIC_NODE; + +/* profile parser declarations */ +struct parse_state { + int state; + int group_level; + int line_num; + struct profile_node *root_section; + struct profile_node *current_section; +}; + +static const char *default_filename = ""; + +static profile_syntax_err_cb_t syntax_err_cb; + +static errcode_t parse_line(char *line, struct parse_state *state); + +#ifdef DEBUG_PROGRAM +static errcode_t profile_write_tree_file + (struct profile_node *root, FILE *dstfile); + +static errcode_t profile_write_tree_to_buffer + (struct profile_node *root, char **buf); +#endif + + +static void profile_free_node + (struct profile_node *relation); + +static errcode_t profile_create_node + (const char *name, const char *value, + struct profile_node **ret_node); + +#ifdef DEBUG_PROGRAM +static errcode_t profile_verify_node + (struct profile_node *node); +#endif + +static errcode_t profile_add_node + (struct profile_node *section, + const char *name, const char *value, + struct profile_node **ret_node); + +static errcode_t profile_find_node + (struct profile_node *section, + const char *name, const char *value, + int section_flag, void **state, + struct profile_node **node); + +static errcode_t profile_node_iterator + (void **iter_p, struct profile_node **ret_node, + char **ret_name, char **ret_value); + +static errcode_t profile_open_file + (const char * file, prf_file_t *ret_prof); + +static errcode_t profile_update_file + (prf_file_t prf); + +static void profile_free_file + (prf_file_t profile); + +static errcode_t profile_get_value(profile_t profile, const char *name, + const char *subname, const char *subsubname, + const char **ret_value); + + +/* + * prof_init.c --- routines that manipulate the user-visible profile_t + * object. + */ + +static int compstr(const void *m1, const void *m2) +{ + const char *s1 = *((const char * const *) m1); + const char *s2 = *((const char * const *) m2); + + return strcmp(s1, s2); +} + +static void free_list(char **list) +{ + char **cp; + + if (list == 0) + return; + + for (cp = list; *cp; cp++) + free(*cp); + free(list); +} + +static errcode_t get_dirlist(const char *dirname, char***ret_array) +{ + DIR *dir; + struct dirent *de; + struct stat st; + errcode_t retval; + char *fn, *cp; + char **array = 0, **new_array; + int max = 0, num = 0; + + dir = opendir(dirname); + if (!dir) + return errno; + + while ((de = readdir(dir)) != NULL) { + for (cp = de->d_name; *cp; cp++) { + if (!isalnum(*cp) && + (*cp != '-') && + (*cp != '_')) + break; + } + if (*cp) + continue; + fn = malloc(strlen(dirname) + strlen(de->d_name) + 2); + if (!fn) { + retval = ENOMEM; + goto errout; + } + sprintf(fn, "%s/%s", dirname, de->d_name); + if ((stat(fn, &st) < 0) || !S_ISREG(st.st_mode)) { + free(fn); + continue; + } + if (num >= max) { + max += 10; + new_array = realloc(array, sizeof(char *) * (max+1)); + if (!new_array) { + retval = ENOMEM; + free(fn); + goto errout; + } + array = new_array; + } + array[num++] = fn; + } + if (array) { + qsort(array, num, sizeof(char *), compstr); + array[num++] = 0; + } + *ret_array = array; + closedir(dir); + return 0; +errout: + if (array) + array[num] = 0; + closedir(dir); + free_list(array); + return retval; +} + +errcode_t +profile_init(const char * const *files, profile_t *ret_profile) +{ + const char * const *fs; + profile_t profile; + prf_file_t new_file, *last; + errcode_t retval = 0; + char **cpp, *cp, **array = 0; + + profile = malloc(sizeof(struct _profile_t)); + if (!profile) + return ENOMEM; + memset(profile, 0, sizeof(struct _profile_t)); + profile->magic = PROF_MAGIC_PROFILE; + last = &profile->first_file; + + /* if the filenames list is not specified return an empty profile */ + if ( files ) { + for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) { + if (array) + free_list(array); + array = NULL; + retval = get_dirlist(*fs, &array); + if (retval == 0) { + if (!array) + continue; + for (cpp = array; (cp = *cpp); cpp++) { + retval = profile_open_file(cp, &new_file); + if (retval == EACCES) + continue; + if (retval) + goto errout; + *last = new_file; + last = &new_file->next; + } + } else if ((retval != ENOTDIR) && + strcmp(*fs, default_filename)) + goto errout; + + retval = profile_open_file(*fs, &new_file); + /* if this file is missing, skip to the next */ + if (retval == ENOENT || retval == EACCES) { + continue; + } + if (retval) + goto errout; + *last = new_file; + last = &new_file->next; + } + /* + * If all the files were not found, return the appropriate error. + */ + if (!profile->first_file) { + retval = ENOENT; + goto errout; + } + } + + free_list(array); + *ret_profile = profile; + return 0; +errout: + free_list(array); + profile_release(profile); + return retval; +} + +void +profile_release(profile_t profile) +{ + prf_file_t p, next; + + if (!profile || profile->magic != PROF_MAGIC_PROFILE) + return; + + for (p = profile->first_file; p; p = next) { + next = p->next; + profile_free_file(p); + } + profile->magic = 0; + free(profile); +} + +/* + * This function sets the value of the pseudo file "". If + * the file "" had previously been passed to profile_init(), + * then def_string parameter will be parsed and used as the profile + * information for the "" file. + */ +errcode_t profile_set_default(profile_t profile, const char *def_string) +{ + struct parse_state state; + prf_file_t prf; + errcode_t retval; + const char *in; + char *line, *p, *end; + int line_size, len; + + if (!def_string || !profile || profile->magic != PROF_MAGIC_PROFILE) + return PROF_MAGIC_PROFILE; + + for (prf = profile->first_file; prf; prf = prf->next) { + if (strcmp(prf->filespec, default_filename) == 0) + break; + } + if (!prf) + return 0; + + if (prf->root) { + profile_free_node(prf->root); + prf->root = 0; + } + + memset(&state, 0, sizeof(struct parse_state)); + retval = profile_create_node("(root)", 0, &state.root_section); + if (retval) + return retval; + + line = 0; + line_size = 0; + in = def_string; + while (*in) { + end = strchr(in, '\n'); + len = end ? (end - in) : (int) strlen(in); + if (len >= line_size) { + line_size = len+1; + p = realloc(line, line_size); + if (!p) { + retval = ENOMEM; + goto errout; + } + line = p; + } + memcpy(line, in, len); + line[len] = 0; + retval = parse_line(line, &state); + if (retval) { + errout: + if (syntax_err_cb) + (syntax_err_cb)(prf->filespec, retval, + state.line_num); + free(line); + if (prf->root) + profile_free_node(prf->root); + return retval; + } + if (!end) + break; + in = end+1; + } + prf->root = state.root_section; + free(line); + + return 0; +} + +/* + * prof_file.c ---- routines that manipulate an individual profile file. + */ + +errcode_t profile_open_file(const char * filespec, + prf_file_t *ret_prof) +{ + prf_file_t prf; + errcode_t retval; + char *home_env = 0; + unsigned int len; + char *expanded_filename; + + prf = malloc(sizeof(struct _prf_file_t)); + if (!prf) + return ENOMEM; + memset(prf, 0, sizeof(struct _prf_file_t)); + prf->magic = PROF_MAGIC_FILE; + + len = strlen(filespec)+1; + if (filespec[0] == '~' && filespec[1] == '/') { + home_env = getenv("HOME"); +#ifdef HAVE_PWD_H + if (home_env == NULL) { +#ifdef HAVE_GETWUID_R + struct passwd *pw, pwx; + uid_t uid; + char pwbuf[BUFSIZ]; + + uid = getuid(); + if (!getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) + && pw != NULL && pw->pw_dir[0] != 0) + home_env = pw->pw_dir; +#else + struct passwd *pw; + + pw = getpwuid(getuid()); + home_env = pw->pw_dir; +#endif + } +#endif + if (home_env) + len += strlen(home_env); + } + expanded_filename = malloc(len); + if (expanded_filename == 0) { + profile_free_file(prf); + return errno; + } + if (home_env) { + strcpy(expanded_filename, home_env); + strcat(expanded_filename, filespec+1); + } else + memcpy(expanded_filename, filespec, len); + + prf->filespec = expanded_filename; + + if (strcmp(prf->filespec, default_filename) != 0) { + retval = profile_update_file(prf); + if (retval) { + profile_free_file(prf); + return retval; + } + } + + *ret_prof = prf; + return 0; +} + +errcode_t profile_update_file(prf_file_t prf) +{ + errcode_t retval; +#ifdef HAVE_STAT + struct stat st; +#ifdef STAT_ONCE_PER_SECOND + time_t now; +#endif +#endif + FILE *f; + char buf[2048]; + struct parse_state state; + + if (prf->flags & PROFILE_FILE_NO_RELOAD) + return 0; + +#ifdef HAVE_STAT +#ifdef STAT_ONCE_PER_SECOND + now = time(0); + if (now == prf->last_stat && prf->root != NULL) { + return 0; + } +#endif + if (stat(prf->filespec, &st)) { + retval = errno; + return retval; + } +#ifdef STAT_ONCE_PER_SECOND + prf->last_stat = now; +#endif + if (st.st_mtime == prf->timestamp && prf->root != NULL) { + return 0; + } + if (prf->root) { + profile_free_node(prf->root); + prf->root = 0; + } +#else + /* + * If we don't have the stat() call, assume that our in-core + * memory image is correct. That is, we won't reread the + * profile file if it changes. + */ + if (prf->root) { + return 0; + } +#endif + memset(&state, 0, sizeof(struct parse_state)); + retval = profile_create_node("(root)", 0, &state.root_section); + if (retval) + return retval; + errno = 0; + f = fopen(prf->filespec, "r"); + if (f == NULL) { + retval = errno; + if (retval == 0) + retval = ENOENT; + return retval; + } + prf->upd_serial++; + while (!feof(f)) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + retval = parse_line(buf, &state); + if (retval) { + if (syntax_err_cb) + (syntax_err_cb)(prf->filespec, retval, + state.line_num); + fclose(f); + return retval; + } + } + prf->root = state.root_section; + + fclose(f); + +#ifdef HAVE_STAT + prf->timestamp = st.st_mtime; +#endif + return 0; +} + +void profile_free_file(prf_file_t prf) +{ + if (prf->root) + profile_free_node(prf->root); + free(prf->filespec); + free(prf); +} + +/* Begin the profile parser */ + +profile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook) +{ + profile_syntax_err_cb_t old; + + old = syntax_err_cb; + syntax_err_cb = hook; + return(old); +} + +#define STATE_INIT_COMMENT 0 +#define STATE_STD_LINE 1 +#define STATE_GET_OBRACE 2 + +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace((int) (*cp))) + cp++; + return cp; +} + +static int end_or_comment(char ch) +{ + return (ch == 0 || ch == '#' || ch == ';'); +} + +static char *skip_over_nonblanks(char *cp) +{ + while (!end_or_comment(*cp) && !isspace(*cp)) + cp++; + return cp; +} + +static void strip_line(char *line) +{ + char *p = line + strlen(line); + while (p > line && (p[-1] == '\n' || p[-1] == '\r')) + *p-- = 0; +} + +static void parse_quoted_string(char *str) +{ + char *to, *from; + + to = from = str; + + for (to = from = str; *from && *from != '"'; to++, from++) { + if (*from == '\\') { + from++; + switch (*from) { + case 'n': + *to = '\n'; + break; + case 't': + *to = '\t'; + break; + case 'b': + *to = '\b'; + break; + default: + *to = *from; + } + continue; + } + *to = *from; + } + *to = '\0'; +} + +static errcode_t parse_line(char *line, struct parse_state *state) +{ + char *cp, ch, *tag, *value; + char *p; + errcode_t retval; + struct profile_node *node; + int do_subsection = 0; + void *iter = 0; + + state->line_num++; + if (state->state == STATE_GET_OBRACE) { + cp = skip_over_blanks(line); + if (*cp != '{') + return PROF_MISSING_OBRACE; + state->state = STATE_STD_LINE; + return 0; + } + if (state->state == STATE_INIT_COMMENT) { + if (line[0] != '[') + return 0; + state->state = STATE_STD_LINE; + } + + if (*line == 0) + return 0; + strip_line(line); + cp = skip_over_blanks(line); + ch = *cp; + if (end_or_comment(ch)) + return 0; + if (ch == '[') { + if (state->group_level > 0) + return PROF_SECTION_NOTOP; + cp++; + cp = skip_over_blanks(cp); + p = strchr(cp, ']'); + if (p == NULL) + return PROF_SECTION_SYNTAX; + if (*cp == '"') { + cp++; + parse_quoted_string(cp); + } else { + *p-- = '\0'; + while (isspace(*p) && (p > cp)) + *p-- = '\0'; + if (*cp == 0) + return PROF_SECTION_SYNTAX; + } + retval = profile_find_node(state->root_section, cp, 0, 1, + &iter, &state->current_section); + if (retval == PROF_NO_SECTION) { + retval = profile_add_node(state->root_section, + cp, 0, + &state->current_section); + if (retval) + return retval; + } else if (retval) + return retval; + + /* + * Finish off the rest of the line. + */ + cp = p+1; + if (*cp == '*') { + state->current_section->final = 1; + cp++; + } + /* + * Spaces or comments after ']' should not be fatal + */ + cp = skip_over_blanks(cp); + if (!end_or_comment(*cp)) + return PROF_SECTION_SYNTAX; + return 0; + } + if (ch == '}') { + if (state->group_level == 0) + return PROF_EXTRA_CBRACE; + if (*(cp+1) == '*') + state->current_section->final = 1; + state->current_section = state->current_section->parent; + state->group_level--; + return 0; + } + /* + * Parse the relations + */ + tag = cp; + cp = strchr(cp, '='); + if (!cp) + return PROF_RELATION_SYNTAX; + if (cp == tag) + return PROF_RELATION_SYNTAX; + *cp = '\0'; + if (*tag == '"') { + tag++; + parse_quoted_string(tag); + } else { + /* Look for whitespace on left-hand side. */ + p = skip_over_nonblanks(tag); + if (*p) + *p++ = 0; + p = skip_over_blanks(p); + /* If we have more non-whitespace, it's an error. */ + if (*p) + return PROF_RELATION_SYNTAX; + } + + cp = skip_over_blanks(cp+1); + value = cp; + ch = value[0]; + if (ch == '"') { + value++; + parse_quoted_string(value); + } else if (end_or_comment(ch)) { + do_subsection++; + state->state = STATE_GET_OBRACE; + } else if (value[0] == '{') { + cp = skip_over_blanks(value+1); + ch = *cp; + if (end_or_comment(ch)) + do_subsection++; + else + return PROF_RELATION_SYNTAX; + } else { + cp = skip_over_nonblanks(value); + p = skip_over_blanks(cp); + ch = *p; + *cp = 0; + if (!end_or_comment(ch)) + return PROF_RELATION_SYNTAX; + } + if (do_subsection) { + p = strchr(tag, '*'); + if (p) + *p = '\0'; + retval = profile_add_node(state->current_section, + tag, 0, &state->current_section); + if (retval) + return retval; + if (p) + state->current_section->final = 1; + state->group_level++; + return 0; + } + p = strchr(tag, '*'); + if (p) + *p = '\0'; + profile_add_node(state->current_section, tag, value, &node); + if (p) + node->final = 1; + return 0; +} + +#ifdef DEBUG_PROGRAM +/* + * Return TRUE if the string begins or ends with whitespace + */ +static int need_double_quotes(char *str) +{ + if (!str || !*str) + return 0; + if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1)))) + return 1; + if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b') || + strchr(str, ' ') || strchr(str, '#') || strchr(str, ';')) + return 1; + return 0; +} + +/* + * Output a string with double quotes, doing appropriate backquoting + * of characters as necessary. + */ +static void output_quoted_string(char *str, void (*cb)(const char *,void *), + void *data) +{ + char ch; + char buf[2]; + + cb("\"", data); + if (!str) { + cb("\"", data); + return; + } + buf[1] = 0; + while ((ch = *str++)) { + switch (ch) { + case '\\': + cb("\\\\", data); + break; + case '\n': + cb("\\n", data); + break; + case '\t': + cb("\\t", data); + break; + case '\b': + cb("\\b", data); + break; + default: + /* This would be a lot faster if we scanned + forward for the next "interesting" + character. */ + buf[0] = ch; + cb(buf, data); + break; + } + } + cb("\"", data); +} + +#ifndef EOL +#define EOL "\n" +#endif + +/* Errors should be returned, not ignored! */ +static void dump_profile(struct profile_node *root, int level, + void (*cb)(const char *, void *), void *data) +{ + int i; + struct profile_node *p; + void *iter; + long retval; + + iter = 0; + do { + retval = profile_find_node(root, 0, 0, 0, &iter, &p); + if (retval) + break; + for (i=0; i < level; i++) + cb("\t", data); + if (need_double_quotes(p->name)) + output_quoted_string(p->name, cb, data); + else + cb(p->name, data); + cb(" = ", data); + if (need_double_quotes(p->value)) + output_quoted_string(p->value, cb, data); + else + cb(p->value, data); + cb(EOL, data); + } while (iter != 0); + + iter = 0; + do { + retval = profile_find_node(root, 0, 0, 1, &iter, &p); + if (retval) + break; + if (level == 0) { /* [xxx] */ + cb("[", data); + if (need_double_quotes(p->name)) + output_quoted_string(p->name, cb, data); + else + cb(p->name, data); + cb("]", data); + cb(p->final ? "*" : "", data); + cb(EOL, data); + dump_profile(p, level+1, cb, data); + cb(EOL, data); + } else { /* xxx = { ... } */ + for (i=0; i < level; i++) + cb("\t", data); + if (need_double_quotes(p->name)) + output_quoted_string(p->name, cb, data); + else + cb(p->name, data); + cb(" = {", data); + cb(EOL, data); + dump_profile(p, level+1, cb, data); + for (i=0; i < level; i++) + cb("\t", data); + cb("}", data); + cb(p->final ? "*" : "", data); + cb(EOL, data); + } + } while (iter != 0); +} + +static void dump_profile_to_file_cb(const char *str, void *data) +{ + fputs(str, data); +} + +errcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile) +{ + dump_profile(root, 0, dump_profile_to_file_cb, dstfile); + return 0; +} + +struct prof_buf { + char *base; + size_t cur, max; + int err; +}; + +static void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len) +{ + if (b->err) + return; + if (b->max - b->cur < len) { + size_t newsize; + char *newptr; + + newsize = b->max + (b->max >> 1) + len + 1024; + newptr = realloc(b->base, newsize); + if (newptr == NULL) { + b->err = 1; + return; + } + b->base = newptr; + b->max = newsize; + } + memcpy(b->base + b->cur, d, len); + b->cur += len; /* ignore overflow */ +} + +static void dump_profile_to_buffer_cb(const char *str, void *data) +{ + add_data_to_buffer((struct prof_buf *)data, str, strlen(str)); +} + +errcode_t profile_write_tree_to_buffer(struct profile_node *root, + char **buf) +{ + struct prof_buf prof_buf = { 0, 0, 0, 0 }; + + dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf); + if (prof_buf.err) { + *buf = NULL; + return ENOMEM; + } + add_data_to_buffer(&prof_buf, "", 1); /* append nul */ + if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) { + char *newptr = realloc(prof_buf.base, prof_buf.cur); + if (newptr) + prof_buf.base = newptr; + } + *buf = prof_buf.base; + return 0; +} +#endif + +/* + * prof_tree.c --- these routines maintain the parse tree of the + * config file. + * + * All of the details of how the tree is stored is abstracted away in + * this file; all of the other profile routines build, access, and + * modify the tree via the accessor functions found in this file. + * + * Each node may represent either a relation or a section header. + * + * A section header must have its value field set to 0, and may a one + * or more child nodes, pointed to by first_child. + * + * A relation has as its value a pointer to allocated memory + * containing a string. Its first_child pointer must be null. + * + */ + +/* + * Free a node, and any children + */ +void profile_free_node(struct profile_node *node) +{ + struct profile_node *child, *next; + + if (node->magic != PROF_MAGIC_NODE) + return; + + free(node->name); + free(node->value); + + for (child=node->first_child; child; child = next) { + next = child->next; + profile_free_node(child); + } + node->magic = 0; + + free(node); +} + +#ifndef HAVE_STRDUP +#undef strdup +#define strdup MYstrdup +static char *MYstrdup (const char *s) +{ + size_t sz = strlen(s) + 1; + char *p = malloc(sz); + if (p != 0) + memcpy(p, s, sz); + return p; +} +#endif + +/* + * Create a node + */ +errcode_t profile_create_node(const char *name, const char *value, + struct profile_node **ret_node) +{ + struct profile_node *new; + + new = malloc(sizeof(struct profile_node)); + if (!new) + return ENOMEM; + memset(new, 0, sizeof(struct profile_node)); + new->magic = PROF_MAGIC_NODE; + new->name = strdup(name); + if (new->name == 0) { + profile_free_node(new); + return ENOMEM; + } + if (value) { + new->value = strdup(value); + if (new->value == 0) { + profile_free_node(new); + return ENOMEM; + } + } + + *ret_node = new; + return 0; +} + +/* + * This function verifies that all of the representation invariants of + * the profile are true. If not, we have a programming bug somewhere, + * probably in this file. + */ +#ifdef DEBUG_PROGRAM +errcode_t profile_verify_node(struct profile_node *node) +{ + struct profile_node *p, *last; + errcode_t retval; + + CHECK_MAGIC(node); + + if (node->value && node->first_child) + return PROF_SECTION_WITH_VALUE; + + last = 0; + for (p = node->first_child; p; last = p, p = p->next) { + if (p->prev != last) + return PROF_BAD_LINK_LIST; + if (last && (last->next != p)) + return PROF_BAD_LINK_LIST; + if (node->group_level+1 != p->group_level) + return PROF_BAD_GROUP_LVL; + if (p->parent != node) + return PROF_BAD_PARENT_PTR; + retval = profile_verify_node(p); + if (retval) + return retval; + } + return 0; +} +#endif + +/* + * Add a node to a particular section + */ +errcode_t profile_add_node(struct profile_node *section, const char *name, + const char *value, struct profile_node **ret_node) +{ + errcode_t retval; + struct profile_node *p, *last, *new; + + CHECK_MAGIC(section); + + if (section->value) + return PROF_ADD_NOT_SECTION; + + /* + * Find the place to insert the new node. We look for the + * place *after* the last match of the node name, since + * order matters. + */ + for (p=section->first_child, last = 0; p; last = p, p = p->next) { + int cmp; + cmp = strcmp(p->name, name); + if (cmp > 0) + break; + } + retval = profile_create_node(name, value, &new); + if (retval) + return retval; + new->group_level = section->group_level+1; + new->deleted = 0; + new->parent = section; + new->prev = last; + new->next = p; + if (p) + p->prev = new; + if (last) + last->next = new; + else + section->first_child = new; + if (ret_node) + *ret_node = new; + return 0; +} + +/* + * Iterate through the section, returning the nodes which match + * the given name. If name is NULL, then iterate through all the + * nodes in the section. If section_flag is non-zero, only return the + * section which matches the name; don't return relations. If value + * is non-NULL, then only return relations which match the requested + * value. (The value argument is ignored if section_flag is non-zero.) + * + * The first time this routine is called, the state pointer must be + * null. When this profile_find_node_relation() returns, if the state + * pointer is non-NULL, then this routine should be called again. + * (This won't happen if section_flag is non-zero, obviously.) + * + */ +errcode_t profile_find_node(struct profile_node *section, const char *name, + const char *value, int section_flag, void **state, + struct profile_node **node) +{ + struct profile_node *p; + + CHECK_MAGIC(section); + p = *state; + if (p) { + CHECK_MAGIC(p); + } else + p = section->first_child; + + for (; p; p = p->next) { + if (name && (strcmp(p->name, name))) + continue; + if (section_flag) { + if (p->value) + continue; + } else { + if (!p->value) + continue; + if (value && (strcmp(p->value, value))) + continue; + } + if (p->deleted) + continue; + /* A match! */ + if (node) + *node = p; + break; + } + if (p == 0) { + *state = 0; + return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION; + } + /* + * OK, we've found one match; now let's try to find another + * one. This way, if we return a non-zero state pointer, + * there's guaranteed to be another match that's returned. + */ + for (p = p->next; p; p = p->next) { + if (name && (strcmp(p->name, name))) + continue; + if (section_flag) { + if (p->value) + continue; + } else { + if (!p->value) + continue; + if (value && (strcmp(p->value, value))) + continue; + } + /* A match! */ + break; + } + *state = p; + return 0; +} + +/* + * This is a general-purpose iterator for returning all nodes that + * match the specified name array. + */ +struct profile_iterator { + prf_magic_t magic; + profile_t profile; + int flags; + const char *const *names; + const char *name; + prf_file_t file; + int file_serial; + int done_idx; + struct profile_node *node; + int num; +}; + +errcode_t +profile_iterator_create(profile_t profile, const char *const *names, int flags, + void **ret_iter) +{ + struct profile_iterator *iter; + int done_idx = 0; + + if (profile == 0) + return PROF_NO_PROFILE; + if (profile->magic != PROF_MAGIC_PROFILE) + return PROF_MAGIC_PROFILE; + if (!names) + return PROF_BAD_NAMESET; + if (!(flags & PROFILE_ITER_LIST_SECTION)) { + if (!names[0]) + return PROF_BAD_NAMESET; + done_idx = 1; + } + + if ((iter = malloc(sizeof(struct profile_iterator))) == NULL) + return ENOMEM; + + iter->magic = PROF_MAGIC_ITERATOR; + iter->profile = profile; + iter->names = names; + iter->flags = flags; + iter->file = profile->first_file; + iter->done_idx = done_idx; + iter->node = 0; + iter->num = 0; + *ret_iter = iter; + return 0; +} + +void profile_iterator_free(void **iter_p) +{ + struct profile_iterator *iter; + + if (!iter_p) + return; + iter = *iter_p; + if (!iter || iter->magic != PROF_MAGIC_ITERATOR) + return; + free(iter); + *iter_p = 0; +} + +/* + * Note: the returned character strings in ret_name and ret_value + * points to the stored character string in the parse string. Before + * this string value is returned to a calling application + * (profile_node_iterator is not an exported interface), it should be + * strdup()'ed. + */ +errcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node, + char **ret_name, char **ret_value) +{ + struct profile_iterator *iter = *iter_p; + struct profile_node *section, *p; + const char *const *cpp; + errcode_t retval; + int skip_num = 0; + + if (!iter || iter->magic != PROF_MAGIC_ITERATOR) + return PROF_MAGIC_ITERATOR; + if (iter->file && iter->file->magic != PROF_MAGIC_FILE) + return PROF_MAGIC_FILE; + /* + * If the file has changed, then the node pointer is invalid, + * so we'll have search the file again looking for it. + */ + if (iter->node && (iter->file && + iter->file->upd_serial != iter->file_serial)) { + iter->flags &= ~PROFILE_ITER_FINAL_SEEN; + skip_num = iter->num; + iter->node = 0; + } + if (iter->node && iter->node->magic != PROF_MAGIC_NODE) { + return PROF_MAGIC_NODE; + } +get_new_file: + if (iter->node == 0) { + if (iter->file == NULL || + (iter->flags & PROFILE_ITER_FINAL_SEEN)) { + profile_iterator_free(iter_p); + if (ret_node) + *ret_node = 0; + if (ret_name) + *ret_name = 0; + if (ret_value) + *ret_value =0; + return 0; + } + if ((retval = profile_update_file(iter->file))) { + if (retval == ENOENT || retval == EACCES) { + /* XXX memory leak? */ + if (iter->file) + iter->file = iter->file->next; + skip_num = 0; + retval = 0; + goto get_new_file; + } else { + profile_iterator_free(iter_p); + return retval; + } + } + iter->file_serial = iter->file->upd_serial; + /* + * Find the section to list if we are a LIST_SECTION, + * or find the containing section if not. + */ + section = iter->file->root; + for (cpp = iter->names; cpp[iter->done_idx]; cpp++) { + for (p=section->first_child; p; p = p->next) { + if (!strcmp(p->name, *cpp) && !p->value) + break; + } + if (!p) { + section = 0; + break; + } + section = p; + if (p->final) + iter->flags |= PROFILE_ITER_FINAL_SEEN; + } + if (!section) { + if (iter->file) + iter->file = iter->file->next; + skip_num = 0; + goto get_new_file; + } + iter->name = *cpp; + iter->node = section->first_child; + } + /* + * OK, now we know iter->node is set up correctly. Let's do + * the search. + */ + for (p = iter->node; p; p = p->next) { + if (iter->name && strcmp(p->name, iter->name)) + continue; + if ((iter->flags & PROFILE_ITER_SECTIONS_ONLY) && + p->value) + continue; + if ((iter->flags & PROFILE_ITER_RELATIONS_ONLY) && + !p->value) + continue; + if (skip_num > 0) { + skip_num--; + continue; + } + if (p->deleted) + continue; + break; + } + iter->num++; + if (!p) { + if (iter->file) + iter->file = iter->file->next; + iter->node = 0; + skip_num = 0; + goto get_new_file; + } + if ((iter->node = p->next) == NULL) + if (iter->file) + iter->file = iter->file->next; + if (ret_node) + *ret_node = p; + if (ret_name) + *ret_name = p->name; + if (ret_value) + *ret_value = p->value; + return 0; +} + + +/* + * prof_get.c --- routines that expose the public interfaces for + * querying items from the profile. + * + */ + +/* + * This function only gets the first value from the file; it is a + * helper function for profile_get_string, profile_get_integer, etc. + */ +errcode_t profile_get_value(profile_t profile, const char *name, + const char *subname, const char *subsubname, + const char **ret_value) +{ + errcode_t retval; + void *state; + char *value; + const char *names[4]; + + names[0] = name; + names[1] = subname; + names[2] = subsubname; + names[3] = 0; + + if ((retval = profile_iterator_create(profile, names, + PROFILE_ITER_RELATIONS_ONLY, + &state))) + return retval; + + if ((retval = profile_node_iterator(&state, 0, 0, &value))) + goto cleanup; + + if (value) + *ret_value = value; + else + retval = PROF_NO_RELATION; + +cleanup: + profile_iterator_free(&state); + return retval; +} + +errcode_t +profile_get_string(profile_t profile, const char *name, const char *subname, + const char *subsubname, const char *def_val, + char **ret_string) +{ + const char *value; + errcode_t retval; + + if (profile) { + retval = profile_get_value(profile, name, subname, + subsubname, &value); + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) + value = def_val; + else if (retval) + return retval; + } else + value = def_val; + + if (value) { + *ret_string = malloc(strlen(value)+1); + if (*ret_string == 0) + return ENOMEM; + strcpy(*ret_string, value); + } else + *ret_string = 0; + return 0; +} + +errcode_t +profile_get_integer(profile_t profile, const char *name, const char *subname, + const char *subsubname, int def_val, int *ret_int) +{ + const char *value; + errcode_t retval; + char *end_value; + long ret_long; + + *ret_int = def_val; + if (profile == 0) + return 0; + + retval = profile_get_value(profile, name, subname, subsubname, &value); + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { + *ret_int = def_val; + return 0; + } else if (retval) + return retval; + + if (value[0] == 0) + /* Empty string is no good. */ + return PROF_BAD_INTEGER; + errno = 0; + ret_long = strtol(value, &end_value, 0); + + /* Overflow or underflow. */ + if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0) + return PROF_BAD_INTEGER; + /* Value outside "int" range. */ + if ((long) (int) ret_long != ret_long) + return PROF_BAD_INTEGER; + /* Garbage in string. */ + if (end_value != value + strlen (value)) + return PROF_BAD_INTEGER; + + + *ret_int = ret_long; + return 0; +} + +errcode_t +profile_get_uint(profile_t profile, const char *name, const char *subname, + const char *subsubname, unsigned int def_val, + unsigned int *ret_int) +{ + const char *value; + errcode_t retval; + char *end_value; + unsigned long ret_long; + + *ret_int = def_val; + if (profile == 0) + return 0; + + retval = profile_get_value(profile, name, subname, subsubname, &value); + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { + *ret_int = def_val; + return 0; + } else if (retval) + return retval; + + if (value[0] == 0) + /* Empty string is no good. */ + return PROF_BAD_INTEGER; + errno = 0; + ret_long = strtoul(value, &end_value, 0); + + /* Overflow or underflow. */ + if ((ret_long == ULONG_MAX) && errno != 0) + return PROF_BAD_INTEGER; + /* Value outside "int" range. */ + if ((unsigned long) (unsigned int) ret_long != ret_long) + return PROF_BAD_INTEGER; + /* Garbage in string. */ + if (end_value != value + strlen (value)) + return PROF_BAD_INTEGER; + + *ret_int = ret_long; + return 0; +} + +errcode_t +profile_get_double(profile_t profile, const char *name, const char *subname, + const char *subsubname, double def_val, double *ret_double) +{ + const char *value; + errcode_t retval; + char *end_value; + double double_val; + + *ret_double = def_val; + if (profile == 0) + return 0; + + retval = profile_get_value(profile, name, subname, subsubname, &value); + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { + *ret_double = def_val; + return 0; + } else if (retval) + return retval; + + if (value[0] == 0) + /* Empty string is no good. */ + return PROF_BAD_INTEGER; + errno = 0; + double_val = strtod(value, &end_value); + + /* Overflow or underflow. */ + if (errno != 0) + return PROF_BAD_INTEGER; + /* Garbage in string. */ + if (end_value != value + strlen(value)) + return PROF_BAD_INTEGER; + + *ret_double = double_val; + return 0; +} + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +static errcode_t +profile_parse_boolean(const char *s, int *ret_boolean) +{ + const char *const *p; + + if (ret_boolean == NULL) + return PROF_EINVAL; + + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) { + *ret_boolean = 1; + return 0; + } + } + + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) { + *ret_boolean = 0; + return 0; + } + } + + return PROF_BAD_BOOLEAN; +} + +errcode_t +profile_get_boolean(profile_t profile, const char *name, const char *subname, + const char *subsubname, int def_val, int *ret_boolean) +{ + const char *value; + errcode_t retval; + + if (profile == 0) { + *ret_boolean = def_val; + return 0; + } + + retval = profile_get_value(profile, name, subname, subsubname, &value); + if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { + *ret_boolean = def_val; + return 0; + } else if (retval) + return retval; + + return profile_parse_boolean (value, ret_boolean); +} + +errcode_t +profile_iterator(void **iter_p, char **ret_name, char **ret_value) +{ + char *name, *value; + errcode_t retval; + + retval = profile_node_iterator(iter_p, 0, &name, &value); + if (retval) + return retval; + + if (ret_name) { + if (name) { + *ret_name = malloc(strlen(name)+1); + if (!*ret_name) + return ENOMEM; + strcpy(*ret_name, name); + } else + *ret_name = 0; + } + if (ret_value) { + if (value) { + *ret_value = malloc(strlen(value)+1); + if (!*ret_value) { + if (ret_name) { + free(*ret_name); + *ret_name = 0; + } + return ENOMEM; + } + strcpy(*ret_value, value); + } else + *ret_value = 0; + } + return 0; +} + +#ifdef DEBUG_PROGRAM + +/* + * test_profile.c --- testing program for the profile routine + */ + +#include "argv_parse.h" +#include "profile_helpers.h" + +const char *program_name = "test_profile"; + +#define PRINT_VALUE 1 +#define PRINT_VALUES 2 + +static void do_cmd(profile_t profile, char **argv) +{ + errcode_t retval; + const char **names, *value; + char **values, **cpp; + char *cmd; + int print_status; + + cmd = *(argv); + names = (const char **) argv + 1; + print_status = 0; + retval = 0; + if (cmd == 0) + return; + if (!strcmp(cmd, "query")) { + retval = profile_get_values(profile, names, &values); + print_status = PRINT_VALUES; + } else if (!strcmp(cmd, "query1")) { + const char *name = 0; + const char *subname = 0; + const char *subsubname = 0; + + name = names[0]; + if (name) + subname = names[1]; + if (subname) + subsubname = names[2]; + if (subsubname && names[3]) { + fprintf(stderr, + "Only 3 levels are allowed with query1\n"); + retval = EINVAL; + } else + retval = profile_get_value(profile, name, subname, + subsubname, &value); + print_status = PRINT_VALUE; + } else if (!strcmp(cmd, "list_sections")) { + retval = profile_get_subsection_names(profile, names, + &values); + print_status = PRINT_VALUES; + } else if (!strcmp(cmd, "list_relations")) { + retval = profile_get_relation_names(profile, names, + &values); + print_status = PRINT_VALUES; + } else if (!strcmp(cmd, "dump")) { + retval = profile_write_tree_file + (profile->first_file->root, stdout); +#if 0 + } else if (!strcmp(cmd, "clear")) { + retval = profile_clear_relation(profile, names); + } else if (!strcmp(cmd, "update")) { + retval = profile_update_relation(profile, names+2, + *names, *(names+1)); +#endif + } else if (!strcmp(cmd, "verify")) { + retval = profile_verify_node + (profile->first_file->root); +#if 0 + } else if (!strcmp(cmd, "rename_section")) { + retval = profile_rename_section(profile, names+1, *names); + } else if (!strcmp(cmd, "add")) { + value = *names; + if (strcmp(value, "NULL") == 0) + value = NULL; + retval = profile_add_relation(profile, names+1, value); + } else if (!strcmp(cmd, "flush")) { + retval = profile_flush(profile); +#endif + } else { + printf("Invalid command.\n"); + } + if (retval) { + com_err(cmd, retval, ""); + print_status = 0; + } + switch (print_status) { + case PRINT_VALUE: + printf("%s\n", value); + break; + case PRINT_VALUES: + for (cpp = values; *cpp; cpp++) + printf("%s\n", *cpp); + profile_free_list(values); + break; + } +} + +static void do_batchmode(profile_t profile) +{ + int argc, ret; + char **argv; + char buf[256]; + + while (!feof(stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) + break; + printf(">%s", buf); + ret = argv_parse(buf, &argc, &argv); + if (ret != 0) { + printf("Argv_parse returned %d!\n", ret); + continue; + } + do_cmd(profile, argv); + printf("\n"); + argv_free(argv); + } + profile_release(profile); + exit(0); + +} + +void syntax_err_report(const char *filename, long err, int line_num) +{ + fprintf(stderr, "Syntax error in %s, line number %d: %s\n", + filename, line_num, error_message(err)); + exit(1); +} + +const char *default_str = "[foo]\n\tbar=quux\n\tsub = {\n\t\twin = true\n}\n"; + +int main(int argc, char **argv) +{ + profile_t profile; + long retval; + char *cmd; + + if (argc < 2) { + fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name); + exit(1); + } + + initialize_prof_error_table(); + + profile_set_syntax_err_cb(syntax_err_report); + + retval = profile_init_path(argv[1], &profile); + if (retval) { + com_err(program_name, retval, "while initializing profile"); + exit(1); + } + retval = profile_set_default(profile, default_str); + if (retval) { + com_err(program_name, retval, "while setting default"); + exit(1); + } + + cmd = *(argv+2); + if (!cmd || !strcmp(cmd, "batch")) + do_batchmode(profile); + else + do_cmd(profile, argv+2); + profile_release(profile); + + return 0; +} + +#endif diff --git a/jni/e2fsprogs/lib/support/profile.o b/jni/e2fsprogs/lib/support/profile.o new file mode 100755 index 0000000000000000000000000000000000000000..88ac9a6043c9eebcbaedf493a328d91b729b6dd7 GIT binary patch literal 22336 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 +#include +#include + +#include +#include "profile.h" +#include "profile_helpers.h" +#include "prof_err.h" + +/* + * These functions --- init_list(), end_list(), and add_to_list() are + * internal functions used to build up a null-terminated char ** list + * of strings to be returned by functions like profile_get_values. + * + * The profile_string_list structure is used for internal booking + * purposes to build up the list, which is returned in *ret_list by + * the end_list() function. + * + * The publicly exported interface for freeing char** list is + * profile_free_list(). + */ + +struct profile_string_list { + char **list; + int num; + int max; +}; + +/* + * Initialize the string list abstraction. + */ +static errcode_t init_list(struct profile_string_list *list) +{ + list->num = 0; + list->max = 10; + list->list = malloc(list->max * sizeof(char *)); + if (list->list == 0) + return ENOMEM; + list->list[0] = 0; + return 0; +} + +/* + * Free any memory left over in the string abstraction, returning the + * built up list in *ret_list if it is non-null. + */ +static void end_list(struct profile_string_list *list, char ***ret_list) +{ + char **cp; + + if (list == 0) + return; + + if (ret_list) { + *ret_list = list->list; + return; + } else { + for (cp = list->list; *cp; cp++) + free(*cp); + free(list->list); + } + list->num = list->max = 0; + list->list = 0; +} + +/* + * Add a string to the list. + */ +static errcode_t add_to_list(struct profile_string_list *list, char *str) +{ + char **newlist; + int newmax; + + if (list->num+1 >= list->max) { + newmax = list->max + 10; + newlist = realloc(list->list, newmax * sizeof(char *)); + if (newlist == 0) + return ENOMEM; + list->max = newmax; + list->list = newlist; + } + + list->list[list->num++] = str; + list->list[list->num] = 0; + return 0; +} + +/* + * Return TRUE if the string is already a member of the list. + */ +static int is_list_member(struct profile_string_list *list, const char *str) +{ + char **cpp; + + if (!list->list) + return 0; + + for (cpp = list->list; *cpp; cpp++) { + if (!strcmp(*cpp, str)) + return 1; + } + return 0; +} + +/* + * This function frees a null-terminated list as returned by + * profile_get_values. + */ +void profile_free_list(char **list) +{ + char **cp; + + if (list == 0) + return; + + for (cp = list; *cp; cp++) + free(*cp); + free(list); +} + +errcode_t +profile_get_values(profile_t profile, const char *const *names, + char ***ret_values) +{ + errcode_t retval; + void *state; + char *value; + struct profile_string_list values; + + if ((retval = profile_iterator_create(profile, names, + PROFILE_ITER_RELATIONS_ONLY, + &state))) + return retval; + + if ((retval = init_list(&values))) + goto cleanup_iterator; + + do { + if ((retval = profile_iterator(&state, 0, &value))) + goto cleanup; + if (value) + add_to_list(&values, value); + } while (state); + + if (values.num == 0) { + retval = PROF_NO_RELATION; + goto cleanup; + } + + end_list(&values, ret_values); + return 0; + +cleanup: + end_list(&values, 0); +cleanup_iterator: + profile_iterator_free(&state); + return retval; +} + +/* + * This function will return the list of the names of subsections in the + * under the specified section name. + */ +errcode_t +profile_get_subsection_names(profile_t profile, const char **names, + char ***ret_names) +{ + errcode_t retval; + void *state; + char *name; + struct profile_string_list values; + + if ((retval = profile_iterator_create(profile, names, + PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, + &state))) + return retval; + + if ((retval = init_list(&values))) + goto cleanup_iterator; + + do { + if ((retval = profile_iterator(&state, &name, 0))) + goto cleanup; + if (name) + add_to_list(&values, name); + } while (state); + + end_list(&values, ret_names); + return 0; + +cleanup: + end_list(&values, 0); +cleanup_iterator: + profile_iterator_free(&state); + return retval; +} + +/* + * This function will return the list of the names of relations in the + * under the specified section name. + */ +errcode_t +profile_get_relation_names(profile_t profile, const char **names, + char ***ret_names) +{ + errcode_t retval; + void *state; + char *name; + struct profile_string_list values; + + if ((retval = profile_iterator_create(profile, names, + PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY, + &state))) + return retval; + + if ((retval = init_list(&values))) + goto cleanup_iterator; + + do { + if ((retval = profile_iterator(&state, &name, 0))) + goto cleanup; + if (name) { + if (is_list_member(&values, name)) + free(name); + else + add_to_list(&values, name); + } + } while (state); + + end_list(&values, ret_names); + return 0; + +cleanup: + end_list(&values, 0); +cleanup_iterator: + profile_iterator_free(&state); + return retval; +} + + +void +profile_release_string(char *str) +{ + free(str); +} + +errcode_t +profile_init_path(const char * filepath, + profile_t *ret_profile) +{ + int n_entries, i; + unsigned int ent_len; + const char *s, *t; + char **filenames; + errcode_t retval; + + /* count the distinct filename components */ + for(s = filepath, n_entries = 1; *s; s++) { + if (*s == ':') + n_entries++; + } + + /* the array is NULL terminated */ + filenames = (char **) malloc((n_entries+1) * sizeof(char*)); + if (filenames == 0) + return ENOMEM; + + /* measure, copy, and skip each one */ + for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) { + ent_len = t-s; + filenames[i] = (char*) malloc(ent_len + 1); + if (filenames[i] == 0) { + /* if malloc fails, free the ones that worked */ + while(--i >= 0) free(filenames[i]); + free(filenames); + return ENOMEM; + } + strncpy(filenames[i], s, ent_len); + filenames[i][ent_len] = 0; + if (*t == 0) { + i++; + break; + } + } + /* cap the array */ + filenames[i] = 0; + + retval = profile_init((const char * const *) filenames, + ret_profile); + + /* count back down and free the entries */ + while(--i >= 0) free(filenames[i]); + free(filenames); + + return retval; +} diff --git a/jni/e2fsprogs/lib/support/profile_helpers.o b/jni/e2fsprogs/lib/support/profile_helpers.o new file mode 100755 index 0000000000000000000000000000000000000000..49ab8410ba6c0585e92e0e6e64a92d86751a693a GIT binary patch literal 5336 zcmbtYO>7&-6@JULBGRTU|Dkf@SaeVqk=2%vgEqC>qM++I(ZMiUBLNb`HAPb!i!eno z1-<#z1>W6D9}>((utiL?DP$CN=;J~1GBS0AGa@B zwe~SuY7A1#8%(vPiQa~e-MjGPXV0bt6-Vb~GTnYA3GV%64^V&K~w-DAl?tGOL)guJ4Nv z%8y;}x!qAQ@OGu@;C_qo#m+0gn0WH-zk9Ih9z4HcpJ}oz;&tT)?ApwGBzXH`^DFBOaE-!^i<*$8k=?sJ@Q-gf)L^bSu?W?6=O>>F$faQ~I!m^eHaq zq$)XEwB|qYkVm#p=PLnT2bhWta?+Cvn{#2;+AE}Tu{uPpD)JDGrRvcE+EK&&;8x77 z*!i#7^cd?<>x>I=CSjzNF04!ZF@R_oXj-xZE;q}E0* zD&VZbw(3He#y0@>tF;p+o@_LOG~#9 zL$=-I?7%wb<7TK<%FxBK%1@(KbUnO<^>97BE;3)N9zMH2y!kmkqc13*$3i|oAU1!N z&-aSYp7c1~AMQtNDn#E@F+)r^Rs-Pb^`sFK9haN`_Irqq%b7lLdGf!Bi*b&*zE*Lz z_}ub2T$HnXVRF4})Y^%@_l~}1BB0c?YILEA?{j02` zmwV5t(ZgVu?)^QzW`*;559+Yn_qm3>z0^|s9ve}*y}in(Bd}G)J9u8FXMRi4gN~h9 z=KfR_85MJu8$iuLAKO|5CkBpZ$Ht;Bre4v#v#|?t!?~>*J(GJ=34UpNZrHvp4d^^N zIDbml2HT1LUw_~7dk5RbHO@Tdc&abZrFA=cbshB+v(C(n+KHSkmVU}w#KZJFi{HrZyLN9S_QiHN^H>#5o*7SB{+vq#Nu zE8T%yuE~1-#qVQaJYU2+g8h96vRWrW=PGPr8*YX6=KX4Hn-#l+cgYccm*LDEL0?d3 zM)u#q`^TVD`=)bYu3v*4>#*Z0{Lp=y?c(=7+t$GQ=YR2u`xN`cvi|$^5%f^M|5G-f zDV*E?oKq_2W()fd9Znuf9>!)ow);1-o3CxQ#5VfNpGomjiUmE`7`(}V*Ni774c@fyUf{c_Z>m?{&xN<<^HPDn595iH zp>J7u@A|y)fcI8BF>df0!uyBM>)Q9HUi)xP)z}mA!zL>ra$LrR_o}b2yYI`r`#vE& zmNET3(RG(bu{1Bd3lYUDYCr7BNIX##M_9)OV-oV4=x(RqvQ4bCcU)HceHz~lS_FSD zi#;k&!0?__xK^d|0_=N&uZb#^2Vn0Behn`N9x6__|5WMSq%iaHlEU$|78+dqJN2fR zt8<9^3GnrqHAS8hzUHa(2#kxdAOAO4>xX}L1OAUTz&X$T^c2LNij4_|I)Aud!jJvB zBB4;{4cJHc_0!W9{)B``ohM+o1*dPq%5BXDdy>8&9e~-!eV?Msug7HI%d)S`h2KY?_H|>l| zo>-4*r)%J*o$ngBsfVNxHxEasO25#!#B>84Ny8~~DP8+zX=Z=A!aT^`vsSzziQy7o;3sS*>?kcPqe!)zSDwn*}(A)8Vvprx=-XoeBJ-9gmA4)_c^Uc_rJ9eU)OyccJR=AUHAN9XX3hFo(|!7vrJU=OGVW}Nt6nQc46ewAkb)Dp+Cm;Vt+0A6n2b(MRiWzr0K(L#WDLZKh<_hNmSnrn3 zmYj_1NQj(iga8JAn#Pf#nM^)EnflqSTV+z{9AC<_Uro}v7+Yz36t-LyovEV%sm8vF)=fs yr$oLQ643T*;@7d>&;RYx{O$;m - sponsored by SuSE CR + * Aditya Kali - Ported to e2fsprogs + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "quotaio.h" + +static const char * const extensions[MAXQUOTAS] = { + [USRQUOTA] = "user", + [GRPQUOTA] = "group", + [PRJQUOTA] = "project", +}; +static const char * const basenames[] = { + "", /* undefined */ + "quota", /* QFMT_VFS_OLD */ + "aquota", /* QFMT_VFS_V0 */ + "", /* QFMT_OCFS2 */ + "aquota" /* QFMT_VFS_V1 */ +}; + +/* Header in all newer quotafiles */ +struct disk_dqheader { + __le32 dqh_magic; + __le32 dqh_version; +} __attribute__ ((packed)); + +/** + * Convert type of quota to written representation + */ +const char *quota_type2name(enum quota_type qtype) +{ + if (qtype >= MAXQUOTAS) + return "unknown"; + return extensions[qtype]; +} + +ext2_ino_t quota_type2inum(enum quota_type qtype, + struct ext2_super_block *sb) +{ + switch (qtype) { + case USRQUOTA: + return EXT4_USR_QUOTA_INO; + case GRPQUOTA: + return EXT4_GRP_QUOTA_INO; + case PRJQUOTA: + return sb->s_prj_quota_inum; + default: + return 0; + } + return 0; +} + +/** + * Creates a quota file name for given type and format. + */ +const char *quota_get_qf_name(enum quota_type type, int fmt, char *buf) +{ + if (!buf) + return NULL; + snprintf(buf, QUOTA_NAME_LEN, "%s.%s", + basenames[fmt], extensions[type]); + + return buf; +} + +/* + * Set grace time if needed + */ +void update_grace_times(struct dquot *q) +{ + time_t now; + + time(&now); + if (q->dq_dqb.dqb_bsoftlimit && toqb(q->dq_dqb.dqb_curspace) > + q->dq_dqb.dqb_bsoftlimit) { + if (!q->dq_dqb.dqb_btime) + q->dq_dqb.dqb_btime = + now + q->dq_h->qh_info.dqi_bgrace; + } else { + q->dq_dqb.dqb_btime = 0; + } + + if (q->dq_dqb.dqb_isoftlimit && q->dq_dqb.dqb_curinodes > + q->dq_dqb.dqb_isoftlimit) { + if (!q->dq_dqb.dqb_itime) + q->dq_dqb.dqb_itime = + now + q->dq_h->qh_info.dqi_igrace; + } else { + q->dq_dqb.dqb_itime = 0; + } +} + +errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode inode; + errcode_t err; + enum quota_type qtype; + + if ((err = ext2fs_read_inode(fs, ino, &inode))) + return err; + + for (qtype = 0; qtype < MAXQUOTAS; qtype++) + if (ino == quota_type2inum(qtype, fs->super)) + break; + + if (qtype != MAXQUOTAS) { + inode.i_dtime = fs->now ? fs->now : time(0); + if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) + return 0; + err = ext2fs_punch(fs, ino, &inode, NULL, 0, ~0ULL); + if (err) + return err; + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + memset(&inode, 0, sizeof(struct ext2_inode)); + } else { + inode.i_flags &= ~EXT2_IMMUTABLE_FL; + } + err = ext2fs_write_inode(fs, ino, &inode); + return err; +} + +/* Functions to read/write quota file. */ +static unsigned int quota_write_nomount(struct quota_file *qf, + ext2_loff_t offset, + void *buf, unsigned int size) +{ + ext2_file_t e2_file = qf->e2_file; + unsigned int bytes_written = 0; + errcode_t err; + + err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL); + if (err) { + log_err("ext2fs_file_llseek failed: %ld", err); + return 0; + } + + err = ext2fs_file_write(e2_file, buf, size, &bytes_written); + if (err) { + log_err("ext2fs_file_write failed: %ld", err); + return 0; + } + + /* Correct inode.i_size is set in end_io. */ + return bytes_written; +} + +static unsigned int quota_read_nomount(struct quota_file *qf, + ext2_loff_t offset, + void *buf, unsigned int size) +{ + ext2_file_t e2_file = qf->e2_file; + unsigned int bytes_read = 0; + errcode_t err; + + err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL); + if (err) { + log_err("ext2fs_file_llseek failed: %ld", err); + return 0; + } + + err = ext2fs_file_read(e2_file, buf, size, &bytes_read); + if (err) { + log_err("ext2fs_file_read failed: %ld", err); + return 0; + } + + return bytes_read; +} + +/* + * Detect quota format and initialize quota IO + */ +errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h, + ext2_ino_t qf_ino, enum quota_type qtype, + int fmt, int flags) +{ + ext2_filsys fs = qctx->fs; + ext2_file_t e2_file; + errcode_t err; + int allocated_handle = 0; + + if (qtype >= MAXQUOTAS) + return EINVAL; + + if (fmt == -1) + fmt = QFMT_VFS_V1; + + err = ext2fs_read_bitmaps(fs); + if (err) + return err; + + if (qf_ino == 0) + qf_ino = *quota_sb_inump(fs->super, qtype); + + log_debug("Opening quota ino=%u, type=%d", qf_ino, qtype); + err = ext2fs_file_open(fs, qf_ino, flags, &e2_file); + if (err) { + log_err("ext2fs_file_open failed: %s", error_message(err)); + return err; + } + + if (!h) { + if (qctx->quota_file[qtype]) { + h = qctx->quota_file[qtype]; + if (((flags & EXT2_FILE_WRITE) == 0) || + (h->qh_file_flags & EXT2_FILE_WRITE)) { + ext2fs_file_close(e2_file); + return 0; + } + (void) quota_file_close(qctx, h); + } + err = ext2fs_get_mem(sizeof(struct quota_handle), &h); + if (err) { + log_err("Unable to allocate quota handle"); + ext2fs_file_close(e2_file); + return err; + } + allocated_handle = 1; + } + + h->qh_qf.e2_file = e2_file; + h->qh_qf.fs = fs; + h->qh_qf.ino = qf_ino; + h->e2fs_write = quota_write_nomount; + h->e2fs_read = quota_read_nomount; + h->qh_file_flags = flags; + h->qh_io_flags = 0; + h->qh_type = qtype; + h->qh_fmt = fmt; + memset(&h->qh_info, 0, sizeof(h->qh_info)); + h->qh_ops = "afile_ops_2; + + if (h->qh_ops->check_file && + (h->qh_ops->check_file(h, qtype, fmt) == 0)) { + log_err("qh_ops->check_file failed"); + err = EIO; + goto errout; + } + + if (h->qh_ops->init_io && (h->qh_ops->init_io(h) < 0)) { + log_err("qh_ops->init_io failed"); + err = EIO; + goto errout; + } + if (allocated_handle) + qctx->quota_file[qtype] = h; + + return 0; +errout: + ext2fs_file_close(e2_file); + if (allocated_handle) + ext2fs_free_mem(&h); + return err; +} + +static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode inode; + errcode_t err = 0; + + err = ext2fs_read_inode(fs, ino, &inode); + if (err) { + log_err("ex2fs_read_inode failed"); + return err; + } + + if (EXT2_I_SIZE(&inode)) { + err = quota_inode_truncate(fs, ino); + if (err) + return err; + } + + memset(&inode, 0, sizeof(struct ext2_inode)); + ext2fs_iblk_set(fs, &inode, 0); + inode.i_atime = inode.i_mtime = + inode.i_ctime = fs->now ? fs->now : time(0); + inode.i_links_count = 1; + inode.i_mode = LINUX_S_IFREG | 0600; + inode.i_flags |= EXT2_IMMUTABLE_FL; + if (ext2fs_has_feature_extents(fs->super)) + inode.i_flags |= EXT4_EXTENTS_FL; + + err = ext2fs_write_new_inode(fs, ino, &inode); + if (err) { + log_err("ext2fs_write_new_inode failed: %ld", err); + return err; + } + return err; +} + +/* + * Create new quotafile of specified format on given filesystem + */ +errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, + enum quota_type qtype, int fmt) +{ + ext2_file_t e2_file; + errcode_t err; + ext2_ino_t qf_inum = 0; + + if (fmt == -1) + fmt = QFMT_VFS_V1; + + h->qh_qf.fs = fs; + qf_inum = quota_type2inum(qtype, fs->super); + if (qf_inum == 0 && qtype == PRJQUOTA) { + err = ext2fs_new_inode(fs, EXT2_ROOT_INO, LINUX_S_IFREG | 0600, + 0, &qf_inum); + if (err) + return err; + ext2fs_inode_alloc_stats2(fs, qf_inum, +1, 0); + ext2fs_mark_ib_dirty(fs); + } else if (qf_inum == 0) { + return EXT2_ET_BAD_INODE_NUM; + } + + err = ext2fs_read_bitmaps(fs); + if (err) + goto out_err; + + err = quota_inode_init_new(fs, qf_inum); + if (err) { + log_err("init_new_quota_inode failed"); + goto out_err; + } + h->qh_qf.ino = qf_inum; + h->qh_file_flags = EXT2_FILE_WRITE | EXT2_FILE_CREATE; + h->e2fs_write = quota_write_nomount; + h->e2fs_read = quota_read_nomount; + + log_debug("Creating quota ino=%u, type=%d", qf_inum, qtype); + err = ext2fs_file_open(fs, qf_inum, h->qh_file_flags, &e2_file); + if (err) { + log_err("ext2fs_file_open failed: %ld", err); + goto out_err; + } + h->qh_qf.e2_file = e2_file; + + h->qh_io_flags = 0; + h->qh_type = qtype; + h->qh_fmt = fmt; + memset(&h->qh_info, 0, sizeof(h->qh_info)); + h->qh_ops = "afile_ops_2; + + if (h->qh_ops->new_io && (h->qh_ops->new_io(h) < 0)) { + log_err("qh_ops->new_io failed"); + err = EIO; + goto out_err1; + } + + return 0; + +out_err1: + ext2fs_file_close(e2_file); +out_err: + + if (qf_inum) + quota_inode_truncate(fs, qf_inum); + + return err; +} + +/* + * Close quotafile and release handle + */ +errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h) +{ + if (h->qh_io_flags & IOFL_INFODIRTY) { + if (h->qh_ops->write_info && h->qh_ops->write_info(h) < 0) + return EIO; + h->qh_io_flags &= ~IOFL_INFODIRTY; + } + + if (h->qh_ops->end_io && h->qh_ops->end_io(h) < 0) + return EIO; + if (h->qh_qf.e2_file) + ext2fs_file_close(h->qh_qf.e2_file); + if (qctx->quota_file[h->qh_type] == h) + ext2fs_free_mem(&qctx->quota_file[h->qh_type]); + return 0; +} + +/* + * Create empty quota structure + */ +struct dquot *get_empty_dquot(void) +{ + struct dquot *dquot; + + if (ext2fs_get_memzero(sizeof(struct dquot), &dquot)) { + log_err("Failed to allocate dquot"); + return NULL; + } + + dquot->dq_id = -1; + return dquot; +} diff --git a/jni/e2fsprogs/lib/support/quotaio.o b/jni/e2fsprogs/lib/support/quotaio.o new file mode 100755 index 0000000000000000000000000000000000000000..8c722a792b23e6bdd2fd96b0e7ff92501849e038 GIT binary patch literal 13752 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 XKZo{K7rJ4Y4PW2^LpoAO?e_l*5xhiq literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/quotaio_tree.c b/jni/e2fsprogs/lib/support/quotaio_tree.c new file mode 100755 index 0000000..5910e63 --- /dev/null +++ b/jni/e2fsprogs/lib/support/quotaio_tree.c @@ -0,0 +1,687 @@ +/* + * Implementation of new quotafile format + * + * Jan Kara - sponsored by SuSE CR + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "quotaio_tree.h" +#include "quotaio.h" + +typedef char *dqbuf_t; + +#define freedqbuf(buf) ext2fs_free_mem(&buf) + +static inline dqbuf_t getdqbuf(void) +{ + dqbuf_t buf; + if (ext2fs_get_memzero(QT_BLKSIZE, &buf)) { + log_err("Failed to allocate dqbuf"); + return NULL; + } + + return buf; +} + +/* Is given dquot empty? */ +int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk) +{ + unsigned int i; + + for (i = 0; i < info->dqi_entry_size; i++) + if (disk[i]) + return 0; + return 1; +} + +int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) +{ + return (QT_BLKSIZE - sizeof(struct qt_disk_dqdbheader)) / + info->dqi_entry_size; +} + +static int get_index(qid_t id, int depth) +{ + return (id >> ((QT_TREEDEPTH - depth - 1) * 8)) & 0xff; +} + +static inline void mark_quotafile_info_dirty(struct quota_handle *h) +{ + h->qh_io_flags |= IOFL_INFODIRTY; +} + +/* Read given block */ +static void read_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf) +{ + int err; + + err = h->e2fs_read(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf, + QT_BLKSIZE); + if (err < 0) + log_err("Cannot read block %u: %s", blk, strerror(errno)); + else if (err != QT_BLKSIZE) + memset(buf + err, 0, QT_BLKSIZE - err); +} + +/* Write block */ +static int write_blk(struct quota_handle *h, unsigned int blk, dqbuf_t buf) +{ + int err; + + err = h->e2fs_write(&h->qh_qf, blk << QT_BLKSIZE_BITS, buf, + QT_BLKSIZE); + if (err < 0 && errno != ENOSPC) + log_err("Cannot write block (%u): %s", blk, strerror(errno)); + if (err != QT_BLKSIZE) + return -ENOSPC; + return 0; +} + +/* Get free block in file (either from free list or create new one) */ +static int get_free_dqblk(struct quota_handle *h) +{ + dqbuf_t buf = getdqbuf(); + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + int blk; + + if (!buf) + return -ENOMEM; + + if (info->dqi_free_blk) { + blk = info->dqi_free_blk; + read_blk(h, blk, buf); + info->dqi_free_blk = ext2fs_le32_to_cpu(dh->dqdh_next_free); + } else { + memset(buf, 0, QT_BLKSIZE); + /* Assure block allocation... */ + if (write_blk(h, info->dqi_blocks, buf) < 0) { + freedqbuf(buf); + log_err("Cannot allocate new quota block " + "(out of disk space)."); + return -ENOSPC; + } + blk = info->dqi_blocks++; + } + mark_quotafile_info_dirty(h); + freedqbuf(buf); + return blk; +} + +/* Put given block to free list */ +static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf, + unsigned int blk) +{ + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + + dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_blk); + dh->dqdh_prev_free = ext2fs_cpu_to_le32(0); + dh->dqdh_entries = ext2fs_cpu_to_le16(0); + info->dqi_free_blk = blk; + mark_quotafile_info_dirty(h); + write_blk(h, blk, buf); +} + +/* Remove given block from the list of blocks with free entries */ +static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf, + unsigned int blk) +{ + dqbuf_t tmpbuf = getdqbuf(); + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + unsigned int nextblk = ext2fs_le32_to_cpu(dh->dqdh_next_free), prevblk = + + ext2fs_le32_to_cpu(dh->dqdh_prev_free); + + if (!tmpbuf) + return; + + if (nextblk) { + read_blk(h, nextblk, tmpbuf); + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = + dh->dqdh_prev_free; + write_blk(h, nextblk, tmpbuf); + } + if (prevblk) { + read_blk(h, prevblk, tmpbuf); + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free = + dh->dqdh_next_free; + write_blk(h, prevblk, tmpbuf); + } else { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry = nextblk; + mark_quotafile_info_dirty(h); + } + freedqbuf(tmpbuf); + dh->dqdh_next_free = dh->dqdh_prev_free = ext2fs_cpu_to_le32(0); + write_blk(h, blk, buf); /* No matter whether write succeeds + * block is out of list */ +} + +/* Insert given block to the beginning of list with free entries */ +static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf, + unsigned int blk) +{ + dqbuf_t tmpbuf = getdqbuf(); + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + + if (!tmpbuf) + return; + + dh->dqdh_next_free = ext2fs_cpu_to_le32(info->dqi_free_entry); + dh->dqdh_prev_free = ext2fs_cpu_to_le32(0); + write_blk(h, blk, buf); + if (info->dqi_free_entry) { + read_blk(h, info->dqi_free_entry, tmpbuf); + ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = + ext2fs_cpu_to_le32(blk); + write_blk(h, info->dqi_free_entry, tmpbuf); + } + freedqbuf(tmpbuf); + info->dqi_free_entry = blk; + mark_quotafile_info_dirty(h); +} + +/* Find space for dquot */ +static unsigned int find_free_dqentry(struct quota_handle *h, + struct dquot *dquot, int *err) +{ + int blk, i; + struct qt_disk_dqdbheader *dh; + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + char *ddquot; + dqbuf_t buf; + + *err = 0; + buf = getdqbuf(); + if (!buf) { + *err = -ENOMEM; + return 0; + } + + dh = (struct qt_disk_dqdbheader *)buf; + if (info->dqi_free_entry) { + blk = info->dqi_free_entry; + read_blk(h, blk, buf); + } else { + blk = get_free_dqblk(h); + if (blk < 0) { + freedqbuf(buf); + *err = blk; + return 0; + } + memset(buf, 0, QT_BLKSIZE); + info->dqi_free_entry = blk; + mark_quotafile_info_dirty(h); + } + + /* Block will be full? */ + if (ext2fs_le16_to_cpu(dh->dqdh_entries) + 1 >= + qtree_dqstr_in_blk(info)) + remove_free_dqentry(h, buf, blk); + + dh->dqdh_entries = + ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) + 1); + /* Find free structure in block */ + ddquot = buf + sizeof(struct qt_disk_dqdbheader); + for (i = 0; + i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot); + i++) + ddquot += info->dqi_entry_size; + + if (i == qtree_dqstr_in_blk(info)) + log_err("find_free_dqentry(): Data block full unexpectedly."); + + write_blk(h, blk, buf); + dquot->dq_dqb.u.v2_mdqb.dqb_off = + (blk << QT_BLKSIZE_BITS) + sizeof(struct qt_disk_dqdbheader) + + i * info->dqi_entry_size; + freedqbuf(buf); + return blk; +} + +/* Insert reference to structure into the trie */ +static int do_insert_tree(struct quota_handle *h, struct dquot *dquot, + unsigned int * treeblk, int depth) +{ + dqbuf_t buf; + int newson = 0, newact = 0; + __le32 *ref; + unsigned int newblk; + int ret = 0; + + log_debug("inserting in tree: treeblk=%u, depth=%d", *treeblk, depth); + buf = getdqbuf(); + if (!buf) + return -ENOMEM; + + if (!*treeblk) { + ret = get_free_dqblk(h); + if (ret < 0) + goto out_buf; + *treeblk = ret; + memset(buf, 0, QT_BLKSIZE); + newact = 1; + } else { + read_blk(h, *treeblk, buf); + } + + ref = (__le32 *) buf; + newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]); + if (!newblk) + newson = 1; + if (depth == QT_TREEDEPTH - 1) { + if (newblk) + log_err("Inserting already present quota entry " + "(block %u).", + ref[get_index(dquot->dq_id, depth)]); + newblk = find_free_dqentry(h, dquot, &ret); + } else { + ret = do_insert_tree(h, dquot, &newblk, depth + 1); + } + + if (newson && ret >= 0) { + ref[get_index(dquot->dq_id, depth)] = + ext2fs_cpu_to_le32(newblk); + write_blk(h, *treeblk, buf); + } else if (newact && ret < 0) { + put_free_dqblk(h, buf, *treeblk); + } + +out_buf: + freedqbuf(buf); + return ret; +} + +/* Wrapper for inserting quota structure into tree */ +static void dq_insert_tree(struct quota_handle *h, struct dquot *dquot) +{ + unsigned int tmp = QT_TREEOFF; + + if (do_insert_tree(h, dquot, &tmp, 0) < 0) + log_err("Cannot write quota (id %u): %s", + (unsigned int) dquot->dq_id, strerror(errno)); +} + +/* Write dquot to file */ +void qtree_write_dquot(struct dquot *dquot) +{ + errcode_t retval; + unsigned int ret; + char *ddquot; + struct quota_handle *h = dquot->dq_h; + struct qtree_mem_dqinfo *info = + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree; + log_debug("writing ddquot 1: off=%llu, info->dqi_entry_size=%u", + dquot->dq_dqb.u.v2_mdqb.dqb_off, + info->dqi_entry_size); + retval = ext2fs_get_mem(info->dqi_entry_size, &ddquot); + if (retval) { + errno = ENOMEM; + log_err("Quota write failed (id %u): %s", + (unsigned int)dquot->dq_id, strerror(errno)); + return; + } + memset(ddquot, 0, info->dqi_entry_size); + + if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) + dq_insert_tree(dquot->dq_h, dquot); + info->dqi_ops->mem2disk_dqblk(ddquot, dquot); + log_debug("writing ddquot 2: off=%llu, info->dqi_entry_size=%u", + dquot->dq_dqb.u.v2_mdqb.dqb_off, + info->dqi_entry_size); + ret = h->e2fs_write(&h->qh_qf, dquot->dq_dqb.u.v2_mdqb.dqb_off, ddquot, + info->dqi_entry_size); + + if (ret != info->dqi_entry_size) { + if (ret > 0) + errno = ENOSPC; + log_err("Quota write failed (id %u): %s", + (unsigned int)dquot->dq_id, strerror(errno)); + } + ext2fs_free_mem(&ddquot); +} + +/* Free dquot entry in data block */ +static void free_dqentry(struct quota_handle *h, struct dquot *dquot, + unsigned int blk) +{ + struct qt_disk_dqdbheader *dh; + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + dqbuf_t buf = getdqbuf(); + + if (!buf) + return; + + if (dquot->dq_dqb.u.v2_mdqb.dqb_off >> QT_BLKSIZE_BITS != blk) + log_err("Quota structure has offset to other block (%u) " + "than it should (%u).", blk, + (unsigned int) (dquot->dq_dqb.u.v2_mdqb.dqb_off >> + QT_BLKSIZE_BITS)); + + read_blk(h, blk, buf); + dh = (struct qt_disk_dqdbheader *)buf; + dh->dqdh_entries = + ext2fs_cpu_to_le16(ext2fs_le16_to_cpu(dh->dqdh_entries) - 1); + + if (!ext2fs_le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */ + remove_free_dqentry(h, buf, blk); + put_free_dqblk(h, buf, blk); + } else { + memset(buf + (dquot->dq_dqb.u.v2_mdqb.dqb_off & + ((1 << QT_BLKSIZE_BITS) - 1)), + 0, info->dqi_entry_size); + + /* First free entry? */ + if (ext2fs_le16_to_cpu(dh->dqdh_entries) == + qtree_dqstr_in_blk(info) - 1) + /* This will also write data block */ + insert_free_dqentry(h, buf, blk); + else + write_blk(h, blk, buf); + } + dquot->dq_dqb.u.v2_mdqb.dqb_off = 0; + freedqbuf(buf); +} + +/* Remove reference to dquot from tree */ +static void remove_tree(struct quota_handle *h, struct dquot *dquot, + unsigned int * blk, int depth) +{ + dqbuf_t buf = getdqbuf(); + unsigned int newblk; + __le32 *ref = (__le32 *) buf; + + if (!buf) + return; + + read_blk(h, *blk, buf); + newblk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]); + if (depth == QT_TREEDEPTH - 1) { + free_dqentry(h, dquot, newblk); + newblk = 0; + } else { + remove_tree(h, dquot, &newblk, depth + 1); + } + + if (!newblk) { + int i; + + ref[get_index(dquot->dq_id, depth)] = ext2fs_cpu_to_le32(0); + + /* Block got empty? */ + for (i = 0; i < QT_BLKSIZE && !buf[i]; i++); + + /* Don't put the root block into the free block list */ + if (i == QT_BLKSIZE && *blk != QT_TREEOFF) { + put_free_dqblk(h, buf, *blk); + *blk = 0; + } else { + write_blk(h, *blk, buf); + } + } + freedqbuf(buf); +} + +/* Delete dquot from tree */ +void qtree_delete_dquot(struct dquot *dquot) +{ + unsigned int tmp = QT_TREEOFF; + + if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) /* Even not allocated? */ + return; + remove_tree(dquot->dq_h, dquot, &tmp, 0); +} + +/* Find entry in block */ +static ext2_loff_t find_block_dqentry(struct quota_handle *h, + struct dquot *dquot, unsigned int blk) +{ + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + dqbuf_t buf = getdqbuf(); + int i; + char *ddquot = buf + sizeof(struct qt_disk_dqdbheader); + + if (!buf) + return -ENOMEM; + + read_blk(h, blk, buf); + for (i = 0; + i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot); + i++) + ddquot += info->dqi_entry_size; + + if (i == qtree_dqstr_in_blk(info)) + log_err("Quota for id %u referenced but not present.", + dquot->dq_id); + freedqbuf(buf); + return (blk << QT_BLKSIZE_BITS) + sizeof(struct qt_disk_dqdbheader) + + i * info->dqi_entry_size; +} + +/* Find entry for given id in the tree */ +static ext2_loff_t find_tree_dqentry(struct quota_handle *h, + struct dquot *dquot, + unsigned int blk, int depth) +{ + dqbuf_t buf = getdqbuf(); + ext2_loff_t ret = 0; + __le32 *ref = (__le32 *) buf; + + if (!buf) + return -ENOMEM; + + read_blk(h, blk, buf); + ret = 0; + blk = ext2fs_le32_to_cpu(ref[get_index(dquot->dq_id, depth)]); + if (!blk) /* No reference? */ + goto out_buf; + if (depth < QT_TREEDEPTH - 1) + ret = find_tree_dqentry(h, dquot, blk, depth + 1); + else + ret = find_block_dqentry(h, dquot, blk); +out_buf: + freedqbuf(buf); + return ret; +} + +/* Find entry for given id in the tree - wrapper function */ +static inline ext2_loff_t find_dqentry(struct quota_handle *h, + struct dquot *dquot) +{ + return find_tree_dqentry(h, dquot, QT_TREEOFF, 0); +} + +/* + * Read dquot from disk. + */ +struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id) +{ + struct qtree_mem_dqinfo *info = &h->qh_info.u.v2_mdqi.dqi_qtree; + ext2_loff_t offset; + unsigned int ret; + char *ddquot; + struct dquot *dquot = get_empty_dquot(); + + if (!dquot) + return NULL; + if (ext2fs_get_mem(info->dqi_entry_size, &ddquot)) { + ext2fs_free_mem(&dquot); + return NULL; + } + + dquot->dq_id = id; + dquot->dq_h = h; + dquot->dq_dqb.u.v2_mdqb.dqb_off = 0; + memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk)); + + offset = find_dqentry(h, dquot); + if (offset > 0) { + dquot->dq_dqb.u.v2_mdqb.dqb_off = offset; + ret = h->e2fs_read(&h->qh_qf, offset, ddquot, + info->dqi_entry_size); + if (ret != info->dqi_entry_size) { + if (ret > 0) + errno = EIO; + log_err("Cannot read quota structure for id %u: %s", + dquot->dq_id, strerror(errno)); + } + info->dqi_ops->disk2mem_dqblk(dquot, ddquot); + } + ext2fs_free_mem(&ddquot); + return dquot; +} + +static int check_reference(struct quota_handle *h, unsigned int blk) +{ + if (blk >= h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks) { + log_err("Illegal reference (%u >= %u) in %s quota file", + blk, h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks, + quota_type2name(h->qh_type)); + return -1; + } + return 0; +} + +/* + * Scan all dquots in file and call callback on each + */ +#define set_bit(bmp, ind) ((bmp)[(ind) >> 3] |= (1 << ((ind) & 7))) +#define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7))) + +static int report_block(struct dquot *dquot, unsigned int blk, char *bitmap, + int (*process_dquot) (struct dquot *, void *), + void *data) +{ + struct qtree_mem_dqinfo *info = + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree; + dqbuf_t buf = getdqbuf(); + struct qt_disk_dqdbheader *dh; + char *ddata; + int entries, i; + + if (!buf) + return -1; + + set_bit(bitmap, blk); + read_blk(dquot->dq_h, blk, buf); + dh = (struct qt_disk_dqdbheader *)buf; + ddata = buf + sizeof(struct qt_disk_dqdbheader); + entries = ext2fs_le16_to_cpu(dh->dqdh_entries); + for (i = 0; i < qtree_dqstr_in_blk(info); + i++, ddata += info->dqi_entry_size) + if (!qtree_entry_unused(info, ddata)) { + dquot->dq_dqb.u.v2_mdqb.dqb_off = + (blk << QT_BLKSIZE_BITS) + + sizeof(struct qt_disk_dqdbheader) + + i * info->dqi_entry_size; + info->dqi_ops->disk2mem_dqblk(dquot, ddata); + if (process_dquot(dquot, data) < 0) + break; + } + freedqbuf(buf); + return entries; +} + +static int report_tree(struct dquot *dquot, unsigned int blk, int depth, + char *bitmap, + int (*process_dquot) (struct dquot *, void *), + void *data) +{ + int entries = 0, ret, i; + dqbuf_t buf = getdqbuf(); + __le32 *ref = (__le32 *) buf; + + if (!buf) + return -1; + + read_blk(dquot->dq_h, blk, buf); + if (depth == QT_TREEDEPTH - 1) { + for (i = 0; i < QT_BLKSIZE >> 2; i++) { + blk = ext2fs_le32_to_cpu(ref[i]); + if (check_reference(dquot->dq_h, blk)) { + entries = -1; + goto errout; + } + if (blk && !get_bit(bitmap, blk)) { + ret = report_block(dquot, blk, bitmap, + process_dquot, data); + if (ret < 0) { + entries = ret; + goto errout; + } + entries += ret; + } + } + } else { + for (i = 0; i < QT_BLKSIZE >> 2; i++) { + blk = ext2fs_le32_to_cpu(ref[i]); + if (blk) { + if (check_reference(dquot->dq_h, blk)) { + entries = -1; + goto errout; + } + ret = report_tree(dquot, blk, depth + 1, + bitmap, process_dquot, + data); + if (ret < 0) { + entries = ret; + goto errout; + } + entries += ret; + } + } + } +errout: + freedqbuf(buf); + return entries; +} + +static unsigned int find_set_bits(char *bmp, int blocks) +{ + unsigned int used = 0; + int i; + + for (i = 0; i < blocks; i++) + if (get_bit(bmp, i)) + used++; + return used; +} + +int qtree_scan_dquots(struct quota_handle *h, + int (*process_dquot) (struct dquot *, void *), + void *data) +{ + int ret; + char *bitmap; + struct v2_mem_dqinfo *v2info = &h->qh_info.u.v2_mdqi; + struct qtree_mem_dqinfo *info = &v2info->dqi_qtree; + struct dquot *dquot = get_empty_dquot(); + + if (!dquot) + return -1; + + dquot->dq_h = h; + if (ext2fs_get_memzero((info->dqi_blocks + 7) >> 3, &bitmap)) { + ext2fs_free_mem(&dquot); + return -1; + } + ret = report_tree(dquot, QT_TREEOFF, 0, bitmap, process_dquot, data); + if (ret < 0) + goto errout; + v2info->dqi_used_entries = ret; + v2info->dqi_data_blocks = find_set_bits(bitmap, info->dqi_blocks); + ret = 0; +errout: + ext2fs_free_mem(&bitmap); + ext2fs_free_mem(&dquot); + return ret; +} diff --git a/jni/e2fsprogs/lib/support/quotaio_tree.o b/jni/e2fsprogs/lib/support/quotaio_tree.o new file mode 100755 index 0000000000000000000000000000000000000000..7565e673629d9c7a055116d7cfdfe291388a8b5c GIT binary patch literal 16664 zcmbtb4RBo5b-ueR43Xje#)td&+P zu(3&%5i?N;Y3;;m+?J%WOlG8%&M*@?(ayB7J4#weGfhYs#+f0lWK6muPKLD1RGQjV zzwh32R(G$YkeNPa_1^p5dFP(5HWiMpPs}sU|)KH>GS`)$>(?_gtCFT~cL~q=Y`ivAM0+RB#nNxiG@@O!iMFQWXlF7O z-xB|9-%sMzul?mXuJPQ-^+#U6a&*zimBz@4!T#E*;r{egygD^qT4kp7I(~QLL}>+d zt#G>d{%QCHH%|`6@J=i})fzLe&<0`yk-pt=V~Y44hac1Ym98!8D?)dXa>k_W`JGj% z;xA(6TjSTJrlI5b24hY{alQxV#=5@URk(f@*L-Iu+8B%-m{MCVz?O+v?G`?>_TGxN zjQKm-!g~W>PUHLuJSS$~14f&uhtEvpQ*V}50sBa5dJ^Zv-R8sy@D0#41erh@DWGpNAKn_?w5IekA!AJki zm3&a|pu~dLSB~C0GSeS%v5hgdv5_ld#>VzEVm0)rd7U{k3_k|p>TU41DvEf- zrhb2poyc9r7dcTx3@h!tR_sJBhjzYw<6Jwh9Bmw#iHU8n`O47<^3I%Kp4vPH4>n)H zd#l6{oUy-5GmaBDUsz#I(B4H7&nrjohQE@_WAyi`kt^_@xorLIUq5xGasB91@Nckx z9rAnsl*{e?Q`$z_a+t=m15=SmsyGChHz3cPuz3sr(SGrC7;mbfZMaVY-jBNvP zD;Z;BZSSdvH3fQqiJDU4J#T^ljQ#q;plf#+lzb+uO_BQL+Ul*n)#*1)s6o|zKhfGU2)PNob3biB zZM5|wVt(_`VyWH86{`pDTbnJ&ry*5lc_sP8W# zpTCLtY=G?-VEbCcesBzZehmH9xLUc?=F|SsN!XZNXNu!^j~ua%3__l^n+>LT7VlXe zwS8%qx@f=Ub1Xet$>-euFx0<(^bGj9h#Y(eV>0Ik=#wXPtS^D{`S>{^{IHImM*d%b zkAH>t&}VJ^YLYyj!Prb&kl&~QRo%~BCHajQPOj=J#*ehYUe_;GR}*3iUvKAon+u0c^&K5h96vyIZw?%)YU-tHQLCr_igl@i{P|? zHpbVW&#XxmhlP7yvn`D6D<|zWZLVIT^P#dItZne?Ur^haC!vp@S+szUuwmAInM(lM zJdeM~4a`fN-Q+ZiHqXHRi?IJ4*#9Ne`i1Pj`ggP+XI}B}|8V!#kjl}^AL>7ULQY$K5=$z?dZ(MVcX57_^0e&F^thMj4RT=TO+Pt_QPjepU|&b zy*&9k>oMLf-3(mvq6f0PXKhVlJQ{?)Xy0rtPa@|^Xw!~Uh#B?TaUXJTLLYsi4W%{c zOKZ@d(a$)x+3^_twFdph&Lc4gC^ew%2Ii#8UFsf&PgVzHIXAdl=7*F^N`Hv^HJmk$ z?V!f_?YzhOfm$*dGg~+}Ui7mz>aCa$p4m9Jj@vwhy%)}y6PL&jY~=buan>BpK`wmT zocIgoCHQmp?i+nI>iVnYGdlG#;;zZWP{+p+ zpUAB4c*NCDYZK#*7;ql(4al=i{SA(}xdQE}%=7y(myF69W_B)VY@Cg&@ew!vE7t~d ze(0^>uNm`me|>>9+BEK0mgp0%X$QxHiZRQdS0kUt$)Pt+mB%iQRft=d%Xd&ebYh$> zzN(zaJ=#RRVy>|`Rpgvuo8&+o+}N>gktyCloAAufX}&|9%wxW{3_PZyj$<9We;W^H zuCC;vHRk#qWA`rf?u6cIQ7I7t1&(L;A0SU7Fy5za9N)`p zOW3r~TIx)^(&y_K7h4yXbq~rsm+|AcXRs!>H50Z}qi&XB)mx&^q`so_L(SKUHBO_g zzr~3qup9m3-6g5w7f>JSA~o%Gm`m4nuX{AU`L*lKIIkGK@u>C+^gollx)RVcQSK_9G^#>90cXYKiZ?xYjvO zQu?gMn{`BMEZfTAoiHyc!!(#JtG(G`VuuW35@H0_=vp+ zozteLM$o6`)CuUd^&Rm-o@`5AjX6=H>}!Oz6Lnz-w%zl;7d%!D)j;5iQRuJNe!S~cC3L9UxPk<&-y0z>+_?qo7|OR(CfdC`wMvg^ZGt)P;RV# zdESoqIp;zfMb`V|A31)`iC$f&(+0~Y&*0bR?$aV$$)A_2{TN$>A3L^i?-Jw8e_wH2 zF-FS89@s+es&8cxKOYed#Sj0@z4&~_huwmi!HW4KR{N8Ga?*1@j2&8aVQjIwnQ zIppt)YJ2Qgtk3LQkSkVKnQpEDCbZUiZ7ze%RcOQa;eX%*oBwr}D*JiDg(GWSq!hL3jK zZNz#U&%cBB>^sPN)_9#~Pi#yTe}!k(PrL7k^*7!@9@{;`mE;OCajZ2S)crYda~idN z2y%SJ`TkGg2kV8dd-OThpLSnOW2@sk<59WS51Q{B zo5=_AJmldap9eheB@Y-oXb)>S-Ybuzs4KH$IP&>9ou_eZu694}UC}qr8RI&hL)Pj; z-Ve_=p5q;kkF-(SjdN}SJN_NxxwQjzwLG4qhQ%?SN9L&)jN2mQ9`sbKHDY(ptr6q> zZmnYXk?k0c?=;|Q5`ND&epkk0fxUj_BgZb(4qG1{p{>>JXJT%x4^C$H58*H6$gzzb zWLYP8joN3&;dj9KFTmS>@EZ+y3jONeQRx@=fH<$1JKlQhfpDG+d%5p-rhnbkMXbB6 zEsUq+(&sPF=91=*wxfHx)!0ws`nzVsYu9s*tou!z`(V!g#U#F|#UnLak`Z%<^$+^( zUKn!jJoGa+;k&EPny=`WtjpvCebeO-_}~~D=E8Hbk7VbQ;E8p%FXs9vIgb1Bg^u~+ z%Xo2qX6Kspe-Xb^xv_xx%)Nbkk9jZe56Yeg_mG&k{Gs0#ZSKO}iaD#7<3HjajpQE3 zf`#URe|+!m-G8`ye`0gbotrav;&0-S-dv$6@l?L8kWI8SwRL1OiDX+QvAMVIPDs_5 zhMqz$-}FSbA$zE|qp6V1G;D2n=*XU2uA`@+>rkO#Tm2pNTN^&p+18NV*3#3J&ppx8 z(9!mILr-s4S1w;@=%)U*T)L3YX6u_xH_vI?Tsp&NX0Az%O`V;&LL#4S$|UUTiJn5f zx4F=phl#m-!kXu-bLuGhLE4;$PF;nAneKF3XHPa?uqMu9&I9&oTjvvrrVh4rB+-@6 z_GCK?VjQmWM-s`$J95qK-VuEWsnd>biaxIBWTTgqUr>m(sOIx5Y-9pl#wxfMvwU%ym!m(?4o&Tklw$6;I zwFD%QFFTr$N=`*fZ%0R>w=;XVE8C2u={N#Q=Df48F)mu-Ryh}4+RSgzBQ}p`6Q#AO z2VAuDWD5zfoGY|u^I}>O`VxiKrp`oLA<@&C>+L|wySNEY)}eWfb8VDU5ETsHs8~h>rC9Xz5cfP?Wj`*^F4b+p2k+ovGtKPOKa`NeCz|*<1qj3xF!+p zy2j#L9c+>gUv>~1MVoNFQ}DM?h#-G(=hAh{z7hR;RqT6_rL_llUSt04=T@#uu+$oX6T-~;>a>tg|CPd82ofElpuH7z`iw&dQuGw}=m2$K8QO>gu z`)BsJoqyrC>f0BzyIthghW=Jn>N_ZMDg48R3SN@Ya=VzvnE{a-kanYe*I14R1;_e? z@ApO2px90*z^!H0#o&h`YdQ98kM5l{p0Rpg(IdnG0?JWe{fvOTe5kQ0N*&s`!nPGO&)S7+^^Tt?(fpf6e~ ztFyWMyvQAQaj)R7 z)E~dr;Wk%s`FZ?^Ul!cvCa^<-XFh}r95%){?-M=4D=chmj^Xl4f{!kDxXn>qK8+vs zU&3OUhw87#HSzPfH0&j=_el|W z31{Mia&N~eTz>-cLXA9eCoZt(!@v-#}*PmxaurFQ%RcEbYg{(J%aExf~H4W1|LmHYFaTod2m;g{u_9~N)$ zaGQv@=XmPlt8vdG)RXY=jZVb=-75GBoIm2>+7CVy;5vS*JoZQJahK>(dBt}G`adV~ zI|F&e8Al$ppJRX?tsaiOuJUo&!#9*sW0p#ahrBHlJmf7Yc*xsU5BGUX39dY7(>kUr z4~p*$0rgX4lLKZ>6WR>-O{izJ;9Or#HOu* zyyDvf`DaA`U4gvfDZxYjPkFe{^HN!_Qr^$Egy10$n*^23+n`Of~&mp91r9bUlz!>i~f~? zyyB|`r@#KZVv~pae4Z3M^!JqDp}*%mJ-2vu?+wA#ug{8|=LJ_D6n`s_SAWL?dBsbC z{8`a|DUetEJ;6gB@NeGj5$3~X5BKZ&;M!SvpErTcBJeC-&I;b{#LKwu_v{MrLAfsk zc(@;_`gMQhdx5;}M_vkW-FI0D`*^4x-51pT1jTjVB@@W&zToo#uKR*72Dt8<{y4yO ze{?Fqbzd+cB&t2SZ>sBh#dY8GU?3mvBdWaakG>qp>wc=PuT@_69d*5|xb8b@92D36 z+LYv@;<_K%8sNJBdOXCXe(@hE`0>(x*6{$>eO7a*Dc_#9UxoRF4PR|ra_LN4zHr2S zt*rchXFp)t57_!ePre*id^gNz59OZBR(u?t=hLUvrE2(%79UizhfRGx+tE~C$Q~}( z54YJvU4 zyU`F_PxGVh?C0I`hv$5j|A+uj@onAI;{$89{{BCB?AD$_6YinWeJXG1%C~hET7B5n&?6ywci!uh#1YiAw5B3s5D;a)sb%xsyy6N7|-kxm6H8lHg9O~gy zq3Ll`-*e;;&zmy!ALXBI{Bs+u%w_PQoKm;pcGKbdtuAT*AAcW1|CAK3(6a0dms!oQon4rPBT z?*}xSlD;1hrv9tOf5rRr@i%aXlhF8)KW-W6`^w*bG#s|gH%puN7yIziKJ6x@;rssw DeBxIz literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/support/quotaio_v2.c b/jni/e2fsprogs/lib/support/quotaio_v2.c new file mode 100755 index 0000000..d09294b --- /dev/null +++ b/jni/e2fsprogs/lib/support/quotaio_v2.c @@ -0,0 +1,389 @@ +/* + * Implementation of new quotafile format + * + * Jan Kara - sponsored by SuSE CR + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "quotaio_v2.h" +#include "dqblk_v2.h" +#include "quotaio.h" +#include "quotaio_tree.h" + +static int v2_check_file(struct quota_handle *h, int type, int fmt); +static int v2_init_io(struct quota_handle *h); +static int v2_new_io(struct quota_handle *h); +static int v2_write_info(struct quota_handle *h); +static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id); +static int v2_commit_dquot(struct dquot *dquot); +static int v2_scan_dquots(struct quota_handle *h, + int (*process_dquot) (struct dquot *dquot, + void *data), + void *data); +static int v2_report(struct quota_handle *h, int verbose); + +struct quotafile_ops quotafile_ops_2 = { + .check_file = v2_check_file, + .init_io = v2_init_io, + .new_io = v2_new_io, + .write_info = v2_write_info, + .read_dquot = v2_read_dquot, + .commit_dquot = v2_commit_dquot, + .scan_dquots = v2_scan_dquots, + .report = v2_report, +}; + +/* + * Copy dquot from disk to memory + */ +static void v2r0_disk2memdqblk(struct dquot *dquot, void *dp) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r0_disk_dqblk *d = dp, empty; + + dquot->dq_id = ext2fs_le32_to_cpu(d->dqb_id); + m->dqb_ihardlimit = ext2fs_le32_to_cpu(d->dqb_ihardlimit); + m->dqb_isoftlimit = ext2fs_le32_to_cpu(d->dqb_isoftlimit); + m->dqb_bhardlimit = ext2fs_le32_to_cpu(d->dqb_bhardlimit); + m->dqb_bsoftlimit = ext2fs_le32_to_cpu(d->dqb_bsoftlimit); + m->dqb_curinodes = ext2fs_le32_to_cpu(d->dqb_curinodes); + m->dqb_curspace = ext2fs_le64_to_cpu(d->dqb_curspace); + m->dqb_itime = ext2fs_le64_to_cpu(d->dqb_itime); + m->dqb_btime = ext2fs_le64_to_cpu(d->dqb_btime); + + memset(&empty, 0, sizeof(struct v2r0_disk_dqblk)); + empty.dqb_itime = ext2fs_cpu_to_le64(1); + if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk))) + m->dqb_itime = 0; +} + +/* + * Copy dquot from memory to disk + */ +static void v2r0_mem2diskdqblk(void *dp, struct dquot *dquot) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r0_disk_dqblk *d = dp; + + d->dqb_ihardlimit = ext2fs_cpu_to_le32(m->dqb_ihardlimit); + d->dqb_isoftlimit = ext2fs_cpu_to_le32(m->dqb_isoftlimit); + d->dqb_bhardlimit = ext2fs_cpu_to_le32(m->dqb_bhardlimit); + d->dqb_bsoftlimit = ext2fs_cpu_to_le32(m->dqb_bsoftlimit); + d->dqb_curinodes = ext2fs_cpu_to_le32(m->dqb_curinodes); + d->dqb_curspace = ext2fs_cpu_to_le64(m->dqb_curspace); + d->dqb_itime = ext2fs_cpu_to_le64(m->dqb_itime); + d->dqb_btime = ext2fs_cpu_to_le64(m->dqb_btime); + d->dqb_id = ext2fs_cpu_to_le32(dquot->dq_id); + if (qtree_entry_unused(&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree, dp)) + d->dqb_itime = ext2fs_cpu_to_le64(1); +} + +static int v2r0_is_id(void *dp, struct dquot *dquot) +{ + struct v2r0_disk_dqblk *d = dp; + struct qtree_mem_dqinfo *info = + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree; + + if (qtree_entry_unused(info, dp)) + return 0; + return ext2fs_le32_to_cpu(d->dqb_id) == dquot->dq_id; +} + +static struct qtree_fmt_operations v2r0_fmt_ops = { + .mem2disk_dqblk = v2r0_mem2diskdqblk, + .disk2mem_dqblk = v2r0_disk2memdqblk, + .is_id = v2r0_is_id, +}; + +/* + * Copy dquot from disk to memory + */ +static void v2r1_disk2memdqblk(struct dquot *dquot, void *dp) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r1_disk_dqblk *d = dp, empty; + + dquot->dq_id = ext2fs_le32_to_cpu(d->dqb_id); + m->dqb_ihardlimit = ext2fs_le64_to_cpu(d->dqb_ihardlimit); + m->dqb_isoftlimit = ext2fs_le64_to_cpu(d->dqb_isoftlimit); + m->dqb_bhardlimit = ext2fs_le64_to_cpu(d->dqb_bhardlimit); + m->dqb_bsoftlimit = ext2fs_le64_to_cpu(d->dqb_bsoftlimit); + m->dqb_curinodes = ext2fs_le64_to_cpu(d->dqb_curinodes); + m->dqb_curspace = ext2fs_le64_to_cpu(d->dqb_curspace); + m->dqb_itime = ext2fs_le64_to_cpu(d->dqb_itime); + m->dqb_btime = ext2fs_le64_to_cpu(d->dqb_btime); + + memset(&empty, 0, sizeof(struct v2r1_disk_dqblk)); + empty.dqb_itime = ext2fs_cpu_to_le64(1); + if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk))) + m->dqb_itime = 0; +} + +/* + * Copy dquot from memory to disk + */ +static void v2r1_mem2diskdqblk(void *dp, struct dquot *dquot) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r1_disk_dqblk *d = dp; + + d->dqb_ihardlimit = ext2fs_cpu_to_le64(m->dqb_ihardlimit); + d->dqb_isoftlimit = ext2fs_cpu_to_le64(m->dqb_isoftlimit); + d->dqb_bhardlimit = ext2fs_cpu_to_le64(m->dqb_bhardlimit); + d->dqb_bsoftlimit = ext2fs_cpu_to_le64(m->dqb_bsoftlimit); + d->dqb_curinodes = ext2fs_cpu_to_le64(m->dqb_curinodes); + d->dqb_curspace = ext2fs_cpu_to_le64(m->dqb_curspace); + d->dqb_itime = ext2fs_cpu_to_le64(m->dqb_itime); + d->dqb_btime = ext2fs_cpu_to_le64(m->dqb_btime); + d->dqb_id = ext2fs_cpu_to_le32(dquot->dq_id); + if (qtree_entry_unused(&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree, dp)) + d->dqb_itime = ext2fs_cpu_to_le64(1); +} + +static int v2r1_is_id(void *dp, struct dquot *dquot) +{ + struct v2r1_disk_dqblk *d = dp; + struct qtree_mem_dqinfo *info = + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree; + + if (qtree_entry_unused(info, dp)) + return 0; + return ext2fs_le32_to_cpu(d->dqb_id) == dquot->dq_id; +} + +static struct qtree_fmt_operations v2r1_fmt_ops = { + .mem2disk_dqblk = v2r1_mem2diskdqblk, + .disk2mem_dqblk = v2r1_disk2memdqblk, + .is_id = v2r1_is_id, +}; + +/* + * Copy dqinfo from disk to memory + */ +static inline void v2_disk2memdqinfo(struct util_dqinfo *m, + struct v2_disk_dqinfo *d) +{ + m->dqi_bgrace = ext2fs_le32_to_cpu(d->dqi_bgrace); + m->dqi_igrace = ext2fs_le32_to_cpu(d->dqi_igrace); + m->u.v2_mdqi.dqi_flags = ext2fs_le32_to_cpu(d->dqi_flags) & V2_DQF_MASK; + m->u.v2_mdqi.dqi_qtree.dqi_blocks = ext2fs_le32_to_cpu(d->dqi_blocks); + m->u.v2_mdqi.dqi_qtree.dqi_free_blk = + ext2fs_le32_to_cpu(d->dqi_free_blk); + m->u.v2_mdqi.dqi_qtree.dqi_free_entry = + ext2fs_le32_to_cpu(d->dqi_free_entry); +} + +/* + * Copy dqinfo from memory to disk + */ +static inline void v2_mem2diskdqinfo(struct v2_disk_dqinfo *d, + struct util_dqinfo *m) +{ + d->dqi_bgrace = ext2fs_cpu_to_le32(m->dqi_bgrace); + d->dqi_igrace = ext2fs_cpu_to_le32(m->dqi_igrace); + d->dqi_flags = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_flags & V2_DQF_MASK); + d->dqi_blocks = ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_blocks); + d->dqi_free_blk = + ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_blk); + d->dqi_free_entry = + ext2fs_cpu_to_le32(m->u.v2_mdqi.dqi_qtree.dqi_free_entry); +} + +static int v2_read_header(struct quota_handle *h, struct v2_disk_dqheader *dqh) +{ + if (h->e2fs_read(&h->qh_qf, 0, dqh, sizeof(struct v2_disk_dqheader)) != + sizeof(struct v2_disk_dqheader)) + return 0; + + return 1; +} + +/* + * Check whether given quota file is in our format + */ +static int v2_check_file(struct quota_handle *h, int type, int fmt) +{ + struct v2_disk_dqheader dqh; + int file_magics[] = INITQMAGICS; + int be_magic; + + if (fmt != QFMT_VFS_V1) + return 0; + + if (!v2_read_header(h, &dqh)) + return 0; + + be_magic = ext2fs_be32_to_cpu((__force __be32)dqh.dqh_magic); + if (be_magic == file_magics[type]) { + log_err("Your quota file is stored in wrong endianness"); + return 0; + } + if (V2_VERSION_R0 != ext2fs_le32_to_cpu(dqh.dqh_version) && + V2_VERSION_R1 != ext2fs_le32_to_cpu(dqh.dqh_version)) + return 0; + return 1; +} + +/* + * Open quotafile + */ +static int v2_init_io(struct quota_handle *h) +{ + struct v2_disk_dqheader dqh; + struct v2_disk_dqinfo ddqinfo; + struct v2_mem_dqinfo *info; + __u64 filesize; + int version; + + if (!v2_read_header(h, &dqh)) + return -1; + version = ext2fs_le32_to_cpu(dqh.dqh_version); + + if (version == V2_VERSION_R0) { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = + sizeof(struct v2r0_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops; + } else { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = + sizeof(struct v2r1_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; + } + + /* Read information about quotafile */ + if (h->e2fs_read(&h->qh_qf, V2_DQINFOOFF, &ddqinfo, + sizeof(ddqinfo)) != sizeof(ddqinfo)) + return -1; + v2_disk2memdqinfo(&h->qh_info, &ddqinfo); + + /* Check to make sure quota file info is sane */ + info = &h->qh_info.u.v2_mdqi; + if (ext2fs_file_get_lsize(h->qh_qf.e2_file, &filesize)) + return -1; + if ((filesize > (1U << 31)) || + (info->dqi_qtree.dqi_blocks > + (filesize + QT_BLKSIZE - 1) >> QT_BLKSIZE_BITS)) { + log_err("Quota inode %u corrupted: file size %llu; " + "dqi_blocks %u", h->qh_qf.ino, + (unsigned long long) filesize, + info->dqi_qtree.dqi_blocks); + return -1; + } + if (info->dqi_qtree.dqi_free_blk >= info->dqi_qtree.dqi_blocks) { + log_err("Quota inode %u corrupted: free_blk %u; dqi_blocks %u", + h->qh_qf.ino, info->dqi_qtree.dqi_free_blk, + info->dqi_qtree.dqi_blocks); + return -1; + } + if (info->dqi_qtree.dqi_free_entry >= info->dqi_qtree.dqi_blocks) { + log_err("Quota inode %u corrupted: free_entry %u; " + "dqi_blocks %u", h->qh_qf.ino, + info->dqi_qtree.dqi_free_entry, + info->dqi_qtree.dqi_blocks); + return -1; + } + return 0; +} + +/* + * Initialize new quotafile + */ +static int v2_new_io(struct quota_handle *h) +{ + int file_magics[] = INITQMAGICS; + struct v2_disk_dqheader ddqheader; + struct v2_disk_dqinfo ddqinfo; + + if (h->qh_fmt != QFMT_VFS_V1) + return -1; + + /* Write basic quota header */ + ddqheader.dqh_magic = ext2fs_cpu_to_le32(file_magics[h->qh_type]); + ddqheader.dqh_version = ext2fs_cpu_to_le32(V2_VERSION_R1); + if (h->e2fs_write(&h->qh_qf, 0, &ddqheader, sizeof(ddqheader)) != + sizeof(ddqheader)) + return -1; + + /* Write information about quotafile */ + h->qh_info.dqi_bgrace = MAX_DQ_TIME; + h->qh_info.dqi_igrace = MAX_IQ_TIME; + h->qh_info.u.v2_mdqi.dqi_flags = 0; + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks = QT_TREEOFF + 1; + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk = 0; + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry = 0; + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = + sizeof(struct v2r1_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; + v2_mem2diskdqinfo(&ddqinfo, &h->qh_info); + if (h->e2fs_write(&h->qh_qf, V2_DQINFOOFF, &ddqinfo, + sizeof(ddqinfo)) != + sizeof(ddqinfo)) + return -1; + + return 0; +} + +/* + * Write information (grace times to file) + */ +static int v2_write_info(struct quota_handle *h) +{ + struct v2_disk_dqinfo ddqinfo; + + v2_mem2diskdqinfo(&ddqinfo, &h->qh_info); + if (h->e2fs_write(&h->qh_qf, V2_DQINFOOFF, &ddqinfo, sizeof(ddqinfo)) != + sizeof(ddqinfo)) + return -1; + + return 0; +} + +/* + * Read dquot from disk + */ +static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) +{ + return qtree_read_dquot(h, id); +} + +/* + * Commit changes of dquot to disk - it might also mean deleting it when quota + * became fake one and user has no blocks. + * User can process use 'errno' to detect errstr. + */ +static int v2_commit_dquot(struct dquot *dquot) +{ + struct util_dqblk *b = &dquot->dq_dqb; + + if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && + !b->dqb_isoftlimit && !b->dqb_bhardlimit && !b->dqb_ihardlimit) + qtree_delete_dquot(dquot); + else + qtree_write_dquot(dquot); + return 0; +} + +static int v2_scan_dquots(struct quota_handle *h, + int (*process_dquot) (struct dquot *, void *), + void *data) +{ + return qtree_scan_dquots(h, process_dquot, data); +} + +/* Report information about quotafile. + * TODO: Not used right now, but we should be able to use this when we add + * support to debugfs to read quota files. + */ +static int v2_report(struct quota_handle *h EXT2FS_ATTR((unused)), + int verbose EXT2FS_ATTR((unused))) +{ + log_err("Not Implemented."); + return -1; +} diff --git a/jni/e2fsprogs/lib/support/quotaio_v2.o b/jni/e2fsprogs/lib/support/quotaio_v2.o new file mode 100755 index 0000000000000000000000000000000000000000..2c5c17eef5e1001a8ac12a1c8ce531e855459184 GIT binary patch literal 9504 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 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/uuid/clear.c b/jni/e2fsprogs/lib/uuid/clear.c new file mode 100755 index 0000000..436f8f7 --- /dev/null +++ b/jni/e2fsprogs/lib/uuid/clear.c @@ -0,0 +1,44 @@ +/* + * clear.c -- Clear a UUID + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include "string.h" + +#include "uuidP.h" + +void uuid_clear(uuid_t uu) +{ + memset(uu, 0, 16); +} + diff --git a/jni/e2fsprogs/lib/uuid/clear.o b/jni/e2fsprogs/lib/uuid/clear.o new file mode 100755 index 0000000000000000000000000000000000000000..2fb594df470e647070502f25495b38305d1a7420 GIT binary patch literal 976 zcmbV~y-EW?5XWatVp2#579vDUige;)tb*0yCy0my#YPD0Wi`Rv1uh$jBKQoxg>PW% zBWPo7X=`~^oH=(e+0({_-T%&S=VQO_cMf)EgaB>=p5Vt~3h*)ky##wuK+o|OyuRll z{>XcAML=B1L5%F-In#Orzo){>>a~sr-F{fDH)LHlY|4^VaoYrOw=BwY6<9<@o!Sx& z+r`pxktTn)4P45?=lC~|49ukPSwhnMG~t<)e={Mu6sP^qPvlSbi;Ojg_cc{T8a*-~ z{eBSW(734xj-O|3z8_xB^2BN$mEzq4eZL#P zg5%HiS<5!waf8SO*5)`~rn + +#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1); + +int uuid_compare(const uuid_t uu1, const uuid_t uu2) +{ + struct uuid uuid1, uuid2; + + uuid_unpack(uu1, &uuid1); + uuid_unpack(uu2, &uuid2); + + UUCMP(uuid1.time_low, uuid2.time_low); + UUCMP(uuid1.time_mid, uuid2.time_mid); + UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); + UUCMP(uuid1.clock_seq, uuid2.clock_seq); + return memcmp(uuid1.node, uuid2.node, 6); +} + diff --git a/jni/e2fsprogs/lib/uuid/compare.o b/jni/e2fsprogs/lib/uuid/compare.o new file mode 100755 index 0000000000000000000000000000000000000000..45782c84f671dd7ffb0e656c0e646fd7a2cc4696 GIT binary patch literal 1456 zcmbW1L2DC16vy9Wqb3?k5fve|o6;Uyu!Heb@ZdsQ4I)xXy@+&Kw_7dgZo+0GiB&B0 z3mEXKrZ@WuY;R&efgYq6h2GMf^p;Dg@9oZPH=8~AAUkh=^M7yV&6~~J#fSG&jDa); zU*PObQh=&*=4-yIK^B##^Xz+nE4|lOSgWn5z1^MhUR%+7$0oE;_P)Kd+B=>M{7zmw zIJu-9WLUObV6cMgTscA3MK%rF%QNg^IWzI;$>&3Le-`IDceEzXHwW~{y2wKPZlIqa z{aw_nF+H*_vbg>#>E}^D8Pg-{B8%&@q^Fu@pw+>87>?gy`-fj6?w4w5AL{%4t%W^2 zlh#*7{|V-%;XE(AwA|W8#VHi$c#+TfX9qAUM)qnM*z0kYqt?7HA%)P#kRrBd$3 z=*QHDw322yb*VH0zkdlu^00z94S!FQW)(;c;f7C!dClkPA-&_1^Fy5Kx*W;x?;qJs z{K;CQL3sX&d`yV)SpS7c0G$n4oXg8fJQGO#r_6H>`9O8twKfgzSq%@kS+Q-)@xZoh z)2;${DxSsfKYBb{^9-{L_4>w|UU#aYkNT?NS`g&0Ug+ztVOtMgT zJF$LAaOwpi*%NuMbI2%1{4k!1jb6jKs0l3F4AfW2qB=JTCTJfBCbk=}yQeY4qQ) zZj3>;Srdjh_Nu)*P6Fqg-v+fOFbaBUXY|mlRP*K1Xl9yc_%!a*E!SfwtH4f&**T| z9~BNMA~B9g_1>#o$#}m+1!}&+0SqXvatQBRofhuRoxm7rKmIfHA7qVpuZYwYq><2_ mgc2lP$U*A6ZbzNICRMNWMbx~rsl_K9XqOFecceG=)_(yk&0#SB literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/uuid/gen_uuid.c b/jni/e2fsprogs/lib/uuid/gen_uuid.c new file mode 100755 index 0000000..2f02886 --- /dev/null +++ b/jni/e2fsprogs/lib/uuid/gen_uuid.c @@ -0,0 +1,682 @@ +/* + * gen_uuid.c --- generate a DCE-compatible uuid + * + * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +/* + * Force inclusion of SVID stuff since we need it if we're compiling in + * gcc-wall wall mode + */ +#define _SVID_SOURCE +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ + +#include "config.h" + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#include +#ifdef HAVE_SYS_FILE_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_RANDOM_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NET_IF_DL_H +#include +#endif +#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include "uuidP.h" +#include "uuidd.h" + +#ifdef HAVE_SRANDOM +#define srand(x) srandom(x) +#define rand() random() +#endif + +#ifdef TLS +#define THREAD_LOCAL static TLS +#else +#define THREAD_LOCAL static +#endif + +#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48) +#define DO_JRAND_MIX +THREAD_LOCAL unsigned short jrand_seed[3]; +#endif + +static int get_random_fd(void) +{ + struct timeval tv; + static int fd = -2; + int i; + + if (fd == -2) { + gettimeofday(&tv, 0); +#ifndef _WIN32 + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + if (fd >= 0) { + i = fcntl(fd, F_GETFD); + if (i >= 0) + fcntl(fd, F_SETFD, i | FD_CLOEXEC); + } +#endif + srand(((unsigned)getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); +#ifdef DO_JRAND_MIX + jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); + jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); + jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; +#endif + } + /* Crank the random number generator a few times */ + gettimeofday(&tv, 0); + for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) + rand(); + return fd; +} + + +/* + * Generate a series of random bytes. Use /dev/urandom if possible, + * and if not, use srandom/random. + */ +static void get_random_bytes(void *buf, int nbytes) +{ + int i, n = nbytes, fd; + int lose_counter = 0; + unsigned char *cp = buf; + +#ifdef HAVE_GETRANDOM + i = getrandom(buf, nbytes, 0); + if (i == nbytes) + return; +#endif +#ifdef HAVE_GETENTROPY + if (getentropy(buf, nbytes) == 0) + return; +#endif + + fd = get_random_fd(); + if (fd >= 0) { + while (n > 0) { + i = read(fd, cp, n); + if (i <= 0) { + if (lose_counter++ > 16) + break; + continue; + } + n -= i; + cp += i; + lose_counter = 0; + } + } + + /* + * We do this all the time, but this is the only source of + * randomness if /dev/random/urandom is out to lunch. + */ + for (cp = buf, i = 0; i < nbytes; i++) + *cp++ ^= (rand() >> 7) & 0xFF; +#ifdef DO_JRAND_MIX + { + unsigned short tmp_seed[3]; + + memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed)); + jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid); + for (cp = buf, i = 0; i < nbytes; i++) + *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF; + memcpy(jrand_seed, tmp_seed, + sizeof(jrand_seed) - sizeof(unsigned short)); + } +#endif + + return; +} + +/* + * Get the ethernet hardware address, if we can find it... + * + * XXX for a windows version, probably should use GetAdaptersInfo: + * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 + * commenting out get_node_id just to get gen_uuid to compile under windows + * is not the right way to go! + */ +static int get_node_id(unsigned char *node_id) +{ +#ifdef HAVE_NET_IF_H + int sd; + struct ifreq ifr, *ifrp; + struct ifconf ifc; + char buf[1024]; + int n, i; + unsigned char *a; +#ifdef HAVE_NET_IF_DL_H + struct sockaddr_dl *sdlp; +#endif + +/* + * BSD 4.4 defines the size of an ifreq to be + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len + * However, under earlier systems, sa_len isn't present, so the size is + * just sizeof(struct ifreq) + */ +#ifdef HAVE_SA_LEN +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#define ifreq_size(i) max(sizeof(struct ifreq),\ + sizeof((i).ifr_name)+(i).ifr_addr.sa_len) +#else +#define ifreq_size(i) sizeof(struct ifreq) +#endif /* HAVE_SA_LEN*/ + + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + return -1; + } + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { + close(sd); + return -1; + } + n = ifc.ifc_len; + for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { + ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); +#ifdef SIOCGIFHWADDR + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) + continue; + a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; +#else +#ifdef SIOCGENADDR + if (ioctl(sd, SIOCGENADDR, &ifr) < 0) + continue; + a = (unsigned char *) ifr.ifr_enaddr; +#else +#ifdef HAVE_NET_IF_DL_H + sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; + if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) + continue; + a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; +#else + /* + * XXX we don't have a way of getting the hardware + * address + */ + close(sd); + return 0; +#endif /* HAVE_NET_IF_DL_H */ +#endif /* SIOCGENADDR */ +#endif /* SIOCGIFHWADDR */ + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + continue; + if (node_id) { + memcpy(node_id, a, 6); + close(sd); + return 1; + } + } + close(sd); +#endif + return 0; +} + +/* Assume that the gettimeofday() has microsecond granularity */ +#define MAX_ADJUSTMENT 10 + +static int get_clock(uint32_t *clock_high, uint32_t *clock_low, + uint16_t *ret_clock_seq, int *num) +{ + THREAD_LOCAL int adjustment = 0; + THREAD_LOCAL struct timeval last = {0, 0}; + THREAD_LOCAL int state_fd = -2; + THREAD_LOCAL FILE *state_f; + THREAD_LOCAL uint16_t clock_seq; + struct timeval tv; +#ifndef _WIN32 + struct flock fl; +#endif + uint64_t clock_reg; + mode_t save_umask; + int len; + + if (state_fd == -2) { + save_umask = umask(0); + state_fd = open("/var/lib/libuuid/clock.txt", + O_RDWR|O_CREAT, 0660); + (void) umask(save_umask); + if (state_fd >= 0) { + state_f = fdopen(state_fd, "r+"); + if (!state_f) { + close(state_fd); + state_fd = -1; + } + } + } +#ifndef _WIN32 + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = 0; + if (state_fd >= 0) { + rewind(state_f); + while (fcntl(state_fd, F_SETLKW, &fl) < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + fclose(state_f); + state_fd = -1; + break; + } + } +#endif + if (state_fd >= 0) { + unsigned int cl; + unsigned long tv1, tv2; + int a; + + if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", + &cl, &tv1, &tv2, &a) == 4) { + clock_seq = cl & 0x3FFF; + last.tv_sec = tv1; + last.tv_usec = tv2; + adjustment = a; + } + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { + get_random_bytes(&clock_seq, sizeof(clock_seq)); + clock_seq &= 0x3FFF; + gettimeofday(&last, 0); + last.tv_sec--; + } + +try_again: + gettimeofday(&tv, 0); + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec < last.tv_usec))) { + clock_seq = (clock_seq+1) & 0x3FFF; + adjustment = 0; + last = tv; + } else if ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec == last.tv_usec)) { + if (adjustment >= MAX_ADJUSTMENT) + goto try_again; + adjustment++; + } else { + adjustment = 0; + last = tv; + } + + clock_reg = tv.tv_usec*10 + adjustment; + clock_reg += ((uint64_t) tv.tv_sec)*10000000; + clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; + + if (num && (*num > 1)) { + adjustment += *num - 1; + last.tv_usec += adjustment / 10; + adjustment = adjustment % 10; + last.tv_sec += last.tv_usec / 1000000; + last.tv_usec = last.tv_usec % 1000000; + } + + if (state_fd > 0) { + rewind(state_f); + len = fprintf(state_f, + "clock: %04x tv: %016lu %08lu adj: %08d\n", + clock_seq, (unsigned long)last.tv_sec, + (unsigned long)last.tv_usec, adjustment); + fflush(state_f); + if (ftruncate(state_fd, len) < 0) { + fprintf(state_f, " \n"); + fflush(state_f); + } + rewind(state_f); +#ifndef _WIN32 + fl.l_type = F_UNLCK; + if (fcntl(state_fd, F_SETLK, &fl) < 0) { + fclose(state_f); + state_fd = -1; + } +#endif + } + + *clock_high = clock_reg >> 32; + *clock_low = clock_reg; + *ret_clock_seq = clock_seq; + return 0; +} + +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) +static ssize_t read_all(int fd, char *buf, size_t count) +{ + ssize_t ret; + ssize_t c = 0; + int tries = 0; + + memset(buf, 0, count); + while (count > 0) { + ret = read(fd, buf, count); + if (ret <= 0) { + if ((errno == EAGAIN || errno == EINTR || ret == 0) && + (tries++ < 5)) + continue; + return c ? c : -1; + } + if (ret > 0) + tries = 0; + count -= ret; + buf += ret; + c += ret; + } + return c; +} + +/* + * Close all file descriptors + */ +static void close_all_fds(void) +{ + int i, max; + +#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) + max = sysconf(_SC_OPEN_MAX); +#elif defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) + struct rlimit rl; + + getrlimit(RLIMIT_NOFILE, &rl); + max = rl.rlim_cur; +#else + max = OPEN_MAX; +#endif + + for (i=0; i < max; i++) { + close(i); + if (i <= 2) + open("/dev/null", O_RDWR); + } +} +#endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */ + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H) +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +#endif +/* + * Try using the uuidd daemon to generate the UUID + * + * Returns 0 on success, non-zero on failure. + */ +static int get_uuid_via_daemon(int op, uuid_t out, int *num) +{ +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) + char op_buf[64]; + int op_len; + int s; + ssize_t ret; + int32_t reply_len = 0, expected = 16; + struct sockaddr_un srv_addr; + struct stat st; + pid_t pid; + static const char *uuidd_path = UUIDD_PATH; + static int access_ret = -2; + static int start_attempts = 0; + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return -1; + + srv_addr.sun_family = AF_UNIX; + strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH); + + if (connect(s, (const struct sockaddr *) &srv_addr, + sizeof(struct sockaddr_un)) < 0) { + if (access_ret == -2) + access_ret = access(uuidd_path, X_OK); + if (access_ret == 0) + access_ret = stat(uuidd_path, &st); + if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0) + access_ret = access(UUIDD_DIR, W_OK); + if (access_ret == 0 && start_attempts++ < 5) { + if ((pid = fork()) == 0) { + close_all_fds(); + execl(uuidd_path, "uuidd", "-qT", "300", + (char *) NULL); + exit(1); + } + (void) waitpid(pid, 0, 0); + if (connect(s, (const struct sockaddr *) &srv_addr, + sizeof(struct sockaddr_un)) < 0) + goto fail; + } else + goto fail; + } + op_buf[0] = op; + op_len = 1; + if (op == UUIDD_OP_BULK_TIME_UUID) { + memcpy(op_buf+1, num, sizeof(*num)); + op_len += sizeof(*num); + expected += sizeof(*num); + } + + ret = write(s, op_buf, op_len); + if (ret < 1) + goto fail; + + ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); + if (ret < 0) + goto fail; + + if (reply_len != expected) + goto fail; + + ret = read_all(s, op_buf, reply_len); + + if (op == UUIDD_OP_BULK_TIME_UUID) + memcpy(op_buf+16, num, sizeof(int)); + + memcpy(out, op_buf, 16); + + close(s); + return ((ret == expected) ? 0 : -1); + +fail: + close(s); +#endif + return -1; +} +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +void uuid__generate_time(uuid_t out, int *num) +{ + static unsigned char node_id[6]; + static int has_init = 0; + struct uuid uu; + uint32_t clock_mid; + + if (!has_init) { + if (get_node_id(node_id) <= 0) { + get_random_bytes(node_id, 6); + /* + * Set multicast bit, to prevent conflicts + * with IEEE 802 addresses obtained from + * network cards + */ + node_id[0] |= 0x01; + } + has_init = 1; + } + get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); + uu.clock_seq |= 0x8000; + uu.time_mid = (uint16_t) clock_mid; + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; + memcpy(uu.node, node_id, 6); + uuid_pack(&uu, out); +} + +void uuid_generate_time(uuid_t out) +{ +#ifdef TLS + THREAD_LOCAL int num = 0; + THREAD_LOCAL struct uuid uu; + THREAD_LOCAL time_t last_time = 0; + time_t now; + + if (num > 0) { + now = time(0); + if (now > last_time+1) + num = 0; + } + if (num <= 0) { + num = 1000; + if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, + out, &num) == 0) { + last_time = time(0); + uuid_unpack(out, &uu); + num--; + return; + } + num = 0; + } + if (num > 0) { + uu.time_low++; + if (uu.time_low == 0) { + uu.time_mid++; + if (uu.time_mid == 0) + uu.time_hi_and_version++; + } + num--; + uuid_pack(&uu, out); + return; + } +#else + if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) + return; +#endif + + uuid__generate_time(out, 0); +} + + +void uuid__generate_random(uuid_t out, int *num) +{ + uuid_t buf; + struct uuid uu; + int i, n; + + if (!num || !*num) + n = 1; + else + n = *num; + + for (i = 0; i < n; i++) { + get_random_bytes(buf, sizeof(buf)); + uuid_unpack(buf, &uu); + + uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; + uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) + | 0x4000; + uuid_pack(&uu, out); + out += sizeof(uuid_t); + } +} + +void uuid_generate_random(uuid_t out) +{ + int num = 1; + /* No real reason to use the daemon for random uuid's -- yet */ + + uuid__generate_random(out, &num); +} + + +/* + * This is the generic front-end to uuid_generate_random and + * uuid_generate_time. It uses uuid_generate_random only if + * /dev/urandom is available, since otherwise we won't have + * high-quality randomness. + */ +void uuid_generate(uuid_t out) +{ + if (get_random_fd() >= 0) + uuid_generate_random(out); + else + uuid_generate_time(out); +} diff --git a/jni/e2fsprogs/lib/uuid/gen_uuid.o b/jni/e2fsprogs/lib/uuid/gen_uuid.o new file mode 100755 index 0000000000000000000000000000000000000000..3a5ebd4e8febca5adda733aa19059a9a8d839bc6 GIT binary patch literal 21304 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 Ll1Qd(j{E-`G=fsq literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/uuid/isnull.c b/jni/e2fsprogs/lib/uuid/isnull.c new file mode 100755 index 0000000..170c9a2 --- /dev/null +++ b/jni/e2fsprogs/lib/uuid/isnull.c @@ -0,0 +1,49 @@ +/* + * isnull.c --- Check whether or not the UUID is null + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include "uuidP.h" + +/* Returns 1 if the uuid is the NULL uuid */ +int uuid_is_null(const uuid_t uu) +{ + const unsigned char *cp; + int i; + + for (i=0, cp = uu; i < 16; i++) + if (*cp++) + return 0; + return 1; +} + diff --git a/jni/e2fsprogs/lib/uuid/isnull.o b/jni/e2fsprogs/lib/uuid/isnull.o new file mode 100755 index 0000000000000000000000000000000000000000..badcb8cc735943cb1d58744e17b997385541db78 GIT binary patch literal 1064 zcmbVKy-&hW5WfNyh{mWfYT^eB4lKL~alpi(CVnjHKy-0wDpVzw5@|7LOf+$E<-hO` zFfrYjopf<_L?<1Y>RovcORI~Q^!@IB_xY~xdSiPtB1s@bf=BqV1PhRf{OF3ODv-cP z_ZD8>hN0`m!RZVu-A)|3m_ONxD^6k!&ORjA<90VGL+c&=2}xPG16U^BO@Wg{?B~cZ zjy0T5*PYJ5O|gT1^1Y=L2Ya>JQS}u{hGrh8&-J=hshR0qf#q0%k2l6qx-5cpwII!o zq+kX)`bca#)<@G3W0bT%WfeU!_;P;>h=Ok!JV5m@%pZ7sG*o8aW8@G|^H2Edd-EbU z$0KE2#y}Tl>rES2saCD(rVWiorL0yg)od6BFtcXsY-@KvYuQ@q6j)t1G^U@ZM|G{L zL&c&fRsv?(bz3_`yr>c`mRX*T94t23QfS8i5F3~j-U2`y??Y1VLI33RfKA*`pXn(I zx5b`>J0=v4aYV`w-sXY(r#K1_{RPgWL+B!g@X2rZ^k8freZ&p?JG7s9PH?US=LKX@ mp*typ;CRm)iT6$Sq*o>K1;2w_u(wx&=ihrqZ${d2F#j9wUtSmh literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/uuid/pack.c b/jni/e2fsprogs/lib/uuid/pack.c new file mode 100755 index 0000000..3db21ae --- /dev/null +++ b/jni/e2fsprogs/lib/uuid/pack.c @@ -0,0 +1,70 @@ +/* + * Internal routine for packing UUID's + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include +#include "uuidP.h" + +void uuid_pack(const struct uuid *uu, uuid_t ptr) +{ + uint32_t tmp; + unsigned char *out = ptr; + + tmp = uu->time_low; + out[3] = (unsigned char) tmp; + tmp >>= 8; + out[2] = (unsigned char) tmp; + tmp >>= 8; + out[1] = (unsigned char) tmp; + tmp >>= 8; + out[0] = (unsigned char) tmp; + + tmp = uu->time_mid; + out[5] = (unsigned char) tmp; + tmp >>= 8; + out[4] = (unsigned char) tmp; + + tmp = uu->time_hi_and_version; + out[7] = (unsigned char) tmp; + tmp >>= 8; + out[6] = (unsigned char) tmp; + + tmp = uu->clock_seq; + out[9] = (unsigned char) tmp; + tmp >>= 8; + out[8] = (unsigned char) tmp; + + memcpy(out+10, uu->node, 6); +} + diff --git a/jni/e2fsprogs/lib/uuid/pack.o b/jni/e2fsprogs/lib/uuid/pack.o new file mode 100755 index 0000000000000000000000000000000000000000..3961473e5e5fae8f7faa502c11ab2858ab0dd4d6 GIT binary patch literal 1232 zcmbu8&o2W(6vy9KW&JD?LMW9~(nt(-(%T&TI*167h)c8DMMGO@m#7dDe}O;2&Cv}v ze*zb0Zgq6r6Yp(i*v@uOCYgP2KJ%UT=FQArF03pzF$StJc!0l=q5v;Vf4=Zs0VXQH zui^DQ3hqY-xU~-9)(o^!;hIc5)uMo1JbfC%O?E+=eDlKGsN-!RJQBj0$6d2cRO{mO zhv<8yzDv``Li9sY->c~-LiFR1ruwMn_FM5dc?*wbOjMIGsN&h&JR6xe$R1k7z4(b; zuH;L_cxsNP_?$e>9%WC& zl|6vt<9sf2L>@2OhZeW@GrMK0U;{Cp1zvH=j0GV45;2U)k&{Otyg>*nVy^C+{^rTG{8nfI%9qP4;GfE ADF6Tf literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/lib/uuid/parse.c b/jni/e2fsprogs/lib/uuid/parse.c new file mode 100755 index 0000000..4c0857d --- /dev/null +++ b/jni/e2fsprogs/lib/uuid/parse.c @@ -0,0 +1,80 @@ +/* + * parse.c --- UUID parsing + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include +#include +#include +#include + +#include "uuidP.h" + +int uuid_parse(const char *in, uuid_t uu) +{ + struct uuid uuid; + int i; + const char *cp; + char buf[3]; + + if (strlen(in) != 36) + return -1; + for (i=0, cp = in; i <= 36; i++,cp++) { + if ((i == 8) || (i == 13) || (i == 18) || + (i == 23)) { + if (*cp == '-') + continue; + else + return -1; + } + if (i== 36) + if (*cp == 0) + continue; + if (!isxdigit(*cp)) + return -1; + } + uuid.time_low = strtoul(in, NULL, 16); + uuid.time_mid = strtoul(in+9, NULL, 16); + uuid.time_hi_and_version = strtoul(in+14, NULL, 16); + uuid.clock_seq = strtoul(in+19, NULL, 16); + cp = in+24; + buf[2] = 0; + for (i=0; i < 6; i++) { + buf[0] = *cp++; + buf[1] = *cp++; + uuid.node[i] = strtoul(buf, NULL, 16); + } + + uuid_pack(&uuid, uu); + return 0; +} diff --git a/jni/e2fsprogs/lib/uuid/parse.o b/jni/e2fsprogs/lib/uuid/parse.o new file mode 100755 index 0000000000000000000000000000000000000000..cf0ea0e4347ee24d6120011857155eef2aa153c3 GIT binary patch literal 2104 zcmbVNO-vI(6n?u)=~fUBfANQ60s%B`#HgVMlTAcHBgPOF6QXr3D>jxwe=s0Mn-CL@ zH1VJZwZsb;uSWMIhJ%SWFWxj@VzTN*Z|#B9_og#+EbYZ z>5yt%SoXh7p`ULDX908EddN}CZ8se~4Y60%g5YVcvRAr9Em3wl5sq&LKdV2ZSY zK$%#O$NCE~)+NdKJZY0!z z4=v^H04VpGl|8k7XvO_5h60!>Iz4sQ`)cI8UC=sd9F`dT zpBu(9txV}S|DTvGiE&xiQMyrtmEJ6qXROF#B361csg^JkA9+3Ii3=R0yF;zS9TNAd z7BT8kszeJXwF6`F67vgt2!q0x^NyDjrA+Q1$4Y2IH?O}UH$`8}FJSs1F2~>G`U_rE bM;eQI!9Rvr>DdUu96w*@ +#include "uuidP.h" + +void uuid_unpack(const uuid_t in, struct uuid *uu) +{ + const uint8_t *ptr = in; + uint32_t tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; + + memcpy(uu->node, ptr, 6); +} + diff --git a/jni/e2fsprogs/lib/uuid/unpack.o b/jni/e2fsprogs/lib/uuid/unpack.o new file mode 100755 index 0000000000000000000000000000000000000000..2cd750bdbf389bd577fe71a486df18b3714b9341 GIT binary patch literal 1296 zcmbu8J5K^Z5P)Yz5vU7RKmCtS~lP_-KfQ(Za+?&hvakISd?zGbR@P0qJe* ztZjtOzhGmn9oSi3r8DO)oCg+$P4;Hy+j;Hdu2)lQ9gKk*44$B2DGCq^HFV*r0yOme zx`CIs0dU`Yz^x7lw;Dki5pFaLr5frQ6HCY{wTP$???(P1xi%G@ZD$ShRcbxLonheR z{!h(%Y!saT_FIqbYa@0L9O|8FcQa9$y@#?E70%2!IC!R|=TQ0;j5FOjieH$y{7Ke| zCz3qDlkys3QnJfUU{@1tw09ClkkO>EOP9FP9}jJ@eh>WdSw`LopI@z(L(tKL_dL?f zcRcQUBr$#2Uw*G&WMk4LjQ#(r!fmr?12?jnjA@}_Wo?tMZ*0%!ZQVG9 zLgC~fU9iqc=Q;CC=jL(xFsEls_@UeYp0{(hzK_z$keoi?i}XprbdfK}!flEbjBh># zfCsr5BalD%uaQl&E8r)jtkNT>t0kT`A^weQX6=_$DO# zb$7_hGCtUs<}ZT!98TJk!08{iGNF3kv`>0fDqisvvS4k>Q + +#include "uuidP.h" + +static const char *fmt_lower = + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; + +static const char *fmt_upper = + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; + +#ifdef UUID_UNPARSE_DEFAULT_UPPER +#define FMT_DEFAULT fmt_upper +#else +#define FMT_DEFAULT fmt_lower +#endif + +static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) +{ + struct uuid uuid; + + uuid_unpack(uu, &uuid); + sprintf(out, fmt, + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); +} + +void uuid_unparse_lower(const uuid_t uu, char *out) +{ + uuid_unparse_x(uu, out, fmt_lower); +} + +void uuid_unparse_upper(const uuid_t uu, char *out) +{ + uuid_unparse_x(uu, out, fmt_upper); +} + +void uuid_unparse(const uuid_t uu, char *out) +{ + uuid_unparse_x(uu, out, FMT_DEFAULT); +} diff --git a/jni/e2fsprogs/lib/uuid/unparse.o b/jni/e2fsprogs/lib/uuid/unparse.o new file mode 100755 index 0000000000000000000000000000000000000000..5ae3e9a3c085c1b90a5507a9b156b3e111ba4fa7 GIT binary patch literal 2448 zcmbu9O=wd=5Xa}`wYFlcRZ)~`6QKoB`)Fbh&27c{0g8wy2#RS;U$vMol2=WwA{g%) zD0ot$Ui9Woa}WeCiir4u3gWkD{W^F{4<*jL%rwt!)Poz|&g^ghGrK$N=G3O`n|+1> z(hRr(^^s73b93sxa$N;}R8|Y{XnNeZHoXywZ(CsMoe5KKTNGL~)rw(0LrpaSOiYh& zxQ5!|Z8Q3;S}-uC8DorMsSv1KG6R*%h0aQ;5Usqs0!2(eQ8J^ION9fK_iI)8!#*|k zF{;KU<7%w=Wb5KjcU0u_eHHofP({8!QIT)YRpjeS6`6daB411>_83rJHy6rl7eaZ> zawxA}1!c-PJ-!L|VDKLPz3*q$>iOUI{qLB2T8vvNPuJbspYQ4J?VIVs`R?8@jcSf= z0R#3@z)Tn3iy9i$9NhxM6S35x;88o98%d{vp?)i5^+P-F!8pDPj1!$khd%&a$d)nh zBRkL*-0EN1e$jWKX}>=Z+}Z}OUm+%)!jIY+>IT{dMdwTS1A{Ci-C>%?_P2biasHgE z`n!%L4b4TQP4KhYXwn4VEd0qOvpMbAz)aHc&bp1>fDeD}InZ~{jdlZmq!*o7#9(^z z(3sj|x3A}ShuoRqc~s0ExOO(b>+%*>)y*B(om&U&S!fq|>LBMxA(y-04Lbe@zK!$T zWU=Hq&HTH@SMYc-7SOxfAoEU*?`GbCyp4S_S3P`zhd*Us@=N_+FqizoTQM&+(bq-* ze&(VVE|&fhy;YTb!b2>S^ERX2d%FgBUbxgPp>e6}gvO<=FgiLi6dg@vV%eM>&4ZP- z6EVxN^A1??bTVnD92ibI(M0-~o&8;0Lo_*>$>@_cWTn!MZEe}Hrzhvc;z#Q7=;t!o zk(4uBXSe}g-aZ^1&c>29@V=}#SUD%_#15hzOS;zG=TOXvLD!JgN8Nhr!qkN@PnzZ^ zDulzXyw%GE_)kOk#%z$I)Let#v^l;8Gjs`h#Pk=aSP|3$^p{OAuLllKI`{&poEL)=F9snPoFe10i2txr0Mm-U|`qou<5d0U3pKj?+% zGoG;>%w!#rKW5=l0c`d7101i(U{ZwIgpTPQ5%a!93XynuZ^Wp{`D-J9v* +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include + +#include "uuidP.h" + +time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) +{ + struct timeval tv; + struct uuid uuid; + uint32_t high; + uint64_t clock_reg; + + uuid_unpack(uu, &uuid); + + high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); + clock_reg = uuid.time_low | ((uint64_t) high << 32); + + clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; + tv.tv_sec = clock_reg / 10000000; + tv.tv_usec = (clock_reg % 10000000) / 10; + + if (ret_tv) + *ret_tv = tv; + + return tv.tv_sec; +} + +int uuid_type(const uuid_t uu) +{ + struct uuid uuid; + + uuid_unpack(uu, &uuid); + return ((uuid.time_hi_and_version >> 12) & 0xF); +} + +int uuid_variant(const uuid_t uu) +{ + struct uuid uuid; + int var; + + uuid_unpack(uu, &uuid); + var = uuid.clock_seq; + + if ((var & 0x8000) == 0) + return UUID_VARIANT_NCS; + if ((var & 0x4000) == 0) + return UUID_VARIANT_DCE; + if ((var & 0x2000) == 0) + return UUID_VARIANT_MICROSOFT; + return UUID_VARIANT_OTHER; +} + +#ifdef DEBUG +static const char *variant_string(int variant) +{ + switch (variant) { + case UUID_VARIANT_NCS: + return "NCS"; + case UUID_VARIANT_DCE: + return "DCE"; + case UUID_VARIANT_MICROSOFT: + return "Microsoft"; + default: + return "Other"; + } +} + + +int +main(int argc, char **argv) +{ + uuid_t buf; + time_t time_reg; + struct timeval tv; + int type, variant; + + if (argc != 2) { + fprintf(stderr, "Usage: %s uuid\n", argv[0]); + exit(1); + } + if (uuid_parse(argv[1], buf)) { + fprintf(stderr, "Invalid UUID: %s\n", argv[1]); + exit(1); + } + variant = uuid_variant(buf); + type = uuid_type(buf); + time_reg = uuid_time(buf, &tv); + + printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); + if (variant != UUID_VARIANT_DCE) { + printf("Warning: This program only knows how to interpret " + "DCE UUIDs.\n\tThe rest of the output is likely " + "to be incorrect!!\n"); + } + printf("UUID type is %d", type); + switch (type) { + case 1: + printf(" (time based)\n"); + break; + case 2: + printf(" (DCE)\n"); + break; + case 3: + printf(" (name-based)\n"); + break; + case 4: + printf(" (random)\n"); + break; + default: + printf("\n"); + } + if (type != 1) { + printf("Warning: not a time-based UUID, so UUID time " + "decoding will likely not work!\n"); + } + printf("UUID time is: (%ld, %ld): %s\n", (long)tv.tv_sec, (long)tv.tv_usec, + ctime(&time_reg)); + + return 0; +} +#endif diff --git a/jni/e2fsprogs/lib/uuid/uuid_time.o b/jni/e2fsprogs/lib/uuid/uuid_time.o new file mode 100755 index 0000000000000000000000000000000000000000..32f40c709318a4691c968058a47bd6ddb84a16c6 GIT binary patch literal 1712 zcmbtUO=uHQ5T4COO=7gAsXtJ4i}uheUE3XI)oJRRK3LD}%z9a@v_Ki^6%_b#t@-oh)T%~bL(C4SB2sCxx(;?e8DBSe{r8@ z?eV(Dmnpd1s|$vY@lo%Z_B69ar3oMn> zgV_qsnCgaLM2+2OpVSf);qh2|Z@=6t_p{G~cbP}HH44J*145fuf(}IXGW-L{p`9as z@BZc&j^|FtYp*oo-w8jygUM4E?|7Bh!+BS{QV*j+C;CE+cfZP0IL{IBN(v`3j-5~u zbi$vColgYECisDgY{u`Ic*AnC$Z1n>TG~hjL&)IToBvE z@ZXGV&H?p(%x=REw~gr}zWxJuA&-ug&+}|Se`D7}RXT8-*A=ngye^OvT11s~ZAu3@ zI3A5^F&&c0@K|6{O@vi6%R#>YmWm;LWNt8H?9+Jr&ogs2+}LETI+(Tu-QI znz_g!2SJ|D6S{g0WhzRtV@&R&S1)u-$vv#X{}WLR7j07H8TioRW8D~G;Pg=mou@1-7M!G{>W|3J)mWuInBx{JNEUb1=4DP+j1G)w5BN!CCMpqji&))*hmI5?lU zj>PbRb6lY)omJ{M=IGoTWX)fxTEN7GF1$0=SIq8JRZS#A$Q3y@z`*Hhf#Lb zsf&SE;zn8+#MAK^#5y?7(@+K9xti%)DZ=x36yRX`v(mn+R-|3VA+A27D^0;&Kz(Jx z2-;TgB@-pxM!{%G;qcUDhZ}e0?%xPWa#k*fpSWnUsvL$>KlG=)ZCgD9;F$dSZR2R) zf{(qf6mT8S6yAHR+A&q~wzl?S2!@SOSh6v(60kMJiXzNipEZU`n| zLBE#&(4T|v_3053=uv#LV%z_TXyezO=*;pn=6=E*Qi4GL$Pl!gX?f2o&g3`p1MpC{ zXyla!>~pm3ci@XP&EVT#C%VuR4Wb`H#^2y~0K@$DdA!y6AHrULnYxX<51U5s^GdrR Yy=ik_1AcHXHLuqG-+O*|Mt1#w06>T@PXGV_ literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/mke2fs/mk_hugefiles.c b/jni/e2fsprogs/mke2fs/mk_hugefiles.c new file mode 100755 index 0000000..3caaf1b --- /dev/null +++ b/jni/e2fsprogs/mke2fs/mk_hugefiles.c @@ -0,0 +1,491 @@ +/* + * mk_hugefiles.c -- create huge files + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#endif +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fsP.h" +#include "et/com_err.h" +#include "uuid/uuid.h" +#include "e2p/e2p.h" +#include "ext2fs/ext2fs.h" +#include "util.h" +#include "support/profile.h" +#include "support/prof_err.h" +#include "support/nls-enable.h" +#include "mke2fs.h" + +static int uid; +static int gid; +static blk64_t num_blocks; +static blk64_t num_slack; +static unsigned long num_files; +static blk64_t goal; +static char *fn_prefix; +static int idx_digits; +static char *fn_buf; +static char *fn_numbuf; +int zero_hugefile = 1; + +static blk64_t +get_partition_start(const char *device_name EXT2FS_ATTR((unused))) +{ +#ifdef __linux__ + unsigned long long start; + char path[128]; + struct stat st; + FILE *f; + int n; + + if ((stat(device_name, &st) < 0) || !S_ISBLK(st.st_mode)) + return 0; + + sprintf(path, "/sys/dev/block/%d:%d/start", + major(st.st_rdev), minor(st.st_rdev)); + f = fopen(path, "r"); + if (!f) + return 0; + n = fscanf(f, "%llu", &start); + fclose(f); + return (n == 1) ? start : 0; +#else + return 0; +#endif +} + +static errcode_t create_directory(ext2_filsys fs, char *dir, + ext2_ino_t *ret_ino) + +{ + struct ext2_inode inode; + ext2_ino_t ino = EXT2_ROOT_INO; + ext2_ino_t newdir; + errcode_t retval = 0; + char *fn, *cp, *next; + + fn = malloc(strlen(dir) + 1); + if (fn == NULL) + return ENOMEM; + + strcpy(fn, dir); + cp = fn; + while(1) { + next = strchr(cp, '/'); + if (next) + *next++ = 0; + if (*cp) { + retval = ext2fs_new_inode(fs, ino, LINUX_S_IFDIR, + NULL, &newdir); + if (retval) + goto errout; + + retval = ext2fs_mkdir(fs, ino, newdir, cp); + if (retval) + goto errout; + + ino = newdir; + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + goto errout; + + inode.i_uid = uid & 0xFFFF; + ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff); + inode.i_gid = gid & 0xFFFF; + ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff); + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) + goto errout; + } + if (next == NULL || *next == '\0') + break; + cp = next; + } +errout: + free(fn); + if (retval == 0) + *ret_ino = ino; + return retval; +} + +static errcode_t mk_hugefile(ext2_filsys fs, blk64_t num, + ext2_ino_t dir, unsigned long idx, ext2_ino_t *ino) + +{ + errcode_t retval; + blk64_t lblk, bend = 0; + __u64 size; + blk64_t left; + blk64_t count = 0; + struct ext2_inode inode; + ext2_extent_handle_t handle; + + retval = ext2fs_new_inode(fs, 0, LINUX_S_IFREG, NULL, ino); + if (retval) + return retval; + + memset(&inode, 0, sizeof(struct ext2_inode)); + inode.i_mode = LINUX_S_IFREG | (0666 & ~fs->umask); + inode.i_links_count = 1; + inode.i_uid = uid & 0xFFFF; + ext2fs_set_i_uid_high(inode, (uid >> 16) & 0xffff); + inode.i_gid = gid & 0xFFFF; + ext2fs_set_i_gid_high(inode, (gid >> 16) & 0xffff); + + retval = ext2fs_write_new_inode(fs, *ino, &inode); + if (retval) + return retval; + + ext2fs_inode_alloc_stats2(fs, *ino, +1, 0); + + retval = ext2fs_extent_open2(fs, *ino, &inode, &handle); + if (retval) + return retval; + + /* + * We don't use ext2fs_fallocate() here because hugefiles are + * designed to be physically contiguous (if the block group + * descriptors are configured to be in a single block at the + * beginning of the file system, by using the + * packed_meta_blocks layout), with the extent tree blocks + * allocated near the beginning of the file system. + */ + lblk = 0; + left = num ? num : 1; + while (left) { + blk64_t pblk, end; + blk64_t n = left; + + retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, + goal, ext2fs_blocks_count(fs->super) - 1, &end); + if (retval) + goto errout; + goal = end; + + retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, goal, + ext2fs_blocks_count(fs->super) - 1, &bend); + if (retval == ENOENT) { + bend = ext2fs_blocks_count(fs->super); + if (num == 0) + left = 0; + } + if (!num || bend - goal < left) + n = bend - goal; + pblk = goal; + if (num) + left -= n; + goal += n; + count += n; + ext2fs_block_alloc_stats_range(fs, pblk, n, +1); + + if (zero_hugefile) { + blk64_t ret_blk; + retval = ext2fs_zero_blocks2(fs, pblk, n, + &ret_blk, NULL); + + if (retval) + com_err(program_name, retval, + _("while zeroing block %llu " + "for hugefile"), + (unsigned long long) ret_blk); + } + + while (n) { + blk64_t l = n; + struct ext2fs_extent newextent; + + if (l > EXT_INIT_MAX_LEN) + l = EXT_INIT_MAX_LEN; + + newextent.e_len = l; + newextent.e_pblk = pblk; + newextent.e_lblk = lblk; + newextent.e_flags = 0; + + retval = ext2fs_extent_insert(handle, + EXT2_EXTENT_INSERT_AFTER, &newextent); + if (retval) + return retval; + pblk += l; + lblk += l; + n -= l; + } + } + + retval = ext2fs_read_inode(fs, *ino, &inode); + if (retval) + goto errout; + + retval = ext2fs_iblk_add_blocks(fs, &inode, + count / EXT2FS_CLUSTER_RATIO(fs)); + if (retval) + goto errout; + size = (__u64) count * fs->blocksize; + retval = ext2fs_inode_size_set(fs, &inode, size); + if (retval) + goto errout; + + retval = ext2fs_write_new_inode(fs, *ino, &inode); + if (retval) + goto errout; + + if (idx_digits) + sprintf(fn_numbuf, "%0*lu", idx_digits, idx); + else if (num_files > 1) + sprintf(fn_numbuf, "%lu", idx); + +retry: + retval = ext2fs_link(fs, dir, fn_buf, *ino, EXT2_FT_REG_FILE); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(fs, dir); + if (retval) + goto errout; + goto retry; + } + + if (retval) + goto errout; + +errout: + if (handle) + ext2fs_extent_free(handle); + + return retval; +} + +static blk64_t calc_overhead(ext2_filsys fs, blk64_t num) +{ + blk64_t e_blocks, e_blocks2, e_blocks3, e_blocks4; + int extents_per_block; + int extents = (num + EXT_INIT_MAX_LEN - 1) / EXT_INIT_MAX_LEN; + + if (extents <= 4) + return 0; + + /* + * This calculation is due to the fact that we are inefficient + * in how handle extent splits when appending to the end of + * the extent tree. Sigh. We should fix this so that we can + * actually store 340 extents per 4k block, instead of only 170. + */ + extents_per_block = ((fs->blocksize - + sizeof(struct ext3_extent_header)) / + sizeof(struct ext3_extent)); + extents_per_block = (extents_per_block/ 2) - 1; + + e_blocks = (extents + extents_per_block - 1) / extents_per_block; + e_blocks2 = (e_blocks + extents_per_block - 1) / extents_per_block; + e_blocks3 = (e_blocks2 + extents_per_block - 1) / extents_per_block; + e_blocks4 = (e_blocks3 + extents_per_block - 1) / extents_per_block; + return (e_blocks + e_blocks2 + e_blocks3 + e_blocks4) * + EXT2FS_CLUSTER_RATIO(fs); +} + +/* + * Find the place where we should start allocating blocks for the huge + * files. Leave free blocks at the beginning of the file + * system for things like metadata blocks. + */ +static blk64_t get_start_block(ext2_filsys fs, blk64_t slack) +{ + errcode_t retval; + blk64_t blk = fs->super->s_first_data_block, next; + blk64_t last_blk = ext2fs_blocks_count(fs->super) - 1; + + while (slack) { + retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, + blk, last_blk, &blk); + if (retval) + break; + + retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, + blk, last_blk, &next); + if (retval) + next = last_blk; + + if (next - blk > slack) { + blk += slack; + break; + } + + slack -= (next - blk); + blk = next; + } + return blk; +} + +static blk64_t round_up_align(blk64_t b, unsigned long align, + blk64_t part_offset) +{ + unsigned long m; + + if (align == 0) + return b; + part_offset = part_offset % align; + m = (b + part_offset) % align; + if (m) + b += align - m; + return b; +} + +errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name) +{ + unsigned long i; + ext2_ino_t dir; + errcode_t retval; + blk64_t fs_blocks, part_offset = 0; + unsigned long align; + int d, dsize; + char *t; + + if (!get_bool_from_profile(fs_types, "make_hugefiles", 0)) + return 0; + + if (!ext2fs_has_feature_extents(fs->super)) + return EXT2_ET_EXTENT_NOT_SUPPORTED; + + uid = get_int_from_profile(fs_types, "hugefiles_uid", 0); + gid = get_int_from_profile(fs_types, "hugefiles_gid", 0); + fs->umask = get_int_from_profile(fs_types, "hugefiles_umask", 077); + num_files = get_int_from_profile(fs_types, "num_hugefiles", 0); + t = get_string_from_profile(fs_types, "hugefiles_slack", "1M"); + num_slack = parse_num_blocks2(t, fs->super->s_log_block_size); + free(t); + t = get_string_from_profile(fs_types, "hugefiles_size", "0"); + num_blocks = parse_num_blocks2(t, fs->super->s_log_block_size); + free(t); + t = get_string_from_profile(fs_types, "hugefiles_align", "0"); + align = parse_num_blocks2(t, fs->super->s_log_block_size); + free(t); + if (get_bool_from_profile(fs_types, "hugefiles_align_disk", 0)) { + part_offset = get_partition_start(device_name) / + (fs->blocksize / 512); + if (part_offset % EXT2FS_CLUSTER_RATIO(fs)) { + fprintf(stderr, + _("Partition offset of %llu (%uk) blocks " + "not compatible with cluster size %u.\n"), + (unsigned long long) part_offset, fs->blocksize, + EXT2_CLUSTER_SIZE(fs->super)); + exit(1); + } + } + num_blocks = round_up_align(num_blocks, align, 0); + zero_hugefile = get_bool_from_profile(fs_types, "zero_hugefiles", + zero_hugefile); + + t = get_string_from_profile(fs_types, "hugefiles_dir", "/"); + retval = create_directory(fs, t, &dir); + free(t); + if (retval) + return retval; + + fn_prefix = get_string_from_profile(fs_types, "hugefiles_name", + "hugefile"); + idx_digits = get_int_from_profile(fs_types, "hugefiles_digits", 5); + d = int_log10(num_files) + 1; + if (idx_digits > d) + d = idx_digits; + dsize = strlen(fn_prefix) + d + 16; + fn_buf = malloc(dsize); + if (!fn_buf) { + free(fn_prefix); + return ENOMEM; + } + strcpy(fn_buf, fn_prefix); + fn_numbuf = fn_buf + strlen(fn_prefix); + free(fn_prefix); + + fs_blocks = ext2fs_free_blocks_count(fs->super); + if (fs_blocks < num_slack + align) + return ENOSPC; + fs_blocks -= num_slack + align; + if (num_blocks && num_blocks > fs_blocks) + return ENOSPC; + if (num_blocks == 0 && num_files == 0) + num_files = 1; + + if (num_files == 0 && num_blocks) { + num_files = fs_blocks / num_blocks; + fs_blocks -= (num_files / 16) + 1; + fs_blocks -= calc_overhead(fs, num_blocks) * num_files; + num_files = fs_blocks / num_blocks; + } + + if (num_blocks == 0 && num_files > 1) { + num_blocks = fs_blocks / num_files; + fs_blocks -= (num_files / 16) + 1; + fs_blocks -= calc_overhead(fs, num_blocks) * num_files; + num_blocks = fs_blocks / num_files; + } + + num_slack += (calc_overhead(fs, num_blocks ? num_blocks : fs_blocks) * + num_files); + num_slack += (num_files / 16) + 1; /* space for dir entries */ + goal = get_start_block(fs, num_slack); + goal = round_up_align(goal, align, part_offset); + + if ((num_blocks ? num_blocks : fs_blocks) > + (0x80000000UL / fs->blocksize)) + ext2fs_set_feature_large_file(fs->super); + + if (!quiet) { + if (zero_hugefile && verbose) + printf("%s", _("Huge files will be zero'ed\n")); + printf(_("Creating %lu huge file(s) "), num_files); + if (num_blocks) + printf(_("with %llu blocks each"), + (unsigned long long) num_blocks); + fputs(": ", stdout); + } + for (i=0; i < num_files; i++) { + ext2_ino_t ino; + + retval = mk_hugefile(fs, num_blocks, dir, i, &ino); + if (retval) { + com_err(program_name, retval, + _("while creating huge file %lu"), i); + goto errout; + } + } + if (!quiet) + fputs(_("done\n"), stdout); + +errout: + free(fn_buf); + return retval; +} diff --git a/jni/e2fsprogs/mke2fs/mk_hugefiles.o b/jni/e2fsprogs/mke2fs/mk_hugefiles.o new file mode 100755 index 0000000000000000000000000000000000000000..120e26e007287765f2519f5a159a5a51b4171d8e GIT binary patch literal 17872 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 I75w)93*(dMuK)l5 literal 0 HcmV?d00001 diff --git a/jni/e2fsprogs/mke2fs/mke2fs.c b/jni/e2fsprogs/mke2fs/mke2fs.c new file mode 100755 index 0000000..c8ed67a --- /dev/null +++ b/jni/e2fsprogs/mke2fs/mke2fs.c @@ -0,0 +1,3518 @@ +/* + * mke2fs.c - Make a ext2fs filesystem. + * + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + * 2003, 2004, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* Usage: mke2fs [options] device + * + * The device may be a block device or a image of one, but this isn't + * enforced (but it's not much fun on a character device :-). + */ + +#define _XOPEN_SOURCE 600 + +#include "config.h" +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#include +#include +#include + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fsP.h" +#include "uuid/uuid.h" +#include "util.h" +#include "support/nls-enable.h" +#include "support/plausible.h" +#include "support/profile.h" +#include "support/prof_err.h" +#include "../version.h" +#include "support/quotaio.h" +#include "mke2fs.h" +#include "create_inode.h" + +#define STRIDE_LENGTH 8 + +#define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1) + +#ifndef __sparc__ +#define ZAP_BOOTBLOCK +#endif + +#define DISCARD_STEP_MB (2048) + +extern int isatty(int); +extern FILE *fpopen(const char *cmd, const char *mode); + +const char * program_name = "mke2fs"; +static const char * device_name /* = NULL */; + +/* Command line options */ +static int cflag; +int verbose; +int quiet; +static int super_only; +static int discard = 1; /* attempt to discard device before fs creation */ +static int direct_io; +static int force; +static int noaction; +static int num_backups = 2; /* number of backup bg's for sparse_super2 */ +static uid_t root_uid; +static gid_t root_gid; +int journal_size; +int journal_flags; +int journal_fc_size; +static int lazy_itable_init; +static int packed_meta_blocks; +int no_copy_xattrs; +static char *bad_blocks_filename = NULL; +static __u32 fs_stride; +/* Initialize usr/grp quotas by default */ +static unsigned int quotatype_bits = (QUOTA_USR_BIT | QUOTA_GRP_BIT); +static __u64 offset; +static blk64_t journal_location = ~0LL; +static int proceed_delay = -1; +static blk64_t dev_size; + +static struct ext2_super_block fs_param; +static __u32 zero_buf[4]; +static char *fs_uuid = NULL; +static char *creator_os; +static char *volume_label; +static char *mount_dir; +char *journal_device; +static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */ +char **fs_types; +const char *src_root_dir; /* Copy files from the specified directory */ +static char *undo_file; + +static int android_sparse_file; /* -E android_sparse */ + +static profile_t profile; + +static int sys_page_size = 4096; + +static int errors_behavior = 0; + +static void usage(void) +{ + fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] " + "[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] " + "[-J journal-options]\n" + "\t[-G flex-group-size] [-N number-of-inodes] " + "[-d root-directory]\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] [-T usage-type ] [-U UUID] [-e errors_behavior]" + "[-z undo_file]\n" + "\t[-jnqvDFSV] device [blocks-count]\n"), + program_name); + exit(1); +} + +static int int_log2(unsigned long long arg) +{ + int l = 0; + + arg >>= 1; + while (arg) { + l++; + arg >>= 1; + } + return l; +} + +int int_log10(unsigned long long arg) +{ + int l; + + for (l=0; arg ; l++) + arg = arg / 10; + return l; +} + +#ifdef __linux__ +static int parse_version_number(const char *s) +{ + int major, minor, rev; + char *endptr; + const char *cp = s; + + if (!s) + return 0; + major = strtol(cp, &endptr, 10); + if (cp == endptr || *endptr != '.') + return 0; + cp = endptr + 1; + minor = strtol(cp, &endptr, 10); + if (cp == endptr || *endptr != '.') + return 0; + cp = endptr + 1; + rev = strtol(cp, &endptr, 10); + if (cp == endptr) + return 0; + return KERNEL_VERSION(major, minor, rev); +} + +static int is_before_linux_ver(unsigned int major, unsigned int minor, + unsigned int rev) +{ + struct utsname ut; + static int linux_version_code = -1; + + if (uname(&ut)) { + perror("uname"); + exit(1); + } + if (linux_version_code < 0) + linux_version_code = parse_version_number(ut.release); + if (linux_version_code == 0) + return 0; + + return linux_version_code < (int) KERNEL_VERSION(major, minor, rev); +} +#else +static int is_before_linux_ver(unsigned int major, unsigned int minor, + unsigned int rev) +{ + return 0; +} +#endif + +/* + * Helper function for read_bb_file and test_disk + */ +static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk) +{ + fprintf(stderr, _("Bad block %u out of range; ignored.\n"), blk); + return; +} + +/* + * Reads the bad blocks list from a file + */ +static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list, + const char *bad_blocks_file) +{ + FILE *f; + errcode_t retval; + + f = fopen(bad_blocks_file, "r"); + if (!f) { + com_err("read_bad_blocks_file", errno, + _("while trying to open %s"), bad_blocks_file); + exit(1); + } + retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); + fclose (f); + if (retval) { + com_err("ext2fs_read_bb_FILE", retval, "%s", + _("while reading in list of bad blocks from file")); + exit(1); + } +} + +/* + * Runs the badblocks program to test the disk + */ +static void test_disk(ext2_filsys fs, badblocks_list *bb_list) +{ + FILE *f; + errcode_t retval; + char buf[1024]; + + sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize, + quiet ? "" : "-s ", (cflag > 1) ? "-w " : "", + fs->device_name, + (unsigned long long) ext2fs_blocks_count(fs->super)-1); + if (verbose) + printf(_("Running command: %s\n"), buf); + f = popen(buf, "r"); + if (!f) { + com_err("popen", errno, + _("while trying to run '%s'"), buf); + exit(1); + } + retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); + pclose(f); + if (retval) { + com_err("ext2fs_read_bb_FILE", retval, "%s", + _("while processing list of bad blocks from program")); + exit(1); + } +} + +static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) +{ + dgrp_t i; + blk_t j; + unsigned must_be_good; + blk_t blk; + badblocks_iterate bb_iter; + errcode_t retval; + blk_t group_block; + int group; + int group_bad; + + if (!bb_list) + return; + + /* + * The primary superblock and group descriptors *must* be + * good; if not, abort. + */ + must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks; + for (i = fs->super->s_first_data_block; i <= must_be_good; i++) { + if (ext2fs_badblocks_list_test(bb_list, i)) { + fprintf(stderr, _("Block %d in primary " + "superblock/group descriptor area bad.\n"), i); + fprintf(stderr, _("Blocks %u through %u must be good " + "in order to build a filesystem.\n"), + fs->super->s_first_data_block, must_be_good); + fputs(_("Aborting....\n"), stderr); + exit(1); + } + } + + /* + * See if any of the bad blocks are showing up in the backup + * superblocks and/or group descriptors. If so, issue a + * warning and adjust the block counts appropriately. + */ + group_block = fs->super->s_first_data_block + + fs->super->s_blocks_per_group; + + for (i = 1; i < fs->group_desc_count; i++) { + group_bad = 0; + for (j=0; j < fs->desc_blocks+1; j++) { + if (ext2fs_badblocks_list_test(bb_list, + group_block + j)) { + if (!group_bad) + fprintf(stderr, +_("Warning: the backup superblock/group descriptors at block %u contain\n" +" bad blocks.\n\n"), + group_block); + group_bad++; + group = ext2fs_group_of_blk2(fs, group_block+j); + ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1); + ext2fs_group_desc_csum_set(fs, group); + ext2fs_free_blocks_count_add(fs->super, 1); + } + } + group_block += fs->super->s_blocks_per_group; + } + + /* + * Mark all the bad blocks as used... + */ + retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); + if (retval) { + com_err("ext2fs_badblocks_list_iterate_begin", retval, "%s", + _("while marking bad blocks as used")); + exit(1); + } + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) + ext2fs_mark_block_bitmap2(fs->block_map, blk); + ext2fs_badblocks_list_iterate_end(bb_iter); +} + +static void write_reserved_inodes(ext2_filsys fs) +{ + errcode_t retval; + ext2_ino_t ino; + struct ext2_inode *inode; + + retval = ext2fs_get_memzero(EXT2_INODE_SIZE(fs->super), &inode); + if (retval) { + com_err("inode_init", retval, _("while allocating memory")); + exit(1); + } + + for (ino = 1; ino < EXT2_FIRST_INO(fs->super); ino++) { + retval = ext2fs_write_inode_full(fs, ino, inode, + EXT2_INODE_SIZE(fs->super)); + if (retval) { + com_err("ext2fs_write_inode_full", retval, + _("while writing reserved inodes")); + exit(1); + } + } + + ext2fs_free_mem(&inode); +} + +static errcode_t packed_allocate_tables(ext2_filsys fs) +{ + errcode_t retval; + dgrp_t i; + blk64_t goal = 0; + + for (i = 0; i < fs->group_desc_count; i++) { + retval = ext2fs_new_block2(fs, goal, NULL, &goal); + if (retval) + return retval; + ext2fs_block_alloc_stats2(fs, goal, +1); + ext2fs_block_bitmap_loc_set(fs, i, goal); + } + for (i = 0; i < fs->group_desc_count; i++) { + retval = ext2fs_new_block2(fs, goal, NULL, &goal); + if (retval) + return retval; + ext2fs_block_alloc_stats2(fs, goal, +1); + ext2fs_inode_bitmap_loc_set(fs, i, goal); + } + for (i = 0; i < fs->group_desc_count; i++) { + blk64_t end = ext2fs_blocks_count(fs->super) - 1; + retval = ext2fs_get_free_blocks2(fs, goal, end, + fs->inode_blocks_per_group, + fs->block_map, &goal); + if (retval) + return retval; + ext2fs_block_alloc_stats_range(fs, goal, + fs->inode_blocks_per_group, +1); + ext2fs_inode_table_loc_set(fs, i, goal); + ext2fs_group_desc_csum_set(fs, i); + } + return 0; +} + +static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed) +{ + errcode_t retval; + blk64_t blk; + dgrp_t i; + int num; + struct ext2fs_numeric_progress_struct progress; + + ext2fs_numeric_progress_init(fs, &progress, + _("Writing inode tables: "), + fs->group_desc_count); + + for (i = 0; i < fs->group_desc_count; i++) { + ext2fs_numeric_progress_update(fs, &progress, i); + + blk = ext2fs_inode_table_loc(fs, i); + num = fs->inode_blocks_per_group; + + if (lazy_flag) + num = ext2fs_div_ceil((fs->super->s_inodes_per_group - + ext2fs_bg_itable_unused(fs, i)) * + EXT2_INODE_SIZE(fs->super), + EXT2_BLOCK_SIZE(fs->super)); + if (!lazy_flag || itable_zeroed) { + /* The kernel doesn't need to zero the itable blocks */ + ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED); + ext2fs_group_desc_csum_set(fs, i); + } + if (!itable_zeroed) { + retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num); + if (retval) { + fprintf(stderr, _("\nCould not write %d " + "blocks in inode table starting at %llu: %s\n"), + num, (unsigned long long) blk, + error_message(retval)); + exit(1); + } + } + if (sync_kludge) { + if (sync_kludge == 1) + io_channel_flush(fs->io); + else if ((i % sync_kludge) == 0) + io_channel_flush(fs->io); + } + } + ext2fs_numeric_progress_close(fs, &progress, + _("done \n")); + + /* Reserved inodes must always have correct checksums */ + if (ext2fs_has_feature_metadata_csum(fs->super)) + write_reserved_inodes(fs); +} + +static void create_root_dir(ext2_filsys fs) +{ + errcode_t retval; + struct ext2_inode inode; + + retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0); + if (retval) { + com_err("ext2fs_mkdir", retval, "%s", + _("while creating root dir")); + exit(1); + } + if (root_uid != 0 || root_gid != 0) { + retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode); + if (retval) { + com_err("ext2fs_read_inode", retval, "%s", + _("while reading root inode")); + exit(1); + } + + inode.i_uid = root_uid; + ext2fs_set_i_uid_high(inode, root_uid >> 16); + inode.i_gid = root_gid; + ext2fs_set_i_gid_high(inode, root_gid >> 16); + + retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); + if (retval) { + com_err("ext2fs_write_inode", retval, "%s", + _("while setting root inode ownership")); + exit(1); + } + } +} + +static void create_lost_and_found(ext2_filsys fs) +{ + unsigned int lpf_size = 0; + errcode_t retval; + ext2_ino_t ino; + const char *name = "lost+found"; + int i; + + fs->umask = 077; + retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name); + if (retval) { + com_err("ext2fs_mkdir", retval, "%s", + _("while creating /lost+found")); + exit(1); + } + + retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino); + if (retval) { + com_err("ext2_lookup", retval, "%s", + _("while looking up /lost+found")); + exit(1); + } + + for (i=1; i < EXT2_NDIR_BLOCKS; i++) { + /* Ensure that lost+found is at least 2 blocks, so we always + * test large empty blocks for big-block filesystems. */ + if ((lpf_size += fs->blocksize) >= 16*1024 && + lpf_size >= 2 * fs->blocksize) + break; + retval = ext2fs_expand_dir(fs, ino); + if (retval) { + com_err("ext2fs_expand_dir", retval, "%s", + _("while expanding /lost+found")); + exit(1); + } + } +} + +static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list) +{ + errcode_t retval; + + ext2fs_mark_inode_bitmap2(fs->inode_map, EXT2_BAD_INO); + ext2fs_inode_alloc_stats2(fs, EXT2_BAD_INO, +1, 0); + retval = ext2fs_update_bb_inode(fs, bb_list); + if (retval) { + com_err("ext2fs_update_bb_inode", retval, "%s", + _("while setting bad block inode")); + exit(1); + } + +} + +static void reserve_inodes(ext2_filsys fs) +{ + ext2_ino_t i; + + for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) + ext2fs_inode_alloc_stats2(fs, i, +1, 0); + ext2fs_mark_ib_dirty(fs); +} + +#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */ +#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */ +#define BSD_LABEL_OFFSET 64 + +static void zap_sector(ext2_filsys fs, int sect, int nsect) +{ + char *buf; + int retval; + unsigned int *magic; + + buf = calloc(512, nsect); + if (!buf) { + printf(_("Out of memory erasing sectors %d-%d\n"), + sect, sect + nsect - 1); + exit(1); + } + + if (sect == 0) { + /* Check for a BSD disklabel, and don't erase it if so */ + retval = io_channel_read_blk64(fs->io, 0, -512, buf); + if (retval) + fprintf(stderr, + _("Warning: could not read block 0: %s\n"), + error_message(retval)); + else { + magic = (unsigned int *) (buf + BSD_LABEL_OFFSET); + if ((*magic == BSD_DISKMAGIC) || + (*magic == BSD_MAGICDISK)) { + free(buf); + return; + } + } + } + + memset(buf, 0, 512*nsect); + io_channel_set_blksize(fs->io, 512); + retval = io_channel_write_blk64(fs->io, sect, -512*nsect, buf); + io_channel_set_blksize(fs->io, fs->blocksize); + free(buf); + if (retval) + fprintf(stderr, _("Warning: could not erase sector %d: %s\n"), + sect, error_message(retval)); +} + +static void create_journal_dev(ext2_filsys fs) +{ + struct ext2fs_numeric_progress_struct progress; + errcode_t retval; + char *buf; + blk64_t blk, err_blk; + int c, count, err_count; + struct ext2fs_journal_params jparams; + + retval = ext2fs_get_journal_params(&jparams, fs); + if (retval) { + com_err("create_journal_dev", retval, "%s", + _("while splitting the journal size")); + exit(1); + } + + retval = ext2fs_create_journal_superblock2(fs, &jparams, 0, &buf); + if (retval) { + com_err("create_journal_dev", retval, "%s", + _("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)); + blk = 0; + count = ext2fs_blocks_count(fs->super); + while (count > 0) { + if (count > 1024) + c = 1024; + else + c = count; + retval = ext2fs_zero_blocks2(fs, blk, c, &err_blk, &err_count); + if (retval) { + com_err("create_journal_dev", retval, + _("while zeroing journal device " + "(block %llu, count %d)"), + (unsigned long long) err_blk, err_count); + exit(1); + } + blk += c; + count -= c; + ext2fs_numeric_progress_update(fs, &progress, blk); + } + + 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); + (void) ext2fs_free_mem(&buf); + if (retval) { + com_err("create_journal_dev", retval, "%s", + _("while writing journal superblock")); + exit(1); + } +} + +static void show_stats(ext2_filsys fs) +{ + struct ext2_super_block *s = fs->super; + char *os; + blk64_t group_block; + dgrp_t i; + int need, col_left; + + if (!verbose) { + printf(_("Creating filesystem with %llu %dk blocks and " + "%u inodes\n"), + (unsigned long long) ext2fs_blocks_count(s), + fs->blocksize >> 10, s->s_inodes_count); + goto skip_details; + } + + if (ext2fs_blocks_count(&fs_param) != ext2fs_blocks_count(s)) + fprintf(stderr, _("warning: %llu blocks unused.\n\n"), + (unsigned long long) (ext2fs_blocks_count(&fs_param) - + ext2fs_blocks_count(s))); + + printf(_("Filesystem label=%.*s\n"), EXT2_LEN_STR(s->s_volume_name)); + + os = e2p_os2string(fs->super->s_creator_os); + if (os) + printf(_("OS type: %s\n"), os); + free(os); + printf(_("Block size=%u (log=%u)\n"), fs->blocksize, + s->s_log_block_size); + if (ext2fs_has_feature_bigalloc(fs->super)) + printf(_("Cluster size=%u (log=%u)\n"), + fs->blocksize << fs->cluster_ratio_bits, + s->s_log_cluster_size); + else + printf(_("Fragment size=%u (log=%u)\n"), EXT2_CLUSTER_SIZE(s), + s->s_log_cluster_size); + printf(_("Stride=%u blocks, Stripe width=%u blocks\n"), + s->s_raid_stride, s->s_raid_stripe_width); + printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count, + (unsigned long long) ext2fs_blocks_count(s)); + printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"), + (unsigned long long) ext2fs_r_blocks_count(s), + 100.0 * ext2fs_r_blocks_count(s) / ext2fs_blocks_count(s)); + printf(_("First data block=%u\n"), s->s_first_data_block); + if (root_uid != 0 || root_gid != 0) + printf(_("Root directory owner=%u:%u\n"), root_uid, root_gid); + if (s->s_reserved_gdt_blocks) + printf(_("Maximum filesystem blocks=%lu\n"), + (s->s_reserved_gdt_blocks + fs->desc_blocks) * + EXT2_DESC_PER_BLOCK(s) * s->s_blocks_per_group); + if (fs->group_desc_count > 1) + printf(_("%u block groups\n"), fs->group_desc_count); + else + printf(_("%u block group\n"), fs->group_desc_count); + if (ext2fs_has_feature_bigalloc(fs->super)) + printf(_("%u blocks per group, %u clusters per group\n"), + s->s_blocks_per_group, s->s_clusters_per_group); + else + printf(_("%u blocks per group, %u fragments per group\n"), + s->s_blocks_per_group, s->s_clusters_per_group); + printf(_("%u inodes per group\n"), s->s_inodes_per_group); + +skip_details: + if (fs->group_desc_count == 1) { + printf("\n"); + return; + } + + if (!e2p_is_null_uuid(s->s_uuid)) + printf(_("Filesystem UUID: %s\n"), e2p_uuid2str(s->s_uuid)); + printf("%s", _("Superblock backups stored on blocks: ")); + group_block = s->s_first_data_block; + col_left = 0; + for (i = 1; i < fs->group_desc_count; i++) { + group_block += s->s_blocks_per_group; + if (!ext2fs_bg_has_super(fs, i)) + continue; + if (i != 1) + printf(", "); + need = int_log10(group_block) + 2; + if (need > col_left) { + printf("\n\t"); + col_left = 72; + } + col_left -= need; + printf("%llu", (unsigned long long) group_block); + } + printf("\n\n"); +} + +/* + * Returns true if making a file system for the Hurd, else 0 + */ +static int for_hurd(const char *os) +{ + if (!os) { +#ifdef __GNU__ + return 1; +#else + return 0; +#endif + } + if (isdigit(*os)) + return (atoi(os) == EXT2_OS_HURD); + return (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0); +} + +/* + * Set the S_CREATOR_OS field. Return true if OS is known, + * otherwise, 0. + */ +static int set_os(struct ext2_super_block *sb, char *os) +{ + if (isdigit (*os)) + sb->s_creator_os = atoi (os); + else if (strcasecmp(os, "linux") == 0) + sb->s_creator_os = EXT2_OS_LINUX; + else if (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0) + sb->s_creator_os = EXT2_OS_HURD; + else if (strcasecmp(os, "freebsd") == 0) + sb->s_creator_os = EXT2_OS_FREEBSD; + else if (strcasecmp(os, "lites") == 0) + sb->s_creator_os = EXT2_OS_LITES; + else + return 0; + return 1; +} + +#define PATH_SET "PATH=/sbin" + +static void parse_extended_opts(struct ext2_super_block *param, + const char *opts) +{ + char *buf, *token, *next, *p, *arg, *badopt = 0; + int len; + int r_usage = 0; + int ret; + int encoding = -1; + char *encoding_flags = NULL; + + len = strlen(opts); + buf = malloc(len+1); + if (!buf) { + fprintf(stderr, "%s", + _("Couldn't allocate memory to parse options!\n")); + exit(1); + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p+1; + } + arg = strchr(token, '='); + if (arg) { + *arg = 0; + arg++; + } + if (strcmp(token, "desc-size") == 0 || + strcmp(token, "desc_size") == 0) { + int desc_size; + + if (!ext2fs_has_feature_64bit(&fs_param)) { + fprintf(stderr, + _("%s requires '-O 64bit'\n"), token); + r_usage++; + continue; + } + if (param->s_reserved_gdt_blocks != 0) { + fprintf(stderr, + _("'%s' must be before 'resize=%u'\n"), + token, param->s_reserved_gdt_blocks); + r_usage++; + continue; + } + if (!arg) { + r_usage++; + badopt = token; + continue; + } + desc_size = strtoul(arg, &p, 0); + if (*p || (desc_size & (desc_size - 1))) { + fprintf(stderr, + _("Invalid desc_size: '%s'\n"), arg); + r_usage++; + continue; + } + param->s_desc_size = desc_size; + } else if (strcmp(token, "hash_seed") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + if (uuid_parse(arg, + (unsigned char *)param->s_hash_seed) != 0) { + fprintf(stderr, + _("Invalid hash seed: %s\n"), arg); + r_usage++; + continue; + } + } else if (strcmp(token, "offset") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + offset = strtoull(arg, &p, 0); + if (*p) { + fprintf(stderr, _("Invalid offset: %s\n"), + arg); + r_usage++; + continue; + } + } else if (strcmp(token, "mmp_update_interval") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + param->s_mmp_update_interval = strtoul(arg, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid mmp_update_interval: %s\n"), + arg); + r_usage++; + continue; + } + } else if (strcmp(token, "no_copy_xattrs") == 0) { + no_copy_xattrs = 1; + continue; + } else if (strcmp(token, "num_backup_sb") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + num_backups = strtoul(arg, &p, 0); + if (*p || num_backups > 2) { + fprintf(stderr, + _("Invalid # of backup " + "superblocks: %s\n"), + arg); + r_usage++; + continue; + } + } else if (strcmp(token, "packed_meta_blocks") == 0) { + if (arg) + packed_meta_blocks = strtoul(arg, &p, 0); + else + packed_meta_blocks = 1; + if (packed_meta_blocks) + journal_location = 0; + } else if (strcmp(token, "stride") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + param->s_raid_stride = strtoul(arg, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid stride parameter: %s\n"), + arg); + r_usage++; + continue; + } + } else if (strcmp(token, "stripe-width") == 0 || + strcmp(token, "stripe_width") == 0) { + if (!arg) { + r_usage++; + badopt = token; + continue; + } + param->s_raid_stripe_width = strtoul(arg, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid stripe-width parameter: %s\n"), + arg); + r_usage++; + continue; + } + } else if (!strcmp(token, "resize")) { + blk64_t resize; + unsigned long bpg, rsv_groups; + unsigned long group_desc_count, desc_blocks; + unsigned int gdpb, blocksize; + int rsv_gdb; + + if (!arg) { + r_usage++; + badopt = token; + continue; + } + + resize = parse_num_blocks2(arg, + param->s_log_block_size); + + if (resize == 0) { + fprintf(stderr, + _("Invalid resize parameter: %s\n"), + arg); + r_usage++; + continue; + } + if (resize <= ext2fs_blocks_count(param)) { + fprintf(stderr, "%s", + _("The resize maximum must be greater " + "than the filesystem size.\n")); + r_usage++; + continue; + } + + blocksize = EXT2_BLOCK_SIZE(param); + bpg = param->s_blocks_per_group; + if (!bpg) + bpg = blocksize * 8; + gdpb = EXT2_DESC_PER_BLOCK(param); + group_desc_count = (__u32) ext2fs_div64_ceil( + ext2fs_blocks_count(param), bpg); + desc_blocks = (group_desc_count + + gdpb - 1) / gdpb; + rsv_groups = ext2fs_div64_ceil(resize, bpg); + rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - + desc_blocks; + if (rsv_gdb > (int) EXT2_ADDR_PER_BLOCK(param)) + rsv_gdb = EXT2_ADDR_PER_BLOCK(param); + + if (rsv_gdb > 0) { + if (param->s_rev_level == EXT2_GOOD_OLD_REV) { + fprintf(stderr, "%s", + _("On-line resizing not supported with revision 0 filesystems\n")); + free(buf); + exit(1); + } + ext2fs_set_feature_resize_inode(param); + + param->s_reserved_gdt_blocks = rsv_gdb; + } + } else if (!strcmp(token, "test_fs")) { + param->s_flags |= EXT2_FLAGS_TEST_FILESYS; + } else if (!strcmp(token, "lazy_itable_init")) { + if (arg) + lazy_itable_init = strtoul(arg, &p, 0); + else + lazy_itable_init = 1; + } 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, "root_owner")) { + if (arg) { + root_uid = strtoul(arg, &p, 0); + if (*p != ':') { + fprintf(stderr, + _("Invalid root_owner: '%s'\n"), + arg); + r_usage++; + continue; + } + p++; + root_gid = strtoul(p, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid root_owner: '%s'\n"), + arg); + r_usage++; + continue; + } + } else { + root_uid = getuid(); + root_gid = getgid(); + } + } else if (!strcmp(token, "discard")) { + discard = 1; + } else if (!strcmp(token, "nodiscard")) { + discard = 0; + } else if (!strcmp(token, "quotatype")) { + char *errtok = NULL; + + if (!arg) { + r_usage++; + badopt = token; + continue; + } + quotatype_bits = 0; + ret = parse_quota_types(arg, "atype_bits, &errtok); + if (ret) { + if (errtok) { + fprintf(stderr, + "Failed to parse quota type at %s", errtok); + free(errtok); + } else + com_err(program_name, ret, + "while parsing quota type"); + r_usage++; + badopt = token; + continue; + } + } else if (!strcmp(token, "android_sparse")) { + android_sparse_file = 1; + } else if (!strcmp(token, "encoding")) { + if (!arg) { + r_usage++; + continue; + } + + encoding = e2p_str2encoding(arg); + if (encoding < 0) { + fprintf(stderr, _("Invalid encoding: %s"), arg); + r_usage++; + continue; + } + param->s_encoding = encoding; + ext2fs_set_feature_casefold(param); + } else if (!strcmp(token, "encoding_flags")) { + if (!arg) { + r_usage++; + continue; + } + encoding_flags = arg; + } else { + r_usage++; + badopt = token; + } + } + if (r_usage) { + fprintf(stderr, _("\nBad 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" + "\tmmp_update_interval=\n" + "\tnum_backup_sb=<0|1|2>\n" + "\tstride=\n" + "\tstripe-width=\n" + "\toffset=\n" + "\tresize=\n" + "\tpacked_meta_blocks=<0 to disable, 1 to enable>\n" + "\tlazy_itable_init=<0 to disable, 1 to enable>\n" + "\tlazy_journal_init=<0 to disable, 1 to enable>\n" + "\troot_owner=:\n" + "\ttest_fs\n" + "\tdiscard\n" + "\tnodiscard\n" + "\tencoding=\n" + "\tencoding_flags=\n" + "\tquotatype=\n\n"), + badopt ? badopt : ""); + free(buf); + exit(1); + } + if (param->s_raid_stride && + (param->s_raid_stripe_width % param->s_raid_stride) != 0) + fprintf(stderr, _("\nWarning: RAID stripe-width %u not an even " + "multiple of stride %u.\n\n"), + param->s_raid_stripe_width, param->s_raid_stride); + + if (ext2fs_has_feature_casefold(param)) { + param->s_encoding_flags = + e2p_get_encoding_flags(param->s_encoding); + + if (encoding_flags && + e2p_str2encoding_flags(param->s_encoding, encoding_flags, + ¶m->s_encoding_flags)) { + fprintf(stderr, _("error: Invalid encoding flag: %s\n"), + encoding_flags); + free(buf); + exit(1); + } + } else if (encoding_flags) { + fprintf(stderr, _("error: An encoding must be explicitly " + "specified when passing encoding-flags\n")); + free(buf); + exit(1); + } + + free(buf); +} + +static __u32 ok_features[3] = { + /* Compat */ + EXT3_FEATURE_COMPAT_HAS_JOURNAL | + EXT2_FEATURE_COMPAT_RESIZE_INODE | + EXT2_FEATURE_COMPAT_DIR_INDEX | + EXT2_FEATURE_COMPAT_EXT_ATTR | + EXT4_FEATURE_COMPAT_SPARSE_SUPER2 | + EXT4_FEATURE_COMPAT_FAST_COMMIT | + EXT4_FEATURE_COMPAT_STABLE_INODES, + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE| + EXT3_FEATURE_INCOMPAT_EXTENTS| + 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| + EXT4_FEATURE_INCOMPAT_INLINE_DATA| + EXT4_FEATURE_INCOMPAT_ENCRYPT | + EXT4_FEATURE_INCOMPAT_CASEFOLD | + EXT4_FEATURE_INCOMPAT_CSUM_SEED | + EXT4_FEATURE_INCOMPAT_LARGEDIR, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| + EXT4_FEATURE_RO_COMPAT_HUGE_FILE| + EXT4_FEATURE_RO_COMPAT_DIR_NLINK| + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| + EXT4_FEATURE_RO_COMPAT_GDT_CSUM| + EXT4_FEATURE_RO_COMPAT_BIGALLOC| + EXT4_FEATURE_RO_COMPAT_QUOTA| + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM| + EXT4_FEATURE_RO_COMPAT_PROJECT| + EXT4_FEATURE_RO_COMPAT_VERITY +}; + + +static void syntax_err_report(const char *filename, long err, int line_num) +{ + fprintf(stderr, + _("Syntax error in mke2fs config file (%s, line #%d)\n\t%s\n"), + filename, line_num, error_message(err)); + exit(1); +} + +static const char *config_fn[] = { ROOT_SYSCONFDIR "/mke2fs.conf", 0 }; + +static void edit_feature(const char *str, __u32 *compat_array) +{ + if (!str) + return; + + if (e2p_edit_feature(str, compat_array, ok_features)) { + fprintf(stderr, _("Invalid filesystem option set: %s\n"), + str); + exit(1); + } +} + +static void edit_mntopts(const char *str, __u32 *mntopts) +{ + if (!str) + return; + + if (e2p_edit_mntopts(str, mntopts, ~0)) { + fprintf(stderr, _("Invalid mount option set: %s\n"), + str); + exit(1); + } +} + +struct str_list { + char **list; + int num; + int max; +}; + +static errcode_t init_list(struct str_list *sl) +{ + sl->num = 0; + sl->max = 1; + sl->list = malloc((sl->max+1) * sizeof(char *)); + if (!sl->list) + return ENOMEM; + sl->list[0] = 0; + return 0; +} + +static errcode_t push_string(struct str_list *sl, const char *str) +{ + char **new_list; + + if (sl->num >= sl->max) { + sl->max += 2; + new_list = realloc(sl->list, (sl->max+1) * sizeof(char *)); + if (!new_list) + return ENOMEM; + sl->list = new_list; + } + sl->list[sl->num] = malloc(strlen(str)+1); + if (sl->list[sl->num] == 0) + return ENOMEM; + strcpy(sl->list[sl->num], str); + sl->num++; + sl->list[sl->num] = 0; + return 0; +} + +static void print_str_list(char **list) +{ + char **cpp; + + for (cpp = list; *cpp; cpp++) { + printf("'%s'", *cpp); + if (cpp[1]) + fputs(", ", stdout); + } + fputc('\n', stdout); +} + +/* + * Return TRUE if the profile has the given subsection + */ +static int profile_has_subsection(profile_t prof, const char *section, + const char *subsection) +{ + void *state; + const char *names[4]; + char *name; + int ret = 0; + + names[0] = section; + names[1] = subsection; + names[2] = 0; + + if (profile_iterator_create(prof, names, + PROFILE_ITER_LIST_SECTION | + PROFILE_ITER_RELATIONS_ONLY, &state)) + return 0; + + if ((profile_iterator(&state, &name, 0) == 0) && name) { + free(name); + ret = 1; + } + + profile_iterator_free(&state); + return ret; +} + +static char **parse_fs_type(const char *fs_type, + const char *usage_types, + struct ext2_super_block *sb, + blk64_t fs_blocks_count, + char *progname) +{ + const char *ext_type = 0; + char *parse_str; + char *profile_type = 0; + char *cp, *t; + const char *size_type; + struct str_list list; + unsigned long long meg; + int is_hurd = for_hurd(creator_os); + + if (init_list(&list)) + return 0; + + if (fs_type) + ext_type = fs_type; + else if (is_hurd) + ext_type = "ext2"; + else if (!strcmp(program_name, "mke3fs")) + ext_type = "ext3"; + else if (!strcmp(program_name, "mke4fs")) + ext_type = "ext4"; + else if (progname) { + ext_type = strrchr(progname, '/'); + if (ext_type) + ext_type++; + else + ext_type = progname; + + if (!strncmp(ext_type, "mkfs.", 5)) { + ext_type += 5; + if (ext_type[0] == 0) + ext_type = 0; + } else + ext_type = 0; + } + + if (!ext_type) { + profile_get_string(profile, "defaults", "fs_type", 0, + "ext2", &profile_type); + ext_type = profile_type; + if (!strcmp(ext_type, "ext2") && (journal_size != 0)) + ext_type = "ext3"; + } + + + if (!profile_has_subsection(profile, "fs_types", ext_type) && + strcmp(ext_type, "ext2")) { + printf(_("\nYour mke2fs.conf file does not define the " + "%s filesystem type.\n"), ext_type); + if (!strcmp(ext_type, "ext3") || !strcmp(ext_type, "ext4") || + !strcmp(ext_type, "ext4dev")) { + printf("%s", _("You probably need to install an " + "updated mke2fs.conf file.\n\n")); + } + if (!force) { + printf("%s", _("Aborting...\n")); + exit(1); + } + } + + meg = (1024 * 1024) / EXT2_BLOCK_SIZE(sb); + if (fs_blocks_count < 3 * meg) + size_type = "floppy"; + else if (fs_blocks_count < 512 * meg) + size_type = "small"; + else if (fs_blocks_count < 4 * 1024 * 1024 * meg) + size_type = "default"; + else if (fs_blocks_count < 16 * 1024 * 1024 * meg) + size_type = "big"; + else + size_type = "huge"; + + if (!usage_types) + usage_types = size_type; + + parse_str = malloc(strlen(usage_types)+1); + if (!parse_str) { + free(profile_type); + free(list.list); + return 0; + } + strcpy(parse_str, usage_types); + + if (ext_type) + push_string(&list, ext_type); + cp = parse_str; + while (1) { + t = strchr(cp, ','); + if (t) + *t = '\0'; + + if (*cp) { + if (profile_has_subsection(profile, "fs_types", cp)) + push_string(&list, cp); + else if (strcmp(cp, "default") != 0) + fprintf(stderr, + _("\nWarning: the fs_type %s is not " + "defined in mke2fs.conf\n\n"), + cp); + } + if (t) + cp = t+1; + else + break; + } + free(parse_str); + free(profile_type); + if (is_hurd) + push_string(&list, "hurd"); + return (list.list); +} + +char *get_string_from_profile(char **types, const char *opt, + const char *def_val) +{ + char *ret = 0; + int i; + + for (i=0; types[i]; i++); + for (i-=1; i >=0 ; i--) { + profile_get_string(profile, "fs_types", types[i], + opt, 0, &ret); + if (ret) + return ret; + } + profile_get_string(profile, "defaults", opt, 0, def_val, &ret); + return (ret); +} + +int get_int_from_profile(char **types, const char *opt, int def_val) +{ + int ret; + char **cpp; + + profile_get_integer(profile, "defaults", opt, 0, def_val, &ret); + for (cpp = types; *cpp; cpp++) + profile_get_integer(profile, "fs_types", *cpp, opt, ret, &ret); + return ret; +} + +static unsigned int get_uint_from_profile(char **types, const char *opt, + unsigned int def_val) +{ + unsigned int ret; + char **cpp; + + profile_get_uint(profile, "defaults", opt, 0, def_val, &ret); + for (cpp = types; *cpp; cpp++) + profile_get_uint(profile, "fs_types", *cpp, opt, ret, &ret); + return ret; +} + +static double get_double_from_profile(char **types, const char *opt, + double def_val) +{ + double ret; + char **cpp; + + profile_get_double(profile, "defaults", opt, 0, def_val, &ret); + for (cpp = types; *cpp; cpp++) + profile_get_double(profile, "fs_types", *cpp, opt, ret, &ret); + return ret; +} + +int get_bool_from_profile(char **types, const char *opt, int def_val) +{ + int ret; + char **cpp; + + profile_get_boolean(profile, "defaults", opt, 0, def_val, &ret); + for (cpp = types; *cpp; cpp++) + profile_get_boolean(profile, "fs_types", *cpp, opt, ret, &ret); + return ret; +} + +extern const char *mke2fs_default_profile; +static const char *default_files[] = { "", 0 }; + +struct device_param { + unsigned long min_io; /* preferred minimum IO size */ + unsigned long opt_io; /* optimal IO size */ + unsigned long alignment_offset; /* alignment offset wrt physical block size */ + unsigned int dax:1; /* supports dax? */ +}; + +#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY +/* + * Sets the geometry of a device (stripe/stride), and returns the + * device's alignment offset, if any, or a negative error. + */ +static int get_device_geometry(const char *file, + unsigned int blocksize, + unsigned int psector_size, + struct device_param *dev_param) +{ + int rc = -1; + blkid_probe pr; + blkid_topology tp; + struct stat statbuf; + + memset(dev_param, 0, sizeof(*dev_param)); + + /* Nothing to do for a regular file */ + if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode)) + return 0; + + pr = blkid_new_probe_from_filename(file); + if (!pr) + goto out; + + tp = blkid_probe_get_topology(pr); + if (!tp) + goto out; + + dev_param->min_io = blkid_topology_get_minimum_io_size(tp); + dev_param->opt_io = blkid_topology_get_optimal_io_size(tp); + if ((dev_param->min_io == 0) && (psector_size > blocksize)) + dev_param->min_io = psector_size; + if ((dev_param->opt_io == 0) && dev_param->min_io > 0) + dev_param->opt_io = dev_param->min_io; + if ((dev_param->opt_io == 0) && (psector_size > blocksize)) + dev_param->opt_io = psector_size; + + dev_param->alignment_offset = blkid_topology_get_alignment_offset(tp); +#ifdef HAVE_BLKID_TOPOLOGY_GET_DAX + dev_param->dax = blkid_topology_get_dax(tp); +#endif + rc = 0; +out: + blkid_free_probe(pr); + return rc; +} +#endif + +static void PRS(int argc, char *argv[]) +{ + int b, c, flags; + int cluster_size = 0; + char *tmp, **cpp; + int explicit_fssize = 0; + int blocksize = 0; + int inode_ratio = 0; + int inode_size = 0; + unsigned long flex_bg_size = 0; + double reserved_ratio = -1.0; + int lsector_size = 0, psector_size = 0; + int show_version_only = 0, is_device = 0; + unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */ + errcode_t retval; + char * oldpath = getenv("PATH"); + char * extended_opts = 0; + char * fs_type = 0; + char * usage_types = 0; + /* + * NOTE: A few words about fs_blocks_count and blocksize: + * + * Initially, blocksize is set to zero, which implies 1024. + * If -b is specified, blocksize is updated to the user's value. + * + * Next, the device size or the user's "blocks" command line argument + * is used to set fs_blocks_count; the units are blocksize. + * + * Later, if blocksize hasn't been set and the profile specifies a + * blocksize, then blocksize is updated and fs_blocks_count is scaled + * appropriately. Note the change in units! + * + * Finally, we complain about fs_blocks_count > 2^32 on a non-64bit fs. + */ + blk64_t fs_blocks_count = 0; + int s_opt = -1, r_opt = -1; + char *fs_features = 0; + int fs_features_size = 0; + int use_bsize; + char *newpath; + int pathlen = sizeof(PATH_SET) + 1; +#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY + struct device_param dev_param; +#endif + + if (oldpath) + pathlen += strlen(oldpath); + newpath = malloc(pathlen); + if (!newpath) { + fprintf(stderr, "%s", + _("Couldn't allocate memory for new PATH.\n")); + exit(1); + } + strcpy(newpath, PATH_SET); + + /* Update our PATH to include /sbin */ + if (oldpath) { + strcat (newpath, ":"); + strcat (newpath, oldpath); + } + putenv (newpath); + + /* Determine the system page size if possible */ +#ifdef HAVE_SYSCONF +#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif +#ifdef _SC_PAGESIZE + { + long sysval = sysconf(_SC_PAGESIZE); + + if (sysval > 0) + sys_page_size = sysval; + } +#endif /* _SC_PAGESIZE */ +#endif /* HAVE_SYSCONF */ + + if ((tmp = getenv("MKE2FS_CONFIG")) != NULL) + config_fn[0] = tmp; + profile_set_syntax_err_cb(syntax_err_report); + retval = profile_init(config_fn, &profile); + if (retval == ENOENT) { + retval = profile_init(default_files, &profile); + if (retval) + goto profile_error; + retval = profile_set_default(profile, mke2fs_default_profile); + if (retval) + goto profile_error; + } else if (retval) { +profile_error: + fprintf(stderr, _("Couldn't init profile successfully" + " (error: %ld).\n"), retval); + exit(1); + } + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + add_error_table(&et_ext2_error_table); + add_error_table(&et_prof_error_table); + memset(&fs_param, 0, sizeof(struct ext2_super_block)); + fs_param.s_rev_level = 1; /* Create revision 1 filesystems now */ + + if (is_before_linux_ver(2, 2, 0)) + fs_param.s_rev_level = 0; + + if (argc && *argv) { + program_name = get_progname(*argv); + + /* If called as mkfs.ext3, create a journal inode */ + if (!strcmp(program_name, "mkfs.ext3") || + !strcmp(program_name, "mke3fs")) + journal_size = -1; + } + + while ((c = getopt (argc, argv, + "b:cd:e:g:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:Vz:")) != EOF) { + switch (c) { + case 'b': + blocksize = parse_num_blocks2(optarg, -1); + b = (blocksize > 0) ? blocksize : -blocksize; + if (b < EXT2_MIN_BLOCK_SIZE || + b > EXT2_MAX_BLOCK_SIZE) { + com_err(program_name, 0, + _("invalid block size - %s"), optarg); + exit(1); + } + if (blocksize > 4096) + fprintf(stderr, _("Warning: blocksize %d not " + "usable on most systems.\n"), + blocksize); + if (blocksize > 0) + fs_param.s_log_block_size = + int_log2(blocksize >> + EXT2_MIN_BLOCK_LOG_SIZE); + break; + case 'c': /* Check for bad blocks */ + cflag++; + break; + case 'C': + cluster_size = parse_num_blocks2(optarg, -1); + if (cluster_size <= EXT2_MIN_CLUSTER_SIZE || + cluster_size > EXT2_MAX_CLUSTER_SIZE) { + com_err(program_name, 0, + _("invalid cluster size - %s"), + optarg); + exit(1); + } + break; + case 'd': + src_root_dir = optarg; + break; + case 'D': + direct_io = 1; + break; + case 'R': + com_err(program_name, 0, "%s", + _("'-R' is deprecated, use '-E' instead")); + /* fallthrough */ + case 'E': + extended_opts = optarg; + break; + case 'e': + if (strcmp(optarg, "continue") == 0) + errors_behavior = EXT2_ERRORS_CONTINUE; + else if (strcmp(optarg, "remount-ro") == 0) + errors_behavior = EXT2_ERRORS_RO; + else if (strcmp(optarg, "panic") == 0) + errors_behavior = EXT2_ERRORS_PANIC; + else { + com_err(program_name, 0, + _("bad error behavior - %s"), + optarg); + usage(); + } + break; + case 'F': + force++; + break; + case 'g': + fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, "%s", + _("Illegal number for blocks per group")); + exit(1); + } + if ((fs_param.s_blocks_per_group % 8) != 0) { + com_err(program_name, 0, "%s", + _("blocks per group must be multiple of 8")); + exit(1); + } + break; + case 'G': + flex_bg_size = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, "%s", + _("Illegal number for flex_bg size")); + exit(1); + } + if (flex_bg_size < 1 || + (flex_bg_size & (flex_bg_size-1)) != 0) { + com_err(program_name, 0, "%s", + _("flex_bg size must be a power of 2")); + exit(1); + } + if (flex_bg_size > MAX_32_NUM) { + com_err(program_name, 0, + _("flex_bg size (%lu) must be less than" + " or equal to 2^31"), flex_bg_size); + exit(1); + } + break; + case 'i': + inode_ratio = parse_num_blocks(optarg, -1); + if (inode_ratio < EXT2_MIN_BLOCK_SIZE || + inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024) { + com_err(program_name, 0, + _("invalid inode ratio %s (min %d/max %d)"), + optarg, EXT2_MIN_BLOCK_SIZE, + EXT2_MAX_BLOCK_SIZE * 1024); + exit(1); + } + break; + case 'I': + inode_size = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, + _("invalid inode size - %s"), optarg); + exit(1); + } + break; + case 'j': + if (!journal_size) + journal_size = -1; + if (!journal_fc_size) + journal_fc_size = -1; + break; + case 'J': + parse_journal_opts(optarg); + break; + case 'K': + fprintf(stderr, "%s", + _("Warning: -K option is deprecated and " + "should not be used anymore. Use " + "\'-E nodiscard\' extended option " + "instead!\n")); + discard = 0; + break; + case 'l': + bad_blocks_filename = realloc(bad_blocks_filename, + strlen(optarg) + 1); + if (!bad_blocks_filename) { + com_err(program_name, ENOMEM, "%s", + _("in malloc for bad_blocks_filename")); + exit(1); + } + strcpy(bad_blocks_filename, optarg); + break; + case 'L': + volume_label = optarg; + if (strlen(volume_label) > EXT2_LABEL_LEN) { + volume_label[EXT2_LABEL_LEN] = '\0'; + fprintf(stderr, _("Warning: label too long; will be truncated to '%s'\n\n"), + volume_label); + } + break; + case 'm': + reserved_ratio = strtod(optarg, &tmp); + if ( *tmp || reserved_ratio > 50 || + reserved_ratio < 0) { + com_err(program_name, 0, + _("invalid reserved blocks percent - %s"), + optarg); + exit(1); + } + break; + case 'M': + mount_dir = optarg; + break; + case 'n': + noaction++; + break; + case 'N': + num_inodes = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, + _("bad num inodes - %s"), optarg); + exit(1); + } + break; + case 'o': + creator_os = optarg; + break; + case 'O': + retval = ext2fs_resize_mem(fs_features_size, + fs_features_size + 1 + strlen(optarg), + &fs_features); + if (retval) { + com_err(program_name, retval, + _("while allocating fs_feature string")); + exit(1); + } + if (fs_features_size) + strcat(fs_features, ","); + else + fs_features[0] = 0; + strcat(fs_features, optarg); + fs_features_size += 1 + strlen(optarg); + break; + case 'q': + quiet = 1; + break; + case 'r': + r_opt = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(program_name, 0, + _("bad revision level - %s"), optarg); + exit(1); + } + if (r_opt > EXT2_MAX_SUPP_REV) { + com_err(program_name, EXT2_ET_REV_TOO_HIGH, + _("while trying to create revision %d"), r_opt); + exit(1); + } + fs_param.s_rev_level = r_opt; + break; + case 's': /* deprecated */ + s_opt = atoi(optarg); + break; + case 'S': + super_only = 1; + break; + case 't': + if (fs_type) { + com_err(program_name, 0, "%s", + _("The -t option may only be used once")); + exit(1); + } + fs_type = strdup(optarg); + break; + case 'T': + if (usage_types) { + com_err(program_name, 0, "%s", + _("The -T option may only be used once")); + exit(1); + } + usage_types = strdup(optarg); + break; + case 'U': + fs_uuid = optarg; + break; + case 'v': + verbose = 1; + break; + case 'V': + /* Print version number and exit */ + show_version_only++; + break; + case 'z': + undo_file = optarg; + break; + default: + usage(); + } + } + if ((optind == argc) && !show_version_only) + usage(); + device_name = argv[optind++]; + + if (!quiet || show_version_only) + fprintf (stderr, "mke2fs %s (%s)\n", E2FSPROGS_VERSION, + E2FSPROGS_DATE); + + if (show_version_only) { + fprintf(stderr, "\tUsing EXT2FS Library version %s\n", EXT2FS_LIB_VERSION_PRIVATE); + exit(0); + } + + /* + * If there's no blocksize specified and there is a journal + * device, use it to figure out the blocksize + */ + if (blocksize <= 0 && journal_device) { + ext2_filsys jfs; + io_manager io_ptr; + +#ifdef CONFIG_TESTIO_DEBUG + if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { + io_ptr = test_io_manager; + test_io_backing_manager = default_io_manager; + } else +#endif + io_ptr = default_io_manager; + retval = ext2fs_open(journal_device, + EXT2_FLAG_JOURNAL_DEV_OK, 0, + 0, io_ptr, &jfs); + if (retval) { + com_err(program_name, retval, + _("while trying to open journal device %s\n"), + journal_device); + exit(1); + } + if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) { + com_err(program_name, 0, + _("Journal dev blocksize (%d) smaller than " + "minimum blocksize %d\n"), jfs->blocksize, + -blocksize); + exit(1); + } + blocksize = jfs->blocksize; + printf(_("Using journal device's blocksize: %d\n"), blocksize); + fs_param.s_log_block_size = + int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); + ext2fs_close_free(&jfs); + } + + if (optind < argc) { + fs_blocks_count = parse_num_blocks2(argv[optind++], + fs_param.s_log_block_size); + if (!fs_blocks_count) { + com_err(program_name, 0, + _("invalid blocks '%s' on device '%s'"), + argv[optind - 1], device_name); + exit(1); + } + } + if (optind < argc) + usage(); + + profile_get_integer(profile, "options", "sync_kludge", 0, 0, + &sync_kludge); + tmp = getenv("MKE2FS_SYNC"); + if (tmp) + sync_kludge = atoi(tmp); + + profile_get_integer(profile, "options", "proceed_delay", 0, 0, + &proceed_delay); + + if (fs_blocks_count) + explicit_fssize = 1; + + check_mount(device_name, force, _("filesystem")); + + /* Determine the size of the device (if possible) */ + if (noaction && fs_blocks_count) { + dev_size = fs_blocks_count; + retval = 0; + } else + retval = ext2fs_get_device_size2(device_name, + EXT2_BLOCK_SIZE(&fs_param), + &dev_size); + if (retval == ENOENT) { + int fd; + + if (!explicit_fssize) { + fprintf(stderr, + _("The file %s does not exist and no " + "size was specified.\n"), device_name); + exit(1); + } + fd = ext2fs_open_file(device_name, + O_CREAT | O_WRONLY, 0666); + if (fd < 0) { + retval = errno; + } else { + dev_size = 0; + retval = 0; + close(fd); + printf(_("Creating regular file %s\n"), device_name); + } + } + if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) { + com_err(program_name, retval, "%s", + _("while trying to determine filesystem size")); + exit(1); + } + if (!fs_blocks_count) { + if (retval == EXT2_ET_UNIMPLEMENTED) { + com_err(program_name, 0, "%s", + _("Couldn't determine device size; you " + "must specify\nthe size of the " + "filesystem\n")); + exit(1); + } else { + if (dev_size == 0) { + com_err(program_name, 0, "%s", + _("Device size reported to be zero. " + "Invalid partition specified, or\n\t" + "partition table wasn't reread " + "after running fdisk, due to\n\t" + "a modified partition being busy " + "and in use. You may need to reboot\n\t" + "to re-read your partition table.\n" + )); + exit(1); + } + fs_blocks_count = dev_size; + if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) + fs_blocks_count &= ~((blk64_t) ((sys_page_size / + EXT2_BLOCK_SIZE(&fs_param))-1)); + } + } else if (!force && is_device && (fs_blocks_count > dev_size)) { + com_err(program_name, 0, "%s", + _("Filesystem larger than apparent device size.")); + proceed_question(proceed_delay); + } + + if (!fs_type) + profile_get_string(profile, "devices", device_name, + "fs_type", 0, &fs_type); + if (!usage_types) + profile_get_string(profile, "devices", device_name, + "usage_types", 0, &usage_types); + if (!creator_os) + profile_get_string(profile, "defaults", "creator_os", 0, + 0, &creator_os); + + /* + * We have the file system (or device) size, so we can now + * determine the appropriate file system types so the fs can + * be appropriately configured. + */ + fs_types = parse_fs_type(fs_type, usage_types, &fs_param, + fs_blocks_count ? fs_blocks_count : dev_size, + argv[0]); + if (!fs_types) { + fprintf(stderr, "%s", _("Failed to parse fs types list\n")); + exit(1); + } + + /* Figure out what features should be enabled */ + + tmp = NULL; + if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) { + tmp = get_string_from_profile(fs_types, "base_features", + "sparse_super,large_file,filetype,resize_inode,dir_index"); + edit_feature(tmp, &fs_param.s_feature_compat); + free(tmp); + + /* And which mount options as well */ + tmp = get_string_from_profile(fs_types, "default_mntopts", + "acl,user_xattr"); + edit_mntopts(tmp, &fs_param.s_default_mount_opts); + if (tmp) + free(tmp); + + for (cpp = fs_types; *cpp; cpp++) { + tmp = NULL; + profile_get_string(profile, "fs_types", *cpp, + "features", "", &tmp); + if (tmp && *tmp) + edit_feature(tmp, &fs_param.s_feature_compat); + if (tmp) + free(tmp); + } + tmp = get_string_from_profile(fs_types, "default_features", + ""); + } + /* Mask off features which aren't supported by the Hurd */ + if (for_hurd(creator_os)) { + ext2fs_clear_feature_filetype(&fs_param); + ext2fs_clear_feature_huge_file(&fs_param); + ext2fs_clear_feature_metadata_csum(&fs_param); + ext2fs_clear_feature_ea_inode(&fs_param); + ext2fs_clear_feature_casefold(&fs_param); + } + edit_feature(fs_features ? fs_features : tmp, + &fs_param.s_feature_compat); + if (tmp) + free(tmp); + (void) ext2fs_free_mem(&fs_features); + /* + * If the user specified features incompatible with the Hurd, complain + */ + if (for_hurd(creator_os)) { + if (ext2fs_has_feature_filetype(&fs_param)) { + fprintf(stderr, "%s", _("The HURD does not support the " + "filetype feature.\n")); + exit(1); + } + if (ext2fs_has_feature_huge_file(&fs_param)) { + fprintf(stderr, "%s", _("The HURD does not support the " + "huge_file feature.\n")); + exit(1); + } + if (ext2fs_has_feature_metadata_csum(&fs_param)) { + fprintf(stderr, "%s", _("The HURD does not support the " + "metadata_csum feature.\n")); + exit(1); + } + if (ext2fs_has_feature_ea_inode(&fs_param)) { + fprintf(stderr, "%s", _("The HURD does not support the " + "ea_inode feature.\n")); + exit(1); + } + } + + /* Get the hardware sector sizes, if available */ + retval = ext2fs_get_device_sectsize(device_name, &lsector_size); + if (retval) { + com_err(program_name, retval, "%s", + _("while trying to determine hardware sector size")); + exit(1); + } + retval = ext2fs_get_device_phys_sectsize(device_name, &psector_size); + if (retval) { + com_err(program_name, retval, "%s", + _("while trying to determine physical sector size")); + exit(1); + } + + tmp = getenv("MKE2FS_DEVICE_SECTSIZE"); + if (tmp != NULL) + lsector_size = atoi(tmp); + tmp = getenv("MKE2FS_DEVICE_PHYS_SECTSIZE"); + if (tmp != NULL) + psector_size = atoi(tmp); + + /* Older kernels may not have physical/logical distinction */ + if (!psector_size) + psector_size = lsector_size; + + if (blocksize <= 0) { + use_bsize = get_int_from_profile(fs_types, "blocksize", 4096); + + if (use_bsize == -1) { + use_bsize = sys_page_size; + if (is_before_linux_ver(2, 6, 0) && use_bsize > 4096) + use_bsize = 4096; + } + if (lsector_size && use_bsize < lsector_size) + use_bsize = lsector_size; + if ((blocksize < 0) && (use_bsize < (-blocksize))) + use_bsize = -blocksize; + blocksize = use_bsize; + fs_blocks_count /= (blocksize / 1024); + } else { + if (blocksize < lsector_size) { /* Impossible */ + com_err(program_name, EINVAL, "%s", + _("while setting blocksize; too small " + "for device\n")); + exit(1); + } else if ((blocksize < psector_size) && + (psector_size <= sys_page_size)) { /* Suboptimal */ + fprintf(stderr, _("Warning: specified blocksize %d is " + "less than device physical sectorsize %d\n"), + blocksize, psector_size); + } + } + + fs_param.s_log_block_size = + int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); + + /* + * We now need to do a sanity check of fs_blocks_count for + * 32-bit vs 64-bit block number support. + */ + if ((fs_blocks_count > MAX_32_NUM) && + ext2fs_has_feature_64bit(&fs_param)) + ext2fs_clear_feature_resize_inode(&fs_param); + if ((fs_blocks_count > MAX_32_NUM) && + !ext2fs_has_feature_64bit(&fs_param) && + get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) { + ext2fs_set_feature_64bit(&fs_param); + ext2fs_clear_feature_resize_inode(&fs_param); + } + if ((fs_blocks_count > MAX_32_NUM) && + !ext2fs_has_feature_64bit(&fs_param)) { + fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s " + "too big to be expressed\n\t" + "in 32 bits using a blocksize of %d.\n"), + program_name, (unsigned long long) fs_blocks_count, + device_name, EXT2_BLOCK_SIZE(&fs_param)); + exit(1); + } + /* + * Guard against group descriptor count overflowing... Mostly to avoid + * strange results for absurdly large devices. This is in log2: + * (blocksize) * (bits per byte) * (maximum number of block groups) + */ + if (fs_blocks_count > + (1ULL << (EXT2_BLOCK_SIZE_BITS(&fs_param) + 3 + 32)) - 1) { + fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s " + "too big to create\n\t" + "a filesystem using a blocksize of %d.\n"), + program_name, (unsigned long long) fs_blocks_count, + device_name, EXT2_BLOCK_SIZE(&fs_param)); + exit(1); + } + + ext2fs_blocks_count_set(&fs_param, fs_blocks_count); + + if (ext2fs_has_feature_journal_dev(&fs_param)) { + int i; + + for (i=0; fs_types[i]; i++) { + free(fs_types[i]); + fs_types[i] = 0; + } + fs_types[0] = strdup("journal"); + fs_types[1] = 0; + } + + if (verbose) { + fputs(_("fs_types for mke2fs.conf resolution: "), stdout); + print_str_list(fs_types); + } + + if (r_opt == EXT2_GOOD_OLD_REV && + (fs_param.s_feature_compat || fs_param.s_feature_incompat || + fs_param.s_feature_ro_compat)) { + fprintf(stderr, "%s", _("Filesystem features not supported " + "with revision 0 filesystems\n")); + exit(1); + } + + if (s_opt > 0) { + if (r_opt == EXT2_GOOD_OLD_REV) { + fprintf(stderr, "%s", + _("Sparse superblocks not supported " + "with revision 0 filesystems\n")); + exit(1); + } + ext2fs_set_feature_sparse_super(&fs_param); + } else if (s_opt == 0) + ext2fs_clear_feature_sparse_super(&fs_param); + + if (journal_size != 0) { + if (r_opt == EXT2_GOOD_OLD_REV) { + fprintf(stderr, "%s", _("Journals not supported with " + "revision 0 filesystems\n")); + exit(1); + } + ext2fs_set_feature_journal(&fs_param); + } + + /* Get reserved_ratio from profile if not specified on cmd line. */ + if (reserved_ratio < 0.0) { + reserved_ratio = get_double_from_profile( + fs_types, "reserved_ratio", 5.0); + if (reserved_ratio > 50 || reserved_ratio < 0) { + com_err(program_name, 0, + _("invalid reserved blocks percent - %lf"), + reserved_ratio); + exit(1); + } + } + + if (ext2fs_has_feature_journal_dev(&fs_param)) { + reserved_ratio = 0; + fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; + fs_param.s_feature_compat = 0; + fs_param.s_feature_ro_compat &= + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; + } + + /* Check the user's mkfs options for 64bit */ + if (ext2fs_has_feature_64bit(&fs_param) && + !ext2fs_has_feature_extents(&fs_param)) { + printf("%s", _("Extents MUST be enabled for a 64-bit " + "filesystem. Pass -O extents to rectify.\n")); + exit(1); + } + + /* Set first meta blockgroup via an environment variable */ + /* (this is mostly for debugging purposes) */ + if (ext2fs_has_feature_meta_bg(&fs_param) && + (tmp = getenv("MKE2FS_FIRST_META_BG"))) + fs_param.s_first_meta_bg = atoi(tmp); + if (ext2fs_has_feature_bigalloc(&fs_param)) { + if (!cluster_size) + cluster_size = get_int_from_profile(fs_types, + "cluster_size", + blocksize*16); + fs_param.s_log_cluster_size = + int_log2(cluster_size >> EXT2_MIN_CLUSTER_LOG_SIZE); + if (fs_param.s_log_cluster_size && + fs_param.s_log_cluster_size < fs_param.s_log_block_size) { + com_err(program_name, 0, "%s", + _("The cluster size may not be " + "smaller than the block size.\n")); + exit(1); + } + } else if (cluster_size) { + com_err(program_name, 0, "%s", + _("specifying a cluster size requires the " + "bigalloc feature")); + exit(1); + } else + fs_param.s_log_cluster_size = fs_param.s_log_block_size; + + if (inode_ratio == 0) { + inode_ratio = get_int_from_profile(fs_types, "inode_ratio", + 8192); + if (inode_ratio < blocksize) + inode_ratio = blocksize; + if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param)) + inode_ratio = EXT2_CLUSTER_SIZE(&fs_param); + } + +#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY + retval = get_device_geometry(device_name, blocksize, + psector_size, &dev_param); + if (retval < 0) { + fprintf(stderr, + _("warning: Unable to get device geometry for %s\n"), + device_name); + } else { + /* setting stripe/stride to blocksize is pointless */ + if (dev_param.min_io > (unsigned) blocksize) + fs_param.s_raid_stride = dev_param.min_io / blocksize; + if (dev_param.opt_io > (unsigned) blocksize) { + fs_param.s_raid_stripe_width = + dev_param.opt_io / blocksize; + } + + if (dev_param.alignment_offset) { + printf(_("%s alignment is offset by %lu bytes.\n"), + device_name, dev_param.alignment_offset); + printf(_("This may result in very poor performance, " + "(re)-partitioning suggested.\n")); + } + + if (dev_param.dax && blocksize != sys_page_size) { + fprintf(stderr, + _("%s is capable of DAX but current block size " + "%u is different from system page size %u so " + "filesystem will not support DAX.\n"), + device_name, blocksize, sys_page_size); + } + } +#endif + + num_backups = get_int_from_profile(fs_types, "num_backup_sb", 2); + + blocksize = EXT2_BLOCK_SIZE(&fs_param); + + /* + * Initialize s_desc_size so that the parse_extended_opts() + * can correctly handle "-E resize=NNN" if the 64-bit option + * is set. + */ + if (ext2fs_has_feature_64bit(&fs_param)) + fs_param.s_desc_size = EXT2_MIN_DESC_SIZE_64BIT; + + /* This check should happen beyond the last assignment to blocksize */ + if (blocksize > sys_page_size) { + if (!force) { + com_err(program_name, 0, + _("%d-byte blocks too big for system (max %d)"), + blocksize, sys_page_size); + proceed_question(proceed_delay); + } + fprintf(stderr, _("Warning: %d-byte blocks too big for system " + "(max %d), forced to continue\n"), + blocksize, sys_page_size); + } + + /* Metadata checksumming wasn't totally stable before 3.18. */ + if (is_before_linux_ver(3, 18, 0) && + ext2fs_has_feature_metadata_csum(&fs_param)) + fprintf(stderr, _("Suggestion: Use Linux kernel >= 3.18 for " + "improved stability of the metadata and journal " + "checksum features.\n")); + + /* + * On newer kernels we do have lazy_itable_init support. So pick the + * right default in case ext4 module is not loaded. + */ + if (is_before_linux_ver(2, 6, 37)) + lazy_itable_init = 0; + else + lazy_itable_init = 1; + + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0) + lazy_itable_init = 1; + + lazy_itable_init = get_bool_from_profile(fs_types, + "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; + journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK; + + if (!journal_location_string) + journal_location_string = get_string_from_profile(fs_types, + "journal_location", ""); + if ((journal_location == ~0ULL) && journal_location_string && + *journal_location_string) + journal_location = parse_num_blocks2(journal_location_string, + fs_param.s_log_block_size); + free(journal_location_string); + + packed_meta_blocks = get_bool_from_profile(fs_types, + "packed_meta_blocks", 0); + if (packed_meta_blocks) + journal_location = 0; + + if (ext2fs_has_feature_casefold(&fs_param)) { + char *ef, *en = get_string_from_profile(fs_types, + "encoding", "utf8"); + int encoding = e2p_str2encoding(en); + + if (encoding < 0) { + com_err(program_name, 0, + _("Unknown filename encoding from profile: %s"), + en); + exit(1); + } + free(en); + fs_param.s_encoding = encoding; + ef = get_string_from_profile(fs_types, "encoding_flags", NULL); + if (ef) { + if (e2p_str2encoding_flags(encoding, ef, + &fs_param.s_encoding_flags) < 0) { + com_err(program_name, 0, + _("Unknown encoding flags from profile: %s"), ef); + exit(1); + } + free(ef); + } else + fs_param.s_encoding_flags = + e2p_get_encoding_flags(encoding); + } + + /* Get options from profile */ + for (cpp = fs_types; *cpp; cpp++) { + tmp = NULL; + profile_get_string(profile, "fs_types", *cpp, "options", "", &tmp); + if (tmp && *tmp) + parse_extended_opts(&fs_param, tmp); + free(tmp); + } + + if (extended_opts) + parse_extended_opts(&fs_param, extended_opts); + + if (explicit_fssize == 0 && offset > 0) { + fs_blocks_count -= offset / EXT2_BLOCK_SIZE(&fs_param); + ext2fs_blocks_count_set(&fs_param, fs_blocks_count); + fprintf(stderr, + _("\nWarning: offset specified without an " + "explicit file system size.\n" + "Creating a file system with %llu blocks " + "but this might\n" + "not be what you want.\n\n"), + (unsigned long long) fs_blocks_count); + } + + if (quotatype_bits & QUOTA_PRJ_BIT) + ext2fs_set_feature_project(&fs_param); + + if (ext2fs_has_feature_project(&fs_param)) { + quotatype_bits |= QUOTA_PRJ_BIT; + if (inode_size == EXT2_GOOD_OLD_INODE_SIZE) { + com_err(program_name, 0, + _("%d byte inodes are too small for " + "project quota"), + inode_size); + exit(1); + } + if (inode_size == 0) { + inode_size = get_int_from_profile(fs_types, + "inode_size", 0); + if (inode_size <= EXT2_GOOD_OLD_INODE_SIZE*2) + inode_size = EXT2_GOOD_OLD_INODE_SIZE*2; + } + } + + /* Don't allow user to set both metadata_csum and uninit_bg bits. */ + if (ext2fs_has_feature_metadata_csum(&fs_param) && + ext2fs_has_feature_gdt_csum(&fs_param)) + ext2fs_clear_feature_gdt_csum(&fs_param); + + /* Can't support bigalloc feature without extents feature */ + if (ext2fs_has_feature_bigalloc(&fs_param) && + !ext2fs_has_feature_extents(&fs_param)) { + com_err(program_name, 0, "%s", + _("Can't support bigalloc feature without " + "extents feature")); + exit(1); + } + + if (ext2fs_has_feature_meta_bg(&fs_param) && + ext2fs_has_feature_resize_inode(&fs_param)) { + fprintf(stderr, "%s", _("The resize_inode and meta_bg " + "features are not compatible.\n" + "They can not be both enabled " + "simultaneously.\n")); + exit(1); + } + + if (!quiet && ext2fs_has_feature_bigalloc(&fs_param) && + EXT2_CLUSTER_SIZE(&fs_param) > 16 * EXT2_BLOCK_SIZE(&fs_param)) + fprintf(stderr, "%s", _("\nWarning: bigalloc file systems " + "with a cluster size greater than\n" + "16 times the block size is considered " + "experimental\n")); + + /* + * Since sparse_super is the default, we would only have a problem + * here if it was explicitly disabled. + */ + if (ext2fs_has_feature_resize_inode(&fs_param) && + !ext2fs_has_feature_sparse_super(&fs_param)) { + com_err(program_name, 0, "%s", + _("reserved online resize blocks not supported " + "on non-sparse filesystem")); + exit(1); + } + + if (fs_param.s_blocks_per_group) { + if (fs_param.s_blocks_per_group < 256 || + fs_param.s_blocks_per_group > 8 * (unsigned) blocksize) { + com_err(program_name, 0, "%s", + _("blocks per group count out of range")); + exit(1); + } + } + + /* + * If the bigalloc feature is enabled, then the -g option will + * specify the number of clusters per group. + */ + if (ext2fs_has_feature_bigalloc(&fs_param)) { + fs_param.s_clusters_per_group = fs_param.s_blocks_per_group; + fs_param.s_blocks_per_group = 0; + } + + if (inode_size == 0) + inode_size = get_int_from_profile(fs_types, "inode_size", 0); + if (!flex_bg_size && ext2fs_has_feature_flex_bg(&fs_param)) + flex_bg_size = get_uint_from_profile(fs_types, + "flex_bg_size", 16); + if (flex_bg_size) { + if (!ext2fs_has_feature_flex_bg(&fs_param)) { + com_err(program_name, 0, "%s", + _("Flex_bg feature not enabled, so " + "flex_bg size may not be specified")); + exit(1); + } + fs_param.s_log_groups_per_flex = int_log2(flex_bg_size); + } + + if (inode_size && fs_param.s_rev_level >= EXT2_DYNAMIC_REV) { + if (inode_size < EXT2_GOOD_OLD_INODE_SIZE || + inode_size > EXT2_BLOCK_SIZE(&fs_param) || + inode_size & (inode_size - 1)) { + com_err(program_name, 0, + _("invalid inode size %d (min %d/max %d)"), + inode_size, EXT2_GOOD_OLD_INODE_SIZE, + blocksize); + exit(1); + } + fs_param.s_inode_size = inode_size; + } + + /* + * If inode size is 128 and inline data is enabled, we need + * to notify users that inline data will never be useful. + */ + if (ext2fs_has_feature_inline_data(&fs_param) && + fs_param.s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) { + com_err(program_name, 0, + _("%d byte inodes are too small for inline data; " + "specify larger size"), + fs_param.s_inode_size); + exit(1); + } + + /* + * Warn the user that filesystems with 128-byte inodes will + * not work properly beyond 2038. This can be suppressed via + * a boolean in the mke2fs.conf file, and we will disable this + * warning for file systems created for the GNU Hurd. + */ + if (inode_size == EXT2_GOOD_OLD_INODE_SIZE && + get_bool_from_profile(fs_types, "warn_y2038_dates", 1)) + printf( +_("128-byte inodes cannot handle dates beyond 2038 and are deprecated\n")); + + /* Make sure number of inodes specified will fit in 32 bits */ + if (num_inodes == 0) { + unsigned long long n; + n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio; + if (n > MAX_32_NUM) { + if (ext2fs_has_feature_64bit(&fs_param)) + num_inodes = MAX_32_NUM; + else { + com_err(program_name, 0, + _("too many inodes (%llu), raise " + "inode ratio?"), + (unsigned long long) n); + exit(1); + } + } + } else if (num_inodes > MAX_32_NUM) { + com_err(program_name, 0, + _("too many inodes (%llu), specify < 2^32 inodes"), + (unsigned long long) num_inodes); + exit(1); + } + /* + * Calculate number of inodes based on the inode ratio + */ + fs_param.s_inodes_count = num_inodes ? num_inodes : + (ext2fs_blocks_count(&fs_param) * blocksize) / inode_ratio; + + if ((((unsigned long long)fs_param.s_inodes_count) * + (inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE)) >= + ((ext2fs_blocks_count(&fs_param)) * + EXT2_BLOCK_SIZE(&fs_param))) { + com_err(program_name, 0, _("inode_size (%u) * inodes_count " + "(%u) too big for a\n\t" + "filesystem with %llu blocks, " + "specify higher inode_ratio (-i)\n\t" + "or lower inode count (-N).\n"), + inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE, + fs_param.s_inodes_count, + (unsigned long long) ext2fs_blocks_count(&fs_param)); + exit(1); + } + + /* + * Calculate number of blocks to reserve + */ + ext2fs_r_blocks_count_set(&fs_param, reserved_ratio * + ext2fs_blocks_count(&fs_param) / 100.0); + + if (ext2fs_has_feature_sparse_super2(&fs_param)) { + if (num_backups >= 1) + fs_param.s_backup_bgs[0] = 1; + if (num_backups >= 2) + fs_param.s_backup_bgs[1] = ~0; + } + + free(fs_type); + free(usage_types); + + /* The isatty() test is so we don't break existing scripts */ + flags = CREATE_FILE; + if (isatty(0) && isatty(1) && !offset) + flags |= CHECK_FS_EXIST; + if (!quiet) + flags |= VERBOSE_CREATE; + if (!explicit_fssize) + flags |= NO_SIZE; + if (!check_plausibility(device_name, flags, &is_device) && !force) + proceed_question(proceed_delay); +} + +static int should_do_undo(const char *name) +{ + errcode_t retval; + io_channel channel; + __u16 s_magic; + struct ext2_super_block super; + io_manager manager = default_io_manager; + int csum_flag, force_undo; + + csum_flag = ext2fs_has_feature_metadata_csum(&fs_param) || + ext2fs_has_feature_gdt_csum(&fs_param); + force_undo = get_int_from_profile(fs_types, "force_undo", 0); + if (!force_undo && (!csum_flag || !lazy_itable_init)) + return 0; + + retval = manager->open(name, IO_FLAG_EXCLUSIVE, &channel); + if (retval) { + /* + * We don't handle error cases instead we + * declare that the file system doesn't exist + * and let the rest of mke2fs take care of + * error + */ + retval = 0; + goto open_err_out; + } + + io_channel_set_blksize(channel, SUPERBLOCK_OFFSET); + retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super); + if (retval) { + retval = 0; + goto err_out; + } + +#if defined(WORDS_BIGENDIAN) + s_magic = ext2fs_swab16(super.s_magic); +#else + s_magic = super.s_magic; +#endif + + if (s_magic == EXT2_SUPER_MAGIC) + retval = 1; + +err_out: + io_channel_close(channel); + +open_err_out: + + return retval; +} + +static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr) +{ + errcode_t retval = ENOMEM; + char *tdb_dir = NULL, *tdb_file = NULL; + char *dev_name, *tmp_name; + int free_tdb_dir = 0; + + /* (re)open a specific undo file */ + if (undo_file && undo_file[0] != 0) { + retval = set_undo_io_backing_manager(*io_ptr); + if (retval) + goto err; + *io_ptr = undo_io_manager; + retval = set_undo_io_backup_file(undo_file); + if (retval) + goto err; + printf(_("Overwriting existing filesystem; this can be undone " + "using the command:\n" + " e2undo %s %s\n\n"), undo_file, name); + return retval; + } + + /* + * Configuration via a conf file would be + * nice + */ + tdb_dir = getenv("E2FSPROGS_UNDO_DIR"); + if (!tdb_dir) { + profile_get_string(profile, "defaults", + "undo_dir", 0, "/var/lib/e2fsprogs", + &tdb_dir); + free_tdb_dir = 1; + } + + if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) || + access(tdb_dir, W_OK)) { + if (free_tdb_dir) + free(tdb_dir); + return 0; + } + + tmp_name = strdup(name); + if (!tmp_name) + goto errout; + dev_name = basename(tmp_name); + tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1); + if (!tdb_file) { + free(tmp_name); + goto errout; + } + sprintf(tdb_file, "%s/mke2fs-%s.e2undo", tdb_dir, dev_name); + free(tmp_name); + + if ((unlink(tdb_file) < 0) && (errno != ENOENT)) { + retval = errno; + com_err(program_name, retval, + _("while trying to delete %s"), tdb_file); + goto errout; + } + + retval = set_undo_io_backing_manager(*io_ptr); + if (retval) + goto errout; + *io_ptr = undo_io_manager; + retval = set_undo_io_backup_file(tdb_file); + if (retval) + goto errout; + printf(_("Overwriting existing filesystem; this can be undone " + "using the command:\n" + " e2undo %s %s\n\n"), tdb_file, name); + + if (free_tdb_dir) + free(tdb_dir); + free(tdb_file); + return 0; + +errout: + if (free_tdb_dir) + free(tdb_dir); + free(tdb_file); +err: + com_err(program_name, retval, "%s", + _("while trying to setup undo file\n")); + return retval; +} + +static int mke2fs_discard_device(ext2_filsys fs) +{ + struct ext2fs_numeric_progress_struct progress; + blk64_t blocks = ext2fs_blocks_count(fs->super); + blk64_t count = DISCARD_STEP_MB; + blk64_t cur = 0; + int retval = 0; + + /* + * Let's try if discard really works on the device, so + * we do not print numeric progress resulting in failure + * afterwards. + */ + retval = io_channel_discard(fs->io, 0, 1); + if (retval) + return retval; + + 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); + if (retval) + break; + cur += count; + } + + if (retval) { + ext2fs_numeric_progress_close(fs, &progress, + _("failed - ")); + if (!quiet) + printf("%s\n",error_message(retval)); + } else + ext2fs_numeric_progress_close(fs, &progress, + _("done \n")); + + return retval; +} + +static void fix_cluster_bg_counts(ext2_filsys fs) +{ + blk64_t block, num_blocks, last_block, next; + blk64_t tot_free = 0; + errcode_t retval; + dgrp_t group = 0; + int grp_free = 0; + + num_blocks = ext2fs_blocks_count(fs->super); + last_block = ext2fs_group_last_block2(fs, group); + block = fs->super->s_first_data_block; + while (block < num_blocks) { + retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, + block, last_block, &next); + if (retval == 0) + block = next; + else { + block = last_block + 1; + goto next_bg; + } + + retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, + block, last_block, &next); + if (retval) + next = last_block + 1; + grp_free += EXT2FS_NUM_B2C(fs, next - block); + tot_free += next - block; + block = next; + + if (block > last_block) { + next_bg: + ext2fs_bg_free_blocks_count_set(fs, group, grp_free); + ext2fs_group_desc_csum_set(fs, group); + grp_free = 0; + group++; + last_block = ext2fs_group_last_block2(fs, group); + } + } + ext2fs_free_blocks_count_set(fs->super, tot_free); +} + +static int create_quota_inodes(ext2_filsys fs) +{ + quota_ctx_t qctx; + errcode_t retval; + + retval = quota_init_context(&qctx, fs, quotatype_bits); + if (retval) { + com_err(program_name, retval, + _("while initializing quota context")); + exit(1); + } + quota_compute_usage(qctx); + retval = quota_write_inode(qctx, quotatype_bits); + if (retval) { + com_err(program_name, retval, + _("while writing quota inodes")); + exit(1); + } + quota_release_context(&qctx); + + return 0; +} + +static errcode_t set_error_behavior(ext2_filsys fs) +{ + char *arg = NULL; + short errors = fs->super->s_errors; + + arg = get_string_from_profile(fs_types, "errors", NULL); + if (arg == NULL) + goto try_user; + + if (strcmp(arg, "continue") == 0) + errors = EXT2_ERRORS_CONTINUE; + else if (strcmp(arg, "remount-ro") == 0) + errors = EXT2_ERRORS_RO; + else if (strcmp(arg, "panic") == 0) + errors = EXT2_ERRORS_PANIC; + else { + com_err(program_name, 0, + _("bad error behavior in profile - %s"), + arg); + free(arg); + return EXT2_ET_INVALID_ARGUMENT; + } + free(arg); + +try_user: + if (errors_behavior) + errors = errors_behavior; + + fs->super->s_errors = errors; + return 0; +} + +int mke2fs_main (int argc, char *argv[]) +{ + errcode_t retval = 0; + ext2_filsys fs; + badblocks_list bb_list = 0; + badblocks_iterate bb_iter; + blk_t blk; + struct ext2fs_journal_params jparams = {0}; + unsigned int i, checkinterval; + int max_mnt_count; + int val, hash_alg; + int flags; + int old_bitmaps; + io_manager io_ptr; + char opt_string[40]; + char *hash_alg_str; + int itable_zeroed = 0; + blk64_t overhead; + argv[0] = basename(argv[0]); + +#ifdef ENABLE_NLS + setlocale(LC_MESSAGES, ""); + setlocale(LC_CTYPE, ""); + bindtextdomain(NLS_CAT_NAME, LOCALEDIR); + textdomain(NLS_CAT_NAME); + set_com_err_gettext(gettext); +#endif + PRS(argc, argv); + +#ifdef CONFIG_TESTIO_DEBUG + if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { + io_ptr = test_io_manager; + test_io_backing_manager = default_io_manager; + } else +#endif + io_ptr = default_io_manager; + + if (undo_file != NULL || should_do_undo(device_name)) { + retval = mke2fs_setup_tdb(device_name, &io_ptr); + if (retval) + exit(1); + } + + /* + * Initialize the superblock.... + */ + flags = EXT2_FLAG_EXCLUSIVE; + if (direct_io) + flags |= EXT2_FLAG_DIRECT_IO; + profile_get_boolean(profile, "options", "old_bitmaps", 0, 0, + &old_bitmaps); + if (!old_bitmaps) + flags |= EXT2_FLAG_64BITS; + /* + * By default, we print how many inode tables or block groups + * or whatever we've written so far. The quiet flag disables + * this, along with a lot of other output. + */ + if (!quiet) + flags |= EXT2_FLAG_PRINT_PROGRESS; + if (android_sparse_file) { + char *android_sparse_params = malloc(strlen(device_name) + 48); + + if (!android_sparse_params) { + com_err(program_name, ENOMEM, "%s", + _("in malloc for android_sparse_params")); + exit(1); + } + sprintf(android_sparse_params, "(%s):%u:%u", + device_name, fs_param.s_blocks_count, + 1024 << fs_param.s_log_block_size); + retval = ext2fs_initialize(android_sparse_params, flags, + &fs_param, sparse_io_manager, &fs); + free(android_sparse_params); + } else + retval = ext2fs_initialize(device_name, flags, &fs_param, + io_ptr, &fs); + if (retval) { + com_err(device_name, retval, "%s", + _("while setting up superblock")); + exit(1); + } + fs->progress_ops = &ext2fs_numeric_progress_ops; + + /* Set the error behavior */ + retval = set_error_behavior(fs); + if (retval) + usage(); + + /* Check the user's mkfs options for metadata checksumming */ + if (!quiet && + !ext2fs_has_feature_journal_dev(fs->super) && + ext2fs_has_feature_metadata_csum(fs->super)) { + if (!ext2fs_has_feature_extents(fs->super)) + printf("%s", + _("Extents are not enabled. The file extent " + "tree can be checksummed, whereas block maps " + "cannot. Not enabling extents reduces the " + "coverage of metadata checksumming. " + "Pass -O extents to rectify.\n")); + if (!ext2fs_has_feature_64bit(fs->super)) + printf("%s", + _("64-bit filesystem support is not enabled. " + "The larger fields afforded by this feature " + "enable full-strength checksumming. " + "Pass -O 64bit to rectify.\n")); + } + + if (ext2fs_has_feature_csum_seed(fs->super) && + !ext2fs_has_feature_metadata_csum(fs->super)) { + printf("%s", _("The metadata_csum_seed feature " + "requires the metadata_csum feature.\n")); + exit(1); + } + + /* Calculate journal blocks */ + if (!journal_device && ((journal_size) || + ext2fs_has_feature_journal(&fs_param))) + figure_journal_size(&jparams, journal_size, journal_fc_size, fs); + + sprintf(opt_string, "tdb_data_size=%d", fs->blocksize <= 4096 ? + 32768 : fs->blocksize * 8); + io_channel_set_options(fs->io, opt_string); + if (offset) { + sprintf(opt_string, "offset=%llu", (unsigned long long) offset); + io_channel_set_options(fs->io, opt_string); + } + + /* Can't undo discard ... */ + if (!noaction && discard && dev_size && (io_ptr != undo_io_manager)) { + retval = mke2fs_discard_device(fs); + if (!retval && io_channel_discard_zeroes_data(fs->io)) { + if (verbose) + printf("%s", + _("Discard succeeded and will return " + "0s - skipping inode table wipe\n")); + lazy_itable_init = 1; + itable_zeroed = 1; + zero_hugefile = 0; + } + } + + if (fs_param.s_flags & EXT2_FLAGS_TEST_FILESYS) + fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS; + + if (ext2fs_has_feature_flex_bg(&fs_param) || + ext2fs_has_feature_huge_file(&fs_param) || + ext2fs_has_feature_gdt_csum(&fs_param) || + ext2fs_has_feature_dir_nlink(&fs_param) || + ext2fs_has_feature_metadata_csum(&fs_param) || + ext2fs_has_feature_extra_isize(&fs_param)) + fs->super->s_kbytes_written = 1; + + /* + * Wipe out the old on-disk superblock + */ + if (!noaction) + zap_sector(fs, 2, 6); + + /* + * Parse or generate a UUID for the filesystem + */ + if (fs_uuid) { + if ((strcasecmp(fs_uuid, "null") == 0) || + (strcasecmp(fs_uuid, "clear") == 0)) { + uuid_clear(fs->super->s_uuid); + } else if (strcasecmp(fs_uuid, "time") == 0) { + uuid_generate_time(fs->super->s_uuid); + } else if (strcasecmp(fs_uuid, "random") == 0) { + uuid_generate(fs->super->s_uuid); + } else if (uuid_parse(fs_uuid, fs->super->s_uuid) != 0) { + com_err(device_name, 0, "could not parse UUID: %s\n", + fs_uuid); + exit(1); + } + } else + uuid_generate(fs->super->s_uuid); + + if (ext2fs_has_feature_csum_seed(fs->super)) + fs->super->s_checksum_seed = ext2fs_crc32c_le(~0, + fs->super->s_uuid, sizeof(fs->super->s_uuid)); + + ext2fs_init_csum_seed(fs); + + /* + * Initialize the directory index variables + */ + hash_alg_str = get_string_from_profile(fs_types, "hash_alg", + "half_md4"); + hash_alg = e2p_string2hash(hash_alg_str); + free(hash_alg_str); + fs->super->s_def_hash_version = (hash_alg >= 0) ? hash_alg : + EXT2_HASH_HALF_MD4; + + if (memcmp(fs_param.s_hash_seed, zero_buf, + sizeof(fs_param.s_hash_seed)) != 0) { + memcpy(fs->super->s_hash_seed, fs_param.s_hash_seed, + sizeof(fs->super->s_hash_seed)); + } else + uuid_generate((unsigned char *) fs->super->s_hash_seed); + + /* + * Periodic checks can be enabled/disabled via config file. + * Note we override the kernel include file's idea of what the default + * check interval (never) should be. It's a good idea to check at + * least *occasionally*, specially since servers will never rarely get + * to reboot, since Linux is so robust these days. :-) + * + * 180 days (six months) seems like a good value. + */ +#ifdef EXT2_DFL_CHECKINTERVAL +#undef EXT2_DFL_CHECKINTERVAL +#endif +#define EXT2_DFL_CHECKINTERVAL (86400L * 180L) + + if (get_bool_from_profile(fs_types, "enable_periodic_fsck", 0)) { + fs->super->s_checkinterval = EXT2_DFL_CHECKINTERVAL; + fs->super->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT; + /* + * Add "jitter" to the superblock's check interval so that we + * don't check all the filesystems at the same time. We use a + * kludgy hack of using the UUID to derive a random jitter value + */ + for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++) + val += fs->super->s_uuid[i]; + fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT; + } else + fs->super->s_max_mnt_count = -1; + + /* + * Override the creator OS, if applicable + */ + if (creator_os && !set_os(fs->super, creator_os)) { + com_err (program_name, 0, _("unknown os - %s"), creator_os); + exit(1); + } + + /* + * For the Hurd, we will turn off filetype since it doesn't + * support it. + */ + if (fs->super->s_creator_os == EXT2_OS_HURD) + ext2fs_clear_feature_filetype(fs->super); + + /* + * Set the volume label... + */ + if (volume_label) { + memset(fs->super->s_volume_name, 0, + sizeof(fs->super->s_volume_name)); + strncpy((char *) fs->super->s_volume_name, volume_label, + sizeof(fs->super->s_volume_name)); + } + + /* + * Set the last mount directory + */ + if (mount_dir) { + memset(fs->super->s_last_mounted, 0, + sizeof(fs->super->s_last_mounted)); + strncpy((char *) fs->super->s_last_mounted, mount_dir, + sizeof(fs->super->s_last_mounted)); + } + + /* Set current default encryption algorithms for data and + * filename encryption */ + if (ext2fs_has_feature_encrypt(fs->super)) { + fs->super->s_encrypt_algos[0] = + EXT4_ENCRYPTION_MODE_AES_256_XTS; + fs->super->s_encrypt_algos[1] = + EXT4_ENCRYPTION_MODE_AES_256_CTS; + } + + if (ext2fs_has_feature_metadata_csum(fs->super)) + fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM; + + if (!quiet || noaction) + show_stats(fs); + + if (noaction) + exit(0); + + if (ext2fs_has_feature_journal_dev(fs->super)) { + create_journal_dev(fs); + printf("\n"); + exit(ext2fs_close_free(&fs) ? 1 : 0); + } + + if (bad_blocks_filename) + read_bb_file(fs, &bb_list, bad_blocks_filename); + if (cflag) + test_disk(fs, &bb_list); + handle_bad_blocks(fs, bb_list); + + fs->stride = fs_stride = fs->super->s_raid_stride; + if (!quiet) + printf("%s", _("Allocating group tables: ")); + if (ext2fs_has_feature_flex_bg(fs->super) && + packed_meta_blocks) + retval = packed_allocate_tables(fs); + else + retval = ext2fs_allocate_tables(fs); + if (retval) { + com_err(program_name, retval, "%s", + _("while trying to allocate filesystem tables")); + exit(1); + } + if (!quiet) + printf("%s", _("done \n")); + + /* + * Unmark bad blocks to calculate overhead, because metadata + * blocks and bad blocks can land on the same allocation cluster. + */ + if (bb_list) { + retval = ext2fs_badblocks_list_iterate_begin(bb_list, + &bb_iter); + if (retval) { + com_err("ext2fs_badblocks_list_iterate_begin", retval, + "%s", _("while unmarking bad blocks")); + exit(1); + } + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) + ext2fs_unmark_block_bitmap2(fs->block_map, blk); + ext2fs_badblocks_list_iterate_end(bb_iter); + } + + retval = ext2fs_convert_subcluster_bitmap(fs, &fs->block_map); + if (retval) { + com_err(program_name, retval, "%s", + _("\n\twhile converting subcluster bitmap")); + exit(1); + } + + retval = ext2fs_count_used_clusters(fs, fs->super->s_first_data_block, + ext2fs_blocks_count(fs->super) - 1, + &overhead); + if (retval) { + com_err(program_name, retval, "%s", + _("while calculating overhead")); + exit(1); + } + + if (bb_list) { + retval = ext2fs_badblocks_list_iterate_begin(bb_list, + &bb_iter); + if (retval) { + com_err("ext2fs_badblocks_list_iterate_begin", retval, + "%s", _("while marking bad blocks as used")); + exit(1); + } + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) + ext2fs_mark_block_bitmap2(fs->block_map, blk); + ext2fs_badblocks_list_iterate_end(bb_iter); + } + + if (super_only) { + check_plausibility(device_name, CHECK_FS_EXIST, NULL); + printf(_("%s may be further corrupted by superblock rewrite\n"), + device_name); + if (!force) + proceed_question(proceed_delay); + fs->super->s_state |= EXT2_ERROR_FS; + fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY); + /* + * The command "mke2fs -S" is used to recover + * corrupted file systems, so do not mark any of the + * inodes as unused; we want e2fsck to consider all + * inodes as potentially containing recoverable data. + */ + if (ext2fs_has_group_desc_csum(fs)) { + for (i = 0; i < fs->group_desc_count; i++) + ext2fs_bg_itable_unused_set(fs, i, 0); + } + } else { + /* rsv must be a power of two (64kB is MD RAID sb alignment) */ + blk64_t rsv = 65536 / fs->blocksize; + blk64_t blocks = ext2fs_blocks_count(fs->super); + blk64_t start; + blk64_t ret_blk; + +#ifdef ZAP_BOOTBLOCK + zap_sector(fs, 0, 2); +#endif + + /* + * Wipe out any old MD RAID (or other) metadata at the end + * of the device. This will also verify that the device is + * as large as we think. Be careful with very small devices. + */ + start = (blocks & ~(rsv - 1)); + if (start > rsv) + start -= rsv; + if (start > 0) + retval = ext2fs_zero_blocks2(fs, start, blocks - start, + &ret_blk, NULL); + + if (retval) { + com_err(program_name, retval, + _("while zeroing block %llu at end of filesystem"), + (unsigned long long) ret_blk); + } + write_inode_tables(fs, lazy_itable_init, itable_zeroed); + create_root_dir(fs); + create_lost_and_found(fs); + reserve_inodes(fs); + create_bad_block_inode(fs, bb_list); + if (ext2fs_has_feature_resize_inode(fs->super)) { + retval = ext2fs_create_resize_inode(fs); + if (retval) { + com_err("ext2fs_create_resize_inode", retval, + "%s", + _("while reserving blocks for online resize")); + exit(1); + } + } + } + + if (journal_device) { + ext2_filsys jfs; + + if (!check_plausibility(journal_device, CHECK_BLOCK_DEV, + NULL) && !force) + proceed_question(proceed_delay); + check_mount(journal_device, force, _("journal")); + + retval = ext2fs_open(journal_device, EXT2_FLAG_RW| + EXT2_FLAG_JOURNAL_DEV_OK, 0, + fs->blocksize, default_io_manager, &jfs); + if (retval) { + com_err(program_name, retval, + _("while trying to open journal device %s\n"), + journal_device); + exit(1); + } + if (!quiet) { + printf(_("Adding journal to device %s: "), + journal_device); + fflush(stdout); + } + retval = ext2fs_add_journal_device(fs, jfs); + if(retval) { + com_err (program_name, retval, + _("\n\twhile trying to add journal to device %s"), + journal_device); + exit(1); + } + if (!quiet) + printf("%s", _("done\n")); + ext2fs_close_free(&jfs); + free(journal_device); + } else if ((journal_size) || + ext2fs_has_feature_journal(&fs_param)) { + overhead += EXT2FS_NUM_B2C(fs, jparams.num_journal_blocks + jparams.num_fc_blocks); + if (super_only) { + printf("%s", _("Skipping journal creation in super-only mode\n")); + fs->super->s_journal_inum = EXT2_JOURNAL_INO; + goto no_journal; + } + + if (!jparams.num_journal_blocks) { + ext2fs_clear_feature_journal(fs->super); + goto no_journal; + } + if (!quiet) { + printf(_("Creating journal (%u blocks): "), + jparams.num_journal_blocks + jparams.num_fc_blocks); + fflush(stdout); + } + retval = ext2fs_add_journal_inode3(fs, &jparams, + journal_location, + journal_flags); + if (retval) { + com_err(program_name, retval, "%s", + _("\n\twhile trying to create journal")); + exit(1); + } + if (!quiet) + printf("%s", _("done\n")); + } +no_journal: + if (!super_only && + ext2fs_has_feature_mmp(fs->super)) { + retval = ext2fs_mmp_init(fs); + if (retval) { + fprintf(stderr, "%s", + _("\nError while enabling multiple " + "mount protection feature.")); + exit(1); + } + if (!quiet) + printf(_("Multiple mount protection is enabled " + "with update interval %d seconds.\n"), + fs->super->s_mmp_update_interval); + } + + overhead += fs->super->s_first_data_block; + if (!super_only) + fs->super->s_overhead_clusters = overhead; + + if (ext2fs_has_feature_bigalloc(&fs_param)) + fix_cluster_bg_counts(fs); + if (ext2fs_has_feature_quota(&fs_param)) + create_quota_inodes(fs); + + retval = mk_hugefiles(fs, device_name); + if (retval) + com_err(program_name, retval, "while creating huge files"); + /* Copy files from the specified directory */ + if (src_root_dir) { + if (!quiet) + printf("%s", _("Copying files into the device: ")); + + retval = populate_fs(fs, EXT2_ROOT_INO, src_root_dir, + EXT2_ROOT_INO); + if (retval) { + com_err(program_name, retval, "%s", + _("while populating file system")); + exit(1); + } else if (!quiet) + printf("%s", _("done\n")); + } + + if (!quiet) + printf("%s", _("Writing superblocks and " + "filesystem accounting information: ")); + checkinterval = fs->super->s_checkinterval; + max_mnt_count = fs->super->s_max_mnt_count; + retval = ext2fs_close_free(&fs); + if (retval) { + com_err(program_name, retval, "%s", + _("while writing out and closing file system")); + retval = 1; + } else if (!quiet) { + printf("%s", _("done\n\n")); + if (!getenv("MKE2FS_SKIP_CHECK_MSG")) + print_check_message(max_mnt_count, checkinterval); + } + + remove_error_table(&et_ext2_error_table); + remove_error_table(&et_prof_error_table); + profile_release(profile); + for (i=0; fs_types[i]; i++) + free(fs_types[i]); + free(fs_types); + return retval; +} diff --git a/jni/e2fsprogs/mke2fs/mke2fs.o b/jni/e2fsprogs/mke2fs/mke2fs.o new file mode 100755 index 0000000000000000000000000000000000000000..ed608903f1b275a848e25ad89ade88cca8b58a52 GIT binary patch literal 140008 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